Home | History | Annotate | Download | only in internal_api
      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