| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/syncable/directory.h" | 5 #include "sync/syncable/directory.h" |
| 6 | 6 |
| 7 #include <iterator> | 7 #include <iterator> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 13 #include "sync/internal_api/public/base/attachment_id_proto.h" | |
| 14 #include "sync/internal_api/public/base/unique_position.h" | 13 #include "sync/internal_api/public/base/unique_position.h" |
| 15 #include "sync/internal_api/public/util/unrecoverable_error_handler.h" | 14 #include "sync/internal_api/public/util/unrecoverable_error_handler.h" |
| 16 #include "sync/syncable/entry.h" | 15 #include "sync/syncable/entry.h" |
| 17 #include "sync/syncable/entry_kernel.h" | 16 #include "sync/syncable/entry_kernel.h" |
| 18 #include "sync/syncable/in_memory_directory_backing_store.h" | 17 #include "sync/syncable/in_memory_directory_backing_store.h" |
| 19 #include "sync/syncable/on_disk_directory_backing_store.h" | 18 #include "sync/syncable/on_disk_directory_backing_store.h" |
| 20 #include "sync/syncable/scoped_kernel_lock.h" | 19 #include "sync/syncable/scoped_kernel_lock.h" |
| 21 #include "sync/syncable/scoped_parent_child_index_updater.h" | 20 #include "sync/syncable/scoped_parent_child_index_updater.h" |
| 22 #include "sync/syncable/syncable-inl.h" | 21 #include "sync/syncable/syncable-inl.h" |
| 23 #include "sync/syncable/syncable_base_transaction.h" | 22 #include "sync/syncable/syncable_base_transaction.h" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 116 |
| 118 const DirOpenResult result = | 117 const DirOpenResult result = |
| 119 OpenImpl(name, delegate, transaction_observer); | 118 OpenImpl(name, delegate, transaction_observer); |
| 120 | 119 |
| 121 if (OPENED != result) | 120 if (OPENED != result) |
| 122 Close(); | 121 Close(); |
| 123 return result; | 122 return result; |
| 124 } | 123 } |
| 125 | 124 |
| 126 void Directory::InitializeIndices(MetahandlesMap* handles_map) { | 125 void Directory::InitializeIndices(MetahandlesMap* handles_map) { |
| 127 ScopedKernelLock lock(this); | |
| 128 kernel_->metahandles_map.swap(*handles_map); | 126 kernel_->metahandles_map.swap(*handles_map); |
| 129 for (MetahandlesMap::const_iterator it = kernel_->metahandles_map.begin(); | 127 for (MetahandlesMap::const_iterator it = kernel_->metahandles_map.begin(); |
| 130 it != kernel_->metahandles_map.end(); ++it) { | 128 it != kernel_->metahandles_map.end(); ++it) { |
| 131 EntryKernel* entry = it->second; | 129 EntryKernel* entry = it->second; |
| 132 if (ParentChildIndex::ShouldInclude(entry)) | 130 if (ParentChildIndex::ShouldInclude(entry)) |
| 133 kernel_->parent_child_index.Insert(entry); | 131 kernel_->parent_child_index.Insert(entry); |
| 134 const int64 metahandle = entry->ref(META_HANDLE); | 132 const int64 metahandle = entry->ref(META_HANDLE); |
| 135 if (entry->ref(IS_UNSYNCED)) | 133 if (entry->ref(IS_UNSYNCED)) |
| 136 kernel_->unsynced_metahandles.insert(metahandle); | 134 kernel_->unsynced_metahandles.insert(metahandle); |
| 137 if (entry->ref(IS_UNAPPLIED_UPDATE)) { | 135 if (entry->ref(IS_UNAPPLIED_UPDATE)) { |
| 138 const ModelType type = entry->GetServerModelType(); | 136 const ModelType type = entry->GetServerModelType(); |
| 139 kernel_->unapplied_update_metahandles[type].insert(metahandle); | 137 kernel_->unapplied_update_metahandles[type].insert(metahandle); |
| 140 } | 138 } |
| 141 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { | 139 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { |
| 142 DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == | 140 DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == |
| 143 kernel_->server_tags_map.end()) | 141 kernel_->server_tags_map.end()) |
| 144 << "Unexpected duplicate use of client tag"; | 142 << "Unexpected duplicate use of client tag"; |
| 145 kernel_->server_tags_map[entry->ref(UNIQUE_SERVER_TAG)] = entry; | 143 kernel_->server_tags_map[entry->ref(UNIQUE_SERVER_TAG)] = entry; |
| 146 } | 144 } |
| 147 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { | 145 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { |
| 148 DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == | 146 DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == |
| 149 kernel_->server_tags_map.end()) | 147 kernel_->server_tags_map.end()) |
| 150 << "Unexpected duplicate use of server tag"; | 148 << "Unexpected duplicate use of server tag"; |
| 151 kernel_->client_tags_map[entry->ref(UNIQUE_CLIENT_TAG)] = entry; | 149 kernel_->client_tags_map[entry->ref(UNIQUE_CLIENT_TAG)] = entry; |
| 152 } | 150 } |
| 153 DCHECK(kernel_->ids_map.find(entry->ref(ID).value()) == | 151 DCHECK(kernel_->ids_map.find(entry->ref(ID).value()) == |
| 154 kernel_->ids_map.end()) << "Unexpected duplicate use of ID"; | 152 kernel_->ids_map.end()) << "Unexpected duplicate use of ID"; |
| 155 kernel_->ids_map[entry->ref(ID).value()] = entry; | 153 kernel_->ids_map[entry->ref(ID).value()] = entry; |
| 156 DCHECK(!entry->is_dirty()); | 154 DCHECK(!entry->is_dirty()); |
| 157 AddToAttachmentIndex(metahandle, entry->ref(ATTACHMENT_METADATA), lock); | |
| 158 } | 155 } |
| 159 } | 156 } |
| 160 | 157 |
| 161 DirOpenResult Directory::OpenImpl( | 158 DirOpenResult Directory::OpenImpl( |
| 162 const string& name, | 159 const string& name, |
| 163 DirectoryChangeDelegate* delegate, | 160 DirectoryChangeDelegate* delegate, |
| 164 const WeakHandle<TransactionObserver>& | 161 const WeakHandle<TransactionObserver>& |
| 165 transaction_observer) { | 162 transaction_observer) { |
| 166 KernelLoadInfo info; | 163 KernelLoadInfo info; |
| 167 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) | 164 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 return false; | 355 return false; |
| 359 } | 356 } |
| 360 if (ParentChildIndex::ShouldInclude(entry)) { | 357 if (ParentChildIndex::ShouldInclude(entry)) { |
| 361 if (!SyncAssert(kernel_->parent_child_index.Insert(entry), | 358 if (!SyncAssert(kernel_->parent_child_index.Insert(entry), |
| 362 FROM_HERE, | 359 FROM_HERE, |
| 363 error, | 360 error, |
| 364 trans)) { | 361 trans)) { |
| 365 return false; | 362 return false; |
| 366 } | 363 } |
| 367 } | 364 } |
| 368 AddToAttachmentIndex( | |
| 369 entry->ref(META_HANDLE), entry->ref(ATTACHMENT_METADATA), *lock); | |
| 370 | 365 |
| 371 // Should NEVER be created with a client tag or server tag. | 366 // Should NEVER be created with a client tag or server tag. |
| 372 if (!SyncAssert(entry->ref(UNIQUE_SERVER_TAG).empty(), FROM_HERE, | 367 if (!SyncAssert(entry->ref(UNIQUE_SERVER_TAG).empty(), FROM_HERE, |
| 373 "Server tag should be empty", trans)) { | 368 "Server tag should be empty", trans)) { |
| 374 return false; | 369 return false; |
| 375 } | 370 } |
| 376 if (!SyncAssert(entry->ref(UNIQUE_CLIENT_TAG).empty(), FROM_HERE, | 371 if (!SyncAssert(entry->ref(UNIQUE_CLIENT_TAG).empty(), FROM_HERE, |
| 377 "Client tag should be empty", trans)) | 372 "Client tag should be empty", trans)) |
| 378 return false; | 373 return false; |
| 379 | 374 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 406 | 401 |
| 407 { | 402 { |
| 408 // Update the indices that depend on the PARENT_ID field. | 403 // Update the indices that depend on the PARENT_ID field. |
| 409 ScopedParentChildIndexUpdater index_updater(lock, entry, | 404 ScopedParentChildIndexUpdater index_updater(lock, entry, |
| 410 &kernel_->parent_child_index); | 405 &kernel_->parent_child_index); |
| 411 entry->put(PARENT_ID, new_parent_id); | 406 entry->put(PARENT_ID, new_parent_id); |
| 412 } | 407 } |
| 413 return true; | 408 return true; |
| 414 } | 409 } |
| 415 | 410 |
| 416 void Directory::RemoveFromAttachmentIndex( | |
| 417 const int64 metahandle, | |
| 418 const sync_pb::AttachmentMetadata& attachment_metadata, | |
| 419 const ScopedKernelLock& lock) { | |
| 420 for (int i = 0; i < attachment_metadata.record_size(); ++i) { | |
| 421 AttachmentIdUniqueId unique_id = | |
| 422 attachment_metadata.record(i).id().unique_id(); | |
| 423 IndexByAttachmentId::iterator iter = | |
| 424 kernel_->index_by_attachment_id.find(unique_id); | |
| 425 if (iter != kernel_->index_by_attachment_id.end()) { | |
| 426 iter->second.erase(metahandle); | |
| 427 if (iter->second.empty()) { | |
| 428 kernel_->index_by_attachment_id.erase(iter); | |
| 429 } | |
| 430 } | |
| 431 } | |
| 432 } | |
| 433 | |
| 434 void Directory::AddToAttachmentIndex( | |
| 435 const int64 metahandle, | |
| 436 const sync_pb::AttachmentMetadata& attachment_metadata, | |
| 437 const ScopedKernelLock& lock) { | |
| 438 for (int i = 0; i < attachment_metadata.record_size(); ++i) { | |
| 439 AttachmentIdUniqueId unique_id = | |
| 440 attachment_metadata.record(i).id().unique_id(); | |
| 441 IndexByAttachmentId::iterator iter = | |
| 442 kernel_->index_by_attachment_id.find(unique_id); | |
| 443 if (iter == kernel_->index_by_attachment_id.end()) { | |
| 444 iter = kernel_->index_by_attachment_id.insert(std::make_pair( | |
| 445 unique_id, | |
| 446 MetahandleSet())).first; | |
| 447 } | |
| 448 iter->second.insert(metahandle); | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 void Directory::UpdateAttachmentIndex( | |
| 453 const int64 metahandle, | |
| 454 const sync_pb::AttachmentMetadata& old_metadata, | |
| 455 const sync_pb::AttachmentMetadata& new_metadata) { | |
| 456 ScopedKernelLock lock(this); | |
| 457 RemoveFromAttachmentIndex(metahandle, old_metadata, lock); | |
| 458 AddToAttachmentIndex(metahandle, new_metadata, lock); | |
| 459 } | |
| 460 | |
| 461 bool Directory::unrecoverable_error_set(const BaseTransaction* trans) const { | 411 bool Directory::unrecoverable_error_set(const BaseTransaction* trans) const { |
| 462 DCHECK(trans != NULL); | 412 DCHECK(trans != NULL); |
| 463 return unrecoverable_error_set_; | 413 return unrecoverable_error_set_; |
| 464 } | 414 } |
| 465 | 415 |
| 466 void Directory::ClearDirtyMetahandles() { | 416 void Directory::ClearDirtyMetahandles() { |
| 467 kernel_->transaction_mutex.AssertAcquired(); | 417 kernel_->transaction_mutex.AssertAcquired(); |
| 468 kernel_->dirty_metahandles.clear(); | 418 kernel_->dirty_metahandles.clear(); |
| 469 } | 419 } |
| 470 | 420 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { | 541 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { |
| 592 num_erased = | 542 num_erased = |
| 593 kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); | 543 kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); |
| 594 DCHECK_EQ(1u, num_erased); | 544 DCHECK_EQ(1u, num_erased); |
| 595 } | 545 } |
| 596 if (!SyncAssert(!kernel_->parent_child_index.Contains(entry), | 546 if (!SyncAssert(!kernel_->parent_child_index.Contains(entry), |
| 597 FROM_HERE, | 547 FROM_HERE, |
| 598 "Deleted entry still present", | 548 "Deleted entry still present", |
| 599 (&trans))) | 549 (&trans))) |
| 600 return false; | 550 return false; |
| 601 RemoveFromAttachmentIndex( | |
| 602 entry->ref(META_HANDLE), entry->ref(ATTACHMENT_METADATA), lock); | |
| 603 | |
| 604 delete entry; | 551 delete entry; |
| 605 } | 552 } |
| 606 if (trans.unrecoverable_error_set()) | 553 if (trans.unrecoverable_error_set()) |
| 607 return false; | 554 return false; |
| 608 } | 555 } |
| 609 return true; | 556 return true; |
| 610 } | 557 } |
| 611 | 558 |
| 612 void Directory::UnapplyEntry(EntryKernel* entry) { | 559 void Directory::UnapplyEntry(EntryKernel* entry) { |
| 613 int64 handle = entry->ref(META_HANDLE); | 560 int64 handle = entry->ref(META_HANDLE); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 } | 600 } |
| 654 | 601 |
| 655 // At this point locally created items that aren't synced will become locally | 602 // At this point locally created items that aren't synced will become locally |
| 656 // deleted items, and purged on the next snapshot. All other items will match | 603 // deleted items, and purged on the next snapshot. All other items will match |
| 657 // the state they would have had if they were just created via a server | 604 // the state they would have had if they were just created via a server |
| 658 // update. See MutableEntry::MutableEntry(.., CreateNewUpdateItem, ..). | 605 // update. See MutableEntry::MutableEntry(.., CreateNewUpdateItem, ..). |
| 659 } | 606 } |
| 660 | 607 |
| 661 void Directory::DeleteEntry(bool save_to_journal, | 608 void Directory::DeleteEntry(bool save_to_journal, |
| 662 EntryKernel* entry, | 609 EntryKernel* entry, |
| 663 EntryKernelSet* entries_to_journal, | 610 EntryKernelSet* entries_to_journal) { |
| 664 const ScopedKernelLock& lock) { | |
| 665 int64 handle = entry->ref(META_HANDLE); | 611 int64 handle = entry->ref(META_HANDLE); |
| 666 ModelType server_type = GetModelTypeFromSpecifics( | 612 ModelType server_type = GetModelTypeFromSpecifics( |
| 667 entry->ref(SERVER_SPECIFICS)); | 613 entry->ref(SERVER_SPECIFICS)); |
| 668 | 614 |
| 669 kernel_->metahandles_to_purge.insert(handle); | 615 kernel_->metahandles_to_purge.insert(handle); |
| 670 | 616 |
| 671 size_t num_erased = 0; | 617 size_t num_erased = 0; |
| 672 num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); | 618 num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); |
| 673 DCHECK_EQ(1u, num_erased); | 619 DCHECK_EQ(1u, num_erased); |
| 674 num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); | 620 num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); |
| 675 DCHECK_EQ(1u, num_erased); | 621 DCHECK_EQ(1u, num_erased); |
| 676 num_erased = kernel_->unsynced_metahandles.erase(handle); | 622 num_erased = kernel_->unsynced_metahandles.erase(handle); |
| 677 DCHECK_EQ(entry->ref(IS_UNSYNCED), num_erased > 0); | 623 DCHECK_EQ(entry->ref(IS_UNSYNCED), num_erased > 0); |
| 678 num_erased = | 624 num_erased = |
| 679 kernel_->unapplied_update_metahandles[server_type].erase(handle); | 625 kernel_->unapplied_update_metahandles[server_type].erase(handle); |
| 680 DCHECK_EQ(entry->ref(IS_UNAPPLIED_UPDATE), num_erased > 0); | 626 DCHECK_EQ(entry->ref(IS_UNAPPLIED_UPDATE), num_erased > 0); |
| 681 if (kernel_->parent_child_index.Contains(entry)) | 627 if (kernel_->parent_child_index.Contains(entry)) |
| 682 kernel_->parent_child_index.Remove(entry); | 628 kernel_->parent_child_index.Remove(entry); |
| 683 | 629 |
| 684 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { | 630 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { |
| 685 num_erased = | 631 num_erased = |
| 686 kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); | 632 kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); |
| 687 DCHECK_EQ(1u, num_erased); | 633 DCHECK_EQ(1u, num_erased); |
| 688 } | 634 } |
| 689 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { | 635 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { |
| 690 num_erased = | 636 num_erased = |
| 691 kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); | 637 kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); |
| 692 DCHECK_EQ(1u, num_erased); | 638 DCHECK_EQ(1u, num_erased); |
| 693 } | 639 } |
| 694 RemoveFromAttachmentIndex(handle, entry->ref(ATTACHMENT_METADATA), lock); | |
| 695 | 640 |
| 696 if (save_to_journal) { | 641 if (save_to_journal) { |
| 697 entries_to_journal->insert(entry); | 642 entries_to_journal->insert(entry); |
| 698 } else { | 643 } else { |
| 699 delete entry; | 644 delete entry; |
| 700 } | 645 } |
| 701 } | 646 } |
| 702 | 647 |
| 703 bool Directory::PurgeEntriesWithTypeIn(ModelTypeSet disabled_types, | 648 bool Directory::PurgeEntriesWithTypeIn(ModelTypeSet disabled_types, |
| 704 ModelTypeSet types_to_journal, | 649 ModelTypeSet types_to_journal, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 | 697 |
| 753 if (types_to_unapply.Has(local_type) || | 698 if (types_to_unapply.Has(local_type) || |
| 754 types_to_unapply.Has(server_type)) { | 699 types_to_unapply.Has(server_type)) { |
| 755 UnapplyEntry(entry); | 700 UnapplyEntry(entry); |
| 756 } else { | 701 } else { |
| 757 bool save_to_journal = | 702 bool save_to_journal = |
| 758 (types_to_journal.Has(local_type) || | 703 (types_to_journal.Has(local_type) || |
| 759 types_to_journal.Has(server_type)) && | 704 types_to_journal.Has(server_type)) && |
| 760 (delete_journal_->IsDeleteJournalEnabled(local_type) || | 705 (delete_journal_->IsDeleteJournalEnabled(local_type) || |
| 761 delete_journal_->IsDeleteJournalEnabled(server_type)); | 706 delete_journal_->IsDeleteJournalEnabled(server_type)); |
| 762 DeleteEntry(save_to_journal, entry, &entries_to_journal, lock); | 707 DeleteEntry(save_to_journal, entry, &entries_to_journal); |
| 763 } | 708 } |
| 764 } | 709 } |
| 765 | 710 |
| 766 delete_journal_->AddJournalBatch(&trans, entries_to_journal); | 711 delete_journal_->AddJournalBatch(&trans, entries_to_journal); |
| 767 | 712 |
| 768 // Ensure meta tracking for these data types reflects the purged state. | 713 // Ensure meta tracking for these data types reflects the purged state. |
| 769 for (ModelTypeSet::Iterator it = disabled_types.First(); | 714 for (ModelTypeSet::Iterator it = disabled_types.First(); |
| 770 it.Good(); it.Inc()) { | 715 it.Good(); it.Inc()) { |
| 771 kernel_->persisted_info.transaction_version[it.Get()] = 0; | 716 kernel_->persisted_info.transaction_version[it.Get()] = 0; |
| 772 | 717 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 810 | 755 |
| 811 // Note that we do not unset IS_UNSYNCED or IS_UNAPPLIED_UPDATE in order | 756 // Note that we do not unset IS_UNSYNCED or IS_UNAPPLIED_UPDATE in order |
| 812 // to ensure no in-transit data is lost. | 757 // to ensure no in-transit data is lost. |
| 813 | 758 |
| 814 entry->mark_dirty(&kernel_->dirty_metahandles); | 759 entry->mark_dirty(&kernel_->dirty_metahandles); |
| 815 } | 760 } |
| 816 | 761 |
| 817 return true; | 762 return true; |
| 818 } | 763 } |
| 819 | 764 |
| 820 bool Directory::IsAttachmentLinked( | |
| 821 const sync_pb::AttachmentIdProto& attachment_id_proto) const { | |
| 822 ScopedKernelLock lock(this); | |
| 823 IndexByAttachmentId::const_iterator iter = | |
| 824 kernel_->index_by_attachment_id.find(attachment_id_proto.unique_id()); | |
| 825 if (iter != kernel_->index_by_attachment_id.end() && !iter->second.empty()) { | |
| 826 return true; | |
| 827 } | |
| 828 return false; | |
| 829 } | |
| 830 | |
| 831 void Directory::HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot) { | 765 void Directory::HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot) { |
| 832 WriteTransaction trans(FROM_HERE, HANDLE_SAVE_FAILURE, this); | 766 WriteTransaction trans(FROM_HERE, HANDLE_SAVE_FAILURE, this); |
| 833 ScopedKernelLock lock(this); | 767 ScopedKernelLock lock(this); |
| 834 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 768 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
| 835 | 769 |
| 836 // Because we optimistically cleared the dirty bit on the real entries when | 770 // Because we optimistically cleared the dirty bit on the real entries when |
| 837 // taking the snapshot, we must restore it on failure. Not doing this could | 771 // taking the snapshot, we must restore it on failure. Not doing this could |
| 838 // cause lost data, if no other changes are made to the in-memory entries | 772 // cause lost data, if no other changes are made to the in-memory entries |
| 839 // that would cause the dirty bit to get set again. Setting the bit ensures | 773 // that would cause the dirty bit to get set again. Setting the bit ensures |
| 840 // that SaveChanges will at least try again later. | 774 // that SaveChanges will at least try again later. |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1422 | 1356 |
| 1423 for (OrderedChildSet::const_iterator i = children->begin(); | 1357 for (OrderedChildSet::const_iterator i = children->begin(); |
| 1424 i != children->end(); ++i) { | 1358 i != children->end(); ++i) { |
| 1425 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); | 1359 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); |
| 1426 result->push_back((*i)->ref(META_HANDLE)); | 1360 result->push_back((*i)->ref(META_HANDLE)); |
| 1427 } | 1361 } |
| 1428 } | 1362 } |
| 1429 | 1363 |
| 1430 } // namespace syncable | 1364 } // namespace syncable |
| 1431 } // namespace syncer | 1365 } // namespace syncer |
| OLD | NEW |