OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |