| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/syncer_util.h" | 5 #include "components/sync/engine_impl/syncer_util.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <set> | 10 #include <set> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/base64.h" | 14 #include "base/base64.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 17 #include "base/rand_util.h" | 17 #include "base/rand_util.h" |
| 18 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
| 19 #include "sync/engine/conflict_resolver.h" | 19 #include "components/sync/base/attachment_id_proto.h" |
| 20 #include "sync/engine/syncer_proto_util.h" | 20 #include "components/sync/base/cryptographer.h" |
| 21 #include "sync/engine/syncer_types.h" | 21 #include "components/sync/base/model_type.h" |
| 22 #include "sync/internal_api/public/base/attachment_id_proto.h" | 22 #include "components/sync/base/time.h" |
| 23 #include "sync/internal_api/public/base/model_type.h" | 23 #include "components/sync/base/unique_position.h" |
| 24 #include "sync/internal_api/public/base/unique_position.h" | 24 #include "components/sync/engine_impl/conflict_resolver.h" |
| 25 #include "sync/protocol/bookmark_specifics.pb.h" | 25 #include "components/sync/engine_impl/syncer_proto_util.h" |
| 26 #include "sync/protocol/password_specifics.pb.h" | 26 #include "components/sync/engine_impl/syncer_types.h" |
| 27 #include "sync/protocol/sync.pb.h" | 27 #include "components/sync/protocol/bookmark_specifics.pb.h" |
| 28 #include "sync/syncable/directory.h" | 28 #include "components/sync/protocol/password_specifics.pb.h" |
| 29 #include "sync/syncable/entry.h" | 29 #include "components/sync/protocol/sync.pb.h" |
| 30 #include "sync/syncable/model_neutral_mutable_entry.h" | 30 #include "components/sync/syncable/directory.h" |
| 31 #include "sync/syncable/mutable_entry.h" | 31 #include "components/sync/syncable/entry.h" |
| 32 #include "sync/syncable/syncable_changes_version.h" | 32 #include "components/sync/syncable/model_neutral_mutable_entry.h" |
| 33 #include "sync/syncable/syncable_model_neutral_write_transaction.h" | 33 #include "components/sync/syncable/mutable_entry.h" |
| 34 #include "sync/syncable/syncable_proto_util.h" | 34 #include "components/sync/syncable/syncable_changes_version.h" |
| 35 #include "sync/syncable/syncable_read_transaction.h" | 35 #include "components/sync/syncable/syncable_model_neutral_write_transaction.h" |
| 36 #include "sync/syncable/syncable_util.h" | 36 #include "components/sync/syncable/syncable_proto_util.h" |
| 37 #include "sync/syncable/syncable_write_transaction.h" | 37 #include "components/sync/syncable/syncable_read_transaction.h" |
| 38 #include "sync/util/cryptographer.h" | 38 #include "components/sync/syncable/syncable_util.h" |
| 39 #include "sync/util/time.h" | 39 #include "components/sync/syncable/syncable_write_transaction.h" |
| 40 | 40 |
| 41 namespace syncer { | 41 namespace syncer { |
| 42 | 42 |
| 43 using syncable::CHANGES_VERSION; | 43 using syncable::CHANGES_VERSION; |
| 44 using syncable::Directory; | 44 using syncable::Directory; |
| 45 using syncable::Entry; | 45 using syncable::Entry; |
| 46 using syncable::GET_BY_HANDLE; | 46 using syncable::GET_BY_HANDLE; |
| 47 using syncable::GET_BY_ID; | 47 using syncable::GET_BY_ID; |
| 48 using syncable::ID; | 48 using syncable::ID; |
| 49 using syncable::Id; | 49 using syncable::Id; |
| 50 | 50 |
| 51 syncable::Id FindLocalIdToUpdate( | 51 syncable::Id FindLocalIdToUpdate(syncable::BaseTransaction* trans, |
| 52 syncable::BaseTransaction* trans, | 52 const sync_pb::SyncEntity& update) { |
| 53 const sync_pb::SyncEntity& update) { | |
| 54 // Expected entry points of this function: | 53 // Expected entry points of this function: |
| 55 // SyncEntity has NOT been applied to SERVER fields. | 54 // SyncEntity has NOT been applied to SERVER fields. |
| 56 // SyncEntity has NOT been applied to LOCAL fields. | 55 // SyncEntity has NOT been applied to LOCAL fields. |
| 57 // DB has not yet been modified, no entries created for this update. | 56 // DB has not yet been modified, no entries created for this update. |
| 58 | 57 |
| 59 const std::string& client_id = trans->directory()->cache_guid(); | 58 const std::string& client_id = trans->directory()->cache_guid(); |
| 60 const syncable::Id& update_id = SyncableIdFromProto(update.id_string()); | 59 const syncable::Id& update_id = SyncableIdFromProto(update.id_string()); |
| 61 | 60 |
| 62 if (update.has_client_defined_unique_tag() && | 61 if (update.has_client_defined_unique_tag() && |
| 63 !update.client_defined_unique_tag().empty()) { | 62 !update.client_defined_unique_tag().empty()) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 // We should change the ID of the local entry to the server entry. | 105 // We should change the ID of the local entry to the server entry. |
| 107 // This will result in an server ID with base version == 0, but that's | 106 // This will result in an server ID with base version == 0, but that's |
| 108 // a legal state for an item with a client tag. By changing the ID, | 107 // a legal state for an item with a client tag. By changing the ID, |
| 109 // update will now be applied to local_entry. | 108 // update will now be applied to local_entry. |
| 110 DCHECK(0 == local_entry.GetBaseVersion() || | 109 DCHECK(0 == local_entry.GetBaseVersion() || |
| 111 CHANGES_VERSION == local_entry.GetBaseVersion()); | 110 CHANGES_VERSION == local_entry.GetBaseVersion()); |
| 112 return local_entry.GetId(); | 111 return local_entry.GetId(); |
| 113 } | 112 } |
| 114 } | 113 } |
| 115 } else if (update.has_originator_cache_guid() && | 114 } else if (update.has_originator_cache_guid() && |
| 116 update.originator_cache_guid() == client_id) { | 115 update.originator_cache_guid() == client_id) { |
| 117 // If a commit succeeds, but the response does not come back fast enough | 116 // If a commit succeeds, but the response does not come back fast enough |
| 118 // then the syncer might assume that it was never committed. | 117 // then the syncer might assume that it was never committed. |
| 119 // The server will track the client that sent up the original commit and | 118 // The server will track the client that sent up the original commit and |
| 120 // return this in a get updates response. When this matches a local | 119 // return this in a get updates response. When this matches a local |
| 121 // uncommitted item, we must mutate our local item and version to pick up | 120 // uncommitted item, we must mutate our local item and version to pick up |
| 122 // the committed version of the same item whose commit response was lost. | 121 // the committed version of the same item whose commit response was lost. |
| 123 // There is however still a race condition if the server has not | 122 // There is however still a race condition if the server has not |
| 124 // completed the commit by the time the syncer tries to get updates | 123 // completed the commit by the time the syncer tries to get updates |
| 125 // again. To mitigate this, we need to have the server time out in | 124 // again. To mitigate this, we need to have the server time out in |
| 126 // a reasonable span, our commit batches have to be small enough | 125 // a reasonable span, our commit batches have to be small enough |
| (...skipping 17 matching lines...) Expand all Loading... |
| 144 int64_t new_version = update.version(); | 143 int64_t new_version = update.version(); |
| 145 DCHECK_LE(old_version, 0); | 144 DCHECK_LE(old_version, 0); |
| 146 DCHECK_GT(new_version, 0); | 145 DCHECK_GT(new_version, 0); |
| 147 // Otherwise setting the base version could cause a consistency failure. | 146 // Otherwise setting the base version could cause a consistency failure. |
| 148 // An entry should never be version 0 and SYNCED. | 147 // An entry should never be version 0 and SYNCED. |
| 149 DCHECK(local_entry.GetIsUnsynced()); | 148 DCHECK(local_entry.GetIsUnsynced()); |
| 150 | 149 |
| 151 // Just a quick sanity check. | 150 // Just a quick sanity check. |
| 152 DCHECK(!local_entry.GetId().ServerKnows()); | 151 DCHECK(!local_entry.GetId().ServerKnows()); |
| 153 | 152 |
| 154 DVLOG(1) << "Reuniting lost commit response IDs. server id: " | 153 DVLOG(1) << "Reuniting lost commit response IDs. server id: " << update_id |
| 155 << update_id << " local id: " << local_entry.GetId() | 154 << " local id: " << local_entry.GetId() |
| 156 << " new version: " << new_version; | 155 << " new version: " << new_version; |
| 157 | 156 |
| 158 return local_entry.GetId(); | 157 return local_entry.GetId(); |
| 159 } | 158 } |
| 160 } else if (update.has_server_defined_unique_tag() && | 159 } else if (update.has_server_defined_unique_tag() && |
| 161 !update.server_defined_unique_tag().empty()) { | 160 !update.server_defined_unique_tag().empty()) { |
| 162 // The client creates type root folders with a local ID on demand when a | 161 // The client creates type root folders with a local ID on demand when a |
| 163 // progress marker for the given type is initially set. | 162 // progress marker for the given type is initially set. |
| 164 // The server might also attempt to send a type root folder for the same | 163 // The server might also attempt to send a type root folder for the same |
| 165 // type (during the transition period until support for root folders is | 164 // type (during the transition period until support for root folders is |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 // treated as an unresolvable conflict. See the description in syncer_types.h. | 196 // treated as an unresolvable conflict. See the description in syncer_types.h. |
| 198 // This prevents any unsynced changes from commiting and postpones conflict | 197 // This prevents any unsynced changes from commiting and postpones conflict |
| 199 // resolution until all data can be decrypted. | 198 // resolution until all data can be decrypted. |
| 200 if (specifics.has_encrypted() && | 199 if (specifics.has_encrypted() && |
| 201 !cryptographer->CanDecrypt(specifics.encrypted())) { | 200 !cryptographer->CanDecrypt(specifics.encrypted())) { |
| 202 // We can't decrypt this node yet. | 201 // We can't decrypt this node yet. |
| 203 DVLOG(1) << "Received an undecryptable " | 202 DVLOG(1) << "Received an undecryptable " |
| 204 << ModelTypeToString(entry->GetServerModelType()) | 203 << ModelTypeToString(entry->GetServerModelType()) |
| 205 << " update, returning conflict_encryption."; | 204 << " update, returning conflict_encryption."; |
| 206 return CONFLICT_ENCRYPTION; | 205 return CONFLICT_ENCRYPTION; |
| 207 } else if (specifics.has_password() && | 206 } else if (specifics.has_password() && entry->GetUniqueServerTag().empty()) { |
| 208 entry->GetUniqueServerTag().empty()) { | |
| 209 // Passwords use their own legacy encryption scheme. | 207 // Passwords use their own legacy encryption scheme. |
| 210 const sync_pb::PasswordSpecifics& password = specifics.password(); | 208 const sync_pb::PasswordSpecifics& password = specifics.password(); |
| 211 if (!cryptographer->CanDecrypt(password.encrypted())) { | 209 if (!cryptographer->CanDecrypt(password.encrypted())) { |
| 212 DVLOG(1) << "Received an undecryptable password update, returning " | 210 DVLOG(1) << "Received an undecryptable password update, returning " |
| 213 << "conflict_encryption."; | 211 << "conflict_encryption."; |
| 214 return CONFLICT_ENCRYPTION; | 212 return CONFLICT_ENCRYPTION; |
| 215 } | 213 } |
| 216 } | 214 } |
| 217 | 215 |
| 218 if (!entry->GetServerIsDel()) { | 216 if (!entry->GetServerIsDel()) { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 // Update our position. | 349 // Update our position. |
| 352 UniquePosition update_pos = | 350 UniquePosition update_pos = |
| 353 GetUpdatePosition(update, local_entry->GetUniqueBookmarkTag()); | 351 GetUpdatePosition(update, local_entry->GetUniqueBookmarkTag()); |
| 354 if (update_pos.IsValid()) { | 352 if (update_pos.IsValid()) { |
| 355 local_entry->PutServerUniquePosition(update_pos); | 353 local_entry->PutServerUniquePosition(update_pos); |
| 356 } | 354 } |
| 357 } | 355 } |
| 358 | 356 |
| 359 } // namespace | 357 } // namespace |
| 360 | 358 |
| 361 void UpdateServerFieldsFromUpdate( | 359 void UpdateServerFieldsFromUpdate(syncable::ModelNeutralMutableEntry* target, |
| 362 syncable::ModelNeutralMutableEntry* target, | 360 const sync_pb::SyncEntity& update, |
| 363 const sync_pb::SyncEntity& update, | 361 const std::string& name) { |
| 364 const std::string& name) { | |
| 365 if (update.deleted()) { | 362 if (update.deleted()) { |
| 366 if (target->GetServerIsDel()) { | 363 if (target->GetServerIsDel()) { |
| 367 // If we already think the item is server-deleted, we're done. | 364 // If we already think the item is server-deleted, we're done. |
| 368 // Skipping these cases prevents our committed deletions from coming | 365 // Skipping these cases prevents our committed deletions from coming |
| 369 // back and overriding subsequent undeletions. For non-deleted items, | 366 // back and overriding subsequent undeletions. For non-deleted items, |
| 370 // the version number check has a similar effect. | 367 // the version number check has a similar effect. |
| 371 return; | 368 return; |
| 372 } | 369 } |
| 373 // Mark entry as unapplied update first to ensure journaling the deletion. | 370 // Mark entry as unapplied update first to ensure journaling the deletion. |
| 374 target->PutIsUnappliedUpdate(true); | 371 target->PutIsUnappliedUpdate(true); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 // Store the datatype-specific part as a protobuf. | 407 // Store the datatype-specific part as a protobuf. |
| 411 if (update.has_specifics()) { | 408 if (update.has_specifics()) { |
| 412 DCHECK_NE(GetModelType(update), UNSPECIFIED) | 409 DCHECK_NE(GetModelType(update), UNSPECIFIED) |
| 413 << "Storing unrecognized datatype in sync database."; | 410 << "Storing unrecognized datatype in sync database."; |
| 414 target->PutServerSpecifics(update.specifics()); | 411 target->PutServerSpecifics(update.specifics()); |
| 415 } else if (update.has_bookmarkdata()) { | 412 } else if (update.has_bookmarkdata()) { |
| 416 // Legacy protocol response for bookmark data. | 413 // Legacy protocol response for bookmark data. |
| 417 const sync_pb::SyncEntity::BookmarkData& bookmark = update.bookmarkdata(); | 414 const sync_pb::SyncEntity::BookmarkData& bookmark = update.bookmarkdata(); |
| 418 UpdateBookmarkSpecifics(update.server_defined_unique_tag(), | 415 UpdateBookmarkSpecifics(update.server_defined_unique_tag(), |
| 419 bookmark.bookmark_url(), | 416 bookmark.bookmark_url(), |
| 420 bookmark.bookmark_favicon(), | 417 bookmark.bookmark_favicon(), target); |
| 421 target); | |
| 422 } | 418 } |
| 423 target->PutServerAttachmentMetadata( | 419 target->PutServerAttachmentMetadata( |
| 424 CreateAttachmentMetadata(update.attachment_id())); | 420 CreateAttachmentMetadata(update.attachment_id())); |
| 425 if (SyncerProtoUtil::ShouldMaintainPosition(update)) { | 421 if (SyncerProtoUtil::ShouldMaintainPosition(update)) { |
| 426 UpdateBookmarkPositioning(update, target); | 422 UpdateBookmarkPositioning(update, target); |
| 427 } | 423 } |
| 428 | 424 |
| 429 // We only mark the entry as unapplied if its version is greater than the | 425 // We only mark the entry as unapplied if its version is greater than the |
| 430 // local data. If we're processing the update that corresponds to one of our | 426 // local data. If we're processing the update that corresponds to one of our |
| 431 // commit we don't apply it as time differences may occur. | 427 // commit we don't apply it as time differences may occur. |
| 432 if (update.version() > target->GetBaseVersion()) { | 428 if (update.version() > target->GetBaseVersion()) { |
| 433 target->PutIsUnappliedUpdate(true); | 429 target->PutIsUnappliedUpdate(true); |
| 434 } | 430 } |
| 435 DCHECK(!update.deleted()); | 431 DCHECK(!update.deleted()); |
| 436 target->PutServerIsDel(false); | 432 target->PutServerIsDel(false); |
| 437 } | 433 } |
| 438 | 434 |
| 439 // Creates a new Entry iff no Entry exists with the given id. | 435 // Creates a new Entry iff no Entry exists with the given id. |
| 440 void CreateNewEntry(syncable::ModelNeutralWriteTransaction *trans, | 436 void CreateNewEntry(syncable::ModelNeutralWriteTransaction* trans, |
| 441 const syncable::Id& id) { | 437 const syncable::Id& id) { |
| 442 syncable::Entry entry(trans, GET_BY_ID, id); | 438 syncable::Entry entry(trans, GET_BY_ID, id); |
| 443 if (!entry.good()) { | 439 if (!entry.good()) { |
| 444 syncable::ModelNeutralMutableEntry new_entry( | 440 syncable::ModelNeutralMutableEntry new_entry( |
| 445 trans, | 441 trans, syncable::CREATE_NEW_UPDATE_ITEM, id); |
| 446 syncable::CREATE_NEW_UPDATE_ITEM, | |
| 447 id); | |
| 448 } | 442 } |
| 449 } | 443 } |
| 450 | 444 |
| 451 // This function is called on an entry when we can update the user-facing data | 445 // This function is called on an entry when we can update the user-facing data |
| 452 // from the server data. | 446 // from the server data. |
| 453 void UpdateLocalDataFromServerData( | 447 void UpdateLocalDataFromServerData(syncable::WriteTransaction* trans, |
| 454 syncable::WriteTransaction* trans, | 448 syncable::MutableEntry* entry) { |
| 455 syncable::MutableEntry* entry) { | |
| 456 DCHECK(!entry->GetIsUnsynced()); | 449 DCHECK(!entry->GetIsUnsynced()); |
| 457 DCHECK(entry->GetIsUnappliedUpdate()); | 450 DCHECK(entry->GetIsUnappliedUpdate()); |
| 458 | 451 |
| 459 DVLOG(2) << "Updating entry : " << *entry; | 452 DVLOG(2) << "Updating entry : " << *entry; |
| 460 // Start by setting the properties that determine the model_type. | 453 // Start by setting the properties that determine the model_type. |
| 461 entry->PutSpecifics(entry->GetServerSpecifics()); | 454 entry->PutSpecifics(entry->GetServerSpecifics()); |
| 462 // Clear the previous server specifics now that we're applying successfully. | 455 // Clear the previous server specifics now that we're applying successfully. |
| 463 entry->PutBaseServerSpecifics(sync_pb::EntitySpecifics()); | 456 entry->PutBaseServerSpecifics(sync_pb::EntitySpecifics()); |
| 464 entry->PutIsDir(entry->GetServerIsDir()); | 457 entry->PutIsDir(entry->GetServerIsDir()); |
| 465 // This strange dance around the IS_DEL flag avoids problems when setting | 458 // This strange dance around the IS_DEL flag avoids problems when setting |
| (...skipping 28 matching lines...) Expand all Loading... |
| 494 LOG(ERROR) << "Permanent item became unsynced " << *entry; | 487 LOG(ERROR) << "Permanent item became unsynced " << *entry; |
| 495 return VERIFY_UNSYNCABLE; | 488 return VERIFY_UNSYNCABLE; |
| 496 } | 489 } |
| 497 if (entry->GetIsDel() && !entry->GetId().ServerKnows()) { | 490 if (entry->GetIsDel() && !entry->GetId().ServerKnows()) { |
| 498 // Drop deleted uncommitted entries. | 491 // Drop deleted uncommitted entries. |
| 499 return VERIFY_UNSYNCABLE; | 492 return VERIFY_UNSYNCABLE; |
| 500 } | 493 } |
| 501 return VERIFY_OK; | 494 return VERIFY_OK; |
| 502 } | 495 } |
| 503 | 496 |
| 504 void MarkDeletedChildrenSynced( | 497 void MarkDeletedChildrenSynced(syncable::Directory* dir, |
| 505 syncable::Directory* dir, | 498 syncable::BaseWriteTransaction* trans, |
| 506 syncable::BaseWriteTransaction* trans, | 499 std::set<syncable::Id>* deleted_folders) { |
| 507 std::set<syncable::Id>* deleted_folders) { | |
| 508 // There's two options here. | 500 // There's two options here. |
| 509 // 1. Scan deleted unsynced entries looking up their pre-delete tree for any | 501 // 1. Scan deleted unsynced entries looking up their pre-delete tree for any |
| 510 // of the deleted folders. | 502 // of the deleted folders. |
| 511 // 2. Take each folder and do a tree walk of all entries underneath it. | 503 // 2. Take each folder and do a tree walk of all entries underneath it. |
| 512 // #2 has a lower big O cost, but writing code to limit the time spent inside | 504 // #2 has a lower big O cost, but writing code to limit the time spent inside |
| 513 // the transaction during each step is simpler with 1. Changing this decision | 505 // the transaction during each step is simpler with 1. Changing this decision |
| 514 // may be sensible if this code shows up in profiling. | 506 // may be sensible if this code shows up in profiling. |
| 515 if (deleted_folders->empty()) | 507 if (deleted_folders->empty()) |
| 516 return; | 508 return; |
| 517 Directory::Metahandles handles; | 509 Directory::Metahandles handles; |
| 518 dir->GetUnsyncedMetaHandles(trans, &handles); | 510 dir->GetUnsyncedMetaHandles(trans, &handles); |
| 519 if (handles.empty()) | 511 if (handles.empty()) |
| 520 return; | 512 return; |
| 521 Directory::Metahandles::iterator it; | 513 Directory::Metahandles::iterator it; |
| 522 for (it = handles.begin() ; it != handles.end() ; ++it) { | 514 for (it = handles.begin(); it != handles.end(); ++it) { |
| 523 syncable::ModelNeutralMutableEntry entry(trans, GET_BY_HANDLE, *it); | 515 syncable::ModelNeutralMutableEntry entry(trans, GET_BY_HANDLE, *it); |
| 524 if (!entry.GetIsUnsynced() || !entry.GetIsDel()) | 516 if (!entry.GetIsUnsynced() || !entry.GetIsDel()) |
| 525 continue; | 517 continue; |
| 526 syncable::Id id = entry.GetParentId(); | 518 syncable::Id id = entry.GetParentId(); |
| 527 while (id != trans->root_id()) { | 519 while (id != trans->root_id()) { |
| 528 if (deleted_folders->find(id) != deleted_folders->end()) { | 520 if (deleted_folders->find(id) != deleted_folders->end()) { |
| 529 // We've synced the deletion of this deleted entries parent. | 521 // We've synced the deletion of this deleted entries parent. |
| 530 entry.PutIsUnsynced(false); | 522 entry.PutIsUnsynced(false); |
| 531 break; | 523 break; |
| 532 } | 524 } |
| 533 Entry parent(trans, GET_BY_ID, id); | 525 Entry parent(trans, GET_BY_ID, id); |
| 534 if (!parent.good() || !parent.GetIsDel()) | 526 if (!parent.good() || !parent.GetIsDel()) |
| 535 break; | 527 break; |
| 536 id = parent.GetParentId(); | 528 id = parent.GetParentId(); |
| 537 } | 529 } |
| 538 } | 530 } |
| 539 } | 531 } |
| 540 | 532 |
| 541 VerifyResult VerifyNewEntry( | 533 VerifyResult VerifyNewEntry(const sync_pb::SyncEntity& update, |
| 542 const sync_pb::SyncEntity& update, | 534 syncable::Entry* target, |
| 543 syncable::Entry* target, | 535 const bool deleted) { |
| 544 const bool deleted) { | |
| 545 if (target->good()) { | 536 if (target->good()) { |
| 546 // Not a new update. | 537 // Not a new update. |
| 547 return VERIFY_UNDECIDED; | 538 return VERIFY_UNDECIDED; |
| 548 } | 539 } |
| 549 if (deleted) { | 540 if (deleted) { |
| 550 // Deletion of an item we've never seen can be ignored. | 541 // Deletion of an item we've never seen can be ignored. |
| 551 return VERIFY_SKIP; | 542 return VERIFY_SKIP; |
| 552 } | 543 } |
| 553 | 544 |
| 554 return VERIFY_SUCCESS; | 545 return VERIFY_SUCCESS; |
| 555 } | 546 } |
| 556 | 547 |
| 557 // Assumes we have an existing entry; check here for updates that break | 548 // Assumes we have an existing entry; check here for updates that break |
| 558 // consistency rules. | 549 // consistency rules. |
| 559 VerifyResult VerifyUpdateConsistency( | 550 VerifyResult VerifyUpdateConsistency( |
| 560 syncable::ModelNeutralWriteTransaction* trans, | 551 syncable::ModelNeutralWriteTransaction* trans, |
| 561 const sync_pb::SyncEntity& update, | 552 const sync_pb::SyncEntity& update, |
| 562 const bool deleted, | 553 const bool deleted, |
| 563 const bool is_directory, | 554 const bool is_directory, |
| 564 ModelType model_type, | 555 ModelType model_type, |
| 565 syncable::ModelNeutralMutableEntry* target) { | 556 syncable::ModelNeutralMutableEntry* target) { |
| 566 | |
| 567 CHECK(target->good()); | 557 CHECK(target->good()); |
| 568 const syncable::Id& update_id = SyncableIdFromProto(update.id_string()); | 558 const syncable::Id& update_id = SyncableIdFromProto(update.id_string()); |
| 569 | 559 |
| 570 // If the update is a delete, we don't really need to worry at this stage. | 560 // If the update is a delete, we don't really need to worry at this stage. |
| 571 if (deleted) | 561 if (deleted) |
| 572 return VERIFY_SUCCESS; | 562 return VERIFY_SUCCESS; |
| 573 | 563 |
| 574 if (model_type == UNSPECIFIED) { | 564 if (model_type == UNSPECIFIED) { |
| 575 // This update is to an item of a datatype we don't recognize. The server | 565 // This update is to an item of a datatype we don't recognize. The server |
| 576 // shouldn't have sent it to us. Throw it on the ground. | 566 // shouldn't have sent it to us. Throw it on the ground. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 if (target->GetIsDel()) { | 639 if (target->GetIsDel()) { |
| 650 if (target->GetUniqueClientTag().empty()) | 640 if (target->GetUniqueClientTag().empty()) |
| 651 LOG(WARNING) << "Doing move-aside undeletion on client-tagged item."; | 641 LOG(WARNING) << "Doing move-aside undeletion on client-tagged item."; |
| 652 target->PutId(trans->directory()->NextId()); | 642 target->PutId(trans->directory()->NextId()); |
| 653 target->PutUniqueClientTag(std::string()); | 643 target->PutUniqueClientTag(std::string()); |
| 654 target->PutBaseVersion(CHANGES_VERSION); | 644 target->PutBaseVersion(CHANGES_VERSION); |
| 655 target->PutServerVersion(0); | 645 target->PutServerVersion(0); |
| 656 return VERIFY_SUCCESS; | 646 return VERIFY_SUCCESS; |
| 657 } | 647 } |
| 658 if (update.version() < target->GetServerVersion()) { | 648 if (update.version() < target->GetServerVersion()) { |
| 659 LOG(WARNING) << "Update older than current server version for " | 649 LOG(WARNING) << "Update older than current server version for " << *target |
| 660 << *target << " Update:" | 650 << " Update:" |
| 661 << SyncerProtoUtil::SyncEntityDebugString(update); | 651 << SyncerProtoUtil::SyncEntityDebugString(update); |
| 662 return VERIFY_SUCCESS; // Expected in new sync protocol. | 652 return VERIFY_SUCCESS; // Expected in new sync protocol. |
| 663 } | 653 } |
| 664 return VERIFY_UNDECIDED; | 654 return VERIFY_UNDECIDED; |
| 665 } | 655 } |
| 666 | 656 |
| 667 } // namespace syncer | 657 } // namespace syncer |
| OLD | NEW |