| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sync/engine/get_commit_ids.h" | 5 #include "sync/engine/get_commit_ids.h" |
| 6 | 6 |
| 7 #include <stddef.h> |
| 8 #include <stdint.h> |
| 9 |
| 7 #include <set> | 10 #include <set> |
| 8 #include <vector> | 11 #include <vector> |
| 9 | 12 |
| 10 #include "base/basictypes.h" | 13 #include "base/macros.h" |
| 11 #include "sync/engine/syncer_util.h" | 14 #include "sync/engine/syncer_util.h" |
| 12 #include "sync/syncable/directory.h" | 15 #include "sync/syncable/directory.h" |
| 13 #include "sync/syncable/entry.h" | 16 #include "sync/syncable/entry.h" |
| 14 #include "sync/syncable/nigori_handler.h" | 17 #include "sync/syncable/nigori_handler.h" |
| 15 #include "sync/syncable/nigori_util.h" | 18 #include "sync/syncable/nigori_util.h" |
| 16 #include "sync/syncable/syncable_base_transaction.h" | 19 #include "sync/syncable/syncable_base_transaction.h" |
| 17 #include "sync/syncable/syncable_util.h" | 20 #include "sync/syncable/syncable_util.h" |
| 18 #include "sync/util/cryptographer.h" | 21 #include "sync/util/cryptographer.h" |
| 19 | 22 |
| 20 using std::set; | 23 using std::set; |
| 21 using std::vector; | 24 using std::vector; |
| 22 | 25 |
| 23 namespace syncer { | 26 namespace syncer { |
| 24 | 27 |
| 25 namespace { | 28 namespace { |
| 26 | 29 |
| 27 // Forward-declare some helper functions. This gives us more options for | 30 // Forward-declare some helper functions. This gives us more options for |
| 28 // ordering the function defintions within this file. | 31 // ordering the function defintions within this file. |
| 29 | 32 |
| 30 // Filters |unsynced_handles| to remove all entries that do not belong to the | 33 // Filters |unsynced_handles| to remove all entries that do not belong to the |
| 31 // specified |requested_types|, or are not eligible for a commit at this time. | 34 // specified |requested_types|, or are not eligible for a commit at this time. |
| 32 void FilterUnreadyEntries( | 35 void FilterUnreadyEntries( |
| 33 syncable::BaseTransaction* trans, | 36 syncable::BaseTransaction* trans, |
| 34 ModelTypeSet requested_types, | 37 ModelTypeSet requested_types, |
| 35 ModelTypeSet encrypted_types, | 38 ModelTypeSet encrypted_types, |
| 36 bool passphrase_missing, | 39 bool passphrase_missing, |
| 37 const syncable::Directory::Metahandles& unsynced_handles, | 40 const syncable::Directory::Metahandles& unsynced_handles, |
| 38 std::set<int64>* ready_unsynced_set); | 41 std::set<int64_t>* ready_unsynced_set); |
| 39 | 42 |
| 40 // Given a set of commit metahandles that are ready for commit | 43 // Given a set of commit metahandles that are ready for commit |
| 41 // (|ready_unsynced_set|), sorts these into commit order and places up to | 44 // (|ready_unsynced_set|), sorts these into commit order and places up to |
| 42 // |max_entries| of them in the output parameter |out|. | 45 // |max_entries| of them in the output parameter |out|. |
| 43 // | 46 // |
| 44 // See the header file for an explanation of commit ordering. | 47 // See the header file for an explanation of commit ordering. |
| 45 void OrderCommitIds( | 48 void OrderCommitIds(syncable::BaseTransaction* trans, |
| 46 syncable::BaseTransaction* trans, | 49 size_t max_entries, |
| 47 size_t max_entries, | 50 const std::set<int64_t>& ready_unsynced_set, |
| 48 const std::set<int64>& ready_unsynced_set, | 51 std::vector<int64_t>* out); |
| 49 std::vector<int64>* out); | |
| 50 | 52 |
| 51 } // namespace | 53 } // namespace |
| 52 | 54 |
| 53 void GetCommitIdsForType( | 55 void GetCommitIdsForType( |
| 54 syncable::BaseTransaction* trans, | 56 syncable::BaseTransaction* trans, |
| 55 ModelType type, | 57 ModelType type, |
| 56 size_t max_entries, | 58 size_t max_entries, |
| 57 syncable::Directory::Metahandles* out) { | 59 syncable::Directory::Metahandles* out) { |
| 58 syncable::Directory* dir = trans->directory(); | 60 syncable::Directory* dir = trans->directory(); |
| 59 | 61 |
| 60 // Gather the full set of unsynced items and store it in the session. They | 62 // Gather the full set of unsynced items and store it in the session. They |
| 61 // are not in the correct order for commit. | 63 // are not in the correct order for commit. |
| 62 std::set<int64> ready_unsynced_set; | 64 std::set<int64_t> ready_unsynced_set; |
| 63 syncable::Directory::Metahandles all_unsynced_handles; | 65 syncable::Directory::Metahandles all_unsynced_handles; |
| 64 GetUnsyncedEntries(trans, &all_unsynced_handles); | 66 GetUnsyncedEntries(trans, &all_unsynced_handles); |
| 65 | 67 |
| 66 ModelTypeSet encrypted_types; | 68 ModelTypeSet encrypted_types; |
| 67 bool passphrase_missing = false; | 69 bool passphrase_missing = false; |
| 68 Cryptographer* cryptographer = dir->GetCryptographer(trans); | 70 Cryptographer* cryptographer = dir->GetCryptographer(trans); |
| 69 if (cryptographer) { | 71 if (cryptographer) { |
| 70 encrypted_types = dir->GetNigoriHandler()->GetEncryptedTypes(trans); | 72 encrypted_types = dir->GetNigoriHandler()->GetEncryptedTypes(trans); |
| 71 passphrase_missing = cryptographer->has_pending_keys(); | 73 passphrase_missing = cryptographer->has_pending_keys(); |
| 72 } | 74 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 } | 187 } |
| 186 | 188 |
| 187 // Filters |unsynced_handles| to remove all entries that do not belong to the | 189 // Filters |unsynced_handles| to remove all entries that do not belong to the |
| 188 // specified |requested_types|, or are not eligible for a commit at this time. | 190 // specified |requested_types|, or are not eligible for a commit at this time. |
| 189 void FilterUnreadyEntries( | 191 void FilterUnreadyEntries( |
| 190 syncable::BaseTransaction* trans, | 192 syncable::BaseTransaction* trans, |
| 191 ModelTypeSet requested_types, | 193 ModelTypeSet requested_types, |
| 192 ModelTypeSet encrypted_types, | 194 ModelTypeSet encrypted_types, |
| 193 bool passphrase_missing, | 195 bool passphrase_missing, |
| 194 const syncable::Directory::Metahandles& unsynced_handles, | 196 const syncable::Directory::Metahandles& unsynced_handles, |
| 195 std::set<int64>* ready_unsynced_set) { | 197 std::set<int64_t>* ready_unsynced_set) { |
| 196 for (syncable::Directory::Metahandles::const_iterator iter = | 198 for (syncable::Directory::Metahandles::const_iterator iter = |
| 197 unsynced_handles.begin(); iter != unsynced_handles.end(); ++iter) { | 199 unsynced_handles.begin(); iter != unsynced_handles.end(); ++iter) { |
| 198 syncable::Entry entry(trans, syncable::GET_BY_HANDLE, *iter); | 200 syncable::Entry entry(trans, syncable::GET_BY_HANDLE, *iter); |
| 199 // TODO(maniscalco): While we check if entry is ready to be committed, we | 201 // TODO(maniscalco): While we check if entry is ready to be committed, we |
| 200 // also need to check that all of its ancestors (parents, transitive) are | 202 // also need to check that all of its ancestors (parents, transitive) are |
| 201 // ready to be committed. Once attachments can prevent an entry from being | 203 // ready to be committed. Once attachments can prevent an entry from being |
| 202 // committable, this method must ensure all ancestors are ready for commit | 204 // committable, this method must ensure all ancestors are ready for commit |
| 203 // (bug 356273). | 205 // (bug 356273). |
| 204 if (IsEntryReadyForCommit(requested_types, | 206 if (IsEntryReadyForCommit(requested_types, |
| 205 encrypted_types, | 207 encrypted_types, |
| 206 passphrase_missing, | 208 passphrase_missing, |
| 207 entry)) { | 209 entry)) { |
| 208 ready_unsynced_set->insert(*iter); | 210 ready_unsynced_set->insert(*iter); |
| 209 } | 211 } |
| 210 } | 212 } |
| 211 } | 213 } |
| 212 | 214 |
| 213 // This class helps to implement OrderCommitIds(). Its members track the | 215 // This class helps to implement OrderCommitIds(). Its members track the |
| 214 // progress of a traversal while its methods extend it. It can return early if | 216 // progress of a traversal while its methods extend it. It can return early if |
| 215 // the traversal reaches the desired size before the full traversal is complete. | 217 // the traversal reaches the desired size before the full traversal is complete. |
| 216 class Traversal { | 218 class Traversal { |
| 217 public: | 219 public: |
| 218 Traversal( | 220 Traversal(syncable::BaseTransaction* trans, |
| 219 syncable::BaseTransaction* trans, | 221 int64_t max_entries, |
| 220 int64 max_entries, | 222 syncable::Directory::Metahandles* out); |
| 221 syncable::Directory::Metahandles* out); | |
| 222 ~Traversal(); | 223 ~Traversal(); |
| 223 | 224 |
| 224 // First step of traversal building. Adds non-deleted items in order. | 225 // First step of traversal building. Adds non-deleted items in order. |
| 225 void AddCreatesAndMoves(const std::set<int64>& ready_unsynced_set); | 226 void AddCreatesAndMoves(const std::set<int64_t>& ready_unsynced_set); |
| 226 | 227 |
| 227 // Second step of traverals building. Appends deleted items. | 228 // Second step of traverals building. Appends deleted items. |
| 228 void AddDeletes(const std::set<int64>& ready_unsynced_set); | 229 void AddDeletes(const std::set<int64_t>& ready_unsynced_set); |
| 229 | 230 |
| 230 private: | 231 private: |
| 231 // The following functions do not modify the traversal directly. They return | 232 // The following functions do not modify the traversal directly. They return |
| 232 // their results in the |result| vector instead. | 233 // their results in the |result| vector instead. |
| 233 bool AddUncommittedParents(const std::set<int64>& ready_unsynced_set, | 234 bool AddUncommittedParents(const std::set<int64_t>& ready_unsynced_set, |
| 234 const syncable::Entry& item, | 235 const syncable::Entry& item, |
| 235 syncable::Directory::Metahandles* result) const; | 236 syncable::Directory::Metahandles* result) const; |
| 236 | 237 |
| 237 void TryAddItem(const std::set<int64>& ready_unsynced_set, | 238 void TryAddItem(const std::set<int64_t>& ready_unsynced_set, |
| 238 const syncable::Entry& item, | 239 const syncable::Entry& item, |
| 239 syncable::Directory::Metahandles* result) const; | 240 syncable::Directory::Metahandles* result) const; |
| 240 | 241 |
| 241 bool AddDeletedParents(const std::set<int64>& ready_unsynced_set, | 242 bool AddDeletedParents(const std::set<int64_t>& ready_unsynced_set, |
| 242 const syncable::Entry& item, | 243 const syncable::Entry& item, |
| 243 const syncable::Directory::Metahandles& traversed, | 244 const syncable::Directory::Metahandles& traversed, |
| 244 syncable::Directory::Metahandles* result) const; | 245 syncable::Directory::Metahandles* result) const; |
| 245 | 246 |
| 246 bool SupportsHierarchy(const syncable::Entry& item) const; | 247 bool SupportsHierarchy(const syncable::Entry& item) const; |
| 247 | 248 |
| 248 // Returns true if we've collected enough items. | 249 // Returns true if we've collected enough items. |
| 249 bool IsFull() const; | 250 bool IsFull() const; |
| 250 | 251 |
| 251 // Returns true if the specified handle is already in the traversal. | 252 // Returns true if the specified handle is already in the traversal. |
| 252 bool HaveItem(int64 handle) const; | 253 bool HaveItem(int64_t handle) const; |
| 253 | 254 |
| 254 // Adds the specified handles to the traversal. | 255 // Adds the specified handles to the traversal. |
| 255 void AppendManyToTraversal(const syncable::Directory::Metahandles& handles); | 256 void AppendManyToTraversal(const syncable::Directory::Metahandles& handles); |
| 256 | 257 |
| 257 // Adds the specifed handle to the traversal. | 258 // Adds the specifed handle to the traversal. |
| 258 void AppendToTraversal(int64 handle); | 259 void AppendToTraversal(int64_t handle); |
| 259 | 260 |
| 260 syncable::Directory::Metahandles* out_; | 261 syncable::Directory::Metahandles* out_; |
| 261 std::set<int64> added_handles_; | 262 std::set<int64_t> added_handles_; |
| 262 const size_t max_entries_; | 263 const size_t max_entries_; |
| 263 syncable::BaseTransaction* trans_; | 264 syncable::BaseTransaction* trans_; |
| 264 | 265 |
| 265 DISALLOW_COPY_AND_ASSIGN(Traversal); | 266 DISALLOW_COPY_AND_ASSIGN(Traversal); |
| 266 }; | 267 }; |
| 267 | 268 |
| 268 Traversal::Traversal( | 269 Traversal::Traversal(syncable::BaseTransaction* trans, |
| 269 syncable::BaseTransaction* trans, | 270 int64_t max_entries, |
| 270 int64 max_entries, | 271 syncable::Directory::Metahandles* out) |
| 271 syncable::Directory::Metahandles* out) | 272 : out_(out), max_entries_(max_entries), trans_(trans) {} |
| 272 : out_(out), | |
| 273 max_entries_(max_entries), | |
| 274 trans_(trans) { } | |
| 275 | 273 |
| 276 Traversal::~Traversal() {} | 274 Traversal::~Traversal() {} |
| 277 | 275 |
| 278 bool Traversal::AddUncommittedParents( | 276 bool Traversal::AddUncommittedParents( |
| 279 const std::set<int64>& ready_unsynced_set, | 277 const std::set<int64_t>& ready_unsynced_set, |
| 280 const syncable::Entry& item, | 278 const syncable::Entry& item, |
| 281 syncable::Directory::Metahandles* result) const { | 279 syncable::Directory::Metahandles* result) const { |
| 282 DCHECK(SupportsHierarchy(item)); | 280 DCHECK(SupportsHierarchy(item)); |
| 283 syncable::Directory::Metahandles dependencies; | 281 syncable::Directory::Metahandles dependencies; |
| 284 syncable::Id parent_id = item.GetParentId(); | 282 syncable::Id parent_id = item.GetParentId(); |
| 285 | 283 |
| 286 // Climb the tree adding entries leaf -> root. | 284 // Climb the tree adding entries leaf -> root. |
| 287 while (!parent_id.ServerKnows()) { | 285 while (!parent_id.ServerKnows()) { |
| 288 syncable::Entry parent(trans_, syncable::GET_BY_ID, parent_id); | 286 syncable::Entry parent(trans_, syncable::GET_BY_ID, parent_id); |
| 289 CHECK(parent.good()) << "Bad user-only parent in item path."; | 287 CHECK(parent.good()) << "Bad user-only parent in item path."; |
| 290 int64 handle = parent.GetMetahandle(); | 288 int64_t handle = parent.GetMetahandle(); |
| 291 if (HaveItem(handle)) { | 289 if (HaveItem(handle)) { |
| 292 // We've already added this parent (and therefore all of its parents). | 290 // We've already added this parent (and therefore all of its parents). |
| 293 // We can return early. | 291 // We can return early. |
| 294 break; | 292 break; |
| 295 } | 293 } |
| 296 if (IsEntryInConflict(parent)) { | 294 if (IsEntryInConflict(parent)) { |
| 297 // We ignore all entries that are children of a conflicing item. Return | 295 // We ignore all entries that are children of a conflicing item. Return |
| 298 // false immediately to forget the traversal we've built up so far. | 296 // false immediately to forget the traversal we've built up so far. |
| 299 DVLOG(1) << "Parent was in conflict, omitting " << item; | 297 DVLOG(1) << "Parent was in conflict, omitting " << item; |
| 300 return false; | 298 return false; |
| 301 } | 299 } |
| 302 TryAddItem(ready_unsynced_set, parent, &dependencies); | 300 TryAddItem(ready_unsynced_set, parent, &dependencies); |
| 303 parent_id = parent.GetParentId(); | 301 parent_id = parent.GetParentId(); |
| 304 } | 302 } |
| 305 | 303 |
| 306 // Reverse what we added to get the correct order. | 304 // Reverse what we added to get the correct order. |
| 307 result->insert(result->end(), dependencies.rbegin(), dependencies.rend()); | 305 result->insert(result->end(), dependencies.rbegin(), dependencies.rend()); |
| 308 return true; | 306 return true; |
| 309 } | 307 } |
| 310 | 308 |
| 311 // Adds the given item to the list if it is unsynced and ready for commit. | 309 // Adds the given item to the list if it is unsynced and ready for commit. |
| 312 void Traversal::TryAddItem(const std::set<int64>& ready_unsynced_set, | 310 void Traversal::TryAddItem(const std::set<int64_t>& ready_unsynced_set, |
| 313 const syncable::Entry& item, | 311 const syncable::Entry& item, |
| 314 syncable::Directory::Metahandles* result) const { | 312 syncable::Directory::Metahandles* result) const { |
| 315 DCHECK(item.GetIsUnsynced()); | 313 DCHECK(item.GetIsUnsynced()); |
| 316 int64 item_handle = item.GetMetahandle(); | 314 int64_t item_handle = item.GetMetahandle(); |
| 317 if (ready_unsynced_set.count(item_handle) != 0) { | 315 if (ready_unsynced_set.count(item_handle) != 0) { |
| 318 result->push_back(item_handle); | 316 result->push_back(item_handle); |
| 319 } | 317 } |
| 320 } | 318 } |
| 321 | 319 |
| 322 // Traverses the tree from bottom to top, adding the deleted parents of the | 320 // Traverses the tree from bottom to top, adding the deleted parents of the |
| 323 // given |item|. Stops traversing if it encounters a non-deleted node, or | 321 // given |item|. Stops traversing if it encounters a non-deleted node, or |
| 324 // a node that was already listed in the |traversed| list. Returns an error | 322 // a node that was already listed in the |traversed| list. Returns an error |
| 325 // (false) if a node along the traversal is in a conflict state. | 323 // (false) if a node along the traversal is in a conflict state. |
| 326 // | 324 // |
| 327 // The result list is reversed before it is returned, so the resulting | 325 // The result list is reversed before it is returned, so the resulting |
| 328 // traversal is in top to bottom order. Also note that this function appends | 326 // traversal is in top to bottom order. Also note that this function appends |
| 329 // to the result list without clearing it. | 327 // to the result list without clearing it. |
| 330 bool Traversal::AddDeletedParents( | 328 bool Traversal::AddDeletedParents( |
| 331 const std::set<int64>& ready_unsynced_set, | 329 const std::set<int64_t>& ready_unsynced_set, |
| 332 const syncable::Entry& item, | 330 const syncable::Entry& item, |
| 333 const syncable::Directory::Metahandles& traversed, | 331 const syncable::Directory::Metahandles& traversed, |
| 334 syncable::Directory::Metahandles* result) const { | 332 syncable::Directory::Metahandles* result) const { |
| 335 DCHECK(SupportsHierarchy(item)); | 333 DCHECK(SupportsHierarchy(item)); |
| 336 syncable::Directory::Metahandles dependencies; | 334 syncable::Directory::Metahandles dependencies; |
| 337 syncable::Id parent_id = item.GetParentId(); | 335 syncable::Id parent_id = item.GetParentId(); |
| 338 | 336 |
| 339 // Climb the tree adding entries leaf -> root. | 337 // Climb the tree adding entries leaf -> root. |
| 340 while (!parent_id.IsRoot()) { | 338 while (!parent_id.IsRoot()) { |
| 341 syncable::Entry parent(trans_, syncable::GET_BY_ID, parent_id); | 339 syncable::Entry parent(trans_, syncable::GET_BY_ID, parent_id); |
| 342 | 340 |
| 343 if (!parent.good()) { | 341 if (!parent.good()) { |
| 344 // This is valid because the parent could have gone away a long time ago | 342 // This is valid because the parent could have gone away a long time ago |
| 345 // | 343 // |
| 346 // Consider the case where a folder is server-unknown and locally | 344 // Consider the case where a folder is server-unknown and locally |
| 347 // deleted, and has a child that is server-known, deleted, and unsynced. | 345 // deleted, and has a child that is server-known, deleted, and unsynced. |
| 348 // The parent could be dropped from memory at any time, but its child | 346 // The parent could be dropped from memory at any time, but its child |
| 349 // needs to be committed first. | 347 // needs to be committed first. |
| 350 break; | 348 break; |
| 351 } | 349 } |
| 352 int64 handle = parent.GetMetahandle(); | 350 int64_t handle = parent.GetMetahandle(); |
| 353 if (!parent.GetIsUnsynced()) { | 351 if (!parent.GetIsUnsynced()) { |
| 354 // In some rare cases, our parent can be both deleted and unsynced. | 352 // In some rare cases, our parent can be both deleted and unsynced. |
| 355 // (ie. the server-unknown parent case). | 353 // (ie. the server-unknown parent case). |
| 356 break; | 354 break; |
| 357 } | 355 } |
| 358 if (!parent.GetIsDel()) { | 356 if (!parent.GetIsDel()) { |
| 359 // We're not intersted in non-deleted parents. | 357 // We're not intersted in non-deleted parents. |
| 360 break; | 358 break; |
| 361 } | 359 } |
| 362 if (std::find(traversed.begin(), traversed.end(), handle) != | 360 if (std::find(traversed.begin(), traversed.end(), handle) != |
| (...skipping 14 matching lines...) Expand all Loading... |
| 377 | 375 |
| 378 // Reverse what we added to get the correct order. | 376 // Reverse what we added to get the correct order. |
| 379 result->insert(result->end(), dependencies.rbegin(), dependencies.rend()); | 377 result->insert(result->end(), dependencies.rbegin(), dependencies.rend()); |
| 380 return true; | 378 return true; |
| 381 } | 379 } |
| 382 | 380 |
| 383 bool Traversal::IsFull() const { | 381 bool Traversal::IsFull() const { |
| 384 return out_->size() >= max_entries_; | 382 return out_->size() >= max_entries_; |
| 385 } | 383 } |
| 386 | 384 |
| 387 bool Traversal::HaveItem(int64 handle) const { | 385 bool Traversal::HaveItem(int64_t handle) const { |
| 388 return added_handles_.find(handle) != added_handles_.end(); | 386 return added_handles_.find(handle) != added_handles_.end(); |
| 389 } | 387 } |
| 390 | 388 |
| 391 bool Traversal::SupportsHierarchy(const syncable::Entry& item) const { | 389 bool Traversal::SupportsHierarchy(const syncable::Entry& item) const { |
| 392 // Types with explicit server supported hierarchy only. | 390 // Types with explicit server supported hierarchy only. |
| 393 return IsTypeWithServerGeneratedRoot(item.GetModelType()); | 391 return IsTypeWithServerGeneratedRoot(item.GetModelType()); |
| 394 } | 392 } |
| 395 | 393 |
| 396 void Traversal::AppendManyToTraversal( | 394 void Traversal::AppendManyToTraversal( |
| 397 const syncable::Directory::Metahandles& handles) { | 395 const syncable::Directory::Metahandles& handles) { |
| 398 out_->insert(out_->end(), handles.begin(), handles.end()); | 396 out_->insert(out_->end(), handles.begin(), handles.end()); |
| 399 added_handles_.insert(handles.begin(), handles.end()); | 397 added_handles_.insert(handles.begin(), handles.end()); |
| 400 } | 398 } |
| 401 | 399 |
| 402 void Traversal::AppendToTraversal(int64 metahandle) { | 400 void Traversal::AppendToTraversal(int64_t metahandle) { |
| 403 out_->push_back(metahandle); | 401 out_->push_back(metahandle); |
| 404 added_handles_.insert(metahandle); | 402 added_handles_.insert(metahandle); |
| 405 } | 403 } |
| 406 | 404 |
| 407 void Traversal::AddCreatesAndMoves( | 405 void Traversal::AddCreatesAndMoves( |
| 408 const std::set<int64>& ready_unsynced_set) { | 406 const std::set<int64_t>& ready_unsynced_set) { |
| 409 // Add moves and creates, and prepend their uncommitted parents. | 407 // Add moves and creates, and prepend their uncommitted parents. |
| 410 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin(); | 408 for (std::set<int64_t>::const_iterator iter = ready_unsynced_set.begin(); |
| 411 !IsFull() && iter != ready_unsynced_set.end(); ++iter) { | 409 !IsFull() && iter != ready_unsynced_set.end(); ++iter) { |
| 412 int64 metahandle = *iter; | 410 int64_t metahandle = *iter; |
| 413 if (HaveItem(metahandle)) | 411 if (HaveItem(metahandle)) |
| 414 continue; | 412 continue; |
| 415 | 413 |
| 416 syncable::Entry entry(trans_, | 414 syncable::Entry entry(trans_, |
| 417 syncable::GET_BY_HANDLE, | 415 syncable::GET_BY_HANDLE, |
| 418 metahandle); | 416 metahandle); |
| 419 if (!entry.GetIsDel()) { | 417 if (!entry.GetIsDel()) { |
| 420 if (SupportsHierarchy(entry)) { | 418 if (SupportsHierarchy(entry)) { |
| 421 // We only commit an item + its dependencies if it and all its | 419 // We only commit an item + its dependencies if it and all its |
| 422 // dependencies are not in conflict. | 420 // dependencies are not in conflict. |
| 423 syncable::Directory::Metahandles item_dependencies; | 421 syncable::Directory::Metahandles item_dependencies; |
| 424 if (AddUncommittedParents(ready_unsynced_set, entry, | 422 if (AddUncommittedParents(ready_unsynced_set, entry, |
| 425 &item_dependencies)) { | 423 &item_dependencies)) { |
| 426 TryAddItem(ready_unsynced_set, entry, &item_dependencies); | 424 TryAddItem(ready_unsynced_set, entry, &item_dependencies); |
| 427 AppendManyToTraversal(item_dependencies); | 425 AppendManyToTraversal(item_dependencies); |
| 428 } | 426 } |
| 429 } else { | 427 } else { |
| 430 // No hierarchy dependencies, just commit the item itself. | 428 // No hierarchy dependencies, just commit the item itself. |
| 431 AppendToTraversal(metahandle); | 429 AppendToTraversal(metahandle); |
| 432 } | 430 } |
| 433 } | 431 } |
| 434 } | 432 } |
| 435 | 433 |
| 436 // It's possible that we overcommitted while trying to expand dependent | 434 // It's possible that we overcommitted while trying to expand dependent |
| 437 // items. If so, truncate the set down to the allowed size. | 435 // items. If so, truncate the set down to the allowed size. |
| 438 if (out_->size() > max_entries_) | 436 if (out_->size() > max_entries_) |
| 439 out_->resize(max_entries_); | 437 out_->resize(max_entries_); |
| 440 } | 438 } |
| 441 | 439 |
| 442 void Traversal::AddDeletes(const std::set<int64>& ready_unsynced_set) { | 440 void Traversal::AddDeletes(const std::set<int64_t>& ready_unsynced_set) { |
| 443 syncable::Directory::Metahandles deletion_list; | 441 syncable::Directory::Metahandles deletion_list; |
| 444 | 442 |
| 445 // Note: we iterate over all the unsynced set, regardless of the max size. | 443 // Note: we iterate over all the unsynced set, regardless of the max size. |
| 446 // The max size is only enforced after the top-to-bottom order has been | 444 // The max size is only enforced after the top-to-bottom order has been |
| 447 // reversed, in order to ensure children are always deleted before parents. | 445 // reversed, in order to ensure children are always deleted before parents. |
| 448 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin(); | 446 for (std::set<int64_t>::const_iterator iter = ready_unsynced_set.begin(); |
| 449 iter != ready_unsynced_set.end(); ++iter) { | 447 iter != ready_unsynced_set.end(); ++iter) { |
| 450 int64 metahandle = *iter; | 448 int64_t metahandle = *iter; |
| 451 | 449 |
| 452 if (HaveItem(metahandle)) | 450 if (HaveItem(metahandle)) |
| 453 continue; | 451 continue; |
| 454 | 452 |
| 455 if (std::find(deletion_list.begin(), deletion_list.end(), metahandle) != | 453 if (std::find(deletion_list.begin(), deletion_list.end(), metahandle) != |
| 456 deletion_list.end()) { | 454 deletion_list.end()) { |
| 457 continue; | 455 continue; |
| 458 } | 456 } |
| 459 | 457 |
| 460 syncable::Entry entry(trans_, syncable::GET_BY_HANDLE, | 458 syncable::Entry entry(trans_, syncable::GET_BY_HANDLE, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 480 // order as we prepare the list. | 478 // order as we prepare the list. |
| 481 std::reverse(deletion_list.begin(), deletion_list.end()); | 479 std::reverse(deletion_list.begin(), deletion_list.end()); |
| 482 AppendManyToTraversal(deletion_list); | 480 AppendManyToTraversal(deletion_list); |
| 483 | 481 |
| 484 // It's possible that we overcommitted while trying to expand dependent | 482 // It's possible that we overcommitted while trying to expand dependent |
| 485 // items. If so, truncate the set down to the allowed size. | 483 // items. If so, truncate the set down to the allowed size. |
| 486 if (out_->size() > max_entries_) | 484 if (out_->size() > max_entries_) |
| 487 out_->resize(max_entries_); | 485 out_->resize(max_entries_); |
| 488 } | 486 } |
| 489 | 487 |
| 490 void OrderCommitIds( | 488 void OrderCommitIds(syncable::BaseTransaction* trans, |
| 491 syncable::BaseTransaction* trans, | 489 size_t max_entries, |
| 492 size_t max_entries, | 490 const std::set<int64_t>& ready_unsynced_set, |
| 493 const std::set<int64>& ready_unsynced_set, | 491 syncable::Directory::Metahandles* out) { |
| 494 syncable::Directory::Metahandles* out) { | |
| 495 // Commits follow these rules: | 492 // Commits follow these rules: |
| 496 // 1. Moves or creates are preceded by needed folder creates, from | 493 // 1. Moves or creates are preceded by needed folder creates, from |
| 497 // root to leaf. | 494 // root to leaf. |
| 498 // 2. Moves/Creates before deletes. | 495 // 2. Moves/Creates before deletes. |
| 499 // 3. Deletes, collapsed. | 496 // 3. Deletes, collapsed. |
| 500 // We commit deleted moves under deleted items as moves when collapsing | 497 // We commit deleted moves under deleted items as moves when collapsing |
| 501 // delete trees. | 498 // delete trees. |
| 502 | 499 |
| 503 Traversal traversal(trans, max_entries, out); | 500 Traversal traversal(trans, max_entries, out); |
| 504 | 501 |
| 505 // Add moves and creates, and prepend their uncommitted parents. | 502 // Add moves and creates, and prepend their uncommitted parents. |
| 506 traversal.AddCreatesAndMoves(ready_unsynced_set); | 503 traversal.AddCreatesAndMoves(ready_unsynced_set); |
| 507 | 504 |
| 508 // Add all deletes. | 505 // Add all deletes. |
| 509 traversal.AddDeletes(ready_unsynced_set); | 506 traversal.AddDeletes(ready_unsynced_set); |
| 510 } | 507 } |
| 511 | 508 |
| 512 } // namespace | 509 } // namespace |
| 513 | 510 |
| 514 } // namespace syncer | 511 } // namespace syncer |
| OLD | NEW |