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

Side by Side Diff: chrome/browser/sync/engine/conflict_resolver.cc

Issue 8587006: [Sync] Add histograms for simple conflict resolution. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rename enum Created 9 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/conflict_resolver.h" 5 #include "chrome/browser/sync/engine/conflict_resolver.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 10
(...skipping 14 matching lines...) Expand all
25 using syncable::Id; 25 using syncable::Id;
26 using syncable::MutableEntry; 26 using syncable::MutableEntry;
27 using syncable::ScopedDirLookup; 27 using syncable::ScopedDirLookup;
28 using syncable::WriteTransaction; 28 using syncable::WriteTransaction;
29 29
30 namespace browser_sync { 30 namespace browser_sync {
31 31
32 using sessions::ConflictProgress; 32 using sessions::ConflictProgress;
33 using sessions::StatusController; 33 using sessions::StatusController;
34 34
35 namespace {
36
35 const int SYNC_CYCLES_BEFORE_ADMITTING_DEFEAT = 8; 37 const int SYNC_CYCLES_BEFORE_ADMITTING_DEFEAT = 8;
36 38
39 // Enumeration of different conflict resolutions. Used for histogramming.
40 enum SimpleConflictResolutions {
41 OVERWRITE_LOCAL, // Resolved by overwriting local changes.
42 OVERWRITE_SERVER, // Resolved by overwriting server changes.
43 UNDELETE, // Resolved by undeleting local item.
44 IGNORE_ENCRYPTION, // Resolved by ignoring an encryption-only server
45 // change. TODO(zea): implement and use this.
46 CONFLICT_RESOLUTION_SIZE,
47 };
48
49 } // namespace
50
37 ConflictResolver::ConflictResolver() { 51 ConflictResolver::ConflictResolver() {
38 } 52 }
39 53
40 ConflictResolver::~ConflictResolver() { 54 ConflictResolver::~ConflictResolver() {
41 } 55 }
42 56
43 void ConflictResolver::IgnoreLocalChanges(MutableEntry* entry) { 57 void ConflictResolver::IgnoreLocalChanges(MutableEntry* entry) {
44 // An update matches local actions, merge the changes. 58 // An update matches local actions, merge the changes.
45 // This is a little fishy because we don't actually merge them. 59 // This is a little fishy because we don't actually merge them.
46 // In the future we should do a 3-way merge. 60 // In the future we should do a 3-way merge.
47 VLOG(1) << "Server and local changes match, merging:" << entry; 61 VLOG(1) << "Resolving conflict by ignoring local changes:" << entry;
48 // With IS_UNSYNCED false, changes should be merged. 62 // With IS_UNSYNCED false, changes should be merged.
49 // METRIC simple conflict resolved by merge.
50 entry->Put(syncable::IS_UNSYNCED, false); 63 entry->Put(syncable::IS_UNSYNCED, false);
51 } 64 }
52 65
53 void ConflictResolver::OverwriteServerChanges(WriteTransaction* trans, 66 void ConflictResolver::OverwriteServerChanges(WriteTransaction* trans,
54 MutableEntry * entry) { 67 MutableEntry * entry) {
55 // This is similar to an overwrite from the old client. 68 // This is similar to an overwrite from the old client.
56 // This is equivalent to a scenario where we got the update before we'd 69 // This is equivalent to a scenario where we got the update before we'd
57 // made our local client changes. 70 // made our local client changes.
58 // TODO(chron): This is really a general property clobber. We clobber 71 // TODO(chron): This is really a general property clobber. We clobber
59 // the server side property. Perhaps we should actually do property merging. 72 // the server side property. Perhaps we should actually do property merging.
73 VLOG(1) << "Resolving conflict by ignoring server changes:" << entry;
60 entry->Put(syncable::BASE_VERSION, entry->Get(syncable::SERVER_VERSION)); 74 entry->Put(syncable::BASE_VERSION, entry->Get(syncable::SERVER_VERSION));
61 entry->Put(syncable::IS_UNAPPLIED_UPDATE, false); 75 entry->Put(syncable::IS_UNAPPLIED_UPDATE, false);
62 // METRIC conflict resolved by overwrite.
63 } 76 }
64 77
65 ConflictResolver::ProcessSimpleConflictResult 78 ConflictResolver::ProcessSimpleConflictResult
66 ConflictResolver::ProcessSimpleConflict(WriteTransaction* trans, 79 ConflictResolver::ProcessSimpleConflict(WriteTransaction* trans,
67 const Id& id, 80 const Id& id,
68 StatusController* status) { 81 StatusController* status) {
69 MutableEntry entry(trans, syncable::GET_BY_ID, id); 82 MutableEntry entry(trans, syncable::GET_BY_ID, id);
70 // Must be good as the entry won't have been cleaned up. 83 // Must be good as the entry won't have been cleaned up.
71 CHECK(entry.good()); 84 CHECK(entry.good());
72 // If an update fails, locally we have to be in a set or unsynced. We're not 85 // If an update fails, locally we have to be in a set or unsynced. We're not
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 bool entry_deleted = entry.Get(syncable::IS_DEL); 125 bool entry_deleted = entry.Get(syncable::IS_DEL);
113 126
114 if (!entry_deleted && name_matches && parent_matches) { 127 if (!entry_deleted && name_matches && parent_matches) {
115 // TODO(zea): We may prefer to choose the local changes over the server 128 // TODO(zea): We may prefer to choose the local changes over the server
116 // if we know the local changes happened before (or vice versa). 129 // if we know the local changes happened before (or vice versa).
117 // See http://crbug.com/76596 130 // See http://crbug.com/76596
118 VLOG(1) << "Resolving simple conflict, ignoring local changes for:" 131 VLOG(1) << "Resolving simple conflict, ignoring local changes for:"
119 << entry; 132 << entry;
120 IgnoreLocalChanges(&entry); 133 IgnoreLocalChanges(&entry);
121 status->increment_num_local_overwrites(); 134 status->increment_num_local_overwrites();
135 UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
136 OVERWRITE_LOCAL,
137 CONFLICT_RESOLUTION_SIZE);
122 } else { 138 } else {
123 VLOG(1) << "Resolving simple conflict, overwriting server changes for:" 139 VLOG(1) << "Resolving simple conflict, overwriting server changes for:"
124 << entry; 140 << entry;
125 OverwriteServerChanges(trans, &entry); 141 OverwriteServerChanges(trans, &entry);
126 status->increment_num_server_overwrites(); 142 status->increment_num_server_overwrites();
143 UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
144 OVERWRITE_SERVER,
145 CONFLICT_RESOLUTION_SIZE);
127 } 146 }
128 return SYNC_PROGRESS; 147 return SYNC_PROGRESS;
129 } else { // SERVER_IS_DEL is true 148 } else { // SERVER_IS_DEL is true
130 // If a server deleted folder has local contents we should be in a set. 149 // If a server deleted folder has local contents we should be in a set.
131 if (entry.Get(syncable::IS_DIR)) { 150 if (entry.Get(syncable::IS_DIR)) {
132 Directory::ChildHandles children; 151 Directory::ChildHandles children;
133 trans->directory()->GetChildHandlesById(trans, 152 trans->directory()->GetChildHandlesById(trans,
134 entry.Get(syncable::ID), 153 entry.Get(syncable::ID),
135 &children); 154 &children);
136 if (0 != children.size()) { 155 if (0 != children.size()) {
137 VLOG(1) << "Entry is a server deleted directory with local contents, " 156 VLOG(1) << "Entry is a server deleted directory with local contents, "
138 "should be in a set. (race condition)."; 157 "should be in a set. (race condition).";
139 return NO_SYNC_PROGRESS; 158 return NO_SYNC_PROGRESS;
140 } 159 }
141 } 160 }
142 161
143 // The entry is deleted on the server but still exists locally. 162 // The entry is deleted on the server but still exists locally.
144 if (!entry.Get(syncable::UNIQUE_CLIENT_TAG).empty()) { 163 if (!entry.Get(syncable::UNIQUE_CLIENT_TAG).empty()) {
145 // If we've got a client-unique tag, we can undelete while retaining 164 // If we've got a client-unique tag, we can undelete while retaining
146 // our present ID. 165 // our present ID.
147 DCHECK_EQ(entry.Get(syncable::SERVER_VERSION), 0) << "For the server to " 166 DCHECK_EQ(entry.Get(syncable::SERVER_VERSION), 0) << "For the server to "
148 "know to re-create, client-tagged items should revert to version 0 " 167 "know to re-create, client-tagged items should revert to version 0 "
149 "when server-deleted."; 168 "when server-deleted.";
150 OverwriteServerChanges(trans, &entry); 169 OverwriteServerChanges(trans, &entry);
151 status->increment_num_server_overwrites(); 170 status->increment_num_server_overwrites();
171 UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
172 OVERWRITE_SERVER,
173 CONFLICT_RESOLUTION_SIZE);
152 // Clobber the versions, just in case the above DCHECK is violated. 174 // Clobber the versions, just in case the above DCHECK is violated.
153 entry.Put(syncable::SERVER_VERSION, 0); 175 entry.Put(syncable::SERVER_VERSION, 0);
154 entry.Put(syncable::BASE_VERSION, 0); 176 entry.Put(syncable::BASE_VERSION, 0);
155 } else { 177 } else {
156 // Otherwise, we've got to undelete by creating a new locally 178 // Otherwise, we've got to undelete by creating a new locally
157 // uncommitted entry. 179 // uncommitted entry.
158 SyncerUtil::SplitServerInformationIntoNewEntry(trans, &entry); 180 SyncerUtil::SplitServerInformationIntoNewEntry(trans, &entry);
159 181
160 MutableEntry server_update(trans, syncable::GET_BY_ID, id); 182 MutableEntry server_update(trans, syncable::GET_BY_ID, id);
161 CHECK(server_update.good()); 183 CHECK(server_update.good());
162 CHECK(server_update.Get(syncable::META_HANDLE) != 184 CHECK(server_update.Get(syncable::META_HANDLE) !=
163 entry.Get(syncable::META_HANDLE)) 185 entry.Get(syncable::META_HANDLE))
164 << server_update << entry; 186 << server_update << entry;
187 UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
188 UNDELETE,
189 CONFLICT_RESOLUTION_SIZE);
165 } 190 }
166 return SYNC_PROGRESS; 191 return SYNC_PROGRESS;
167 } 192 }
168 } 193 }
169 194
170 ConflictResolver::ConflictSetCountMapKey ConflictResolver::GetSetKey( 195 ConflictResolver::ConflictSetCountMapKey ConflictResolver::GetSetKey(
171 ConflictSet* set) { 196 ConflictSet* set) {
172 // TODO(sync): Come up with a better scheme for set hashing. This scheme 197 // TODO(sync): Come up with a better scheme for set hashing. This scheme
173 // will make debugging easy. 198 // will make debugging easy.
174 // If this call to sort is removed, we need to add one before we use 199 // If this call to sort is removed, we need to add one before we use
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 conflict_set_count_map_.erase(i++); 538 conflict_set_count_map_.erase(i++);
514 // METRIC self resolved conflict sets ++. 539 // METRIC self resolved conflict sets ++.
515 } else { 540 } else {
516 ++i; 541 ++i;
517 } 542 }
518 } 543 }
519 return rv; 544 return rv;
520 } 545 }
521 546
522 } // namespace browser_sync 547 } // namespace browser_sync
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698