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

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

Issue 371029: Remove unique naming. (Closed)
Patch Set: Ready and about to go in! Created 11 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
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 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/build_and_process_conflict_sets_command.h" 5 #include "chrome/browser/sync/engine/build_and_process_conflict_sets_command.h"
6 6
7 #include <string> 7 #include <string>
8 #include <sstream> 8 #include <sstream>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 85
86 void StoreLocalDataForUpdateRollback(syncable::Entry* entry, 86 void StoreLocalDataForUpdateRollback(syncable::Entry* entry,
87 syncable::EntryKernel* backup) { 87 syncable::EntryKernel* backup) {
88 CHECK(!entry->Get(syncable::IS_UNSYNCED)) << " Storing Rollback data for " 88 CHECK(!entry->Get(syncable::IS_UNSYNCED)) << " Storing Rollback data for "
89 "entry that's unsynced." << *entry; 89 "entry that's unsynced." << *entry;
90 CHECK(entry->Get(syncable::IS_UNAPPLIED_UPDATE)) << " Storing Rollback data " 90 CHECK(entry->Get(syncable::IS_UNAPPLIED_UPDATE)) << " Storing Rollback data "
91 "for entry that's not an unapplied update." << *entry; 91 "for entry that's not an unapplied update." << *entry;
92 *backup = entry->GetKernelCopy(); 92 *backup = entry->GetKernelCopy();
93 } 93 }
94 94
95 class UniqueNameGenerator {
96 public:
97 void Initialize() {
98 // To avoid name collisions we prefix the names with hex data derived from
99 // 64 bits of randomness.
100 int64 name_prefix = static_cast<int64>(base::RandUint64());
101 name_stem_ = StringPrintf("%0" PRId64 "x.", name_prefix);
102 }
103 string StringNameForEntry(const syncable::Entry& entry) {
104 CHECK(!name_stem_.empty());
105 std::stringstream rv;
106 rv << name_stem_ << entry.Get(syncable::ID);
107 return rv.str();
108 }
109 PathString PathStringNameForEntry(const syncable::Entry& entry) {
110 string name = StringNameForEntry(entry);
111 return PathString(name.begin(), name.end());
112 }
113
114 private:
115 string name_stem_;
116 };
117 95
118 bool RollbackEntry(syncable::WriteTransaction* trans, 96 bool RollbackEntry(syncable::WriteTransaction* trans,
119 syncable::EntryKernel* backup) { 97 syncable::EntryKernel* backup) {
120 syncable::MutableEntry entry(trans, syncable::GET_BY_HANDLE, 98 syncable::MutableEntry entry(trans, syncable::GET_BY_HANDLE,
121 backup->ref(syncable::META_HANDLE)); 99 backup->ref(syncable::META_HANDLE));
122 CHECK(entry.good()); 100 CHECK(entry.good());
123 101
124 if (!entry.Put(syncable::IS_DEL, backup->ref(syncable::IS_DEL))) 102 if (!entry.Put(syncable::IS_DEL, backup->ref(syncable::IS_DEL)))
125 return false; 103 return false;
126 syncable::Name name = syncable::Name::FromEntryKernel(backup); 104
127 if (!entry.PutParentIdAndName(backup->ref(syncable::PARENT_ID), name)) 105 entry.Put(syncable::NON_UNIQUE_NAME, backup->ref(syncable::NON_UNIQUE_NAME));
128 return false; 106 entry.Put(syncable::PARENT_ID, backup->ref(syncable::PARENT_ID));
129 107
130 if (!backup->ref(syncable::IS_DEL)) { 108 if (!backup->ref(syncable::IS_DEL)) {
131 if (!entry.PutPredecessor(backup->ref(syncable::PREV_ID))) 109 if (!entry.PutPredecessor(backup->ref(syncable::PREV_ID)))
132 return false; 110 return false;
133 } 111 }
134 112
135 if (backup->ref(syncable::PREV_ID) != entry.Get(syncable::PREV_ID)) 113 if (backup->ref(syncable::PREV_ID) != entry.Get(syncable::PREV_ID))
136 return false; 114 return false;
137 115
138 entry.Put(syncable::CTIME, backup->ref(syncable::CTIME)); 116 entry.Put(syncable::CTIME, backup->ref(syncable::CTIME));
139 entry.Put(syncable::MTIME, backup->ref(syncable::MTIME)); 117 entry.Put(syncable::MTIME, backup->ref(syncable::MTIME));
140 entry.Put(syncable::BASE_VERSION, backup->ref(syncable::BASE_VERSION)); 118 entry.Put(syncable::BASE_VERSION, backup->ref(syncable::BASE_VERSION));
141 entry.Put(syncable::IS_DIR, backup->ref(syncable::IS_DIR)); 119 entry.Put(syncable::IS_DIR, backup->ref(syncable::IS_DIR));
142 entry.Put(syncable::IS_DEL, backup->ref(syncable::IS_DEL)); 120 entry.Put(syncable::IS_DEL, backup->ref(syncable::IS_DEL));
143 entry.Put(syncable::ID, backup->ref(syncable::ID)); 121 entry.Put(syncable::ID, backup->ref(syncable::ID));
144 entry.Put(syncable::IS_UNAPPLIED_UPDATE, 122 entry.Put(syncable::IS_UNAPPLIED_UPDATE,
145 backup->ref(syncable::IS_UNAPPLIED_UPDATE)); 123 backup->ref(syncable::IS_UNAPPLIED_UPDATE));
146 return true; 124 return true;
147 } 125 }
148 126
149 class TransactionalUpdateEntryPreparer { 127 void PlaceEntriesAtRoot(syncable::WriteTransaction* trans,
150 public: 128 const vector<syncable::Id>* ids) {
151 TransactionalUpdateEntryPreparer() { 129 vector<syncable::Id>::const_iterator it;
152 namegen_.Initialize(); 130 for (it = ids->begin(); it != ids->end(); ++it) {
131 syncable::MutableEntry entry(trans, syncable::GET_BY_ID, *it);
132 entry.Put(syncable::PARENT_ID, trans->root_id());
153 } 133 }
154 134 }
155 void PrepareEntries(syncable::WriteTransaction* trans,
156 const vector<syncable::Id>* ids) {
157 vector<syncable::Id>::const_iterator it;
158 for (it = ids->begin(); it != ids->end(); ++it) {
159 syncable::MutableEntry entry(trans, syncable::GET_BY_ID, *it);
160 syncable::Name random_name(namegen_.PathStringNameForEntry(entry));
161 CHECK(entry.PutParentIdAndName(trans->root_id(), random_name));
162 }
163 }
164
165 private:
166 UniqueNameGenerator namegen_;
167 DISALLOW_COPY_AND_ASSIGN(TransactionalUpdateEntryPreparer);
168 };
169 135
170 } // namespace 136 } // namespace
171 137
172 bool BuildAndProcessConflictSetsCommand::ApplyUpdatesTransactionally( 138 bool BuildAndProcessConflictSetsCommand::ApplyUpdatesTransactionally(
173 syncable::WriteTransaction* trans, 139 syncable::WriteTransaction* trans,
174 const vector<syncable::Id>* const update_set, 140 const vector<syncable::Id>* const update_set,
175 SyncerSession* const session) { 141 SyncerSession* const session) {
176 // The handles in the |update_set| order. 142 // The handles in the |update_set| order.
177 vector<int64> handles; 143 vector<int64> handles;
178 144
(...skipping 22 matching lines...) Expand all
201 DCHECK_EQ(rollback_ids_inserted_items.size(), update_set->size()); 167 DCHECK_EQ(rollback_ids_inserted_items.size(), update_set->size());
202 168
203 // 3. Store the information needed to rollback if the transaction fails. 169 // 3. Store the information needed to rollback if the transaction fails.
204 // Do this before modifying anything to keep the next/prev values intact. 170 // Do this before modifying anything to keep the next/prev values intact.
205 vector<syncable::EntryKernel> rollback_data(rollback_ids.size()); 171 vector<syncable::EntryKernel> rollback_data(rollback_ids.size());
206 for (size_t i = 0; i < rollback_ids.size(); ++i) { 172 for (size_t i = 0; i < rollback_ids.size(); ++i) {
207 syncable::Entry entry(trans, syncable::GET_BY_ID, rollback_ids[i]); 173 syncable::Entry entry(trans, syncable::GET_BY_ID, rollback_ids[i]);
208 StoreLocalDataForUpdateRollback(&entry, &rollback_data[i]); 174 StoreLocalDataForUpdateRollback(&entry, &rollback_data[i]);
209 } 175 }
210 176
211 // 4. Use the preparer to move things to an initial starting state where no 177 // 4. Use the preparer to move things to an initial starting state where
212 // names collide, and nothing in the set is a child of anything else. If 178 // nothing in the set is a child of anything else. If
213 // we've correctly calculated the set, the server tree is valid and no 179 // we've correctly calculated the set, the server tree is valid and no
214 // changes have occurred locally we should be able to apply updates from this 180 // changes have occurred locally we should be able to apply updates from this
215 // state. 181 // state.
216 TransactionalUpdateEntryPreparer preparer; 182 PlaceEntriesAtRoot(trans, update_set);
217 preparer.PrepareEntries(trans, update_set);
218 183
219 // 5. Use the usual apply updates from the special start state we've just 184 // 5. Use the usual apply updates from the special start state we've just
220 // prepared. 185 // prepared.
221 UpdateApplicator applicator(session->resolver(), handles.begin(), 186 UpdateApplicator applicator(session->resolver(), handles.begin(),
222 handles.end()); 187 handles.end());
223 while (applicator.AttemptOneApplication(trans)) { 188 while (applicator.AttemptOneApplication(trans)) {
224 // Keep going till all updates are applied. 189 // Keep going till all updates are applied.
225 } 190 }
226 if (!applicator.AllUpdatesApplied()) { 191 if (!applicator.AllUpdatesApplied()) {
227 LOG(ERROR) << "Transactional Apply Failed, Rolling back."; 192 LOG(ERROR) << "Transactional Apply Failed, Rolling back.";
228 // We have to move entries into the temp dir again. e.g. if a swap was in a 193 // We have to move entries into the temp dir again. e.g. if a swap was in a
229 // set with other failing updates, the swap may have gone through, meaning 194 // set with other failing updates, the swap may have gone through, meaning
230 // the roll back needs to be transactional. But as we're going to a known 195 // the roll back needs to be transactional. But as we're going to a known
231 // good state we should always succeed. 196 // good state we should always succeed.
232 preparer.PrepareEntries(trans, update_set); 197 PlaceEntriesAtRoot(trans, update_set);
233 198
234 // Rollback all entries. 199 // Rollback all entries.
235 for (size_t i = 0; i < rollback_data.size(); ++i) { 200 for (size_t i = 0; i < rollback_data.size(); ++i) {
236 CHECK(RollbackEntry(trans, &rollback_data[i])); 201 CHECK(RollbackEntry(trans, &rollback_data[i]));
237 } 202 }
238 return false; // Don't save progress -- we just undid it. 203 return false; // Don't save progress -- we just undid it.
239 } 204 }
240 applicator.SaveProgressIntoSessionState(session); 205 applicator.SaveProgressIntoSessionState(session);
241 return true; 206 return true;
242 } 207 }
243 208
244 void BuildAndProcessConflictSetsCommand::BuildConflictSets( 209 void BuildAndProcessConflictSetsCommand::BuildConflictSets(
245 syncable::BaseTransaction* trans, 210 syncable::BaseTransaction* trans,
246 ConflictResolutionView* view) { 211 ConflictResolutionView* view) {
247 view->CleanupSets(); 212 view->CleanupSets();
248 set<syncable::Id>::iterator i = view->CommitConflictsBegin(); 213 set<syncable::Id>::iterator i = view->CommitConflictsBegin();
249 while (i != view->CommitConflictsEnd()) { 214 while (i != view->CommitConflictsEnd()) {
250 syncable::Entry entry(trans, syncable::GET_BY_ID, *i); 215 syncable::Entry entry(trans, syncable::GET_BY_ID, *i);
251 CHECK(entry.good()); 216 CHECK(entry.good());
252 if (!entry.Get(syncable::IS_UNSYNCED) && 217 if (!entry.Get(syncable::IS_UNSYNCED) &&
253 !entry.Get(syncable::IS_UNAPPLIED_UPDATE)) { 218 !entry.Get(syncable::IS_UNAPPLIED_UPDATE)) {
254 // This can happen very rarely. It means we had a simply conflicting item 219 // This can happen very rarely. It means we had a simply conflicting item
255 // that randomly committed. We drop the entry as it's no longer 220 // that randomly committed. We drop the entry as it's no longer
256 // conflicting. 221 // conflicting.
257 view->EraseCommitConflict(i++); 222 view->EraseCommitConflict(i++);
258 continue; 223 continue;
259 } 224 }
260 if (entry.ExistsOnClientBecauseDatabaseNameIsNonEmpty() && 225 if (entry.ExistsOnClientBecauseNameIsNonEmpty() &&
261 (entry.Get(syncable::IS_DEL) || entry.Get(syncable::SERVER_IS_DEL))) { 226 (entry.Get(syncable::IS_DEL) || entry.Get(syncable::SERVER_IS_DEL))) {
262 // If we're deleted on client or server we can't be in a complex set. 227 // If we're deleted on client or server we can't be in a complex set.
263 ++i; 228 ++i;
264 continue; 229 continue;
265 } 230 }
266 bool new_parent = 231 bool new_parent =
267 entry.Get(syncable::PARENT_ID) != entry.Get(syncable::SERVER_PARENT_ID); 232 entry.Get(syncable::PARENT_ID) != entry.Get(syncable::SERVER_PARENT_ID);
268 bool new_name = 0 != syncable::ComparePathNames(entry.GetSyncNameValue(),
269 entry.Get(syncable::SERVER_NAME));
270 if (new_parent || new_name)
271 MergeSetsForNameClash(trans, &entry, view);
272 if (new_parent) 233 if (new_parent)
273 MergeSetsForIntroducedLoops(trans, &entry, view); 234 MergeSetsForIntroducedLoops(trans, &entry, view);
274 MergeSetsForNonEmptyDirectories(trans, &entry, view); 235 MergeSetsForNonEmptyDirectories(trans, &entry, view);
275 ++i; 236 ++i;
276 } 237 }
277 } 238 }
278 239
279 void BuildAndProcessConflictSetsCommand::MergeSetsForNameClash(
280 syncable::BaseTransaction* trans, syncable::Entry* entry,
281 ConflictResolutionView* view) {
282 PathString server_name = entry->Get(syncable::SERVER_NAME);
283 // Uncommitted entries have no server name. We trap this because the root
284 // item has a null name and 0 parentid.
285 if (server_name.empty())
286 return;
287 syncable::Id conflicting_id =
288 SyncerUtil::GetNameConflictingItemId(
289 trans, entry->Get(syncable::SERVER_PARENT_ID), server_name);
290 if (syncable::kNullId != conflicting_id)
291 view->MergeSets(entry->Get(syncable::ID), conflicting_id);
292 }
293
294 void BuildAndProcessConflictSetsCommand::MergeSetsForIntroducedLoops( 240 void BuildAndProcessConflictSetsCommand::MergeSetsForIntroducedLoops(
295 syncable::BaseTransaction* trans, syncable::Entry* entry, 241 syncable::BaseTransaction* trans, syncable::Entry* entry,
296 ConflictResolutionView* view) { 242 ConflictResolutionView* view) {
297 // This code crawls up from the item in question until it gets to the root 243 // This code crawls up from the item in question until it gets to the root
298 // or itself. If it gets to the root it does nothing. If it finds a loop all 244 // or itself. If it gets to the root it does nothing. If it finds a loop all
299 // moved unsynced entries in the list of crawled entries have their sets 245 // moved unsynced entries in the list of crawled entries have their sets
300 // merged with the entry. 246 // merged with the entry.
301 // TODO(sync): Build test cases to cover this function when the argument list 247 // TODO(sync): Build test cases to cover this function when the argument list
302 // has settled. 248 // has settled.
303 syncable::Id parent_id = entry->Get(syncable::SERVER_PARENT_ID); 249 syncable::Id parent_id = entry->Get(syncable::SERVER_PARENT_ID);
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 return; 381 return;
436 LocallyDeletedPathChecker checker; 382 LocallyDeletedPathChecker checker;
437 if (!checker.CausingConflict(parent, *entry)) 383 if (!checker.CausingConflict(parent, *entry))
438 return; 384 return;
439 view->MergeSets(entry->Get(syncable::ID), parent.Get(syncable::ID)); 385 view->MergeSets(entry->Get(syncable::ID), parent.Get(syncable::ID));
440 CrawlDeletedTreeMergingSets(trans, parent, view, checker); 386 CrawlDeletedTreeMergingSets(trans, parent, view, checker);
441 } 387 }
442 } 388 }
443 389
444 } // namespace browser_sync 390 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/apply_updates_command_unittest.cc ('k') | chrome/browser/sync/engine/build_commit_command.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698