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

Side by Side Diff: chrome/browser/sync/engine/syncer_util.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-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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/syncer_util.h" 5 #include "chrome/browser/sync/engine/syncer_util.h"
6 6
7 #include <set> 7 #include <set>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 14 matching lines...) Expand all
25 using syncable::CHANGES_VERSION; 25 using syncable::CHANGES_VERSION;
26 using syncable::CREATE; 26 using syncable::CREATE;
27 using syncable::CREATE_NEW_UPDATE_ITEM; 27 using syncable::CREATE_NEW_UPDATE_ITEM;
28 using syncable::CTIME; 28 using syncable::CTIME;
29 using syncable::ComparePathNames; 29 using syncable::ComparePathNames;
30 using syncable::Directory; 30 using syncable::Directory;
31 using syncable::Entry; 31 using syncable::Entry;
32 using syncable::ExtendedAttributeKey; 32 using syncable::ExtendedAttributeKey;
33 using syncable::GET_BY_HANDLE; 33 using syncable::GET_BY_HANDLE;
34 using syncable::GET_BY_ID; 34 using syncable::GET_BY_ID;
35 using syncable::GET_BY_PARENTID_AND_DBNAME;
36 using syncable::ID; 35 using syncable::ID;
37 using syncable::IS_BOOKMARK_OBJECT; 36 using syncable::IS_BOOKMARK_OBJECT;
38 using syncable::IS_DEL; 37 using syncable::IS_DEL;
39 using syncable::IS_DIR; 38 using syncable::IS_DIR;
40 using syncable::IS_UNAPPLIED_UPDATE; 39 using syncable::IS_UNAPPLIED_UPDATE;
41 using syncable::IS_UNSYNCED; 40 using syncable::IS_UNSYNCED;
42 using syncable::Id; 41 using syncable::Id;
43 using syncable::META_HANDLE; 42 using syncable::META_HANDLE;
44 using syncable::MTIME; 43 using syncable::MTIME;
45 using syncable::MutableEntry; 44 using syncable::MutableEntry;
46 using syncable::MutableExtendedAttribute; 45 using syncable::MutableExtendedAttribute;
47 using syncable::NEXT_ID; 46 using syncable::NEXT_ID;
48 using syncable::Name; 47 using syncable::NON_UNIQUE_NAME;
49 using syncable::PARENT_ID; 48 using syncable::PARENT_ID;
50 using syncable::PREV_ID; 49 using syncable::PREV_ID;
51 using syncable::ReadTransaction; 50 using syncable::ReadTransaction;
52 using syncable::SERVER_BOOKMARK_FAVICON; 51 using syncable::SERVER_BOOKMARK_FAVICON;
53 using syncable::SERVER_BOOKMARK_URL; 52 using syncable::SERVER_BOOKMARK_URL;
54 using syncable::SERVER_CTIME; 53 using syncable::SERVER_CTIME;
55 using syncable::SERVER_IS_BOOKMARK_OBJECT; 54 using syncable::SERVER_IS_BOOKMARK_OBJECT;
56 using syncable::SERVER_IS_DEL; 55 using syncable::SERVER_IS_DEL;
57 using syncable::SERVER_IS_DIR; 56 using syncable::SERVER_IS_DIR;
58 using syncable::SERVER_MTIME; 57 using syncable::SERVER_MTIME;
59 using syncable::SERVER_NAME; 58 using syncable::SERVER_NON_UNIQUE_NAME;
60 using syncable::SERVER_PARENT_ID; 59 using syncable::SERVER_PARENT_ID;
61 using syncable::SERVER_POSITION_IN_PARENT; 60 using syncable::SERVER_POSITION_IN_PARENT;
62 using syncable::SERVER_VERSION; 61 using syncable::SERVER_VERSION;
63 using syncable::SINGLETON_TAG; 62 using syncable::SINGLETON_TAG;
64 using syncable::SYNCER; 63 using syncable::SYNCER;
65 using syncable::SyncName;
66 using syncable::UNSANITIZED_NAME;
67 using syncable::WriteTransaction; 64 using syncable::WriteTransaction;
68 65
69 namespace browser_sync { 66 namespace browser_sync {
70 67
71 using std::string; 68 using std::string;
72 using std::vector; 69 using std::vector;
73 70
74 // TODO(ncarter): Remove unique-in-parent title support and name conflicts.
75 // static
76 syncable::Id SyncerUtil::GetNameConflictingItemId(
77 syncable::BaseTransaction* trans,
78 const syncable::Id& parent_id,
79 const PathString& server_name) {
80
81 Entry same_path(trans, GET_BY_PARENTID_AND_DBNAME, parent_id, server_name);
82 if (same_path.good() && !same_path.GetName().HasBeenSanitized())
83 return same_path.Get(ID);
84 Name doctored_name(server_name);
85 doctored_name.db_value().MakeOSLegal();
86 if (!doctored_name.HasBeenSanitized())
87 return syncable::kNullId;
88 Directory::ChildHandles children;
89 trans->directory()->GetChildHandles(trans, parent_id, &children);
90 Directory::ChildHandles::iterator i = children.begin();
91 while (i != children.end()) {
92 Entry child_entry(trans, GET_BY_HANDLE, *i++);
93 CHECK(child_entry.good());
94 if (0 == ComparePathNames(child_entry.Get(UNSANITIZED_NAME), server_name))
95 return child_entry.Get(ID);
96 }
97 return syncable::kNullId;
98 }
99
100 // Returns the number of unsynced entries. 71 // Returns the number of unsynced entries.
101 // static 72 // static
102 int SyncerUtil::GetUnsyncedEntries(syncable::BaseTransaction* trans, 73 int SyncerUtil::GetUnsyncedEntries(syncable::BaseTransaction* trans,
103 vector<int64> *handles) { 74 vector<int64> *handles) {
104 trans->directory()->GetUnsyncedMetaHandles(trans, handles); 75 trans->directory()->GetUnsyncedMetaHandles(trans, handles);
105 LOG_IF(INFO, handles->size() > 0) 76 LOG_IF(INFO, handles->size() > 0)
106 << "Have " << handles->size() << " unsynced items."; 77 << "Have " << handles->size() << " unsynced items.";
107 return handles->size(); 78 return handles->size();
108 } 79 }
109 80
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 // of this system and just have client side generated IDs as a whole. 184 // of this system and just have client side generated IDs as a whole.
214 } 185 }
215 } 186 }
216 187
217 // static 188 // static
218 UpdateAttemptResponse SyncerUtil::AttemptToUpdateEntry( 189 UpdateAttemptResponse SyncerUtil::AttemptToUpdateEntry(
219 syncable::WriteTransaction* const trans, 190 syncable::WriteTransaction* const trans,
220 syncable::MutableEntry* const entry, 191 syncable::MutableEntry* const entry,
221 ConflictResolver* resolver) { 192 ConflictResolver* resolver) {
222 193
223 syncable::Id conflicting_id;
224 UpdateAttemptResponse result =
225 AttemptToUpdateEntryWithoutMerge(trans, entry, &conflicting_id);
226 if (result != NAME_CONFLICT) {
227 return result;
228 }
229 syncable::MutableEntry same_path(trans, syncable::GET_BY_ID, conflicting_id);
230 CHECK(same_path.good());
231
232 if (resolver &&
233 resolver->AttemptItemMerge(trans, &same_path, entry)) {
234 return SUCCESS;
235 }
236 LOG(INFO) << "Not updating item, path collision. Update:\n" << *entry
237 << "\nSame Path:\n" << same_path;
238 return CONFLICT;
239 }
240
241 // static
242 UpdateAttemptResponse SyncerUtil::AttemptToUpdateEntryWithoutMerge(
243 syncable::WriteTransaction* const trans,
244 syncable::MutableEntry* const entry,
245 syncable::Id* const conflicting_id) {
246
247 CHECK(entry->good()); 194 CHECK(entry->good());
248 if (!entry->Get(IS_UNAPPLIED_UPDATE)) 195 if (!entry->Get(IS_UNAPPLIED_UPDATE))
249 return SUCCESS; // No work to do. 196 return SUCCESS; // No work to do.
250 syncable::Id id = entry->Get(ID); 197 syncable::Id id = entry->Get(ID);
251 198
252 if (entry->Get(IS_UNSYNCED)) { 199 if (entry->Get(IS_UNSYNCED)) {
253 LOG(INFO) << "Skipping update, returning conflict for: " << id 200 LOG(INFO) << "Skipping update, returning conflict for: " << id
254 << " ; it's unsynced."; 201 << " ; it's unsynced.";
255 return CONFLICT; 202 return CONFLICT;
256 } 203 }
257 if (!entry->Get(SERVER_IS_DEL)) { 204 if (!entry->Get(SERVER_IS_DEL)) {
258 syncable::Id new_parent = entry->Get(SERVER_PARENT_ID); 205 syncable::Id new_parent = entry->Get(SERVER_PARENT_ID);
259 Entry parent(trans, GET_BY_ID, new_parent); 206 Entry parent(trans, GET_BY_ID, new_parent);
260 // A note on non-directory parents: 207 // A note on non-directory parents:
261 // We catch most unfixable tree invariant errors at update receipt time, 208 // We catch most unfixable tree invariant errors at update receipt time,
262 // however we deal with this case here because we may receive the child 209 // however we deal with this case here because we may receive the child
263 // first then the illegal parent. Instead of dealing with it twice in 210 // first then the illegal parent. Instead of dealing with it twice in
264 // different ways we deal with it once here to reduce the amount of code and 211 // different ways we deal with it once here to reduce the amount of code and
265 // potential errors. 212 // potential errors.
266 if (!parent.good() || parent.Get(IS_DEL) || !parent.Get(IS_DIR)) { 213 if (!parent.good() || parent.Get(IS_DEL) || !parent.Get(IS_DIR)) {
267 return CONFLICT; 214 return CONFLICT;
268 } 215 }
269 if (entry->Get(PARENT_ID) != new_parent) { 216 if (entry->Get(PARENT_ID) != new_parent) {
270 if (!entry->Get(IS_DEL) && !IsLegalNewParent(trans, id, new_parent)) { 217 if (!entry->Get(IS_DEL) && !IsLegalNewParent(trans, id, new_parent)) {
271 LOG(INFO) << "Not updating item " << id << ", illegal new parent " 218 LOG(INFO) << "Not updating item " << id << ", illegal new parent "
272 "(would cause loop)."; 219 "(would cause loop).";
273 return CONFLICT; 220 return CONFLICT;
274 } 221 }
275 } 222 }
276 PathString server_name = entry->Get(SERVER_NAME);
277 syncable::Id conflict_id =
278 SyncerUtil::GetNameConflictingItemId(trans,
279 entry->Get(SERVER_PARENT_ID),
280 server_name);
281 if (conflict_id != syncable::kNullId && conflict_id != id) {
282 if (conflicting_id)
283 *conflicting_id = conflict_id;
284 return NAME_CONFLICT;
285 }
286 } else if (entry->Get(IS_DIR)) { 223 } else if (entry->Get(IS_DIR)) {
287 Directory::ChildHandles handles; 224 Directory::ChildHandles handles;
288 trans->directory()->GetChildHandles(trans, id, &handles); 225 trans->directory()->GetChildHandles(trans, id, &handles);
289 if (!handles.empty()) { 226 if (!handles.empty()) {
290 // If we have still-existing children, then we need to deal with 227 // If we have still-existing children, then we need to deal with
291 // them before we can process this change. 228 // them before we can process this change.
292 LOG(INFO) << "Not deleting directory; it's not empty " << *entry; 229 LOG(INFO) << "Not deleting directory; it's not empty " << *entry;
293 return CONFLICT; 230 return CONFLICT;
294 } 231 }
295 } 232 }
296 233
297 SyncerUtil::UpdateLocalDataFromServerData(trans, entry); 234 SyncerUtil::UpdateLocalDataFromServerData(trans, entry);
298 235
299 return SUCCESS; 236 return SUCCESS;
300 } 237 }
301 238
302 // Pass in name and checksum because of UTF8 conversion. 239 // Pass in name and checksum because of UTF8 conversion.
303 // static 240 // static
304 void SyncerUtil::UpdateServerFieldsFromUpdate( 241 void SyncerUtil::UpdateServerFieldsFromUpdate(
305 MutableEntry* local_entry, 242 MutableEntry* local_entry,
306 const SyncEntity& server_entry, 243 const SyncEntity& server_entry,
307 const SyncName& name) { 244 const PathString& name) {
308 if (server_entry.deleted()) { 245 if (server_entry.deleted()) {
309 // The server returns very lightweight replies for deletions, so we don't 246 // The server returns very lightweight replies for deletions, so we don't
310 // clobber a bunch of fields on delete. 247 // clobber a bunch of fields on delete.
311 local_entry->Put(SERVER_IS_DEL, true); 248 local_entry->Put(SERVER_IS_DEL, true);
312 local_entry->Put(SERVER_VERSION, 249 local_entry->Put(SERVER_VERSION,
313 std::max(local_entry->Get(SERVER_VERSION), 250 std::max(local_entry->Get(SERVER_VERSION),
314 local_entry->Get(BASE_VERSION)) + 1L); 251 local_entry->Get(BASE_VERSION)) + 1L);
315 local_entry->Put(IS_UNAPPLIED_UPDATE, true); 252 local_entry->Put(IS_UNAPPLIED_UPDATE, true);
316 return; 253 return;
317 } 254 }
318 255
319 CHECK(local_entry->Get(ID) == server_entry.id()) 256 CHECK(local_entry->Get(ID) == server_entry.id())
320 << "ID Changing not supported here"; 257 << "ID Changing not supported here";
321 local_entry->Put(SERVER_PARENT_ID, server_entry.parent_id()); 258 local_entry->Put(SERVER_PARENT_ID, server_entry.parent_id());
322 local_entry->PutServerName(name); 259 local_entry->Put(SERVER_NON_UNIQUE_NAME, name);
323 local_entry->Put(SERVER_VERSION, server_entry.version()); 260 local_entry->Put(SERVER_VERSION, server_entry.version());
324 local_entry->Put(SERVER_CTIME, 261 local_entry->Put(SERVER_CTIME,
325 ServerTimeToClientTime(server_entry.ctime())); 262 ServerTimeToClientTime(server_entry.ctime()));
326 local_entry->Put(SERVER_MTIME, 263 local_entry->Put(SERVER_MTIME,
327 ServerTimeToClientTime(server_entry.mtime())); 264 ServerTimeToClientTime(server_entry.mtime()));
328 local_entry->Put(SERVER_IS_BOOKMARK_OBJECT, server_entry.has_bookmarkdata()); 265 local_entry->Put(SERVER_IS_BOOKMARK_OBJECT, server_entry.has_bookmarkdata());
329 local_entry->Put(SERVER_IS_DIR, server_entry.IsFolder()); 266 local_entry->Put(SERVER_IS_DIR, server_entry.IsFolder());
330 if (server_entry.has_singleton_tag()) { 267 if (server_entry.has_singleton_tag()) {
331 const PathString& tag = server_entry.singleton_tag(); 268 const PathString& tag = server_entry.singleton_tag();
332 local_entry->Put(SINGLETON_TAG, tag); 269 local_entry->Put(SINGLETON_TAG, tag);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 // static 351 // static
415 bool SyncerUtil::ServerAndLocalEntriesMatch(syncable::Entry* entry) { 352 bool SyncerUtil::ServerAndLocalEntriesMatch(syncable::Entry* entry) {
416 if (!ClientAndServerTimeMatch( 353 if (!ClientAndServerTimeMatch(
417 entry->Get(CTIME), ClientTimeToServerTime(entry->Get(SERVER_CTIME)))) { 354 entry->Get(CTIME), ClientTimeToServerTime(entry->Get(SERVER_CTIME)))) {
418 LOG(WARNING) << "Client and server time mismatch"; 355 LOG(WARNING) << "Client and server time mismatch";
419 return false; 356 return false;
420 } 357 }
421 if (entry->Get(IS_DEL) && entry->Get(SERVER_IS_DEL)) 358 if (entry->Get(IS_DEL) && entry->Get(SERVER_IS_DEL))
422 return true; 359 return true;
423 // Name should exactly match here. 360 // Name should exactly match here.
424 if (!entry->SyncNameMatchesServerName()) { 361 if (!(entry->Get(NON_UNIQUE_NAME) == entry->Get(SERVER_NON_UNIQUE_NAME))) {
425 LOG(WARNING) << "Unsanitized name mismatch"; 362 LOG(WARNING) << "Unsanitized name mismatch";
426 return false; 363 return false;
427 } 364 }
428 365
429 if (entry->Get(PARENT_ID) != entry->Get(SERVER_PARENT_ID) || 366 if (entry->Get(PARENT_ID) != entry->Get(SERVER_PARENT_ID) ||
430 entry->Get(IS_DIR) != entry->Get(SERVER_IS_DIR) || 367 entry->Get(IS_DIR) != entry->Get(SERVER_IS_DIR) ||
431 entry->Get(IS_DEL) != entry->Get(SERVER_IS_DEL)) { 368 entry->Get(IS_DEL) != entry->Get(SERVER_IS_DEL)) {
432 LOG(WARNING) << "Metabit mismatch"; 369 LOG(WARNING) << "Metabit mismatch";
433 return false; 370 return false;
434 } 371 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 // static 416 // static
480 void SyncerUtil::UpdateLocalDataFromServerData( 417 void SyncerUtil::UpdateLocalDataFromServerData(
481 syncable::WriteTransaction* trans, 418 syncable::WriteTransaction* trans,
482 syncable::MutableEntry* entry) { 419 syncable::MutableEntry* entry) {
483 CHECK(!entry->Get(IS_UNSYNCED)); 420 CHECK(!entry->Get(IS_UNSYNCED));
484 CHECK(entry->Get(IS_UNAPPLIED_UPDATE)); 421 CHECK(entry->Get(IS_UNAPPLIED_UPDATE));
485 LOG(INFO) << "Updating entry : " << *entry; 422 LOG(INFO) << "Updating entry : " << *entry;
486 entry->Put(IS_BOOKMARK_OBJECT, entry->Get(SERVER_IS_BOOKMARK_OBJECT)); 423 entry->Put(IS_BOOKMARK_OBJECT, entry->Get(SERVER_IS_BOOKMARK_OBJECT));
487 // This strange dance around the IS_DEL flag avoids problems when setting 424 // This strange dance around the IS_DEL flag avoids problems when setting
488 // the name. 425 // the name.
426 // TODO(chron): Is this still an issue? Unit test this codepath.
489 if (entry->Get(SERVER_IS_DEL)) { 427 if (entry->Get(SERVER_IS_DEL)) {
490 entry->Put(IS_DEL, true); 428 entry->Put(IS_DEL, true);
491 } else { 429 } else {
492 Name name = Name::FromSyncName(entry->GetServerName()); 430 entry->Put(NON_UNIQUE_NAME, entry->Get(SERVER_NON_UNIQUE_NAME));
493 name.db_value().MakeOSLegal(); 431 entry->Put(PARENT_ID, entry->Get(SERVER_PARENT_ID));
494 bool was_doctored_before_made_noncolliding = name.HasBeenSanitized();
495 name.db_value().MakeNoncollidingForEntry(trans,
496 entry->Get(SERVER_PARENT_ID),
497 entry);
498 bool was_doctored = name.HasBeenSanitized();
499 if (was_doctored) {
500 // If we're changing the name of entry, either its name should be
501 // illegal, or some other entry should have an unsanitized name.
502 // There's should be a CHECK in every code path.
503 Entry blocking_entry(trans, GET_BY_PARENTID_AND_DBNAME,
504 entry->Get(SERVER_PARENT_ID),
505 name.value());
506 if (blocking_entry.good())
507 CHECK(blocking_entry.GetName().HasBeenSanitized());
508 else
509 CHECK(was_doctored_before_made_noncolliding);
510 }
511 CHECK(entry->PutParentIdAndName(entry->Get(SERVER_PARENT_ID), name))
512 << "Name Clash in UpdateLocalDataFromServerData: "
513 << *entry;
514 CHECK(entry->Put(IS_DEL, false)); 432 CHECK(entry->Put(IS_DEL, false));
515 Id new_predecessor = ComputePrevIdFromServerPosition(trans, entry, 433 Id new_predecessor = ComputePrevIdFromServerPosition(trans, entry,
516 entry->Get(SERVER_PARENT_ID)); 434 entry->Get(SERVER_PARENT_ID));
517 CHECK(entry->PutPredecessor(new_predecessor)) 435 CHECK(entry->PutPredecessor(new_predecessor))
518 << " Illegal predecessor after converting from server position."; 436 << " Illegal predecessor after converting from server position.";
519 } 437 }
520 438
521 entry->Put(CTIME, entry->Get(SERVER_CTIME)); 439 entry->Put(CTIME, entry->Get(SERVER_CTIME));
522 entry->Put(MTIME, entry->Get(SERVER_MTIME)); 440 entry->Put(MTIME, entry->Get(SERVER_MTIME));
523 entry->Put(BASE_VERSION, entry->Get(SERVER_VERSION)); 441 entry->Put(BASE_VERSION, entry->Get(SERVER_VERSION));
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 743
826 // |update_entry| is considered to be somewhere after |candidate|, so store 744 // |update_entry| is considered to be somewhere after |candidate|, so store
827 // it as the upper bound. 745 // it as the upper bound.
828 closest_sibling = candidate.Get(ID); 746 closest_sibling = candidate.Get(ID);
829 } 747 }
830 748
831 return closest_sibling; 749 return closest_sibling;
832 } 750 }
833 751
834 } // namespace browser_sync 752 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/syncer_util.h ('k') | chrome/browser/sync/engine/update_applicator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698