| 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 |