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

Side by Side Diff: chrome/browser/sync/engine/syncer_util.cc

Issue 6588119: First-time sync: asymptotic running time improvement (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/Release
Patch Set: Fix unit_tests Created 9 years, 9 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
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/browser/sync/engine/syncer_util.h" 5 #include "chrome/browser/sync/engine/syncer_util.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 Entry local_prev(entry->trans(), GET_BY_ID, local_up_to_date_predecessor); 468 Entry local_prev(entry->trans(), GET_BY_ID, local_up_to_date_predecessor);
469 if (!local_prev.good() || local_prev.Get(IS_DEL)) 469 if (!local_prev.good() || local_prev.Get(IS_DEL))
470 return false; 470 return false;
471 if (!local_prev.Get(IS_UNAPPLIED_UPDATE) && !local_prev.Get(IS_UNSYNCED)) 471 if (!local_prev.Get(IS_UNAPPLIED_UPDATE) && !local_prev.Get(IS_UNSYNCED))
472 break; 472 break;
473 local_up_to_date_predecessor = local_prev.Get(PREV_ID); 473 local_up_to_date_predecessor = local_prev.Get(PREV_ID);
474 } 474 }
475 475
476 // Now find the closest up-to-date sibling in the server order. 476 // Now find the closest up-to-date sibling in the server order.
477 syncable::Id server_up_to_date_predecessor = 477 syncable::Id server_up_to_date_predecessor =
478 ComputePrevIdFromServerPosition(entry->trans(), entry, 478 entry->ComputePrevIdFromServerPosition(entry->Get(SERVER_PARENT_ID));
479 entry->Get(SERVER_PARENT_ID));
480 return server_up_to_date_predecessor == local_up_to_date_predecessor; 479 return server_up_to_date_predecessor == local_up_to_date_predecessor;
481 } 480 }
482 481
483 // static 482 // static
484 bool SyncerUtil::ServerAndLocalEntriesMatch(syncable::Entry* entry) { 483 bool SyncerUtil::ServerAndLocalEntriesMatch(syncable::Entry* entry) {
485 if (!ClientAndServerTimeMatch( 484 if (!ClientAndServerTimeMatch(
486 entry->Get(CTIME), ClientTimeToServerTime(entry->Get(SERVER_CTIME)))) { 485 entry->Get(CTIME), ClientTimeToServerTime(entry->Get(SERVER_CTIME)))) {
487 LOG(WARNING) << "Client and server time mismatch"; 486 LOG(WARNING) << "Client and server time mismatch";
488 return false; 487 return false;
489 } 488 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 entry->Put(IS_DIR, entry->Get(SERVER_IS_DIR)); 555 entry->Put(IS_DIR, entry->Get(SERVER_IS_DIR));
557 // This strange dance around the IS_DEL flag avoids problems when setting 556 // This strange dance around the IS_DEL flag avoids problems when setting
558 // the name. 557 // the name.
559 // TODO(chron): Is this still an issue? Unit test this codepath. 558 // TODO(chron): Is this still an issue? Unit test this codepath.
560 if (entry->Get(SERVER_IS_DEL)) { 559 if (entry->Get(SERVER_IS_DEL)) {
561 entry->Put(IS_DEL, true); 560 entry->Put(IS_DEL, true);
562 } else { 561 } else {
563 entry->Put(NON_UNIQUE_NAME, entry->Get(SERVER_NON_UNIQUE_NAME)); 562 entry->Put(NON_UNIQUE_NAME, entry->Get(SERVER_NON_UNIQUE_NAME));
564 entry->Put(PARENT_ID, entry->Get(SERVER_PARENT_ID)); 563 entry->Put(PARENT_ID, entry->Get(SERVER_PARENT_ID));
565 CHECK(entry->Put(IS_DEL, false)); 564 CHECK(entry->Put(IS_DEL, false));
566 Id new_predecessor = ComputePrevIdFromServerPosition(trans, entry, 565 Id new_predecessor =
567 entry->Get(SERVER_PARENT_ID)); 566 entry->ComputePrevIdFromServerPosition(entry->Get(SERVER_PARENT_ID));
568 CHECK(entry->PutPredecessor(new_predecessor)) 567 CHECK(entry->PutPredecessor(new_predecessor))
569 << " Illegal predecessor after converting from server position."; 568 << " Illegal predecessor after converting from server position.";
570 } 569 }
571 570
572 entry->Put(CTIME, entry->Get(SERVER_CTIME)); 571 entry->Put(CTIME, entry->Get(SERVER_CTIME));
573 entry->Put(MTIME, entry->Get(SERVER_MTIME)); 572 entry->Put(MTIME, entry->Get(SERVER_MTIME));
574 entry->Put(BASE_VERSION, entry->Get(SERVER_VERSION)); 573 entry->Put(BASE_VERSION, entry->Get(SERVER_VERSION));
575 entry->Put(IS_DEL, entry->Get(SERVER_IS_DEL)); 574 entry->Put(IS_DEL, entry->Get(SERVER_IS_DEL));
576 entry->Put(IS_UNAPPLIED_UPDATE, false); 575 entry->Put(IS_UNAPPLIED_UPDATE, false);
577 } 576 }
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 } 836 }
838 if (update.version() < target->Get(SERVER_VERSION)) { 837 if (update.version() < target->Get(SERVER_VERSION)) {
839 LOG(WARNING) << "Update older than current server version for " 838 LOG(WARNING) << "Update older than current server version for "
840 << *target << " Update:" 839 << *target << " Update:"
841 << SyncerProtoUtil::SyncEntityDebugString(update); 840 << SyncerProtoUtil::SyncEntityDebugString(update);
842 return VERIFY_SUCCESS; // Expected in new sync protocol. 841 return VERIFY_SUCCESS; // Expected in new sync protocol.
843 } 842 }
844 return VERIFY_UNDECIDED; 843 return VERIFY_UNDECIDED;
845 } 844 }
846 845
847 // static
848 syncable::Id SyncerUtil::ComputePrevIdFromServerPosition(
849 syncable::BaseTransaction* trans,
850 syncable::Entry* update_item,
851 const syncable::Id& parent_id) {
852 const int64 position_in_parent = update_item->Get(SERVER_POSITION_IN_PARENT);
853
854 // TODO(ncarter): This computation is linear in the number of children, but
855 // we could make it logarithmic if we kept an index on server position.
856 syncable::Id closest_sibling;
857 syncable::Id next_id = trans->directory()->GetFirstChildId(trans, parent_id);
858 while (!next_id.IsRoot()) {
859 syncable::Entry candidate(trans, GET_BY_ID, next_id);
860 if (!candidate.good()) {
861 LOG(WARNING) << "Should not happen";
862 return closest_sibling;
863 }
864 next_id = candidate.Get(NEXT_ID);
865
866 // Defensively prevent self-comparison.
867 if (candidate.Get(META_HANDLE) == update_item->Get(META_HANDLE)) {
868 continue;
869 }
870
871 // Ignore unapplied updates -- they might not even be server-siblings.
872 if (candidate.Get(IS_UNAPPLIED_UPDATE)) {
873 continue;
874 }
875
876 // Unsynced items don't have a valid server position.
877 if (!candidate.Get(IS_UNSYNCED)) {
878 // If |candidate| is after |update_entry| according to the server
879 // ordering, then we're done. ID is the tiebreaker.
880 if ((candidate.Get(SERVER_POSITION_IN_PARENT) > position_in_parent) ||
881 ((candidate.Get(SERVER_POSITION_IN_PARENT) == position_in_parent) &&
882 (candidate.Get(ID) > update_item->Get(ID)))) {
883 return closest_sibling;
884 }
885 }
886
887 // We can't trust the SERVER_ fields of unsynced items, but they are
888 // potentially legitimate local predecessors. In the case where
889 // |update_item| and an unsynced item wind up in the same insertion
890 // position, we need to choose how to order them. The following check puts
891 // the unapplied update first; removing it would put the unsynced item(s)
892 // first.
893 if (candidate.Get(IS_UNSYNCED)) {
894 continue;
895 }
896
897 // |update_entry| is considered to be somewhere after |candidate|, so store
898 // it as the upper bound.
899 closest_sibling = candidate.Get(ID);
900 }
901
902 return closest_sibling;
903 }
904
905 } // namespace browser_sync 846 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698