• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SyncRollbackManager()18 SyncRollbackManager::SyncRollbackManager()
19     : change_delegate_(NULL) {
20 }
21 
~SyncRollbackManager()22 SyncRollbackManager::~SyncRollbackManager() {
23 }
24 
Init(InitArgs * args)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 
StartSyncingNormally(const ModelSafeRoutingInfo & routing_info)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 
DeleteOnWorkerThread(ModelType type,std::vector<int64> handles)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 
NotifyRollbackDone()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