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

Side by Side Diff: sync/engine/get_commit_ids.cc

Issue 331863010: sync: Remove support for hierarchy deletions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « sync/engine/get_commit_ids.h ('k') | sync/engine/syncer_unittest.cc » ('j') | 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 "sync/engine/get_commit_ids.h" 5 #include "sync/engine/get_commit_ids.h"
6 6
7 #include <set> 7 #include <set>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 void AddItemThenPredecessors( 243 void AddItemThenPredecessors(
244 const std::set<int64>& ready_unsynced_set, 244 const std::set<int64>& ready_unsynced_set,
245 const syncable::Entry& item, 245 const syncable::Entry& item,
246 syncable::Directory::Metahandles* result) const; 246 syncable::Directory::Metahandles* result) const;
247 247
248 void AddPredecessorsThenItem( 248 void AddPredecessorsThenItem(
249 const std::set<int64>& ready_unsynced_set, 249 const std::set<int64>& ready_unsynced_set,
250 const syncable::Entry& item, 250 const syncable::Entry& item,
251 syncable::Directory::Metahandles* result) const; 251 syncable::Directory::Metahandles* result) const;
252 252
253 bool AddDeletedParents(const std::set<int64>& ready_unsynced_set,
254 const syncable::Entry& item,
255 const syncable::Directory::Metahandles& traversed,
256 syncable::Directory::Metahandles* result) const;
257
253 // Returns true if we've collected enough items. 258 // Returns true if we've collected enough items.
254 bool IsFull() const; 259 bool IsFull() const;
255 260
256 // Returns true if the specified handle is already in the traversal. 261 // Returns true if the specified handle is already in the traversal.
257 bool HaveItem(int64 handle) const; 262 bool HaveItem(int64 handle) const;
258 263
259 // Adds the specified handles to the traversal. 264 // Adds the specified handles to the traversal.
260 void AppendManyToTraversal(const syncable::Directory::Metahandles& handles); 265 void AppendManyToTraversal(const syncable::Directory::Metahandles& handles);
261 266
262 // Adds the specifed handle to the traversal. 267 // Adds the specifed handle to the traversal.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 const std::set<int64>& ready_unsynced_set, 374 const std::set<int64>& ready_unsynced_set,
370 const syncable::Entry& item, 375 const syncable::Entry& item,
371 syncable::Directory::Metahandles* result) const { 376 syncable::Directory::Metahandles* result) const {
372 syncable::Directory::Metahandles dependencies; 377 syncable::Directory::Metahandles dependencies;
373 AddItemThenPredecessors(ready_unsynced_set, item, &dependencies); 378 AddItemThenPredecessors(ready_unsynced_set, item, &dependencies);
374 379
375 // Reverse what we added to get the correct order. 380 // Reverse what we added to get the correct order.
376 result->insert(result->end(), dependencies.rbegin(), dependencies.rend()); 381 result->insert(result->end(), dependencies.rbegin(), dependencies.rend());
377 } 382 }
378 383
384 // Traverses the tree from bottom to top, adding the deleted parents of the
385 // given |item|. Stops traversing if it encounters a non-deleted node, or
386 // a node that was already listed in the |traversed| list. Returns an error
387 // (false) if a node along the traversal is in a conflict state.
388 //
389 // The result list is reversed before it is returned, so the resulting
390 // traversal is in top to bottom order. Also note that this function appends
391 // to the result list without clearing it.
392 bool Traversal::AddDeletedParents(
393 const std::set<int64>& ready_unsynced_set,
394 const syncable::Entry& item,
395 const syncable::Directory::Metahandles& traversed,
396 syncable::Directory::Metahandles* result) const {
397 syncable::Directory::Metahandles dependencies;
398 syncable::Id parent_id = item.GetParentId();
399
400 // Climb the tree adding entries leaf -> root.
401 while (!parent_id.IsRoot()) {
402 syncable::Entry parent(trans_, syncable::GET_BY_ID, parent_id);
403
404 if (!parent.good()) {
405 // This is valid because the parent could have gone away a long time ago
406 //
407 // Consider the case where a folder is server-unknown and locally
408 // deleted, and has a child that is server-known, deleted, and unsynced.
409 // The parent could be dropped from memory at any time, but its child
410 // needs to be committed first.
411 break;
412 }
413 int64 handle = parent.GetMetahandle();
414 if (!parent.GetIsUnsynced()) {
415 // In some rare cases, our parent can be both deleted and unsynced.
416 // (ie. the server-unknown parent case).
417 break;
418 }
419 if (!parent.GetIsDel()) {
420 // We're not intersted in non-deleted parents.
421 break;
422 }
423 if (std::find(traversed.begin(), traversed.end(), handle) !=
424 traversed.end()) {
425 // We've already added this parent (and therefore all of its parents).
426 // We can return early.
427 break;
428 }
429 if (IsEntryInConflict(parent)) {
430 // We ignore all entries that are children of a conflicing item. Return
431 // false immediately to forget the traversal we've built up so far.
432 DVLOG(1) << "Parent was in conflict, omitting " << item;
433 return false;
434 }
435 TryAddItem(ready_unsynced_set, parent, &dependencies);
436 parent_id = parent.GetParentId();
437 }
438
439 // Reverse what we added to get the correct order.
440 result->insert(result->end(), dependencies.rbegin(), dependencies.rend());
441 return true;
442 }
443
379 bool Traversal::IsFull() const { 444 bool Traversal::IsFull() const {
380 return out_->size() >= max_entries_; 445 return out_->size() >= max_entries_;
381 } 446 }
382 447
383 bool Traversal::HaveItem(int64 handle) const { 448 bool Traversal::HaveItem(int64 handle) const {
384 return added_handles_.find(handle) != added_handles_.end(); 449 return added_handles_.find(handle) != added_handles_.end();
385 } 450 }
386 451
387 void Traversal::AppendManyToTraversal( 452 void Traversal::AppendManyToTraversal(
388 const syncable::Directory::Metahandles& handles) { 453 const syncable::Directory::Metahandles& handles) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 } 487 }
423 } 488 }
424 } 489 }
425 490
426 // It's possible that we overcommitted while trying to expand dependent 491 // It's possible that we overcommitted while trying to expand dependent
427 // items. If so, truncate the set down to the allowed size. 492 // items. If so, truncate the set down to the allowed size.
428 if (out_->size() > max_entries_) 493 if (out_->size() > max_entries_)
429 out_->resize(max_entries_); 494 out_->resize(max_entries_);
430 } 495 }
431 496
432 void Traversal::AddDeletes( 497 void Traversal::AddDeletes(const std::set<int64>& ready_unsynced_set) {
433 const std::set<int64>& ready_unsynced_set) { 498 syncable::Directory::Metahandles deletion_list;
434 set<syncable::Id> legal_delete_parents;
435 499
436 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin(); 500 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin();
437 !IsFull() && iter != ready_unsynced_set.end(); ++iter) { 501 !IsFull() && iter != ready_unsynced_set.end(); ++iter) {
438 int64 metahandle = *iter; 502 int64 metahandle = *iter;
503
439 if (HaveItem(metahandle)) 504 if (HaveItem(metahandle))
440 continue; 505 continue;
441 506
507 if (std::find(deletion_list.begin(), deletion_list.end(), metahandle) !=
508 deletion_list.end()) {
509 continue;
510 }
511
442 syncable::Entry entry(trans_, syncable::GET_BY_HANDLE, 512 syncable::Entry entry(trans_, syncable::GET_BY_HANDLE,
443 metahandle); 513 metahandle);
444 514
445 if (entry.GetIsDel()) { 515 if (entry.GetIsDel()) {
446 syncable::Entry parent(trans_, syncable::GET_BY_ID, 516 syncable::Directory::Metahandles parents;
447 entry.GetParentId()); 517 if (AddDeletedParents(
448 // If the parent is deleted and unsynced, then any children of that 518 ready_unsynced_set, entry, deletion_list, &parents)) {
449 // parent don't need to be added to the delete queue. 519 // Append parents and chilren in top to bottom order.
450 // 520 deletion_list.insert(deletion_list.end(),
451 // Note: the parent could be synced if there was an update deleting a 521 parents.begin(),
452 // folder when we had a deleted all items in it. 522 parents.end());
453 // We may get more updates, or we may want to delete the entry. 523 deletion_list.push_back(metahandle);
454 if (parent.good() && parent.GetIsDel() && parent.GetIsUnsynced()) { 524 }
455 // However, if an entry is moved, these rules can apply differently. 525 }
456 //
457 // If the entry was moved, then the destination parent was deleted,
458 // then we'll miss it in the roll up. We have to add it in manually.
459 // TODO(chron): Unit test for move / delete cases:
460 // Case 1: Locally moved, then parent deleted
461 // Case 2: Server moved, then locally issue recursive delete.
462 if (entry.GetId().ServerKnows() &&
463 entry.GetParentId() != entry.GetServerParentId()) {
464 DVLOG(1) << "Inserting moved and deleted entry, will be missed by "
465 << "delete roll." << entry.GetId();
466 526
467 AppendToTraversal(metahandle); 527 if (deletion_list.size() + out_->size() > max_entries_)
468 } 528 break;
469
470 // Skip this entry since it's a child of a parent that will be
471 // deleted. The server will unroll the delete and delete the
472 // child as well.
473 continue;
474 }
475
476 legal_delete_parents.insert(entry.GetParentId());
477 }
478 } 529 }
479 530
480 // We could store all the potential entries with a particular parent during 531 // We've been gathering deletions in top to bottom order. Now we reverse the
481 // the above scan, but instead we rescan here. This is less efficient, but 532 // order as we prepare the list.
482 // we're dropping memory alloc/dealloc in favor of linear scans of recently 533 std::reverse(deletion_list.begin(), deletion_list.end());
483 // examined entries. 534 AppendManyToTraversal(deletion_list);
484 // 535
485 // Scan through the UnsyncedMetaHandles again. If we have a deleted 536 // It's possible that we overcommitted while trying to expand dependent
486 // entry, then check if the parent is in legal_delete_parents. 537 // items. If so, truncate the set down to the allowed size.
487 // 538 if (out_->size() > max_entries_)
488 // Parent being in legal_delete_parents means for the child: 539 out_->resize(max_entries_);
489 // a recursive delete is not currently happening (no recent deletes in same
490 // folder)
491 // parent did expect at least one old deleted child
492 // parent was not deleted
493 for (std::set<int64>::const_iterator iter = ready_unsynced_set.begin();
494 !IsFull() && iter != ready_unsynced_set.end(); ++iter) {
495 int64 metahandle = *iter;
496 if (HaveItem(metahandle))
497 continue;
498 syncable::Entry entry(trans_, syncable::GET_BY_HANDLE, metahandle);
499 if (entry.GetIsDel()) {
500 syncable::Id parent_id = entry.GetParentId();
501 if (legal_delete_parents.count(parent_id)) {
502 AppendToTraversal(metahandle);
503 }
504 }
505 }
506 } 540 }
507 541
508 void OrderCommitIds( 542 void OrderCommitIds(
509 syncable::BaseTransaction* trans, 543 syncable::BaseTransaction* trans,
510 size_t max_entries, 544 size_t max_entries,
511 const std::set<int64>& ready_unsynced_set, 545 const std::set<int64>& ready_unsynced_set,
512 syncable::Directory::Metahandles* out) { 546 syncable::Directory::Metahandles* out) {
513 // Commits follow these rules: 547 // Commits follow these rules:
514 // 1. Moves or creates are preceded by needed folder creates, from 548 // 1. Moves or creates are preceded by needed folder creates, from
515 // root to leaf. For folders whose contents are ordered, moves 549 // root to leaf. For folders whose contents are ordered, moves
516 // and creates appear in order. 550 // and creates appear in order.
517 // 2. Moves/Creates before deletes. 551 // 2. Moves/Creates before deletes.
518 // 3. Deletes, collapsed. 552 // 3. Deletes, collapsed.
519 // We commit deleted moves under deleted items as moves when collapsing 553 // We commit deleted moves under deleted items as moves when collapsing
520 // delete trees. 554 // delete trees.
521 555
522 Traversal traversal(trans, max_entries, out); 556 Traversal traversal(trans, max_entries, out);
523 557
524 // Add moves and creates, and prepend their uncommitted parents. 558 // Add moves and creates, and prepend their uncommitted parents.
525 traversal.AddCreatesAndMoves(ready_unsynced_set); 559 traversal.AddCreatesAndMoves(ready_unsynced_set);
526 560
527 // Add all deletes. 561 // Add all deletes.
528 traversal.AddDeletes(ready_unsynced_set); 562 traversal.AddDeletes(ready_unsynced_set);
529 } 563 }
530 564
531 } // namespace 565 } // namespace
532 566
533 } // namespace syncer 567 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/engine/get_commit_ids.h ('k') | sync/engine/syncer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698