1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "sync/internal_api/sync_rollback_manager.h" 6 7#include "sync/internal_api/public/base/model_type.h" 8#include "sync/internal_api/public/read_node.h" 9#include "sync/internal_api/public/read_transaction.h" 10#include "sync/internal_api/public/util/syncer_error.h" 11#include "sync/internal_api/public/write_transaction.h" 12#include "sync/syncable/directory.h" 13#include "sync/syncable/mutable_entry.h" 14 15namespace syncer { 16 17SyncRollbackManager::SyncRollbackManager() 18 : change_delegate_(NULL) { 19} 20 21SyncRollbackManager::~SyncRollbackManager() { 22} 23 24void SyncRollbackManager::Init( 25 const base::FilePath& database_location, 26 const WeakHandle<JsEventHandler>& event_handler, 27 const std::string& sync_server_and_path, 28 int sync_server_port, 29 bool use_ssl, 30 scoped_ptr<HttpPostProviderFactory> post_factory, 31 const std::vector<scoped_refptr<ModelSafeWorker> >& workers, 32 ExtensionsActivity* extensions_activity, 33 SyncManager::ChangeDelegate* change_delegate, 34 const SyncCredentials& credentials, 35 const std::string& invalidator_client_id, 36 const std::string& restored_key_for_bootstrapping, 37 const std::string& restored_keystore_key_for_bootstrapping, 38 InternalComponentsFactory* internal_components_factory, 39 Encryptor* encryptor, 40 scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler, 41 ReportUnrecoverableErrorFunction 42 report_unrecoverable_error_function, 43 CancelationSignal* cancelation_signal) { 44 if (SyncRollbackManagerBase::InitInternal( 45 database_location, 46 internal_components_factory, 47 unrecoverable_error_handler.Pass(), 48 report_unrecoverable_error_function)) { 49 change_delegate_ = change_delegate; 50 51 for (size_t i = 0; i < workers.size(); ++i) { 52 ModelSafeGroup group = workers[i]->GetModelSafeGroup(); 53 CHECK(workers_.find(group) == workers_.end()); 54 workers_[group] = workers[i]; 55 } 56 57 rollback_ready_types_ = GetUserShare()->directory->InitialSyncEndedTypes(); 58 rollback_ready_types_.RetainAll(BackupTypes()); 59 } 60} 61 62void SyncRollbackManager::StartSyncingNormally( 63 const ModelSafeRoutingInfo& routing_info){ 64 if (rollback_ready_types_.Empty()) { 65 NotifyRollbackDone(); 66 return; 67 } 68 69 std::map<ModelType, syncable::Directory::Metahandles> to_delete; 70 { 71 WriteTransaction trans(FROM_HERE, GetUserShare()); 72 syncable::Directory::Metahandles unsynced; 73 GetUserShare()->directory->GetUnsyncedMetaHandles(trans.GetWrappedTrans(), 74 &unsynced); 75 for (size_t i = 0; i < unsynced.size(); ++i) { 76 syncable::MutableEntry e(trans.GetWrappedWriteTrans(), 77 syncable::GET_BY_HANDLE, unsynced[i]); 78 if (!e.good() || e.GetIsDel() || e.GetId().ServerKnows()) 79 continue; 80 81 // TODO(haitaol): roll back entries that are backed up but whose content 82 // is merged with local model during association. 83 84 ModelType type = GetModelTypeFromSpecifics(e.GetSpecifics()); 85 if (!rollback_ready_types_.Has(type)) 86 continue; 87 88 to_delete[type].push_back(unsynced[i]); 89 } 90 } 91 92 for (std::map<ModelType, syncable::Directory::Metahandles>::iterator it = 93 to_delete.begin(); it != to_delete.end(); ++it) { 94 ModelSafeGroup group = routing_info.find(it->first)->second; 95 CHECK(workers_.find(group) != workers_.end()); 96 workers_[group]->DoWorkAndWaitUntilDone( 97 base::Bind(&SyncRollbackManager::DeleteOnWorkerThread, 98 base::Unretained(this), 99 it->first, it->second)); 100 } 101 102 NotifyRollbackDone(); 103} 104 105SyncerError SyncRollbackManager::DeleteOnWorkerThread( 106 ModelType type, std::vector<int64> handles) { 107 CHECK(change_delegate_); 108 109 { 110 ChangeRecordList deletes; 111 WriteTransaction trans(FROM_HERE, GetUserShare()); 112 for (size_t i = 0; i < handles.size(); ++i) { 113 syncable::MutableEntry e(trans.GetWrappedWriteTrans(), 114 syncable::GET_BY_HANDLE, handles[i]); 115 if (!e.good() || e.GetIsDel()) 116 continue; 117 118 ChangeRecord del; 119 del.action = ChangeRecord::ACTION_DELETE; 120 del.id = handles[i]; 121 del.specifics = e.GetSpecifics(); 122 deletes.push_back(del); 123 } 124 125 change_delegate_->OnChangesApplied(type, 1, &trans, 126 MakeImmutable(&deletes)); 127 } 128 129 change_delegate_->OnChangesComplete(type); 130 return SYNCER_OK; 131} 132 133void SyncRollbackManager::NotifyRollbackDone() { 134 SyncProtocolError error; 135 error.action = ROLLBACK_DONE; 136 FOR_EACH_OBSERVER(SyncManager::Observer, *GetObservers(), 137 OnActionableError(error)); 138} 139 140} // namespace syncer 141