Chromium Code Reviews| 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 "components/sync/syncable/directory.h" | 5 #include "components/sync/syncable/directory.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <iterator> | 11 #include <iterator> |
| 12 #include <utility> | 12 #include <utility> |
| 13 | 13 |
| 14 #include "base/base64.h" | 14 #include "base/base64.h" |
| 15 #include "base/guid.h" | 15 #include "base/guid.h" |
| 16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
| 17 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
| 18 #include "base/stl_util.h" | |
| 19 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/trace_event/trace_event.h" | 19 #include "base/trace_event/trace_event.h" |
| 21 #include "components/sync/base/attachment_id_proto.h" | 20 #include "components/sync/base/attachment_id_proto.h" |
| 22 #include "components/sync/base/unique_position.h" | 21 #include "components/sync/base/unique_position.h" |
| 23 #include "components/sync/base/unrecoverable_error_handler.h" | 22 #include "components/sync/base/unrecoverable_error_handler.h" |
| 24 #include "components/sync/syncable/entry.h" | 23 #include "components/sync/syncable/entry.h" |
| 25 #include "components/sync/syncable/entry_kernel.h" | 24 #include "components/sync/syncable/entry_kernel.h" |
| 26 #include "components/sync/syncable/in_memory_directory_backing_store.h" | 25 #include "components/sync/syncable/in_memory_directory_backing_store.h" |
| 27 #include "components/sync/syncable/model_neutral_mutable_entry.h" | 26 #include "components/sync/syncable/model_neutral_mutable_entry.h" |
| 28 #include "components/sync/syncable/on_disk_directory_backing_store.h" | 27 #include "components/sync/syncable/on_disk_directory_backing_store.h" |
| 29 #include "components/sync/syncable/scoped_kernel_lock.h" | 28 #include "components/sync/syncable/scoped_kernel_lock.h" |
| 30 #include "components/sync/syncable/scoped_parent_child_index_updater.h" | 29 #include "components/sync/syncable/scoped_parent_child_index_updater.h" |
| 31 #include "components/sync/syncable/syncable-inl.h" | |
| 32 #include "components/sync/syncable/syncable_base_transaction.h" | 30 #include "components/sync/syncable/syncable_base_transaction.h" |
| 33 #include "components/sync/syncable/syncable_changes_version.h" | 31 #include "components/sync/syncable/syncable_changes_version.h" |
| 34 #include "components/sync/syncable/syncable_read_transaction.h" | 32 #include "components/sync/syncable/syncable_read_transaction.h" |
| 35 #include "components/sync/syncable/syncable_util.h" | 33 #include "components/sync/syncable/syncable_util.h" |
| 36 #include "components/sync/syncable/syncable_write_transaction.h" | 34 #include "components/sync/syncable/syncable_write_transaction.h" |
| 37 | 35 |
| 38 using std::string; | 36 using std::string; |
| 39 | 37 |
| 40 namespace syncer { | 38 namespace syncer { |
| 41 namespace syncable { | 39 namespace syncable { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 69 bool Directory::PersistedKernelInfo::HasEmptyDownloadProgress( | 67 bool Directory::PersistedKernelInfo::HasEmptyDownloadProgress( |
| 70 ModelType model_type) { | 68 ModelType model_type) { |
| 71 const sync_pb::DataTypeProgressMarker& progress_marker = | 69 const sync_pb::DataTypeProgressMarker& progress_marker = |
| 72 download_progress[model_type]; | 70 download_progress[model_type]; |
| 73 return progress_marker.token().empty(); | 71 return progress_marker.token().empty(); |
| 74 } | 72 } |
| 75 | 73 |
| 76 Directory::SaveChangesSnapshot::SaveChangesSnapshot() | 74 Directory::SaveChangesSnapshot::SaveChangesSnapshot() |
| 77 : kernel_info_status(KERNEL_SHARE_INFO_INVALID) {} | 75 : kernel_info_status(KERNEL_SHARE_INFO_INVALID) {} |
| 78 | 76 |
| 79 Directory::SaveChangesSnapshot::~SaveChangesSnapshot() { | 77 Directory::SaveChangesSnapshot::~SaveChangesSnapshot() {} |
| 80 base::STLDeleteElements(&dirty_metas); | |
| 81 base::STLDeleteElements(&delete_journals); | |
| 82 } | |
| 83 | 78 |
| 84 bool Directory::SaveChangesSnapshot::HasUnsavedMetahandleChanges() const { | 79 bool Directory::SaveChangesSnapshot::HasUnsavedMetahandleChanges() const { |
| 85 return !dirty_metas.empty() || !metahandles_to_purge.empty() || | 80 return !dirty_metas.empty() || !metahandles_to_purge.empty() || |
| 86 !delete_journals.empty() || !delete_journals_to_purge.empty(); | 81 !delete_journals.empty() || !delete_journals_to_purge.empty(); |
| 87 } | 82 } |
| 88 | 83 |
| 89 Directory::Kernel::Kernel( | 84 Directory::Kernel::Kernel( |
| 90 const std::string& name, | 85 const std::string& name, |
| 91 const KernelLoadInfo& info, | 86 const KernelLoadInfo& info, |
| 92 DirectoryChangeDelegate* delegate, | 87 DirectoryChangeDelegate* delegate, |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 | 171 |
| 177 DirOpenResult Directory::OpenImpl( | 172 DirOpenResult Directory::OpenImpl( |
| 178 const string& name, | 173 const string& name, |
| 179 DirectoryChangeDelegate* delegate, | 174 DirectoryChangeDelegate* delegate, |
| 180 const WeakHandle<TransactionObserver>& transaction_observer) { | 175 const WeakHandle<TransactionObserver>& transaction_observer) { |
| 181 KernelLoadInfo info; | 176 KernelLoadInfo info; |
| 182 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) | 177 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) |
| 183 // swap these later. | 178 // swap these later. |
| 184 Directory::MetahandlesMap tmp_handles_map; | 179 Directory::MetahandlesMap tmp_handles_map; |
| 185 | 180 |
| 186 JournalIndex delete_journals; | 181 std::unique_ptr<JournalIndex> delete_journals = |
| 182 base::MakeUnique<JournalIndex>(); | |
| 187 MetahandleSet metahandles_to_purge; | 183 MetahandleSet metahandles_to_purge; |
| 188 | 184 |
| 189 DirOpenResult result = store_->Load(&tmp_handles_map, &delete_journals, | 185 DirOpenResult result = store_->Load(&tmp_handles_map, delete_journals.get(), |
| 190 &metahandles_to_purge, &info); | 186 &metahandles_to_purge, &info); |
| 191 if (OPENED != result) | 187 if (OPENED != result) |
| 192 return result; | 188 return result; |
| 193 | 189 |
| 194 DCHECK(!kernel_); | 190 DCHECK(!kernel_); |
| 195 kernel_ = new Kernel(name, info, delegate, transaction_observer); | 191 kernel_ = new Kernel(name, info, delegate, transaction_observer); |
| 196 kernel_->metahandles_to_purge.swap(metahandles_to_purge); | 192 kernel_->metahandles_to_purge.swap(metahandles_to_purge); |
| 197 delete_journal_.reset(new DeleteJournal(&delete_journals)); | 193 delete_journal_ = base::MakeUnique<DeleteJournal>(std::move(delete_journals)); |
|
maxbogue
2016/09/01 21:10:22
I don't think you need the MakeUnique here, do you
maxbogue
2016/09/01 21:13:17
Never mind, Pavel pointed out that these are diffe
| |
| 198 InitializeIndices(&tmp_handles_map); | 194 InitializeIndices(&tmp_handles_map); |
| 199 | 195 |
| 200 // Save changes back in case there are any metahandles to purge. | 196 // Save changes back in case there are any metahandles to purge. |
| 201 if (!SaveChanges()) | 197 if (!SaveChanges()) |
| 202 return FAILED_INITIAL_WRITE; | 198 return FAILED_INITIAL_WRITE; |
| 203 | 199 |
| 204 // Now that we've successfully opened the store, install an error handler to | 200 // Now that we've successfully opened the store, install an error handler to |
| 205 // deal with catastrophic errors that may occur later on. Use a weak pointer | 201 // deal with catastrophic errors that may occur later on. Use a weak pointer |
| 206 // because we cannot guarantee that this Directory will outlive the Closure. | 202 // because we cannot guarantee that this Directory will outlive the Closure. |
| 207 store_->SetCatastrophicErrorHandler(base::Bind( | 203 store_->SetCatastrophicErrorHandler(base::Bind( |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 534 // clear dirty flags. | 530 // clear dirty flags. |
| 535 for (MetahandleSet::const_iterator i = kernel_->dirty_metahandles.begin(); | 531 for (MetahandleSet::const_iterator i = kernel_->dirty_metahandles.begin(); |
| 536 i != kernel_->dirty_metahandles.end(); ++i) { | 532 i != kernel_->dirty_metahandles.end(); ++i) { |
| 537 EntryKernel* entry = GetEntryByHandle(lock, *i); | 533 EntryKernel* entry = GetEntryByHandle(lock, *i); |
| 538 if (!entry) | 534 if (!entry) |
| 539 continue; | 535 continue; |
| 540 // Skip over false positives; it happens relatively infrequently. | 536 // Skip over false positives; it happens relatively infrequently. |
| 541 if (!entry->is_dirty()) | 537 if (!entry->is_dirty()) |
| 542 continue; | 538 continue; |
| 543 snapshot->dirty_metas.insert(snapshot->dirty_metas.end(), | 539 snapshot->dirty_metas.insert(snapshot->dirty_metas.end(), |
| 544 new EntryKernel(*entry)); | 540 base::MakeUnique<EntryKernel>(*entry)); |
| 545 DCHECK_EQ(1U, kernel_->dirty_metahandles.count(*i)); | 541 DCHECK_EQ(1U, kernel_->dirty_metahandles.count(*i)); |
| 546 // We don't bother removing from the index here as we blow the entire thing | 542 // We don't bother removing from the index here as we blow the entire thing |
| 547 // in a moment, and it unnecessarily complicates iteration. | 543 // in a moment, and it unnecessarily complicates iteration. |
| 548 entry->clear_dirty(NULL); | 544 entry->clear_dirty(NULL); |
| 549 } | 545 } |
| 550 ClearDirtyMetahandles(lock); | 546 ClearDirtyMetahandles(lock); |
| 551 | 547 |
| 552 // Set purged handles. | 548 // Set purged handles. |
| 553 DCHECK(snapshot->metahandles_to_purge.empty()); | 549 DCHECK(snapshot->metahandles_to_purge.empty()); |
| 554 snapshot->metahandles_to_purge.swap(kernel_->metahandles_to_purge); | 550 snapshot->metahandles_to_purge.swap(kernel_->metahandles_to_purge); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 582 } | 578 } |
| 583 | 579 |
| 584 bool Directory::VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot) { | 580 bool Directory::VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot) { |
| 585 if (snapshot.dirty_metas.empty()) | 581 if (snapshot.dirty_metas.empty()) |
| 586 return true; | 582 return true; |
| 587 | 583 |
| 588 // Need a write transaction as we are about to permanently purge entries. | 584 // Need a write transaction as we are about to permanently purge entries. |
| 589 WriteTransaction trans(FROM_HERE, VACUUM_AFTER_SAVE, this); | 585 WriteTransaction trans(FROM_HERE, VACUUM_AFTER_SAVE, this); |
| 590 ScopedKernelLock lock(this); | 586 ScopedKernelLock lock(this); |
| 591 // Now drop everything we can out of memory. | 587 // Now drop everything we can out of memory. |
| 592 for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); | 588 for (auto i = snapshot.dirty_metas.begin(); i != snapshot.dirty_metas.end(); |
| 593 i != snapshot.dirty_metas.end(); ++i) { | 589 ++i) { |
| 594 MetahandlesMap::iterator found = | 590 MetahandlesMap::iterator found = |
| 595 kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); | 591 kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); |
| 596 EntryKernel* entry = | 592 EntryKernel* entry = |
| 597 (found == kernel_->metahandles_map.end() ? NULL : found->second.get()); | 593 (found == kernel_->metahandles_map.end() ? NULL : found->second.get()); |
| 598 if (entry && SafeToPurgeFromMemory(&trans, entry)) { | 594 if (entry && SafeToPurgeFromMemory(&trans, entry)) { |
| 599 // We now drop deleted metahandles that are up to date on both the client | 595 // We now drop deleted metahandles that are up to date on both the client |
| 600 // and the server. | 596 // and the server. |
| 601 std::unique_ptr<EntryKernel> unique_entry = std::move(found->second); | 597 std::unique_ptr<EntryKernel> unique_entry = std::move(found->second); |
| 602 | 598 |
| 603 size_t num_erased = 0; | 599 size_t num_erased = 0; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 679 | 675 |
| 680 // At this point locally created items that aren't synced will become locally | 676 // At this point locally created items that aren't synced will become locally |
| 681 // deleted items, and purged on the next snapshot. All other items will match | 677 // deleted items, and purged on the next snapshot. All other items will match |
| 682 // the state they would have had if they were just created via a server | 678 // the state they would have had if they were just created via a server |
| 683 // update. See MutableEntry::MutableEntry(.., CreateNewUpdateItem, ..). | 679 // update. See MutableEntry::MutableEntry(.., CreateNewUpdateItem, ..). |
| 684 } | 680 } |
| 685 | 681 |
| 686 void Directory::DeleteEntry(const ScopedKernelLock& lock, | 682 void Directory::DeleteEntry(const ScopedKernelLock& lock, |
| 687 bool save_to_journal, | 683 bool save_to_journal, |
| 688 EntryKernel* entry, | 684 EntryKernel* entry, |
| 689 EntryKernelSet* entries_to_journal) { | 685 OwnedEntryKernelSet* entries_to_journal) { |
| 690 int64_t handle = entry->ref(META_HANDLE); | 686 int64_t handle = entry->ref(META_HANDLE); |
| 691 ModelType server_type = | 687 ModelType server_type = |
| 692 GetModelTypeFromSpecifics(entry->ref(SERVER_SPECIFICS)); | 688 GetModelTypeFromSpecifics(entry->ref(SERVER_SPECIFICS)); |
| 693 | 689 |
| 694 kernel_->metahandles_to_purge.insert(handle); | 690 kernel_->metahandles_to_purge.insert(handle); |
| 695 | 691 |
| 696 std::unique_ptr<EntryKernel> entry_ptr = | 692 std::unique_ptr<EntryKernel> entry_ptr = |
| 697 std::move(kernel_->metahandles_map[handle]); | 693 std::move(kernel_->metahandles_map[handle]); |
| 698 | 694 |
| 699 size_t num_erased = 0; | 695 size_t num_erased = 0; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 712 num_erased = kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); | 708 num_erased = kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); |
| 713 DCHECK_EQ(1u, num_erased); | 709 DCHECK_EQ(1u, num_erased); |
| 714 } | 710 } |
| 715 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { | 711 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { |
| 716 num_erased = kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); | 712 num_erased = kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); |
| 717 DCHECK_EQ(1u, num_erased); | 713 DCHECK_EQ(1u, num_erased); |
| 718 } | 714 } |
| 719 RemoveFromAttachmentIndex(lock, handle, entry->ref(ATTACHMENT_METADATA)); | 715 RemoveFromAttachmentIndex(lock, handle, entry->ref(ATTACHMENT_METADATA)); |
| 720 | 716 |
| 721 if (save_to_journal) { | 717 if (save_to_journal) { |
| 722 entries_to_journal->insert(entry_ptr.release()); | 718 entries_to_journal->insert(std::move(entry_ptr)); |
| 723 } | 719 } |
| 724 } | 720 } |
| 725 | 721 |
| 726 bool Directory::PurgeEntriesWithTypeIn(ModelTypeSet disabled_types, | 722 bool Directory::PurgeEntriesWithTypeIn(ModelTypeSet disabled_types, |
| 727 ModelTypeSet types_to_journal, | 723 ModelTypeSet types_to_journal, |
| 728 ModelTypeSet types_to_unapply) { | 724 ModelTypeSet types_to_unapply) { |
| 729 disabled_types.RemoveAll(ProxyTypes()); | 725 disabled_types.RemoveAll(ProxyTypes()); |
| 730 | 726 |
| 731 if (disabled_types.Empty()) | 727 if (disabled_types.Empty()) |
| 732 return true; | 728 return true; |
| 733 | 729 |
| 734 { | 730 { |
| 735 WriteTransaction trans(FROM_HERE, PURGE_ENTRIES, this); | 731 WriteTransaction trans(FROM_HERE, PURGE_ENTRIES, this); |
| 736 | 732 |
| 737 EntryKernelSet entries_to_journal; | 733 OwnedEntryKernelSet entries_to_journal; |
| 738 base::STLElementDeleter<EntryKernelSet> journal_deleter( | |
| 739 &entries_to_journal); | |
| 740 | 734 |
| 741 { | 735 { |
| 742 ScopedKernelLock lock(this); | 736 ScopedKernelLock lock(this); |
| 743 | 737 |
| 744 bool found_progress = false; | 738 bool found_progress = false; |
| 745 for (ModelTypeSet::Iterator iter = disabled_types.First(); iter.Good(); | 739 for (ModelTypeSet::Iterator iter = disabled_types.First(); iter.Good(); |
| 746 iter.Inc()) { | 740 iter.Inc()) { |
| 747 if (!kernel_->persisted_info.HasEmptyDownloadProgress(iter.Get())) | 741 if (!kernel_->persisted_info.HasEmptyDownloadProgress(iter.Get())) |
| 748 found_progress = true; | 742 found_progress = true; |
| 749 } | 743 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 850 void Directory::HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot) { | 844 void Directory::HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot) { |
| 851 WriteTransaction trans(FROM_HERE, HANDLE_SAVE_FAILURE, this); | 845 WriteTransaction trans(FROM_HERE, HANDLE_SAVE_FAILURE, this); |
| 852 ScopedKernelLock lock(this); | 846 ScopedKernelLock lock(this); |
| 853 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 847 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
| 854 | 848 |
| 855 // Because we optimistically cleared the dirty bit on the real entries when | 849 // Because we optimistically cleared the dirty bit on the real entries when |
| 856 // taking the snapshot, we must restore it on failure. Not doing this could | 850 // taking the snapshot, we must restore it on failure. Not doing this could |
| 857 // cause lost data, if no other changes are made to the in-memory entries | 851 // cause lost data, if no other changes are made to the in-memory entries |
| 858 // that would cause the dirty bit to get set again. Setting the bit ensures | 852 // that would cause the dirty bit to get set again. Setting the bit ensures |
| 859 // that SaveChanges will at least try again later. | 853 // that SaveChanges will at least try again later. |
| 860 for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); | 854 for (auto i = snapshot.dirty_metas.begin(); i != snapshot.dirty_metas.end(); |
| 861 i != snapshot.dirty_metas.end(); ++i) { | 855 ++i) { |
| 862 MetahandlesMap::iterator found = | 856 MetahandlesMap::iterator found = |
| 863 kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); | 857 kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); |
| 864 if (found != kernel_->metahandles_map.end()) { | 858 if (found != kernel_->metahandles_map.end()) { |
| 865 found->second->mark_dirty(&kernel_->dirty_metahandles); | 859 found->second->mark_dirty(&kernel_->dirty_metahandles); |
| 866 } | 860 } |
| 867 } | 861 } |
| 868 | 862 |
| 869 kernel_->metahandles_to_purge.insert(snapshot.metahandles_to_purge.begin(), | 863 kernel_->metahandles_to_purge.insert(snapshot.metahandles_to_purge.begin(), |
| 870 snapshot.metahandles_to_purge.end()); | 864 snapshot.metahandles_to_purge.end()); |
| 871 | 865 |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1539 Directory::Kernel* Directory::kernel() { | 1533 Directory::Kernel* Directory::kernel() { |
| 1540 return kernel_; | 1534 return kernel_; |
| 1541 } | 1535 } |
| 1542 | 1536 |
| 1543 const Directory::Kernel* Directory::kernel() const { | 1537 const Directory::Kernel* Directory::kernel() const { |
| 1544 return kernel_; | 1538 return kernel_; |
| 1545 } | 1539 } |
| 1546 | 1540 |
| 1547 } // namespace syncable | 1541 } // namespace syncable |
| 1548 } // namespace syncer | 1542 } // namespace syncer |
| OLD | NEW |