// 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_rollback_manager.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/read_node.h" #include "sync/internal_api/public/read_transaction.h" #include "sync/internal_api/public/util/syncer_error.h" #include "sync/internal_api/public/write_transaction.h" #include "sync/syncable/directory.h" #include "sync/syncable/mutable_entry.h" namespace syncer { SyncRollbackManager::SyncRollbackManager() : change_delegate_(NULL) { } SyncRollbackManager::~SyncRollbackManager() { } void SyncRollbackManager::Init( const base::FilePath& database_location, const WeakHandle& event_handler, const std::string& sync_server_and_path, int sync_server_port, bool use_ssl, scoped_ptr post_factory, const std::vector >& workers, ExtensionsActivity* extensions_activity, SyncManager::ChangeDelegate* change_delegate, const SyncCredentials& credentials, const std::string& invalidator_client_id, const std::string& restored_key_for_bootstrapping, const std::string& restored_keystore_key_for_bootstrapping, InternalComponentsFactory* internal_components_factory, Encryptor* encryptor, scoped_ptr unrecoverable_error_handler, ReportUnrecoverableErrorFunction report_unrecoverable_error_function, CancelationSignal* cancelation_signal) { SyncRollbackManagerBase::Init(database_location, event_handler, sync_server_and_path, sync_server_port, use_ssl, post_factory.Pass(), workers, extensions_activity, change_delegate, credentials, invalidator_client_id, restored_key_for_bootstrapping, restored_keystore_key_for_bootstrapping, internal_components_factory, encryptor, unrecoverable_error_handler.Pass(), report_unrecoverable_error_function, cancelation_signal); change_delegate_ = change_delegate; for (size_t i = 0; i < workers.size(); ++i) { ModelSafeGroup group = workers[i]->GetModelSafeGroup(); CHECK(workers_.find(group) == workers_.end()); workers_[group] = workers[i]; } rollback_ready_types_ = GetUserShare()->directory->InitialSyncEndedTypes(); rollback_ready_types_.RetainAll(BackupTypes()); } void SyncRollbackManager::StartSyncingNormally( const ModelSafeRoutingInfo& routing_info){ std::map to_delete; { WriteTransaction trans(FROM_HERE, GetUserShare()); syncable::Directory::Metahandles unsynced; GetUserShare()->directory->GetUnsyncedMetaHandles(trans.GetWrappedTrans(), &unsynced); for (size_t i = 0; i < unsynced.size(); ++i) { syncable::MutableEntry e(trans.GetWrappedWriteTrans(), syncable::GET_BY_HANDLE, unsynced[i]); if (!e.good() || e.GetIsDel() || e.GetId().ServerKnows()) continue; // TODO(haitaol): roll back entries that are backed up but whose content // is merged with local model during association. ModelType type = GetModelTypeFromSpecifics(e.GetSpecifics()); if (!rollback_ready_types_.Has(type)) continue; to_delete[type].push_back(unsynced[i]); } } for (std::map::iterator it = to_delete.begin(); it != to_delete.end(); ++it) { ModelSafeGroup group = routing_info.find(it->first)->second; CHECK(workers_.find(group) != workers_.end()); workers_[group]->DoWorkAndWaitUntilDone( base::Bind(&SyncRollbackManager::DeleteOnWorkerThread, base::Unretained(this), it->first, it->second)); } } SyncerError SyncRollbackManager::DeleteOnWorkerThread( ModelType type, std::vector handles) { CHECK(change_delegate_); { ChangeRecordList deletes; WriteTransaction trans(FROM_HERE, GetUserShare()); for (size_t i = 0; i < handles.size(); ++i) { syncable::MutableEntry e(trans.GetWrappedWriteTrans(), syncable::GET_BY_HANDLE, handles[i]); if (!e.good() || e.GetIsDel()) continue; ChangeRecord del; del.action = ChangeRecord::ACTION_DELETE; del.id = handles[i]; del.specifics = e.GetSpecifics(); deletes.push_back(del); } change_delegate_->OnChangesApplied(type, 1, &trans, MakeImmutable(&deletes)); } change_delegate_->OnChangesComplete(type); return SYNCER_OK; } } // namespace syncer