Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: components/sync/engine_impl/get_commit_ids.cc

Issue 2826503002: [Sync] Act defensively when parent lookups fail on commit. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/sync/engine_impl/directory_commit_contribution_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « components/sync/engine_impl/directory_commit_contribution_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698