Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Unified Diff: sync/engine/conflict_resolver.cc

Issue 11636006: WIP: The Bookmark Position Megapatch (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Various updates, including switch suffix to unique_client_tag style Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sync/engine/build_commit_command_unittest.cc ('k') | sync/engine/get_commit_ids_command.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sync/engine/conflict_resolver.cc
diff --git a/sync/engine/conflict_resolver.cc b/sync/engine/conflict_resolver.cc
index 4d91b0fc879bde1303bd2d353a50d7ae577cfce0..9c4d66ac6bc24dde9f649dec0808181a90597755 100644
--- a/sync/engine/conflict_resolver.cc
+++ b/sync/engine/conflict_resolver.cc
@@ -95,55 +95,14 @@ void ConflictResolver::ProcessSimpleConflict(WriteTransaction* trans,
entry.Get(syncable::SERVER_PARENT_ID);
bool entry_deleted = entry.Get(syncable::IS_DEL);
- // This positional check is meant to be necessary but not sufficient. As a
- // result, it may be false even when the position hasn't changed, possibly
- // resulting in unnecessary commits, but if it's true the position has
- // definitely not changed. The check works by verifying that the prev id
- // as calculated from the server position (which will ignore any
- // unsynced/unapplied predecessors and be root for non-bookmark datatypes)
- // matches the client prev id. Because we traverse chains of conflicting
- // items in predecessor -> successor order, we don't need to also verify the
- // successor matches (If it's in conflict, we'll verify it next. If it's
- // not, then it should be taken into account already in the
- // ComputePrevIdFromServerPosition calculation). This works even when there
- // are chains of conflicting items.
- //
- // Example: Original sequence was abcde. Server changes to aCDbe, while
- // client changes to aDCbe (C and D are in conflict). Locally, D's prev id
- // is a, while C's prev id is D. On the other hand, the server prev id will
- // ignore unsynced/unapplied items, so D's server prev id will also be a,
- // just like C's. Because we traverse in client predecessor->successor
- // order, we evaluate D first. Since prev id and server id match, we
- // consider the position to have remained the same for D, and will unset
- // it's UNSYNCED/UNAPPLIED bits. When we evaluate C though, we'll see that
- // the prev id is D locally while the server's prev id is a. C will
- // therefore count as a positional conflict (and the local data will be
- // overwritten by the server data typically). The final result will be
- // aCDbe (the same as the server's view). Even though both C and D were
- // modified, only one counted as being in actual conflict and was resolved
- // with local/server wins.
- //
- // In general, when there are chains of positional conflicts, only the first
- // item in chain (based on the clients point of view) will have both its
- // server prev id and local prev id match. For all the rest the server prev
- // id will be the predecessor of the first item in the chain, and therefore
- // not match the local prev id.
- //
- // Similarly, chains of conflicts where the server and client info are the
- // same are supported due to the predecessor->successor ordering. In this
- // case, from the first item onward, we unset the UNSYNCED/UNAPPLIED bits as
- // we decide that nothing changed. The subsequent item's server prev id will
- // accurately match the local prev id because the predecessor is no longer
- // UNSYNCED/UNAPPLIED.
- // TODO(zea): simplify all this once we can directly compare server position
- // to client position.
- syncable::Id server_prev_id = entry.ComputePrevIdFromServerPosition(
- entry.Get(syncable::SERVER_PARENT_ID));
- bool needs_reinsertion = !parent_matches ||
- server_prev_id != entry.Get(syncable::PREV_ID);
- DVLOG_IF(1, needs_reinsertion) << "Insertion needed, server prev id "
- << " is " << server_prev_id << ", local prev id is "
- << entry.Get(syncable::PREV_ID);
+ // The position check might fail spuriously if one of the positions was
+ // based on a legacy random suffix, rather than a deterministic one based on
+ // originator_cache_guid and originator_item_id. If an item is being
+ // modified regularly, it shouldn't take long for the suffix and position to
+ // be updated, so such false failures shouldn't be a problem for long.
+ bool position_matches = parent_matches &&
+ entry.Get(syncable::SERVER_UNIQUE_POSITION).Equals(
+ entry.Get(syncable::UNIQUE_POSITION));
const sync_pb::EntitySpecifics& specifics =
entry.Get(syncable::SPECIFICS);
const sync_pb::EntitySpecifics& server_specifics =
@@ -189,7 +148,7 @@ void ConflictResolver::ProcessSimpleConflict(WriteTransaction* trans,
}
if (!entry_deleted && name_matches && parent_matches && specifics_match &&
- !needs_reinsertion) {
+ position_matches) {
DVLOG(1) << "Resolving simple conflict, everything matches, ignoring "
<< "changes for: " << entry;
conflict_util::IgnoreConflict(&entry);
@@ -260,13 +219,10 @@ void ConflictResolver::ResolveConflicts(
sessions::StatusController* status) {
// Iterate over simple conflict items.
set<Id>::const_iterator conflicting_item_it;
- set<Id> processed_items;
for (conflicting_item_it = simple_conflict_ids.begin();
conflicting_item_it != simple_conflict_ids.end();
++conflicting_item_it) {
Id id = *conflicting_item_it;
- if (processed_items.count(id) > 0)
- continue;
// We don't resolve conflicts for control types here.
Entry conflicting_node(trans, syncable::GET_BY_ID, id);
@@ -276,30 +232,7 @@ void ConflictResolver::ResolveConflicts(
continue;
}
- // We have a simple conflict. In order check if positions have changed,
- // we need to process conflicting predecessors before successors. Traverse
- // backwards through all continuous conflicting predecessors, building a
- // stack of items to resolve in predecessor->successor order, then process
- // each item individually.
- list<Id> predecessors;
- Id prev_id = id;
- do {
- predecessors.push_back(prev_id);
- Entry entry(trans, syncable::GET_BY_ID, prev_id);
- // Any entry in conflict must be valid.
- CHECK(entry.good());
- Id new_prev_id = entry.Get(syncable::PREV_ID);
- if (new_prev_id == prev_id)
- break;
- prev_id = new_prev_id;
- } while (processed_items.count(prev_id) == 0 &&
- simple_conflict_ids.count(prev_id) > 0); // Excludes root.
- while (!predecessors.empty()) {
- id = predecessors.back();
- predecessors.pop_back();
- ProcessSimpleConflict(trans, id, cryptographer, status);
- processed_items.insert(id);
- }
+ ProcessSimpleConflict(trans, id, cryptographer, status);
}
return;
}
« no previous file with comments | « sync/engine/build_commit_command_unittest.cc ('k') | sync/engine/get_commit_ids_command.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698