OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "sync/engine/syncer_util.h" | 5 #include "sync/engine/syncer_util.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
| 12 #include "base/base64.h" |
12 #include "base/location.h" | 13 #include "base/location.h" |
13 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/string_number_conversions.h" |
14 #include "sync/engine/conflict_resolver.h" | 16 #include "sync/engine/conflict_resolver.h" |
15 #include "sync/engine/syncer_proto_util.h" | 17 #include "sync/engine/syncer_proto_util.h" |
16 #include "sync/engine/syncer_types.h" | 18 #include "sync/engine/syncer_types.h" |
17 #include "sync/internal_api/public/base/model_type.h" | 19 #include "sync/internal_api/public/base/model_type.h" |
| 20 #include "sync/internal_api/public/base/unique_position.h" |
18 #include "sync/protocol/bookmark_specifics.pb.h" | 21 #include "sync/protocol/bookmark_specifics.pb.h" |
19 #include "sync/protocol/password_specifics.pb.h" | 22 #include "sync/protocol/password_specifics.pb.h" |
20 #include "sync/protocol/sync.pb.h" | 23 #include "sync/protocol/sync.pb.h" |
21 #include "sync/syncable/directory.h" | 24 #include "sync/syncable/directory.h" |
22 #include "sync/syncable/entry.h" | 25 #include "sync/syncable/entry.h" |
23 #include "sync/syncable/mutable_entry.h" | 26 #include "sync/syncable/mutable_entry.h" |
24 #include "sync/syncable/read_transaction.h" | 27 #include "sync/syncable/read_transaction.h" |
25 #include "sync/syncable/syncable_changes_version.h" | 28 #include "sync/syncable/syncable_changes_version.h" |
26 #include "sync/syncable/syncable_proto_util.h" | 29 #include "sync/syncable/syncable_proto_util.h" |
27 #include "sync/syncable/syncable_util.h" | 30 #include "sync/syncable/syncable_util.h" |
28 #include "sync/syncable/write_transaction.h" | 31 #include "sync/syncable/write_transaction.h" |
29 #include "sync/util/cryptographer.h" | 32 #include "sync/util/cryptographer.h" |
30 #include "sync/util/time.h" | 33 #include "sync/util/time.h" |
31 | 34 |
32 // TODO(vishwath): Remove this include after node positions have | |
33 // shifted to completely uing Ordinals. | |
34 // See http://crbug.com/145412 . | |
35 #include "sync/internal_api/public/base/node_ordinal.h" | |
36 | |
37 namespace syncer { | 35 namespace syncer { |
38 | 36 |
| 37 using syncable::BASE_SERVER_SPECIFICS; |
39 using syncable::BASE_VERSION; | 38 using syncable::BASE_VERSION; |
40 using syncable::CHANGES_VERSION; | 39 using syncable::CHANGES_VERSION; |
41 using syncable::CREATE_NEW_UPDATE_ITEM; | 40 using syncable::CREATE_NEW_UPDATE_ITEM; |
42 using syncable::CTIME; | 41 using syncable::CTIME; |
43 using syncable::Directory; | 42 using syncable::Directory; |
44 using syncable::Entry; | 43 using syncable::Entry; |
45 using syncable::GET_BY_HANDLE; | 44 using syncable::GET_BY_HANDLE; |
46 using syncable::GET_BY_ID; | 45 using syncable::GET_BY_ID; |
47 using syncable::ID; | 46 using syncable::ID; |
48 using syncable::IS_DEL; | 47 using syncable::IS_DEL; |
49 using syncable::IS_DIR; | 48 using syncable::IS_DIR; |
50 using syncable::IS_UNAPPLIED_UPDATE; | 49 using syncable::IS_UNAPPLIED_UPDATE; |
51 using syncable::IS_UNSYNCED; | 50 using syncable::IS_UNSYNCED; |
52 using syncable::Id; | 51 using syncable::Id; |
53 using syncable::META_HANDLE; | 52 using syncable::META_HANDLE; |
54 using syncable::MTIME; | 53 using syncable::MTIME; |
55 using syncable::MutableEntry; | 54 using syncable::MutableEntry; |
56 using syncable::NON_UNIQUE_NAME; | 55 using syncable::NON_UNIQUE_NAME; |
57 using syncable::BASE_SERVER_SPECIFICS; | |
58 using syncable::PARENT_ID; | 56 using syncable::PARENT_ID; |
59 using syncable::PREV_ID; | |
60 using syncable::SERVER_CTIME; | 57 using syncable::SERVER_CTIME; |
61 using syncable::SERVER_IS_DEL; | 58 using syncable::SERVER_IS_DEL; |
62 using syncable::SERVER_IS_DIR; | 59 using syncable::SERVER_IS_DIR; |
63 using syncable::SERVER_MTIME; | 60 using syncable::SERVER_MTIME; |
64 using syncable::SERVER_NON_UNIQUE_NAME; | 61 using syncable::SERVER_NON_UNIQUE_NAME; |
65 using syncable::SERVER_PARENT_ID; | 62 using syncable::SERVER_PARENT_ID; |
66 using syncable::SERVER_ORDINAL_IN_PARENT; | |
67 using syncable::SERVER_SPECIFICS; | 63 using syncable::SERVER_SPECIFICS; |
| 64 using syncable::SERVER_UNIQUE_POSITION; |
68 using syncable::SERVER_VERSION; | 65 using syncable::SERVER_VERSION; |
69 using syncable::UNIQUE_CLIENT_TAG; | |
70 using syncable::UNIQUE_SERVER_TAG; | |
71 using syncable::SPECIFICS; | 66 using syncable::SPECIFICS; |
72 using syncable::SYNCER; | 67 using syncable::SYNCER; |
| 68 using syncable::UNIQUE_BOOKMARK_TAG; |
| 69 using syncable::UNIQUE_CLIENT_TAG; |
| 70 using syncable::UNIQUE_POSITION; |
| 71 using syncable::UNIQUE_SERVER_TAG; |
73 using syncable::WriteTransaction; | 72 using syncable::WriteTransaction; |
74 | 73 |
75 syncable::Id FindLocalIdToUpdate( | 74 syncable::Id FindLocalIdToUpdate( |
76 syncable::BaseTransaction* trans, | 75 syncable::BaseTransaction* trans, |
77 const sync_pb::SyncEntity& update) { | 76 const sync_pb::SyncEntity& update) { |
78 // Expected entry points of this function: | 77 // Expected entry points of this function: |
79 // SyncEntity has NOT been applied to SERVER fields. | 78 // SyncEntity has NOT been applied to SERVER fields. |
80 // SyncEntity has NOT been applied to LOCAL fields. | 79 // SyncEntity has NOT been applied to LOCAL fields. |
81 // DB has not yet been modified, no entries created for this update. | 80 // DB has not yet been modified, no entries created for this update. |
82 | 81 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 DVLOG(2) << "Received an unencrypted " | 266 DVLOG(2) << "Received an unencrypted " |
268 << ModelTypeToString(entry->GetServerModelType()) | 267 << ModelTypeToString(entry->GetServerModelType()) |
269 << " update, applying normally."; | 268 << " update, applying normally."; |
270 } | 269 } |
271 | 270 |
272 UpdateLocalDataFromServerData(trans, entry); | 271 UpdateLocalDataFromServerData(trans, entry); |
273 | 272 |
274 return SUCCESS; | 273 return SUCCESS; |
275 } | 274 } |
276 | 275 |
| 276 std::string GetUniqueBookmarkTagFromUpdate(const sync_pb::SyncEntity& update) { |
| 277 if (!update.has_originator_cache_guid() || |
| 278 !update.has_originator_client_item_id()) { |
| 279 return ""; |
| 280 } |
| 281 |
| 282 return syncable::GenerateSyncableBookmarkHash( |
| 283 update.originator_cache_guid(), update.originator_client_item_id()); |
| 284 } |
| 285 |
| 286 UniquePosition GetUpdatePosition(const sync_pb::SyncEntity& update, |
| 287 const std::string& suffix) { |
| 288 DCHECK(UniquePosition::IsValidSuffix(suffix)); |
| 289 if (!ShouldMaintainPosition(GetModelType(update))) { |
| 290 return UniquePosition::CreateInvalid(); |
| 291 } else if (update.has_unique_position()) { |
| 292 return UniquePosition::FromBytes(update.unique_position()); |
| 293 } else if (update.has_position_in_parent()) { |
| 294 return UniquePosition::FromInt64(update.position_in_parent(), suffix); |
| 295 } else { |
| 296 return UniquePosition::CreateInvalid(); |
| 297 } |
| 298 } |
| 299 |
277 namespace { | 300 namespace { |
| 301 |
278 // Helper to synthesize a new-style sync_pb::EntitySpecifics for use locally, | 302 // Helper to synthesize a new-style sync_pb::EntitySpecifics for use locally, |
279 // when the server speaks only the old sync_pb::SyncEntity_BookmarkData-based | 303 // when the server speaks only the old sync_pb::SyncEntity_BookmarkData-based |
280 // protocol. | 304 // protocol. |
281 void UpdateBookmarkSpecifics(const std::string& singleton_tag, | 305 void UpdateBookmarkSpecifics(const std::string& singleton_tag, |
282 const std::string& url, | 306 const std::string& url, |
283 const std::string& favicon_bytes, | 307 const std::string& favicon_bytes, |
284 MutableEntry* local_entry) { | 308 MutableEntry* local_entry) { |
285 // In the new-style protocol, the server no longer sends bookmark info for | 309 // In the new-style protocol, the server no longer sends bookmark info for |
286 // the "google_chrome" folder. Mimic that here. | 310 // the "google_chrome" folder. Mimic that here. |
287 if (singleton_tag == "google_chrome") | 311 if (singleton_tag == "google_chrome") |
288 return; | 312 return; |
289 sync_pb::EntitySpecifics pb; | 313 sync_pb::EntitySpecifics pb; |
290 sync_pb::BookmarkSpecifics* bookmark = pb.mutable_bookmark(); | 314 sync_pb::BookmarkSpecifics* bookmark = pb.mutable_bookmark(); |
291 if (!url.empty()) | 315 if (!url.empty()) |
292 bookmark->set_url(url); | 316 bookmark->set_url(url); |
293 if (!favicon_bytes.empty()) | 317 if (!favicon_bytes.empty()) |
294 bookmark->set_favicon(favicon_bytes); | 318 bookmark->set_favicon(favicon_bytes); |
295 local_entry->Put(SERVER_SPECIFICS, pb); | 319 local_entry->Put(SERVER_SPECIFICS, pb); |
296 } | 320 } |
297 | 321 |
298 } // namespace | 322 } // namespace |
299 | 323 |
300 // Pass in name and checksum because of UTF8 conversion. | |
301 void UpdateServerFieldsFromUpdate( | 324 void UpdateServerFieldsFromUpdate( |
302 MutableEntry* target, | 325 MutableEntry* target, |
303 const sync_pb::SyncEntity& update, | 326 const sync_pb::SyncEntity& update, |
304 const std::string& name) { | 327 const std::string& name) { |
305 if (update.deleted()) { | 328 if (update.deleted()) { |
306 if (target->Get(SERVER_IS_DEL)) { | 329 if (target->Get(SERVER_IS_DEL)) { |
307 // If we already think the item is server-deleted, we're done. | 330 // If we already think the item is server-deleted, we're done. |
308 // Skipping these cases prevents our committed deletions from coming | 331 // Skipping these cases prevents our committed deletions from coming |
309 // back and overriding subsequent undeletions. For non-deleted items, | 332 // back and overriding subsequent undeletions. For non-deleted items, |
310 // the version number check has a similar effect. | 333 // the version number check has a similar effect. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 << "Storing unrecognized datatype in sync database."; | 372 << "Storing unrecognized datatype in sync database."; |
350 target->Put(SERVER_SPECIFICS, update.specifics()); | 373 target->Put(SERVER_SPECIFICS, update.specifics()); |
351 } else if (update.has_bookmarkdata()) { | 374 } else if (update.has_bookmarkdata()) { |
352 // Legacy protocol response for bookmark data. | 375 // Legacy protocol response for bookmark data. |
353 const sync_pb::SyncEntity::BookmarkData& bookmark = update.bookmarkdata(); | 376 const sync_pb::SyncEntity::BookmarkData& bookmark = update.bookmarkdata(); |
354 UpdateBookmarkSpecifics(update.server_defined_unique_tag(), | 377 UpdateBookmarkSpecifics(update.server_defined_unique_tag(), |
355 bookmark.bookmark_url(), | 378 bookmark.bookmark_url(), |
356 bookmark.bookmark_favicon(), | 379 bookmark.bookmark_favicon(), |
357 target); | 380 target); |
358 } | 381 } |
359 if (update.has_position_in_parent()) | 382 if (GetModelType(update) == BOOKMARKS && |
360 target->Put(SERVER_ORDINAL_IN_PARENT, | 383 !update.has_server_defined_unique_tag()) { |
361 Int64ToNodeOrdinal(update.position_in_parent())); | 384 // Update our unique bookmark tag. This is usually unnecessary, but there |
| 385 // will be some legacy bookmarks out theere with less than ideal tags. |
| 386 // This will fix them, eventually. |
| 387 std::string bookmark_tag = GetUniqueBookmarkTagFromUpdate(update); |
| 388 if (UniquePosition::IsValidSuffix(bookmark_tag)) { |
| 389 target->PutUniqueBookmarkTag(bookmark_tag); |
| 390 } |
| 391 |
| 392 // Update our position. |
| 393 UniquePosition update_pos = |
| 394 GetUpdatePosition(update, target->Get(UNIQUE_BOOKMARK_TAG)); |
| 395 if (update_pos.IsValid()) |
| 396 target->Put(syncable::SERVER_UNIQUE_POSITION, update_pos); |
| 397 // TODO(rlarocque): Throw an UnrecoverableError if this fails. |
| 398 } |
362 | 399 |
363 target->Put(SERVER_IS_DEL, update.deleted()); | 400 target->Put(SERVER_IS_DEL, update.deleted()); |
364 // We only mark the entry as unapplied if its version is greater than the | 401 // We only mark the entry as unapplied if its version is greater than the |
365 // local data. If we're processing the update that corresponds to one of our | 402 // local data. If we're processing the update that corresponds to one of our |
366 // commit we don't apply it as time differences may occur. | 403 // commit we don't apply it as time differences may occur. |
367 if (update.version() > target->Get(BASE_VERSION)) { | 404 if (update.version() > target->Get(BASE_VERSION)) { |
368 target->Put(IS_UNAPPLIED_UPDATE, true); | 405 target->Put(IS_UNAPPLIED_UPDATE, true); |
369 } | 406 } |
370 } | 407 } |
371 | 408 |
372 // Creates a new Entry iff no Entry exists with the given id. | 409 // Creates a new Entry iff no Entry exists with the given id. |
373 void CreateNewEntry(syncable::WriteTransaction *trans, | 410 void CreateNewEntry(syncable::WriteTransaction *trans, |
374 const syncable::Id& id) { | 411 const syncable::Id& id) { |
375 syncable::MutableEntry entry(trans, GET_BY_ID, id); | 412 syncable::MutableEntry entry(trans, GET_BY_ID, id); |
376 if (!entry.good()) { | 413 if (!entry.good()) { |
377 syncable::MutableEntry new_entry(trans, syncable::CREATE_NEW_UPDATE_ITEM, | 414 syncable::MutableEntry new_entry(trans, syncable::CREATE_NEW_UPDATE_ITEM, |
378 id); | 415 id); |
379 } | 416 } |
380 } | 417 } |
381 | 418 |
382 void SplitServerInformationIntoNewEntry( | |
383 syncable::WriteTransaction* trans, | |
384 syncable::MutableEntry* entry) { | |
385 syncable::Id id = entry->Get(ID); | |
386 ChangeEntryIDAndUpdateChildren(trans, entry, trans->directory()->NextId()); | |
387 entry->Put(BASE_VERSION, 0); | |
388 | |
389 MutableEntry new_entry(trans, CREATE_NEW_UPDATE_ITEM, id); | |
390 CopyServerFields(entry, &new_entry); | |
391 ClearServerData(entry); | |
392 | |
393 DVLOG(1) << "Splitting server information, local entry: " << *entry | |
394 << " server entry: " << new_entry; | |
395 } | |
396 | |
397 // This function is called on an entry when we can update the user-facing data | 419 // This function is called on an entry when we can update the user-facing data |
398 // from the server data. | 420 // from the server data. |
399 void UpdateLocalDataFromServerData( | 421 void UpdateLocalDataFromServerData( |
400 syncable::WriteTransaction* trans, | 422 syncable::WriteTransaction* trans, |
401 syncable::MutableEntry* entry) { | 423 syncable::MutableEntry* entry) { |
402 DCHECK(!entry->Get(IS_UNSYNCED)); | 424 DCHECK(!entry->Get(IS_UNSYNCED)); |
403 DCHECK(entry->Get(IS_UNAPPLIED_UPDATE)); | 425 DCHECK(entry->Get(IS_UNAPPLIED_UPDATE)); |
404 | 426 |
405 DVLOG(2) << "Updating entry : " << *entry; | 427 DVLOG(2) << "Updating entry : " << *entry; |
406 // Start by setting the properties that determine the model_type. | 428 // Start by setting the properties that determine the model_type. |
407 entry->Put(SPECIFICS, entry->Get(SERVER_SPECIFICS)); | 429 entry->Put(SPECIFICS, entry->Get(SERVER_SPECIFICS)); |
408 // Clear the previous server specifics now that we're applying successfully. | 430 // Clear the previous server specifics now that we're applying successfully. |
409 entry->Put(BASE_SERVER_SPECIFICS, sync_pb::EntitySpecifics()); | 431 entry->Put(BASE_SERVER_SPECIFICS, sync_pb::EntitySpecifics()); |
410 entry->Put(IS_DIR, entry->Get(SERVER_IS_DIR)); | 432 entry->Put(IS_DIR, entry->Get(SERVER_IS_DIR)); |
411 // This strange dance around the IS_DEL flag avoids problems when setting | 433 // This strange dance around the IS_DEL flag avoids problems when setting |
412 // the name. | 434 // the name. |
413 // TODO(chron): Is this still an issue? Unit test this codepath. | 435 // TODO(chron): Is this still an issue? Unit test this codepath. |
414 if (entry->Get(SERVER_IS_DEL)) { | 436 if (entry->Get(SERVER_IS_DEL)) { |
415 entry->Put(IS_DEL, true); | 437 entry->Put(IS_DEL, true); |
416 } else { | 438 } else { |
417 entry->Put(NON_UNIQUE_NAME, entry->Get(SERVER_NON_UNIQUE_NAME)); | 439 entry->Put(NON_UNIQUE_NAME, entry->Get(SERVER_NON_UNIQUE_NAME)); |
418 entry->Put(PARENT_ID, entry->Get(SERVER_PARENT_ID)); | 440 entry->Put(PARENT_ID, entry->Get(SERVER_PARENT_ID)); |
| 441 entry->Put(UNIQUE_POSITION, entry->Get(SERVER_UNIQUE_POSITION)); |
419 CHECK(entry->Put(IS_DEL, false)); | 442 CHECK(entry->Put(IS_DEL, false)); |
420 Id new_predecessor = | |
421 entry->ComputePrevIdFromServerPosition(entry->Get(SERVER_PARENT_ID)); | |
422 CHECK(entry->PutPredecessor(new_predecessor)) | |
423 << " Illegal predecessor after converting from server position."; | |
424 } | 443 } |
425 | 444 |
426 entry->Put(CTIME, entry->Get(SERVER_CTIME)); | 445 entry->Put(CTIME, entry->Get(SERVER_CTIME)); |
427 entry->Put(MTIME, entry->Get(SERVER_MTIME)); | 446 entry->Put(MTIME, entry->Get(SERVER_MTIME)); |
428 entry->Put(BASE_VERSION, entry->Get(SERVER_VERSION)); | 447 entry->Put(BASE_VERSION, entry->Get(SERVER_VERSION)); |
429 entry->Put(IS_DEL, entry->Get(SERVER_IS_DEL)); | 448 entry->Put(IS_DEL, entry->Get(SERVER_IS_DEL)); |
430 entry->Put(IS_UNAPPLIED_UPDATE, false); | 449 entry->Put(IS_UNAPPLIED_UPDATE, false); |
431 } | 450 } |
432 | 451 |
433 VerifyCommitResult ValidateCommitEntry(syncable::Entry* entry) { | 452 VerifyCommitResult ValidateCommitEntry(syncable::Entry* entry) { |
434 syncable::Id id = entry->Get(ID); | 453 syncable::Id id = entry->Get(ID); |
435 if (id == entry->Get(PARENT_ID)) { | 454 if (id == entry->Get(PARENT_ID)) { |
436 CHECK(id.IsRoot()) << "Non-root item is self parenting." << *entry; | 455 CHECK(id.IsRoot()) << "Non-root item is self parenting." << *entry; |
437 // If the root becomes unsynced it can cause us problems. | 456 // If the root becomes unsynced it can cause us problems. |
438 LOG(ERROR) << "Root item became unsynced " << *entry; | 457 LOG(ERROR) << "Root item became unsynced " << *entry; |
439 return VERIFY_UNSYNCABLE; | 458 return VERIFY_UNSYNCABLE; |
440 } | 459 } |
441 if (entry->IsRoot()) { | 460 if (entry->IsRoot()) { |
442 LOG(ERROR) << "Permanent item became unsynced " << *entry; | 461 LOG(ERROR) << "Permanent item became unsynced " << *entry; |
443 return VERIFY_UNSYNCABLE; | 462 return VERIFY_UNSYNCABLE; |
444 } | 463 } |
445 if (entry->Get(IS_DEL) && !entry->Get(ID).ServerKnows()) { | 464 if (entry->Get(IS_DEL) && !entry->Get(ID).ServerKnows()) { |
446 // Drop deleted uncommitted entries. | 465 // Drop deleted uncommitted entries. |
447 return VERIFY_UNSYNCABLE; | 466 return VERIFY_UNSYNCABLE; |
448 } | 467 } |
449 return VERIFY_OK; | 468 return VERIFY_OK; |
450 } | 469 } |
451 | 470 |
452 bool AddItemThenPredecessors( | |
453 syncable::BaseTransaction* trans, | |
454 syncable::Entry* item, | |
455 syncable::IndexedBitField inclusion_filter, | |
456 syncable::MetahandleSet* inserted_items, | |
457 std::vector<syncable::Id>* commit_ids) { | |
458 | |
459 if (!inserted_items->insert(item->Get(META_HANDLE)).second) | |
460 return false; | |
461 commit_ids->push_back(item->Get(ID)); | |
462 if (item->Get(IS_DEL)) | |
463 return true; // Deleted items have no predecessors. | |
464 | |
465 Id prev_id = item->Get(PREV_ID); | |
466 while (!prev_id.IsRoot()) { | |
467 Entry prev(trans, GET_BY_ID, prev_id); | |
468 CHECK(prev.good()) << "Bad id when walking predecessors."; | |
469 if (!prev.Get(inclusion_filter)) | |
470 break; | |
471 if (!inserted_items->insert(prev.Get(META_HANDLE)).second) | |
472 break; | |
473 commit_ids->push_back(prev_id); | |
474 prev_id = prev.Get(PREV_ID); | |
475 } | |
476 return true; | |
477 } | |
478 | |
479 void AddPredecessorsThenItem( | |
480 syncable::BaseTransaction* trans, | |
481 syncable::Entry* item, | |
482 syncable::IndexedBitField inclusion_filter, | |
483 syncable::MetahandleSet* inserted_items, | |
484 std::vector<syncable::Id>* commit_ids) { | |
485 size_t initial_size = commit_ids->size(); | |
486 if (!AddItemThenPredecessors(trans, item, inclusion_filter, inserted_items, | |
487 commit_ids)) | |
488 return; | |
489 // Reverse what we added to get the correct order. | |
490 std::reverse(commit_ids->begin() + initial_size, commit_ids->end()); | |
491 } | |
492 | |
493 void MarkDeletedChildrenSynced( | 471 void MarkDeletedChildrenSynced( |
494 syncable::Directory* dir, | 472 syncable::Directory* dir, |
495 std::set<syncable::Id>* deleted_folders) { | 473 std::set<syncable::Id>* deleted_folders) { |
496 // There's two options here. | 474 // There's two options here. |
497 // 1. Scan deleted unsynced entries looking up their pre-delete tree for any | 475 // 1. Scan deleted unsynced entries looking up their pre-delete tree for any |
498 // of the deleted folders. | 476 // of the deleted folders. |
499 // 2. Take each folder and do a tree walk of all entries underneath it. | 477 // 2. Take each folder and do a tree walk of all entries underneath it. |
500 // #2 has a lower big O cost, but writing code to limit the time spent inside | 478 // #2 has a lower big O cost, but writing code to limit the time spent inside |
501 // the transaction during each step is simpler with 1. Changing this decision | 479 // the transaction during each step is simpler with 1. Changing this decision |
502 // may be sensible if this code shows up in profiling. | 480 // may be sensible if this code shows up in profiling. |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 if (update.version() < target->Get(SERVER_VERSION)) { | 629 if (update.version() < target->Get(SERVER_VERSION)) { |
652 LOG(WARNING) << "Update older than current server version for " | 630 LOG(WARNING) << "Update older than current server version for " |
653 << *target << " Update:" | 631 << *target << " Update:" |
654 << SyncerProtoUtil::SyncEntityDebugString(update); | 632 << SyncerProtoUtil::SyncEntityDebugString(update); |
655 return VERIFY_SUCCESS; // Expected in new sync protocol. | 633 return VERIFY_SUCCESS; // Expected in new sync protocol. |
656 } | 634 } |
657 return VERIFY_UNDECIDED; | 635 return VERIFY_UNDECIDED; |
658 } | 636 } |
659 | 637 |
660 } // namespace syncer | 638 } // namespace syncer |
OLD | NEW |