Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(414)

Side by Side Diff: components/sync_driver/glue/sync_backend_registrar.cc

Issue 2203673002: [Sync] Move //components/sync_driver to //components/sync/driver. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sd-a
Patch Set: Full change rebased on static lib. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2012 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 "components/sync_driver/glue/sync_backend_registrar.h"
6
7 #include <cstddef>
8 #include <utility>
9
10 #include "base/compiler_specific.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "components/sync/core/user_share.h"
14 #include "components/sync_driver/change_processor.h"
15 #include "components/sync_driver/sync_client.h"
16
17 namespace browser_sync {
18
19 SyncBackendRegistrar::SyncBackendRegistrar(
20 const std::string& name,
21 sync_driver::SyncClient* sync_client,
22 std::unique_ptr<base::Thread> sync_thread,
23 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
24 const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
25 const scoped_refptr<base::SingleThreadTaskRunner>& file_thread)
26 : name_(name),
27 sync_client_(sync_client),
28 ui_thread_(ui_thread),
29 db_thread_(db_thread),
30 file_thread_(file_thread) {
31 DCHECK(ui_thread_->BelongsToCurrentThread());
32 DCHECK(sync_client_);
33
34 sync_thread_ = std::move(sync_thread);
35 if (!sync_thread_) {
36 sync_thread_.reset(new base::Thread("Chrome_SyncThread"));
37 base::Thread::Options options;
38 options.timer_slack = base::TIMER_SLACK_MAXIMUM;
39 CHECK(sync_thread_->StartWithOptions(options));
40 }
41
42 MaybeAddWorker(syncer::GROUP_DB);
43 MaybeAddWorker(syncer::GROUP_FILE);
44 MaybeAddWorker(syncer::GROUP_UI);
45 MaybeAddWorker(syncer::GROUP_PASSIVE);
46 MaybeAddWorker(syncer::GROUP_HISTORY);
47 MaybeAddWorker(syncer::GROUP_PASSWORD);
48
49 // Must have at least one worker for SyncBackendRegistrar to be destroyed
50 // correctly, as it is destroyed after the last worker dies.
51 DCHECK_GT(workers_.size(), 0u);
52 }
53
54 void SyncBackendRegistrar::RegisterNonBlockingType(syncer::ModelType type) {
55 DCHECK(ui_thread_->BelongsToCurrentThread());
56 base::AutoLock lock(lock_);
57 DCHECK(routing_info_.find(type) == routing_info_.end() ||
58 routing_info_[type] == syncer::GROUP_NON_BLOCKING);
59 non_blocking_types_.Put(type);
60 }
61
62 void SyncBackendRegistrar::SetInitialTypes(syncer::ModelTypeSet initial_types) {
63 base::AutoLock lock(lock_);
64
65 // This function should be called only once, shortly after construction. The
66 // routing info at that point is expected to be empty.
67 DCHECK(routing_info_.empty());
68
69 // Set our initial state to reflect the current status of the sync directory.
70 // This will ensure that our calculations in ConfigureDataTypes() will always
71 // return correct results.
72 for (syncer::ModelTypeSet::Iterator it = initial_types.First(); it.Good();
73 it.Inc()) {
74 routing_info_[it.Get()] = GetInitialGroupForType(it.Get());
75 }
76
77 if (!workers_.count(syncer::GROUP_HISTORY)) {
78 LOG_IF(WARNING, initial_types.Has(syncer::TYPED_URLS))
79 << "History store disabled, cannot sync Omnibox History";
80 routing_info_.erase(syncer::TYPED_URLS);
81 }
82
83 if (!workers_.count(syncer::GROUP_PASSWORD)) {
84 LOG_IF(WARNING, initial_types.Has(syncer::PASSWORDS))
85 << "Password store not initialized, cannot sync passwords";
86 routing_info_.erase(syncer::PASSWORDS);
87 }
88
89 last_configured_types_ = syncer::GetRoutingInfoTypes(routing_info_);
90 }
91
92 void SyncBackendRegistrar::AddRestoredNonBlockingType(syncer::ModelType type) {
93 DCHECK(ui_thread_->BelongsToCurrentThread());
94 base::AutoLock lock(lock_);
95 DCHECK(non_blocking_types_.Has(type));
96 DCHECK(routing_info_.find(type) == routing_info_.end());
97 routing_info_[type] = syncer::GROUP_NON_BLOCKING;
98 last_configured_types_.Put(type);
99 }
100
101 bool SyncBackendRegistrar::IsNigoriEnabled() const {
102 DCHECK(ui_thread_->BelongsToCurrentThread());
103 base::AutoLock lock(lock_);
104 return routing_info_.find(syncer::NIGORI) != routing_info_.end();
105 }
106
107 syncer::ModelTypeSet SyncBackendRegistrar::ConfigureDataTypes(
108 syncer::ModelTypeSet types_to_add,
109 syncer::ModelTypeSet types_to_remove) {
110 DCHECK(Intersection(types_to_add, types_to_remove).Empty());
111 syncer::ModelTypeSet filtered_types_to_add = types_to_add;
112 if (workers_.count(syncer::GROUP_HISTORY) == 0) {
113 LOG(WARNING) << "No history worker -- removing TYPED_URLS";
114 filtered_types_to_add.Remove(syncer::TYPED_URLS);
115 }
116 if (workers_.count(syncer::GROUP_PASSWORD) == 0) {
117 LOG(WARNING) << "No password worker -- removing PASSWORDS";
118 filtered_types_to_add.Remove(syncer::PASSWORDS);
119 }
120
121 base::AutoLock lock(lock_);
122 syncer::ModelTypeSet newly_added_types;
123 for (syncer::ModelTypeSet::Iterator it = filtered_types_to_add.First();
124 it.Good(); it.Inc()) {
125 // Add a newly specified data type as syncer::GROUP_PASSIVE into the
126 // routing_info, if it does not already exist.
127 if (routing_info_.count(it.Get()) == 0) {
128 routing_info_[it.Get()] = GetInitialGroupForType(it.Get());
129 newly_added_types.Put(it.Get());
130 }
131 }
132 for (syncer::ModelTypeSet::Iterator it = types_to_remove.First(); it.Good();
133 it.Inc()) {
134 routing_info_.erase(it.Get());
135 }
136
137 // TODO(akalin): Use SVLOG/SLOG if we add any more logging.
138 DVLOG(1) << name_ << ": Adding types "
139 << syncer::ModelTypeSetToString(types_to_add)
140 << " (with newly-added types "
141 << syncer::ModelTypeSetToString(newly_added_types)
142 << ") and removing types "
143 << syncer::ModelTypeSetToString(types_to_remove)
144 << " to get new routing info "
145 << syncer::ModelSafeRoutingInfoToString(routing_info_);
146 last_configured_types_ = syncer::GetRoutingInfoTypes(routing_info_);
147
148 return newly_added_types;
149 }
150
151 syncer::ModelTypeSet SyncBackendRegistrar::GetLastConfiguredTypes() const {
152 return last_configured_types_;
153 }
154
155 void SyncBackendRegistrar::RequestWorkerStopOnUIThread() {
156 DCHECK(ui_thread_->BelongsToCurrentThread());
157 base::AutoLock lock(lock_);
158 for (WorkerMap::const_iterator it = workers_.begin(); it != workers_.end();
159 ++it) {
160 it->second->RequestStop();
161 }
162 }
163
164 void SyncBackendRegistrar::ActivateDataType(
165 syncer::ModelType type,
166 syncer::ModelSafeGroup group,
167 sync_driver::ChangeProcessor* change_processor,
168 syncer::UserShare* user_share) {
169 DVLOG(1) << "Activate: " << syncer::ModelTypeToString(type);
170
171 base::AutoLock lock(lock_);
172 // Ensure that the given data type is in the PASSIVE group.
173 syncer::ModelSafeRoutingInfo::iterator i = routing_info_.find(type);
174 DCHECK(i != routing_info_.end());
175 DCHECK_EQ(i->second, syncer::GROUP_PASSIVE);
176 routing_info_[type] = group;
177
178 // Add the data type's change processor to the list of change
179 // processors so it can receive updates.
180 DCHECK_EQ(processors_.count(type), 0U);
181 processors_[type] = change_processor;
182
183 // Start the change processor.
184 change_processor->Start(user_share);
185 DCHECK(GetProcessorUnsafe(type));
186 }
187
188 void SyncBackendRegistrar::DeactivateDataType(syncer::ModelType type) {
189 DVLOG(1) << "Deactivate: " << syncer::ModelTypeToString(type);
190
191 DCHECK(ui_thread_->BelongsToCurrentThread() || IsControlType(type));
192 base::AutoLock lock(lock_);
193
194 routing_info_.erase(type);
195 ignore_result(processors_.erase(type));
196 DCHECK(!GetProcessorUnsafe(type));
197 }
198
199 bool SyncBackendRegistrar::IsTypeActivatedForTest(
200 syncer::ModelType type) const {
201 return GetProcessor(type) != NULL;
202 }
203
204 void SyncBackendRegistrar::OnChangesApplied(
205 syncer::ModelType model_type,
206 int64_t model_version,
207 const syncer::BaseTransaction* trans,
208 const syncer::ImmutableChangeRecordList& changes) {
209 sync_driver::ChangeProcessor* processor = GetProcessor(model_type);
210 if (!processor)
211 return;
212
213 processor->ApplyChangesFromSyncModel(trans, model_version, changes);
214 }
215
216 void SyncBackendRegistrar::OnChangesComplete(syncer::ModelType model_type) {
217 sync_driver::ChangeProcessor* processor = GetProcessor(model_type);
218 if (!processor)
219 return;
220
221 // This call just notifies the processor that it can commit; it
222 // already buffered any changes it plans to makes so needs no
223 // further information.
224 processor->CommitChangesFromSyncModel();
225 }
226
227 void SyncBackendRegistrar::GetWorkers(
228 std::vector<scoped_refptr<syncer::ModelSafeWorker>>* out) {
229 base::AutoLock lock(lock_);
230 out->clear();
231 for (WorkerMap::const_iterator it = workers_.begin(); it != workers_.end();
232 ++it) {
233 out->push_back(it->second.get());
234 }
235 }
236
237 void SyncBackendRegistrar::GetModelSafeRoutingInfo(
238 syncer::ModelSafeRoutingInfo* out) {
239 base::AutoLock lock(lock_);
240 syncer::ModelSafeRoutingInfo copy(routing_info_);
241 out->swap(copy);
242 }
243
244 sync_driver::ChangeProcessor* SyncBackendRegistrar::GetProcessor(
245 syncer::ModelType type) const {
246 base::AutoLock lock(lock_);
247 sync_driver::ChangeProcessor* processor = GetProcessorUnsafe(type);
248 if (!processor)
249 return NULL;
250
251 // We can only check if |processor| exists, as otherwise the type is
252 // mapped to syncer::GROUP_PASSIVE.
253 CHECK(IsCurrentThreadSafeForModel(type));
254 return processor;
255 }
256
257 sync_driver::ChangeProcessor* SyncBackendRegistrar::GetProcessorUnsafe(
258 syncer::ModelType type) const {
259 lock_.AssertAcquired();
260 std::map<syncer::ModelType, sync_driver::ChangeProcessor*>::const_iterator
261 it = processors_.find(type);
262
263 // Until model association happens for a datatype, it will not
264 // appear in the processors list. During this time, it is OK to
265 // drop changes on the floor (since model association has not
266 // happened yet). When the data type is activated, model
267 // association takes place then the change processor is added to the
268 // |processors_| list.
269 if (it == processors_.end())
270 return NULL;
271
272 return it->second;
273 }
274
275 bool SyncBackendRegistrar::IsCurrentThreadSafeForModel(
276 syncer::ModelType model_type) const {
277 lock_.AssertAcquired();
278 return IsOnThreadForGroup(model_type,
279 GetGroupForModelType(model_type, routing_info_));
280 }
281
282 bool SyncBackendRegistrar::IsOnThreadForGroup(
283 syncer::ModelType type,
284 syncer::ModelSafeGroup group) const {
285 switch (group) {
286 case syncer::GROUP_PASSIVE:
287 return IsControlType(type);
288 case syncer::GROUP_UI:
289 return ui_thread_->BelongsToCurrentThread();
290 case syncer::GROUP_DB:
291 return db_thread_->BelongsToCurrentThread();
292 case syncer::GROUP_FILE:
293 return file_thread_->BelongsToCurrentThread();
294 case syncer::GROUP_HISTORY:
295 // TODO(sync): How to check we're on the right thread?
296 return type == syncer::TYPED_URLS;
297 case syncer::GROUP_PASSWORD:
298 // TODO(sync): How to check we're on the right thread?
299 return type == syncer::PASSWORDS;
300 case syncer::GROUP_NON_BLOCKING:
301 // IsOnThreadForGroup shouldn't be called for non-blocking types.
302 return false;
303 }
304 NOTREACHED();
305 return false;
306 }
307
308 SyncBackendRegistrar::~SyncBackendRegistrar() {
309 DCHECK(workers_.empty());
310 }
311
312 void SyncBackendRegistrar::OnWorkerLoopDestroyed(syncer::ModelSafeGroup group) {
313 RemoveWorker(group);
314 }
315
316 void SyncBackendRegistrar::MaybeAddWorker(syncer::ModelSafeGroup group) {
317 const scoped_refptr<syncer::ModelSafeWorker> worker =
318 sync_client_->CreateModelWorkerForGroup(group, this);
319 if (worker) {
320 DCHECK(workers_.find(group) == workers_.end());
321 workers_[group] = worker;
322 workers_[group]->RegisterForLoopDestruction();
323 }
324 }
325
326 void SyncBackendRegistrar::OnWorkerUnregistrationDone(
327 syncer::ModelSafeGroup group) {
328 RemoveWorker(group);
329 }
330
331 void SyncBackendRegistrar::RemoveWorker(syncer::ModelSafeGroup group) {
332 DVLOG(1) << "Remove " << ModelSafeGroupToString(group) << " worker.";
333
334 bool last_worker = false;
335 {
336 base::AutoLock al(lock_);
337 WorkerMap::iterator it = workers_.find(group);
338 CHECK(it != workers_.end());
339 stopped_workers_.push_back(it->second);
340 workers_.erase(it);
341 last_worker = workers_.empty();
342 }
343
344 if (last_worker) {
345 // Self-destruction after last worker.
346 DVLOG(1) << "Destroy registrar on loop of "
347 << ModelSafeGroupToString(group);
348 delete this;
349 }
350 }
351
352 std::unique_ptr<base::Thread> SyncBackendRegistrar::ReleaseSyncThread() {
353 return std::move(sync_thread_);
354 }
355
356 void SyncBackendRegistrar::Shutdown() {
357 // All data types should have been deactivated by now.
358 DCHECK(processors_.empty());
359
360 // Unregister worker from observing loop destruction.
361 base::AutoLock al(lock_);
362 for (WorkerMap::iterator it = workers_.begin(); it != workers_.end(); ++it) {
363 it->second->UnregisterForLoopDestruction(
364 base::Bind(&SyncBackendRegistrar::OnWorkerUnregistrationDone,
365 base::Unretained(this)));
366 }
367 }
368
369 base::Thread* SyncBackendRegistrar::sync_thread() {
370 return sync_thread_.get();
371 }
372
373 syncer::ModelSafeGroup SyncBackendRegistrar::GetInitialGroupForType(
374 syncer::ModelType type) const {
375 if (non_blocking_types_.Has(type))
376 return syncer::GROUP_NON_BLOCKING;
377 else
378 return syncer::GROUP_PASSIVE;
379 }
380
381 } // namespace browser_sync
OLDNEW
« no previous file with comments | « components/sync_driver/glue/sync_backend_registrar.h ('k') | components/sync_driver/glue/sync_backend_registrar_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698