| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/syncable/syncable.h" | 5 #include "chrome/browser/sync/syncable/syncable.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 #include <functional> | 9 #include <functional> |
| 10 #include <iomanip> | 10 #include <iomanip> |
| (...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 | 812 |
| 813 // Might not be in it | 813 // Might not be in it |
| 814 num_erased = kernel_->client_tag_index->erase(entry); | 814 num_erased = kernel_->client_tag_index->erase(entry); |
| 815 DCHECK_EQ(entry->ref(UNIQUE_CLIENT_TAG).empty(), !num_erased); | 815 DCHECK_EQ(entry->ref(UNIQUE_CLIENT_TAG).empty(), !num_erased); |
| 816 CHECK(!kernel_->parent_id_child_index->count(entry)); | 816 CHECK(!kernel_->parent_id_child_index->count(entry)); |
| 817 delete entry; | 817 delete entry; |
| 818 } | 818 } |
| 819 } | 819 } |
| 820 } | 820 } |
| 821 | 821 |
| 822 void Directory::PurgeEntriesWithTypeIn(const std::set<ModelType>& types) { | 822 void Directory::PurgeEntriesWithTypeIn(ModelEnumSet types) { |
| 823 if (types.count(UNSPECIFIED) != 0U || types.count(TOP_LEVEL_FOLDER) != 0U) { | 823 if (types.Empty()) |
| 824 NOTREACHED() << "Don't support purging unspecified or top level entries."; | |
| 825 return; | |
| 826 } | |
| 827 | |
| 828 if (types.empty()) | |
| 829 return; | 824 return; |
| 830 | 825 |
| 831 { | 826 { |
| 832 WriteTransaction trans(FROM_HERE, PURGE_ENTRIES, this); | 827 WriteTransaction trans(FROM_HERE, PURGE_ENTRIES, this); |
| 833 { | 828 { |
| 834 ScopedKernelLock lock(this); | 829 ScopedKernelLock lock(this); |
| 835 MetahandlesIndex::iterator it = kernel_->metahandles_index->begin(); | 830 MetahandlesIndex::iterator it = kernel_->metahandles_index->begin(); |
| 836 while (it != kernel_->metahandles_index->end()) { | 831 while (it != kernel_->metahandles_index->end()) { |
| 837 const sync_pb::EntitySpecifics& local_specifics = (*it)->ref(SPECIFICS); | 832 const sync_pb::EntitySpecifics& local_specifics = (*it)->ref(SPECIFICS); |
| 838 const sync_pb::EntitySpecifics& server_specifics = | 833 const sync_pb::EntitySpecifics& server_specifics = |
| 839 (*it)->ref(SERVER_SPECIFICS); | 834 (*it)->ref(SERVER_SPECIFICS); |
| 840 ModelType local_type = GetModelTypeFromSpecifics(local_specifics); | 835 ModelType local_type = GetModelTypeFromSpecifics(local_specifics); |
| 841 ModelType server_type = GetModelTypeFromSpecifics(server_specifics); | 836 ModelType server_type = GetModelTypeFromSpecifics(server_specifics); |
| 842 | 837 |
| 843 // Note the dance around incrementing |it|, since we sometimes erase(). | 838 // Note the dance around incrementing |it|, since we sometimes erase(). |
| 844 if (types.count(local_type) > 0 || types.count(server_type) > 0) { | 839 if ((IsRealDataType(local_type) && types.Has(local_type)) || |
| 840 (IsRealDataType(server_type) && types.Has(server_type))) { |
| 845 UnlinkEntryFromOrder(*it, NULL, &lock); | 841 UnlinkEntryFromOrder(*it, NULL, &lock); |
| 846 int64 handle = (*it)->ref(META_HANDLE); | 842 int64 handle = (*it)->ref(META_HANDLE); |
| 847 kernel_->metahandles_to_purge->insert(handle); | 843 kernel_->metahandles_to_purge->insert(handle); |
| 848 | 844 |
| 849 size_t num_erased = 0; | 845 size_t num_erased = 0; |
| 850 EntryKernel* entry = *it; | 846 EntryKernel* entry = *it; |
| 851 num_erased = kernel_->ids_index->erase(entry); | 847 num_erased = kernel_->ids_index->erase(entry); |
| 852 DCHECK_EQ(1u, num_erased); | 848 DCHECK_EQ(1u, num_erased); |
| 853 num_erased = kernel_->client_tag_index->erase(entry); | 849 num_erased = kernel_->client_tag_index->erase(entry); |
| 854 DCHECK_EQ(entry->ref(UNIQUE_CLIENT_TAG).empty(), !num_erased); | 850 DCHECK_EQ(entry->ref(UNIQUE_CLIENT_TAG).empty(), !num_erased); |
| 855 num_erased = kernel_->unsynced_metahandles->erase(handle); | 851 num_erased = kernel_->unsynced_metahandles->erase(handle); |
| 856 DCHECK_EQ(entry->ref(IS_UNSYNCED), num_erased > 0); | 852 DCHECK_EQ(entry->ref(IS_UNSYNCED), num_erased > 0); |
| 857 num_erased = | 853 num_erased = |
| 858 kernel_->unapplied_update_metahandles[server_type].erase(handle); | 854 kernel_->unapplied_update_metahandles[server_type].erase(handle); |
| 859 DCHECK_EQ(entry->ref(IS_UNAPPLIED_UPDATE), num_erased > 0); | 855 DCHECK_EQ(entry->ref(IS_UNAPPLIED_UPDATE), num_erased > 0); |
| 860 num_erased = kernel_->parent_id_child_index->erase(entry); | 856 num_erased = kernel_->parent_id_child_index->erase(entry); |
| 861 DCHECK_EQ(entry->ref(IS_DEL), !num_erased); | 857 DCHECK_EQ(entry->ref(IS_DEL), !num_erased); |
| 862 kernel_->metahandles_index->erase(it++); | 858 kernel_->metahandles_index->erase(it++); |
| 863 delete entry; | 859 delete entry; |
| 864 } else { | 860 } else { |
| 865 ++it; | 861 ++it; |
| 866 } | 862 } |
| 867 } | 863 } |
| 868 | 864 |
| 869 // Ensure meta tracking for these data types reflects the deleted state. | 865 // Ensure meta tracking for these data types reflects the deleted state. |
| 870 for (std::set<ModelType>::const_iterator it = types.begin(); | 866 for (syncable::ModelEnumSet::Iterator it = types.First(); |
| 871 it != types.end(); ++it) { | 867 it.Good(); it.Inc()) { |
| 872 set_initial_sync_ended_for_type_unsafe(*it, false); | 868 set_initial_sync_ended_for_type_unsafe(it.Get(), false); |
| 873 kernel_->persisted_info.reset_download_progress(*it); | 869 kernel_->persisted_info.reset_download_progress(it.Get()); |
| 874 } | 870 } |
| 875 } | 871 } |
| 876 } | 872 } |
| 877 } | 873 } |
| 878 | 874 |
| 879 void Directory::HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot) { | 875 void Directory::HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot) { |
| 880 ScopedKernelLock lock(this); | 876 ScopedKernelLock lock(this); |
| 881 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 877 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
| 882 | 878 |
| 883 // Because we optimistically cleared the dirty bit on the real entries when | 879 // Because we optimistically cleared the dirty bit on the real entries when |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 void Directory::SetDownloadProgress( | 919 void Directory::SetDownloadProgress( |
| 924 ModelType model_type, | 920 ModelType model_type, |
| 925 const sync_pb::DataTypeProgressMarker& new_progress) { | 921 const sync_pb::DataTypeProgressMarker& new_progress) { |
| 926 ScopedKernelLock lock(this); | 922 ScopedKernelLock lock(this); |
| 927 kernel_->persisted_info.download_progress[model_type].CopyFrom(new_progress); | 923 kernel_->persisted_info.download_progress[model_type].CopyFrom(new_progress); |
| 928 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 924 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
| 929 } | 925 } |
| 930 | 926 |
| 931 bool Directory::initial_sync_ended_for_type(ModelType type) const { | 927 bool Directory::initial_sync_ended_for_type(ModelType type) const { |
| 932 ScopedKernelLock lock(this); | 928 ScopedKernelLock lock(this); |
| 933 return kernel_->persisted_info.initial_sync_ended[type]; | 929 return kernel_->persisted_info.initial_sync_ended.Has(type); |
| 934 } | 930 } |
| 935 | 931 |
| 936 template <class T> void Directory::TestAndSet( | 932 template <class T> void Directory::TestAndSet( |
| 937 T* kernel_data, const T* data_to_set) { | 933 T* kernel_data, const T* data_to_set) { |
| 938 if (*kernel_data != *data_to_set) { | 934 if (*kernel_data != *data_to_set) { |
| 939 *kernel_data = *data_to_set; | 935 *kernel_data = *data_to_set; |
| 940 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 936 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
| 941 } | 937 } |
| 942 } | 938 } |
| 943 | 939 |
| 944 void Directory::set_initial_sync_ended_for_type(ModelType type, bool x) { | 940 void Directory::set_initial_sync_ended_for_type(ModelType type, bool x) { |
| 945 ScopedKernelLock lock(this); | 941 ScopedKernelLock lock(this); |
| 946 set_initial_sync_ended_for_type_unsafe(type, x); | 942 set_initial_sync_ended_for_type_unsafe(type, x); |
| 947 } | 943 } |
| 948 | 944 |
| 949 void Directory::set_initial_sync_ended_for_type_unsafe(ModelType type, | 945 void Directory::set_initial_sync_ended_for_type_unsafe(ModelType type, |
| 950 bool x) { | 946 bool x) { |
| 951 if (kernel_->persisted_info.initial_sync_ended[type] == x) | 947 if (kernel_->persisted_info.initial_sync_ended.Has(type) == x) |
| 952 return; | 948 return; |
| 953 kernel_->persisted_info.initial_sync_ended.set(type, x); | 949 if (x) { |
| 950 kernel_->persisted_info.initial_sync_ended.Put(type); |
| 951 } else { |
| 952 kernel_->persisted_info.initial_sync_ended.Remove(type); |
| 953 } |
| 954 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 954 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
| 955 } | 955 } |
| 956 | 956 |
| 957 void Directory::SetNotificationStateUnsafe( | 957 void Directory::SetNotificationStateUnsafe( |
| 958 const std::string& notification_state) { | 958 const std::string& notification_state) { |
| 959 if (notification_state == kernel_->persisted_info.notification_state) | 959 if (notification_state == kernel_->persisted_info.notification_state) |
| 960 return; | 960 return; |
| 961 kernel_->persisted_info.notification_state = notification_state; | 961 kernel_->persisted_info.notification_state = notification_state; |
| 962 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 962 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
| 963 } | 963 } |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1301 // Not actually mutated, so erase from |mutations_|. | 1301 // Not actually mutated, so erase from |mutations_|. |
| 1302 mutations_.erase(it++); | 1302 mutations_.erase(it++); |
| 1303 } | 1303 } |
| 1304 } | 1304 } |
| 1305 return ImmutableEntryKernelMutationMap(&mutations_); | 1305 return ImmutableEntryKernelMutationMap(&mutations_); |
| 1306 } | 1306 } |
| 1307 | 1307 |
| 1308 void WriteTransaction::UnlockAndNotify( | 1308 void WriteTransaction::UnlockAndNotify( |
| 1309 const ImmutableEntryKernelMutationMap& mutations) { | 1309 const ImmutableEntryKernelMutationMap& mutations) { |
| 1310 // Work while transaction mutex is held. | 1310 // Work while transaction mutex is held. |
| 1311 ModelTypeBitSet models_with_changes; | 1311 ModelEnumSet models_with_changes; |
| 1312 bool has_mutations = !mutations.Get().empty(); | 1312 bool has_mutations = !mutations.Get().empty(); |
| 1313 if (has_mutations) { | 1313 if (has_mutations) { |
| 1314 models_with_changes = NotifyTransactionChangingAndEnding(mutations); | 1314 models_with_changes = NotifyTransactionChangingAndEnding(mutations); |
| 1315 } | 1315 } |
| 1316 Unlock(); | 1316 Unlock(); |
| 1317 | 1317 |
| 1318 // Work after mutex is relased. | 1318 // Work after mutex is relased. |
| 1319 if (has_mutations) { | 1319 if (has_mutations) { |
| 1320 NotifyTransactionComplete(models_with_changes); | 1320 NotifyTransactionComplete(models_with_changes); |
| 1321 } | 1321 } |
| 1322 } | 1322 } |
| 1323 | 1323 |
| 1324 ModelTypeBitSet WriteTransaction::NotifyTransactionChangingAndEnding( | 1324 ModelEnumSet WriteTransaction::NotifyTransactionChangingAndEnding( |
| 1325 const ImmutableEntryKernelMutationMap& mutations) { | 1325 const ImmutableEntryKernelMutationMap& mutations) { |
| 1326 dirkernel_->transaction_mutex.AssertAcquired(); | 1326 dirkernel_->transaction_mutex.AssertAcquired(); |
| 1327 DCHECK(!mutations.Get().empty()); | 1327 DCHECK(!mutations.Get().empty()); |
| 1328 | 1328 |
| 1329 WriteTransactionInfo write_transaction_info( | 1329 WriteTransactionInfo write_transaction_info( |
| 1330 dirkernel_->next_write_transaction_id, from_here_, writer_, mutations); | 1330 dirkernel_->next_write_transaction_id, from_here_, writer_, mutations); |
| 1331 ++dirkernel_->next_write_transaction_id; | 1331 ++dirkernel_->next_write_transaction_id; |
| 1332 | 1332 |
| 1333 ImmutableWriteTransactionInfo immutable_write_transaction_info( | 1333 ImmutableWriteTransactionInfo immutable_write_transaction_info( |
| 1334 &write_transaction_info); | 1334 &write_transaction_info); |
| 1335 DirectoryChangeDelegate* const delegate = dirkernel_->delegate; | 1335 DirectoryChangeDelegate* const delegate = dirkernel_->delegate; |
| 1336 if (writer_ == syncable::SYNCAPI) { | 1336 if (writer_ == syncable::SYNCAPI) { |
| 1337 delegate->HandleCalculateChangesChangeEventFromSyncApi( | 1337 delegate->HandleCalculateChangesChangeEventFromSyncApi( |
| 1338 immutable_write_transaction_info, this); | 1338 immutable_write_transaction_info, this); |
| 1339 } else { | 1339 } else { |
| 1340 delegate->HandleCalculateChangesChangeEventFromSyncer( | 1340 delegate->HandleCalculateChangesChangeEventFromSyncer( |
| 1341 immutable_write_transaction_info, this); | 1341 immutable_write_transaction_info, this); |
| 1342 } | 1342 } |
| 1343 | 1343 |
| 1344 ModelTypeBitSet models_with_changes = | 1344 ModelEnumSet models_with_changes = |
| 1345 delegate->HandleTransactionEndingChangeEvent( | 1345 delegate->HandleTransactionEndingChangeEvent( |
| 1346 immutable_write_transaction_info, this); | 1346 immutable_write_transaction_info, this); |
| 1347 | 1347 |
| 1348 dirkernel_->transaction_observer.Call(FROM_HERE, | 1348 dirkernel_->transaction_observer.Call(FROM_HERE, |
| 1349 &TransactionObserver::OnTransactionWrite, | 1349 &TransactionObserver::OnTransactionWrite, |
| 1350 immutable_write_transaction_info, models_with_changes); | 1350 immutable_write_transaction_info, models_with_changes); |
| 1351 | 1351 |
| 1352 return models_with_changes; | 1352 return models_with_changes; |
| 1353 } | 1353 } |
| 1354 | 1354 |
| 1355 void WriteTransaction::NotifyTransactionComplete( | 1355 void WriteTransaction::NotifyTransactionComplete( |
| 1356 ModelTypeBitSet models_with_changes) { | 1356 ModelEnumSet models_with_changes) { |
| 1357 dirkernel_->delegate->HandleTransactionCompleteChangeEvent( | 1357 dirkernel_->delegate->HandleTransactionCompleteChangeEvent( |
| 1358 models_with_changes); | 1358 models_with_changes); |
| 1359 } | 1359 } |
| 1360 | 1360 |
| 1361 WriteTransaction::~WriteTransaction() { | 1361 WriteTransaction::~WriteTransaction() { |
| 1362 const ImmutableEntryKernelMutationMap& mutations = RecordMutations(); | 1362 const ImmutableEntryKernelMutationMap& mutations = RecordMutations(); |
| 1363 | 1363 |
| 1364 if (OFF != kInvariantCheckLevel) { | 1364 if (OFF != kInvariantCheckLevel) { |
| 1365 const bool full_scan = (FULL_DB_VERIFICATION == kInvariantCheckLevel); | 1365 const bool full_scan = (FULL_DB_VERIFICATION == kInvariantCheckLevel); |
| 1366 if (full_scan) | 1366 if (full_scan) |
| (...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2112 if (entry->ref(NEXT_ID).IsRoot() || | 2112 if (entry->ref(NEXT_ID).IsRoot() || |
| 2113 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { | 2113 entry->ref(NEXT_ID) != entry->ref(PREV_ID)) { |
| 2114 return entry; | 2114 return entry; |
| 2115 } | 2115 } |
| 2116 } | 2116 } |
| 2117 // There were no children in the linked list. | 2117 // There were no children in the linked list. |
| 2118 return NULL; | 2118 return NULL; |
| 2119 } | 2119 } |
| 2120 | 2120 |
| 2121 } // namespace syncable | 2121 } // namespace syncable |
| OLD | NEW |