OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 void SyncerUtil::CreateNewEntry(syncable::WriteTransaction *trans, | 467 void SyncerUtil::CreateNewEntry(syncable::WriteTransaction *trans, |
468 const syncable::Id& id) { | 468 const syncable::Id& id) { |
469 syncable::MutableEntry entry(trans, syncable::GET_BY_ID, id); | 469 syncable::MutableEntry entry(trans, syncable::GET_BY_ID, id); |
470 if (!entry.good()) { | 470 if (!entry.good()) { |
471 syncable::MutableEntry new_entry(trans, syncable::CREATE_NEW_UPDATE_ITEM, | 471 syncable::MutableEntry new_entry(trans, syncable::CREATE_NEW_UPDATE_ITEM, |
472 id); | 472 id); |
473 } | 473 } |
474 } | 474 } |
475 | 475 |
476 // static | 476 // static |
477 bool SyncerUtil::ServerAndLocalOrdersMatch(syncable::Entry* entry) { | |
478 // Find the closest up-to-date local sibling by walking the linked list. | |
479 syncable::Id local_up_to_date_predecessor = entry->Get(PREV_ID); | |
480 while (!local_up_to_date_predecessor.IsRoot()) { | |
481 Entry local_prev(entry->trans(), GET_BY_ID, local_up_to_date_predecessor); | |
482 if (!local_prev.good() || local_prev.Get(IS_DEL)) | |
483 return false; | |
484 if (!local_prev.Get(IS_UNAPPLIED_UPDATE) && !local_prev.Get(IS_UNSYNCED)) | |
485 break; | |
486 local_up_to_date_predecessor = local_prev.Get(PREV_ID); | |
487 } | |
488 | |
489 // Now find the closest up-to-date sibling in the server order. | |
490 syncable::Id server_up_to_date_predecessor = | |
491 entry->ComputePrevIdFromServerPosition(entry->Get(SERVER_PARENT_ID)); | |
492 return server_up_to_date_predecessor == local_up_to_date_predecessor; | |
493 } | |
494 | |
495 // static | |
496 bool SyncerUtil::ServerAndLocalEntriesMatch(syncable::Entry* entry) { | |
497 if (entry->Get(CTIME) != entry->Get(SERVER_CTIME)) { | |
498 LOG(WARNING) << "Client and server time mismatch"; | |
499 return false; | |
500 } | |
501 if (entry->Get(IS_DEL) && entry->Get(SERVER_IS_DEL)) | |
502 return true; | |
503 // Name should exactly match here. | |
504 if (!(entry->Get(NON_UNIQUE_NAME) == entry->Get(SERVER_NON_UNIQUE_NAME))) { | |
505 LOG(WARNING) << "Unsanitized name mismatch"; | |
506 return false; | |
507 } | |
508 | |
509 if (entry->Get(PARENT_ID) != entry->Get(SERVER_PARENT_ID) || | |
510 entry->Get(IS_DIR) != entry->Get(SERVER_IS_DIR) || | |
511 entry->Get(IS_DEL) != entry->Get(SERVER_IS_DEL)) { | |
512 LOG(WARNING) << "Metabit mismatch"; | |
513 return false; | |
514 } | |
515 | |
516 if (!ServerAndLocalOrdersMatch(entry)) { | |
517 LOG(WARNING) << "Server/local ordering mismatch"; | |
518 return false; | |
519 } | |
520 | |
521 // TODO(ncarter): This is unfortunately heavyweight. Can we do better? | |
522 if (entry->Get(SPECIFICS).SerializeAsString() != | |
523 entry->Get(SERVER_SPECIFICS).SerializeAsString()) { | |
524 LOG(WARNING) << "Specifics mismatch"; | |
525 return false; | |
526 } | |
527 if (entry->Get(IS_DIR)) | |
528 return true; | |
529 // For historical reasons, a folder's MTIME changes when its contents change. | |
530 // TODO(ncarter): Remove the special casing of MTIME. | |
531 if (entry->Get(MTIME) != entry->Get(SERVER_MTIME)) { | |
532 LOG(WARNING) << "Time mismatch"; | |
533 return false; | |
534 } | |
535 return true; | |
536 } | |
537 | |
538 // static | |
539 void SyncerUtil::SplitServerInformationIntoNewEntry( | 477 void SyncerUtil::SplitServerInformationIntoNewEntry( |
540 syncable::WriteTransaction* trans, | 478 syncable::WriteTransaction* trans, |
541 syncable::MutableEntry* entry) { | 479 syncable::MutableEntry* entry) { |
542 syncable::Id id = entry->Get(ID); | 480 syncable::Id id = entry->Get(ID); |
543 ChangeEntryIDAndUpdateChildren(trans, entry, trans->directory()->NextId()); | 481 ChangeEntryIDAndUpdateChildren(trans, entry, trans->directory()->NextId()); |
544 entry->Put(BASE_VERSION, 0); | 482 entry->Put(BASE_VERSION, 0); |
545 | 483 |
546 MutableEntry new_entry(trans, CREATE_NEW_UPDATE_ITEM, id); | 484 MutableEntry new_entry(trans, CREATE_NEW_UPDATE_ITEM, id); |
547 CopyServerFields(entry, &new_entry); | 485 CopyServerFields(entry, &new_entry); |
548 ClearServerData(entry); | 486 ClearServerData(entry); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 // We've committed this update in the past. | 703 // We've committed this update in the past. |
766 if (is_directory != target->Get(IS_DIR) || | 704 if (is_directory != target->Get(IS_DIR) || |
767 model_type != target->GetModelType()) { | 705 model_type != target->GetModelType()) { |
768 LOG(ERROR) << "Server update doesn't agree with committed item. "; | 706 LOG(ERROR) << "Server update doesn't agree with committed item. "; |
769 LOG(ERROR) << " Entry: " << *target; | 707 LOG(ERROR) << " Entry: " << *target; |
770 LOG(ERROR) << " Update: " | 708 LOG(ERROR) << " Update: " |
771 << SyncerProtoUtil::SyncEntityDebugString(update); | 709 << SyncerProtoUtil::SyncEntityDebugString(update); |
772 return VERIFY_FAIL; | 710 return VERIFY_FAIL; |
773 } | 711 } |
774 if (target->Get(ID) == update.id()) { | 712 if (target->Get(ID) == update.id()) { |
775 // Checks that are only valid if we're not changing the ID. | |
776 if (target->Get(BASE_VERSION) == update.version() && | |
777 !target->Get(IS_UNSYNCED) && | |
778 !SyncerProtoUtil::Compare(*target, update)) { | |
779 // TODO(sync): This constraint needs to be relaxed. For now it's OK to | |
780 // fail the verification and deal with it when we ApplyUpdates. | |
781 LOG(ERROR) << "Server update doesn't match local data with same " | |
782 "version. A bug should be filed. Entry: " << *target << | |
783 "Update: " << SyncerProtoUtil::SyncEntityDebugString(update); | |
784 return VERIFY_FAIL; | |
785 } | |
786 if (target->Get(SERVER_VERSION) > update.version()) { | 713 if (target->Get(SERVER_VERSION) > update.version()) { |
787 LOG(WARNING) << "We've already seen a more recent version."; | 714 LOG(WARNING) << "We've already seen a more recent version."; |
788 LOG(WARNING) << " Entry: " << *target; | 715 LOG(WARNING) << " Entry: " << *target; |
789 LOG(WARNING) << " Update: " | 716 LOG(WARNING) << " Update: " |
790 << SyncerProtoUtil::SyncEntityDebugString(update); | 717 << SyncerProtoUtil::SyncEntityDebugString(update); |
791 return VERIFY_SKIP; | 718 return VERIFY_SKIP; |
792 } | 719 } |
793 } | 720 } |
794 } | 721 } |
795 return VERIFY_SUCCESS; | 722 return VERIFY_SUCCESS; |
(...skipping 30 matching lines...) Expand all Loading... |
826 if (update.version() < target->Get(SERVER_VERSION)) { | 753 if (update.version() < target->Get(SERVER_VERSION)) { |
827 LOG(WARNING) << "Update older than current server version for " | 754 LOG(WARNING) << "Update older than current server version for " |
828 << *target << " Update:" | 755 << *target << " Update:" |
829 << SyncerProtoUtil::SyncEntityDebugString(update); | 756 << SyncerProtoUtil::SyncEntityDebugString(update); |
830 return VERIFY_SUCCESS; // Expected in new sync protocol. | 757 return VERIFY_SUCCESS; // Expected in new sync protocol. |
831 } | 758 } |
832 return VERIFY_UNDECIDED; | 759 return VERIFY_UNDECIDED; |
833 } | 760 } |
834 | 761 |
835 } // namespace browser_sync | 762 } // namespace browser_sync |
OLD | NEW |