summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/engine/process_updates_command.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/sync/engine/process_updates_command.cc')
-rw-r--r--chrome/browser/sync/engine/process_updates_command.cc39
1 files changed, 24 insertions, 15 deletions
diff --git a/chrome/browser/sync/engine/process_updates_command.cc b/chrome/browser/sync/engine/process_updates_command.cc
index 6e42b1b..d55582e 100644
--- a/chrome/browser/sync/engine/process_updates_command.cc
+++ b/chrome/browser/sync/engine/process_updates_command.cc
@@ -124,29 +124,38 @@ ServerUpdateProcessingResult ProcessUpdatesCommand::ProcessUpdate(
// If we're repurposing an existing local entry with a new server ID,
// change the ID now, after we're sure that the update can succeed.
if (local_id != server_id) {
+ DCHECK(!update.deleted());
SyncerUtil::ChangeEntryIDAndUpdateChildren(&trans, &target_entry,
server_id);
// When IDs change, versions become irrelevant. Forcing BASE_VERSION
- // to zero would ensure that this update gets applied, but historically,
- // that's an illegal state unless the item is using the client tag.
- // Alternatively, we can force BASE_VERSION to entry.version(), but
- // this has the effect of suppressing update application.
- // TODO(nick): Make the treatment of these two cases consistent.
- int64 new_version = target_entry.Get(UNIQUE_CLIENT_TAG).empty() ?
- update.version() : 0;
- target_entry.Put(BASE_VERSION, new_version);
+ // to zero would ensure that this update gets applied, but would indicate
+ // creation or undeletion if it were committed that way. Instead, prefer
+ // forcing BASE_VERSION to entry.version() while also forcing
+ // IS_UNAPPLIED_UPDATE to true. If the item is UNSYNCED, it's committable
+ // from the new state; it may commit before the conflict resolver gets
+ // a crack at it.
+ if (target_entry.Get(IS_UNSYNCED) || target_entry.Get(BASE_VERSION) > 0) {
+ // If either of these conditions are met, then we can expect valid client
+ // fields for this entry. When BASE_VERSION is positive, consistency is
+ // enforced on the client fields at update-application time. Otherwise,
+ // we leave the BASE_VERSION field alone; it'll get updated the first time
+ // we successfully apply this update.
+ target_entry.Put(BASE_VERSION, update.version());
+ }
+ // Force application of this update, no matter what.
+ target_entry.Put(IS_UNAPPLIED_UPDATE, true);
}
SyncerUtil::UpdateServerFieldsFromUpdate(&target_entry, update, name);
if (target_entry.Get(SERVER_VERSION) == target_entry.Get(BASE_VERSION) &&
- !target_entry.Get(IS_UNSYNCED)) {
- // It's largely OK if data doesn't match exactly since a future update
- // will just clobber the data. Conflict resolution will overwrite and
- // take one side as the winner and does not try to merge, so strict
- // equality isn't necessary.
- LOG_IF(ERROR, !SyncerUtil::ServerAndLocalEntriesMatch(&target_entry))
- << target_entry;
+ !target_entry.Get(IS_UNSYNCED) &&
+ !target_entry.Get(IS_UNAPPLIED_UPDATE)) {
+ // If these don't match, it means that we have a different view of the
+ // truth from other clients. That's a sync bug, though we may be able
+ // to recover the next time this item commits.
+ LOG_IF(ERROR, !SyncerUtil::ServerAndLocalEntriesMatch(&target_entry))
+ << target_entry;
}
return SUCCESS_PROCESSED;
}