| 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 "components/sync/engine_impl/get_commit_ids.h" | 5 #include "components/sync/engine_impl/get_commit_ids.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "components/sync/base/cryptographer.h" | 10 #include "components/sync/base/cryptographer.h" |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 | 155 |
| 156 // First step of traversal building. Adds non-deleted items in order. | 156 // First step of traversal building. Adds non-deleted items in order. |
| 157 void AddCreatesAndMoves(const std::set<int64_t>& ready_unsynced_set); | 157 void AddCreatesAndMoves(const std::set<int64_t>& ready_unsynced_set); |
| 158 | 158 |
| 159 // Second step of traverals building. Appends deleted items. | 159 // Second step of traverals building. Appends deleted items. |
| 160 void AddDeletes(const std::set<int64_t>& ready_unsynced_set); | 160 void AddDeletes(const std::set<int64_t>& ready_unsynced_set); |
| 161 | 161 |
| 162 private: | 162 private: |
| 163 // The following functions do not modify the traversal directly. They return | 163 // The following functions do not modify the traversal directly. They return |
| 164 // their results in the |result| vector instead. | 164 // their results in the |result| vector instead. |
| 165 void AddUncommittedParents(const std::set<int64_t>& ready_unsynced_set, | 165 bool TryAddUncommittedParents(const std::set<int64_t>& ready_unsynced_set, |
| 166 const Entry& item, | 166 const Entry& item, |
| 167 Directory::Metahandles* result) const; | 167 Directory::Metahandles* result) const; |
| 168 | 168 |
| 169 bool TryAddItem(const std::set<int64_t>& ready_unsynced_set, | 169 bool TryAddItem(const std::set<int64_t>& ready_unsynced_set, |
| 170 const Entry& item, | 170 const Entry& item, |
| 171 Directory::Metahandles* result) const; | 171 Directory::Metahandles* result) const; |
| 172 | 172 |
| 173 void AddDeletedParents(const std::set<int64_t>& ready_unsynced_set, | 173 void AddDeletedParents(const std::set<int64_t>& ready_unsynced_set, |
| 174 const Entry& item, | 174 const Entry& item, |
| 175 const Directory::Metahandles& traversed, | 175 const Directory::Metahandles& traversed, |
| 176 Directory::Metahandles* result) const; | 176 Directory::Metahandles* result) const; |
| 177 | 177 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 195 DISALLOW_COPY_AND_ASSIGN(Traversal); | 195 DISALLOW_COPY_AND_ASSIGN(Traversal); |
| 196 }; | 196 }; |
| 197 | 197 |
| 198 Traversal::Traversal(syncable::BaseTransaction* trans, | 198 Traversal::Traversal(syncable::BaseTransaction* trans, |
| 199 int64_t max_entries, | 199 int64_t max_entries, |
| 200 Directory::Metahandles* out) | 200 Directory::Metahandles* out) |
| 201 : out_(out), max_entries_(max_entries), trans_(trans) {} | 201 : out_(out), max_entries_(max_entries), trans_(trans) {} |
| 202 | 202 |
| 203 Traversal::~Traversal() {} | 203 Traversal::~Traversal() {} |
| 204 | 204 |
| 205 void Traversal::AddUncommittedParents( | 205 bool Traversal::TryAddUncommittedParents( |
| 206 const std::set<int64_t>& ready_unsynced_set, | 206 const std::set<int64_t>& ready_unsynced_set, |
| 207 const Entry& item, | 207 const Entry& item, |
| 208 Directory::Metahandles* result) const { | 208 Directory::Metahandles* result) const { |
| 209 DCHECK(SupportsHierarchy(item)); | 209 DCHECK(SupportsHierarchy(item)); |
| 210 Directory::Metahandles dependencies; | 210 Directory::Metahandles dependencies; |
| 211 syncable::Id parent_id = item.GetParentId(); | 211 syncable::Id parent_id = item.GetParentId(); |
| 212 | 212 |
| 213 // Climb the tree adding entries leaf -> root. | 213 // Climb the tree adding entries leaf -> root. |
| 214 while (!parent_id.ServerKnows()) { | 214 while (!parent_id.ServerKnows()) { |
| 215 Entry parent(trans_, syncable::GET_BY_ID, parent_id); | 215 Entry parent(trans_, syncable::GET_BY_ID, parent_id); |
| 216 CHECK(parent.good()) << "Bad user-only parent in item path."; | 216 |
| 217 // This apparently does happen, see crbug.com/711381. Someone is violating |
| 218 // some constraint and some ancestor isn't current present in the directory |
| 219 // while the child is. Because we do not know where this comes from, be |
| 220 // defensive and skip this inclusion instead. |
| 221 if (!parent.good()) { |
| 222 DVLOG(1) << "Bad user-only parent in item path with id " << parent_id; |
| 223 return false; |
| 224 } |
| 225 |
| 217 int64_t handle = parent.GetMetahandle(); | 226 int64_t handle = parent.GetMetahandle(); |
| 218 if (HaveItem(handle)) { | 227 if (HaveItem(handle)) { |
| 219 // We've already added this parent (and therefore all of its parents). | 228 // We've already added this parent (and therefore all of its parents). |
| 220 // We can return early. | 229 // We can return early. |
| 221 break; | 230 break; |
| 222 } | 231 } |
| 223 | 232 |
| 224 if (!TryAddItem(ready_unsynced_set, parent, &dependencies)) { | 233 if (!TryAddItem(ready_unsynced_set, parent, &dependencies)) { |
| 225 // The parent isn't in |ready_unsynced_set|. | 234 // The parent isn't in |ready_unsynced_set|. |
| 226 break; | 235 break; |
| 227 } | 236 } |
| 228 | 237 |
| 229 parent_id = parent.GetParentId(); | 238 parent_id = parent.GetParentId(); |
| 230 } | 239 } |
| 231 | 240 |
| 232 // Reverse what we added to get the correct order. | 241 // Reverse what we added to get the correct order. |
| 233 result->insert(result->end(), dependencies.rbegin(), dependencies.rend()); | 242 result->insert(result->end(), dependencies.rbegin(), dependencies.rend()); |
| 243 return true; |
| 234 } | 244 } |
| 235 | 245 |
| 236 // Adds the given item to the list if it is unsynced and ready for commit. | 246 // Adds the given item to the list if it is unsynced and ready for commit. |
| 237 bool Traversal::TryAddItem(const std::set<int64_t>& ready_unsynced_set, | 247 bool Traversal::TryAddItem(const std::set<int64_t>& ready_unsynced_set, |
| 238 const Entry& item, | 248 const Entry& item, |
| 239 Directory::Metahandles* result) const { | 249 Directory::Metahandles* result) const { |
| 240 DCHECK(item.GetIsUnsynced()); | 250 DCHECK(item.GetIsUnsynced()); |
| 241 int64_t item_handle = item.GetMetahandle(); | 251 int64_t item_handle = item.GetMetahandle(); |
| 242 if (ready_unsynced_set.count(item_handle) != 0) { | 252 if (ready_unsynced_set.count(item_handle) != 0) { |
| 243 result->push_back(item_handle); | 253 result->push_back(item_handle); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 } | 340 } |
| 331 if (HaveItem(handle)) | 341 if (HaveItem(handle)) |
| 332 continue; | 342 continue; |
| 333 | 343 |
| 334 Entry entry(trans_, syncable::GET_BY_HANDLE, handle); | 344 Entry entry(trans_, syncable::GET_BY_HANDLE, handle); |
| 335 if (!entry.GetIsDel()) { | 345 if (!entry.GetIsDel()) { |
| 336 if (SupportsHierarchy(entry)) { | 346 if (SupportsHierarchy(entry)) { |
| 337 // We only commit an item + its dependencies if it and all its | 347 // We only commit an item + its dependencies if it and all its |
| 338 // dependencies are not in conflict. | 348 // dependencies are not in conflict. |
| 339 Directory::Metahandles item_dependencies; | 349 Directory::Metahandles item_dependencies; |
| 340 AddUncommittedParents(ready_unsynced_set, entry, &item_dependencies); | 350 |
| 351 // If we fail to add a required parent, give up on this entry. |
| 352 if (!TryAddUncommittedParents(ready_unsynced_set, entry, |
| 353 &item_dependencies)) { |
| 354 continue; |
| 355 } |
| 356 |
| 357 // Okay if this fails, the parents were still valid. |
| 341 TryAddItem(ready_unsynced_set, entry, &item_dependencies); | 358 TryAddItem(ready_unsynced_set, entry, &item_dependencies); |
| 342 AppendManyToTraversal(item_dependencies); | 359 AppendManyToTraversal(item_dependencies); |
| 343 } else { | 360 } else { |
| 344 // No hierarchy dependencies, just commit the item itself. | 361 // No hierarchy dependencies, just commit the item itself. |
| 345 AppendToTraversal(handle); | 362 AppendToTraversal(handle); |
| 346 } | 363 } |
| 347 } | 364 } |
| 348 } | 365 } |
| 349 | 366 |
| 350 // It's possible that we over committed while trying to expand dependent | 367 // It's possible that we over committed while trying to expand dependent |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 AppendManyToTraversal(deletion_list); | 408 AppendManyToTraversal(deletion_list); |
| 392 | 409 |
| 393 // It's possible that we over committed while trying to expand dependent | 410 // It's possible that we over committed while trying to expand dependent |
| 394 // items. If so, truncate the set down to the allowed size. This is safe | 411 // items. If so, truncate the set down to the allowed size. This is safe |
| 395 // because of the reverse above, which should guarantee the leafy nodes are | 412 // because of the reverse above, which should guarantee the leafy nodes are |
| 396 // in the front of the ancestors nodes. | 413 // in the front of the ancestors nodes. |
| 397 if (out_->size() > max_entries_) | 414 if (out_->size() > max_entries_) |
| 398 out_->resize(max_entries_); | 415 out_->resize(max_entries_); |
| 399 } | 416 } |
| 400 | 417 |
| 401 // Excludes ancestors of deleted conflicted items from | 418 // Excludes ancestors of deleted conflicted items from |ready_unsynced_set|. |
| 402 // |ready_unsynced_set|. | |
| 403 void ExcludeDeletedAncestors( | 419 void ExcludeDeletedAncestors( |
| 404 syncable::BaseTransaction* trans, | 420 syncable::BaseTransaction* trans, |
| 405 const std::vector<int64_t>& deleted_conflicted_items, | 421 const std::vector<int64_t>& deleted_conflicted_items, |
| 406 std::set<int64_t>* ready_unsynced_set) { | 422 std::set<int64_t>* ready_unsynced_set) { |
| 407 for (const int64_t& deleted_conflicted_handle : deleted_conflicted_items) { | 423 for (const int64_t& deleted_conflicted_handle : deleted_conflicted_items) { |
| 408 Entry item(trans, syncable::GET_BY_HANDLE, deleted_conflicted_handle); | 424 Entry item(trans, syncable::GET_BY_HANDLE, deleted_conflicted_handle); |
| 409 syncable::Id parent_id = item.GetParentId(); | 425 syncable::Id parent_id = item.GetParentId(); |
| 410 DCHECK(!parent_id.IsNull()); | 426 DCHECK(!parent_id.IsNull()); |
| 411 | 427 |
| 412 while (!parent_id.IsRoot()) { | 428 while (!parent_id.IsRoot()) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 &ready_unsynced_set); | 555 &ready_unsynced_set); |
| 540 | 556 |
| 541 OrderCommitIds(trans, max_entries, ready_unsynced_set, out); | 557 OrderCommitIds(trans, max_entries, ready_unsynced_set, out); |
| 542 | 558 |
| 543 for (const int64_t& handle : *out) { | 559 for (const int64_t& handle : *out) { |
| 544 DVLOG(1) << "Debug commit batch result:" << handle; | 560 DVLOG(1) << "Debug commit batch result:" << handle; |
| 545 } | 561 } |
| 546 } | 562 } |
| 547 | 563 |
| 548 } // namespace syncer | 564 } // namespace syncer |
| OLD | NEW |