1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_
#define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_
#include <map>
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "sync/internal_api/public/base/model_type.h"
#include "sync/internal_api/public/engine/model_safe_worker.h"
#include "sync/internal_api/public/sync_manager.h"
class Profile;
namespace base {
class MessageLoop;
}
namespace syncer {
struct UserShare;
} // namespace syncer
namespace browser_sync {
class ChangeProcessor;
class UIModelWorker;
// A class that keep track of the workers, change processors, and
// routing info for the enabled sync types, and also routes change
// events to the right processors.
class SyncBackendRegistrar : public syncer::SyncManager::ChangeDelegate,
public syncer::WorkerLoopDestructionObserver {
public:
// |name| is used for debugging. Does not take ownership of |profile| or
// |sync_loop|. Must be created on the UI thread.
SyncBackendRegistrar(const std::string& name,
Profile* profile,
scoped_ptr<base::Thread> sync_thread);
// SyncBackendRegistrar must be destroyed as follows:
//
// 1) On the UI thread, call RequestWorkerStopOnUIThread().
// 2) UI posts task to shut down syncer on sync thread.
// 3) If sync is disabled, call ReleaseSyncThread() on the UI thread.
// 3) UI posts SyncBackendRegistrar::ShutDown() on sync thread to
// unregister workers from observing destruction of their working loops.
// 4) Workers notify registrar when unregistration finishes or working
// loops are destroyed. Registrar destroys itself on last worker
// notification. Sync thread will be stopped if ownership was not
// released.
virtual ~SyncBackendRegistrar();
// Informs the SyncBackendRegistrar of the currently enabled set of types.
// These types will be placed in the passive group. This function should be
// called exactly once during startup.
void SetInitialTypes(syncer::ModelTypeSet initial_types);
// Returns whether or not we are currently syncing encryption keys.
// Must be called on the UI thread.
bool IsNigoriEnabled() const;
// Removes all types in |types_to_remove| from the routing info and
// adds all the types in |types_to_add| to the routing info that are
// not already there (initially put in the passive group).
// |types_to_remove| and |types_to_add| must be disjoint. Returns
// the set of newly-added types. Must be called on the UI thread.
syncer::ModelTypeSet ConfigureDataTypes(
syncer::ModelTypeSet types_to_add,
syncer::ModelTypeSet types_to_remove);
// Returns the set of enabled types as of the last configuration. Note that
// this might be different from the current types in the routing info due
// to DeactiveDataType being called separately from ConfigureDataTypes.
syncer::ModelTypeSet GetLastConfiguredTypes() const;
// Must be called from the UI thread. (See destructor comment.)
void RequestWorkerStopOnUIThread();
// Activates the given data type (which should belong to the given
// group) and starts the given change processor. Must be called
// from |group|'s native thread.
void ActivateDataType(syncer::ModelType type,
syncer::ModelSafeGroup group,
ChangeProcessor* change_processor,
syncer::UserShare* user_share);
// Deactivates the given type if necessary. Must be called from the
// UI thread and not |type|'s native thread. Yes, this is
// surprising: see http://crbug.com/92804.
void DeactivateDataType(syncer::ModelType type);
// Returns true only between calls to ActivateDataType(type, ...)
// and DeactivateDataType(type). Used only by tests.
bool IsTypeActivatedForTest(syncer::ModelType type) const;
// SyncManager::ChangeDelegate implementation. May be called from
// any thread.
virtual void OnChangesApplied(
syncer::ModelType model_type,
int64 model_version,
const syncer::BaseTransaction* trans,
const syncer::ImmutableChangeRecordList& changes) OVERRIDE;
virtual void OnChangesComplete(syncer::ModelType model_type) OVERRIDE;
void GetWorkers(std::vector<syncer::ModelSafeWorker*>* out);
void GetModelSafeRoutingInfo(syncer::ModelSafeRoutingInfo* out);
// syncer::WorkerLoopDestructionObserver implementation.
virtual void OnWorkerLoopDestroyed(syncer::ModelSafeGroup group) OVERRIDE;
// Release ownership of |sync_thread_|. Called when sync is disabled.
scoped_ptr<base::Thread> ReleaseSyncThread();
// Unregister workers from loop destruction observation.
void Shutdown();
base::Thread* sync_thread();
private:
typedef std::map<syncer::ModelSafeGroup,
scoped_refptr<syncer::ModelSafeWorker> > WorkerMap;
typedef std::map<syncer::ModelType, ChangeProcessor*>
ProcessorMap;
// Callback after workers unregister from observing destruction of their
// working loops.
void OnWorkerUnregistrationDone(syncer::ModelSafeGroup group);
void RemoveWorker(syncer::ModelSafeGroup group);
// Returns the change processor for the given model, or NULL if none
// exists. Must be called from |group|'s native thread.
ChangeProcessor* GetProcessor(syncer::ModelType type) const;
// Must be called with |lock_| held. Simply returns the change
// processor for the given type, if it exists. May be called from
// any thread.
ChangeProcessor* GetProcessorUnsafe(syncer::ModelType type) const;
// Return true if |model_type| lives on the current thread. Must be
// called with |lock_| held. May be called on any thread.
bool IsCurrentThreadSafeForModel(
syncer::ModelType model_type) const;
// Name used for debugging.
const std::string name_;
Profile* const profile_;
// Protects all variables below.
mutable base::Lock lock_;
// We maintain ownership of all workers. In some cases, we need to
// ensure shutdown occurs in an expected sequence by Stop()ing
// certain workers. They are guaranteed to be valid because we only
// destroy elements of |workers_| after the syncapi has been
// destroyed. Unless a worker is no longer needed because all types
// that get routed to it have been disabled (from syncing). In that
// case, we'll destroy on demand *after* routing any dependent types
// to syncer::GROUP_PASSIVE, so that the syncapi doesn't call into garbage.
// If a key is present, it means at least one ModelType that routes
// to that model safe group is being synced.
WorkerMap workers_;
syncer::ModelSafeRoutingInfo routing_info_;
// The change processors that handle the different data types.
ProcessorMap processors_;
// The types that were enabled as of the last configuration. Updated on each
// call to ConfigureDataTypes as well as SetInitialTypes.
syncer::ModelTypeSet last_configured_types_;
// Parks stopped workers because they may still be referenced by syncer.
std::vector<scoped_refptr<syncer::ModelSafeWorker> > stopped_workers_;
// Declare |sync_thread_| at the end so that it will be destroyed before
// objects above because tasks on sync thread depend on those objects,
// e.g. Shutdown() depends on |lock_|, SyncManager::Init() depends on
// workers, etc.
scoped_ptr<base::Thread> sync_thread_;
DISALLOW_COPY_AND_ASSIGN(SyncBackendRegistrar);
};
} // namespace browser_sync
#endif // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_
|