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 #include "url/gurl.h" 15 16 namespace syncer { 17 18 SyncRollbackManager::SyncRollbackManager() 19 : change_delegate_(NULL) { 20 } 21 22 SyncRollbackManager::~SyncRollbackManager() { 23 } 24 25 void SyncRollbackManager::Init(InitArgs* args) { 26 if (SyncRollbackManagerBase::InitInternal( 27 args->database_location, 28 args->internal_components_factory.get(), 29 InternalComponentsFactory::STORAGE_ON_DISK, 30 args->unrecoverable_error_handler.Pass(), 31 args->report_unrecoverable_error_function)) { 32 change_delegate_ = args->change_delegate; 33 34 for (size_t i = 0; i < args->workers.size(); ++i) { 35 ModelSafeGroup group = args->workers[i]->GetModelSafeGroup(); 36 CHECK(workers_.find(group) == workers_.end()); 37 workers_[group] = args->workers[i]; 38 } 39 40 rollback_ready_types_ = GetUserShare()->directory->InitialSyncEndedTypes(); 41 rollback_ready_types_.RetainAll(BackupTypes()); 42 } 43 } 44 45 void SyncRollbackManager::StartSyncingNormally( 46 const ModelSafeRoutingInfo& routing_info){ 47 if (rollback_ready_types_.Empty()) { 48 NotifyRollbackDone(); 49 return; 50 } 51 52 std::map<ModelType, syncable::Directory::Metahandles> to_delete; 53 { 54 WriteTransaction trans(FROM_HERE, GetUserShare()); 55 syncable::Directory::Metahandles unsynced; 56 GetUserShare()->directory->GetUnsyncedMetaHandles(trans.GetWrappedTrans(), 57 &unsynced); 58 for (size_t i = 0; i < unsynced.size(); ++i) { 59 syncable::MutableEntry e(trans.GetWrappedWriteTrans(), 60 syncable::GET_BY_HANDLE, unsynced[i]); 61 if (!e.good() || e.GetIsDel() || e.GetId().ServerKnows()) 62 continue; 63 64 // TODO(haitaol): roll back entries that are backed up but whose content 65 // is merged with local model during association. 66 67 ModelType type = GetModelTypeFromSpecifics(e.GetSpecifics()); 68 if (!rollback_ready_types_.Has(type)) 69 continue; 70 71 to_delete[type].push_back(unsynced[i]); 72 } 73 } 74 75 for (std::map<ModelType, syncable::Directory::Metahandles>::iterator it = 76 to_delete.begin(); it != to_delete.end(); ++it) { 77 ModelSafeGroup group = routing_info.find(it->first)->second; 78 CHECK(workers_.find(group) != workers_.end()); 79 workers_[group]->DoWorkAndWaitUntilDone( 80 base::Bind(&SyncRollbackManager::DeleteOnWorkerThread, 81 base::Unretained(this), 82 it->first, it->second)); 83 } 84 85 NotifyRollbackDone(); 86 } 87 88 SyncerError SyncRollbackManager::DeleteOnWorkerThread( 89 ModelType type, std::vector<int64> handles) { 90 CHECK(change_delegate_); 91 92 { 93 ChangeRecordList deletes; 94 WriteTransaction trans(FROM_HERE, GetUserShare()); 95 for (size_t i = 0; i < handles.size(); ++i) { 96 syncable::MutableEntry e(trans.GetWrappedWriteTrans(), 97 syncable::GET_BY_HANDLE, handles[i]); 98 if (!e.good() || e.GetIsDel()) 99 continue; 100 101 ChangeRecord del; 102 del.action = ChangeRecord::ACTION_DELETE; 103 del.id = handles[i]; 104 del.specifics = e.GetSpecifics(); 105 deletes.push_back(del); 106 } 107 108 change_delegate_->OnChangesApplied(type, 1, &trans, 109 MakeImmutable(&deletes)); 110 } 111 112 change_delegate_->OnChangesComplete(type); 113 return SYNCER_OK; 114 } 115 116 void SyncRollbackManager::NotifyRollbackDone() { 117 SyncProtocolError error; 118 error.action = ROLLBACK_DONE; 119 FOR_EACH_OBSERVER(SyncManager::Observer, *GetObservers(), 120 OnActionableError(error)); 121 } 122 123 } // namespace syncer 124