| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "sync/internal_api/sync_backup_manager.h" |
| |
| #include "sync/internal_api/public/read_node.h" |
| #include "sync/internal_api/public/write_transaction.h" |
| #include "sync/syncable/directory.h" |
| #include "sync/syncable/mutable_entry.h" |
| #include "url/gurl.h" |
| |
| namespace syncer { |
| |
| SyncBackupManager::SyncBackupManager() |
| : in_normalization_(false) { |
| } |
| |
| SyncBackupManager::~SyncBackupManager() { |
| } |
| |
| void SyncBackupManager::Init(InitArgs* args) { |
| if (SyncRollbackManagerBase::InitInternal( |
| args->database_location, |
| args->internal_components_factory.get(), |
| InternalComponentsFactory::STORAGE_ON_DISK_DEFERRED, |
| args->unrecoverable_error_handler.Pass(), |
| args->report_unrecoverable_error_function)) { |
| GetUserShare()->directory->CollectMetaHandleCounts( |
| &status_.num_entries_by_type, &status_.num_to_delete_entries_by_type); |
| |
| HideSyncPreference(PRIORITY_PREFERENCES); |
| HideSyncPreference(PREFERENCES); |
| } |
| } |
| |
| void SyncBackupManager::SaveChanges() { |
| if (initialized()) |
| NormalizeEntries(); |
| } |
| |
| SyncStatus SyncBackupManager::GetDetailedStatus() const { |
| return status_; |
| } |
| |
| ModelTypeSet SyncBackupManager::HandleTransactionEndingChangeEvent( |
| const syncable::ImmutableWriteTransactionInfo& write_transaction_info, |
| syncable::BaseTransaction* trans) { |
| ModelTypeSet types; |
| if (in_normalization_) { |
| // Skip if in our own WriteTransaction from NormalizeEntries(). |
| in_normalization_ = false; |
| return types; |
| } |
| |
| for (syncable::EntryKernelMutationMap::const_iterator it = |
| write_transaction_info.Get().mutations.Get().begin(); |
| it != write_transaction_info.Get().mutations.Get().end(); ++it) { |
| int64 id = it->first; |
| if (unsynced_.find(id) == unsynced_.end()) { |
| unsynced_.insert(id); |
| |
| const syncable::EntryKernel& e = it->second.mutated; |
| ModelType type = e.GetModelType(); |
| types.Put(type); |
| if (!e.ref(syncable::ID).ServerKnows()) |
| status_.num_entries_by_type[type]++; |
| if (e.ref(syncable::IS_DEL)) |
| status_.num_to_delete_entries_by_type[type]++; |
| } |
| } |
| return types; |
| } |
| |
| void SyncBackupManager::NormalizeEntries() { |
| WriteTransaction trans(FROM_HERE, GetUserShare()); |
| in_normalization_ = true; |
| for (std::set<int64>::const_iterator it = unsynced_.begin(); |
| it != unsynced_.end(); ++it) { |
| syncable::MutableEntry entry(trans.GetWrappedWriteTrans(), |
| syncable::GET_BY_HANDLE, *it); |
| CHECK(entry.good()); |
| |
| if (!entry.GetId().ServerKnows()) |
| entry.PutId(syncable::Id::CreateFromServerId(entry.GetId().value())); |
| if (!entry.GetParentId().IsNull() && !entry.GetParentId().ServerKnows()) { |
| entry.PutParentIdPropertyOnly(syncable::Id::CreateFromServerId( |
| entry.GetParentId().value())); |
| } |
| entry.PutBaseVersion(1); |
| entry.PutIsUnsynced(false); |
| } |
| unsynced_.clear(); |
| } |
| |
| void SyncBackupManager::HideSyncPreference(ModelType type) { |
| WriteTransaction trans(FROM_HERE, GetUserShare()); |
| ReadNode pref_root(&trans); |
| if (BaseNode::INIT_OK != pref_root.InitTypeRoot(type)) |
| return; |
| |
| std::vector<int64> pref_ids; |
| pref_root.GetChildIds(&pref_ids); |
| for (uint32 i = 0; i < pref_ids.size(); ++i) { |
| syncable::MutableEntry entry(trans.GetWrappedWriteTrans(), |
| syncable::GET_BY_HANDLE, pref_ids[i]); |
| if (entry.good()) { |
| // HACKY: Set IS_DEL to true to remove entry from parent-children |
| // index so that it's not returned when syncable service asks |
| // for sync data. Syncable service then creates entry for local |
| // model. Then the existing entry is undeleted and set to local value |
| // because it has the same unique client tag. |
| entry.PutIsDel(true); |
| entry.PutIsUnsynced(false); |
| |
| // Don't persist on disk so that if backup is aborted before receiving |
| // local preference values, values in sync DB are saved. |
| GetUserShare()->directory->UnmarkDirtyEntry( |
| trans.GetWrappedWriteTrans(), &entry); |
| } |
| } |
| } |
| |
| void SyncBackupManager::ShutdownOnSyncThread(ShutdownReason reason) { |
| if (reason == SWITCH_MODE_SYNC) { |
| NormalizeEntries(); |
| GetUserShare()->directory->SaveChanges(); |
| } |
| |
| SyncRollbackManagerBase::ShutdownOnSyncThread(reason); |
| } |
| |
| void SyncBackupManager::RegisterDirectoryTypeDebugInfoObserver( |
| syncer::TypeDebugInfoObserver* observer) {} |
| |
| void SyncBackupManager::UnregisterDirectoryTypeDebugInfoObserver( |
| syncer::TypeDebugInfoObserver* observer) {} |
| |
| bool SyncBackupManager::HasDirectoryTypeDebugInfoObserver( |
| syncer::TypeDebugInfoObserver* observer) { return false; } |
| |
| void SyncBackupManager::RequestEmitDebugInfo() {} |
| |
| } // namespace syncer |