OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/sync/driver/model_association_manager.h" | 5 #include "components/sync/driver/model_association_manager.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <functional> | 11 #include <functional> |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/macros.h" | 14 #include "base/macros.h" |
15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
16 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
17 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" |
18 #include "components/sync/api/sync_merge_result.h" | 18 #include "components/sync/api/sync_merge_result.h" |
19 #include "components/sync/base/model_type.h" | 19 #include "components/sync/base/model_type.h" |
20 | 20 |
21 using syncer::ModelTypeSet; | 21 namespace syncer { |
22 | |
23 namespace sync_driver { | |
24 | 22 |
25 namespace { | 23 namespace { |
26 | 24 |
27 static const syncer::ModelType kStartOrder[] = { | 25 static const ModelType kStartOrder[] = { |
28 syncer::NIGORI, // Listed for completeness. | 26 NIGORI, // Listed for completeness. |
29 syncer::DEVICE_INFO, // Listed for completeness. | 27 DEVICE_INFO, // Listed for completeness. |
30 syncer::EXPERIMENTS, // Listed for completeness. | 28 EXPERIMENTS, // Listed for completeness. |
31 syncer::PROXY_TABS, // Listed for completeness. | 29 PROXY_TABS, // Listed for completeness. |
32 | 30 |
33 // Kick off the association of the non-UI types first so they can associate | 31 // Kick off the association of the non-UI types first so they can associate |
34 // in parallel with the UI types. | 32 // in parallel with the UI types. |
35 syncer::PASSWORDS, syncer::AUTOFILL, syncer::AUTOFILL_PROFILE, | 33 PASSWORDS, AUTOFILL, AUTOFILL_PROFILE, AUTOFILL_WALLET_DATA, |
36 syncer::AUTOFILL_WALLET_DATA, syncer::AUTOFILL_WALLET_METADATA, | 34 AUTOFILL_WALLET_METADATA, EXTENSION_SETTINGS, APP_SETTINGS, TYPED_URLS, |
37 syncer::EXTENSION_SETTINGS, syncer::APP_SETTINGS, syncer::TYPED_URLS, | 35 HISTORY_DELETE_DIRECTIVES, SYNCED_NOTIFICATIONS, |
38 syncer::HISTORY_DELETE_DIRECTIVES, syncer::SYNCED_NOTIFICATIONS, | 36 SYNCED_NOTIFICATION_APP_INFO, |
39 syncer::SYNCED_NOTIFICATION_APP_INFO, | |
40 | 37 |
41 // UI thread data types. | 38 // UI thread data types. |
42 syncer::BOOKMARKS, | 39 BOOKMARKS, |
43 syncer::SUPERVISED_USERS, // Syncing supervised users on initial login | 40 SUPERVISED_USERS, // Syncing supervised users on initial login |
44 // might block creating a new supervised user, | 41 // might block creating a new supervised user, |
45 // so we want to do it early. | 42 // so we want to do it early. |
46 syncer::PREFERENCES, syncer::PRIORITY_PREFERENCES, syncer::EXTENSIONS, | 43 PREFERENCES, PRIORITY_PREFERENCES, EXTENSIONS, APPS, APP_LIST, ARC_PACKAGE, |
47 syncer::APPS, syncer::APP_LIST, syncer::ARC_PACKAGE, syncer::READING_LIST, | 44 READING_LIST, THEMES, SEARCH_ENGINES, SESSIONS, APP_NOTIFICATIONS, |
48 syncer::THEMES, syncer::SEARCH_ENGINES, syncer::SESSIONS, | 45 DICTIONARY, FAVICON_IMAGES, FAVICON_TRACKING, PRINTERS, |
49 syncer::APP_NOTIFICATIONS, syncer::DICTIONARY, syncer::FAVICON_IMAGES, | 46 SUPERVISED_USER_SETTINGS, SUPERVISED_USER_SHARED_SETTINGS, |
50 syncer::FAVICON_TRACKING, syncer::PRINTERS, | 47 SUPERVISED_USER_WHITELISTS, ARTICLES, WIFI_CREDENTIALS, |
51 syncer::SUPERVISED_USER_SETTINGS, syncer::SUPERVISED_USER_SHARED_SETTINGS, | |
52 syncer::SUPERVISED_USER_WHITELISTS, syncer::ARTICLES, | |
53 syncer::WIFI_CREDENTIALS, | |
54 }; | 48 }; |
55 | 49 |
56 static_assert(arraysize(kStartOrder) == | 50 static_assert(arraysize(kStartOrder) == |
57 syncer::MODEL_TYPE_COUNT - syncer::FIRST_REAL_MODEL_TYPE, | 51 MODEL_TYPE_COUNT - FIRST_REAL_MODEL_TYPE, |
58 "kStartOrder must have MODEL_TYPE_COUNT - " | 52 "kStartOrder must have MODEL_TYPE_COUNT - " |
59 "FIRST_REAL_MODEL_TYPE elements"); | 53 "FIRST_REAL_MODEL_TYPE elements"); |
60 | 54 |
61 // The amount of time we wait for association to finish. If some types haven't | 55 // The amount of time we wait for association to finish. If some types haven't |
62 // finished association by the time, DataTypeManager is notified of the | 56 // finished association by the time, DataTypeManager is notified of the |
63 // unfinished types. | 57 // unfinished types. |
64 const int64_t kAssociationTimeOutInSeconds = 600; | 58 const int64_t kAssociationTimeOutInSeconds = 600; |
65 | 59 |
66 syncer::DataTypeAssociationStats BuildAssociationStatsFromMergeResults( | 60 DataTypeAssociationStats BuildAssociationStatsFromMergeResults( |
67 const syncer::SyncMergeResult& local_merge_result, | 61 const SyncMergeResult& local_merge_result, |
68 const syncer::SyncMergeResult& syncer_merge_result, | 62 const SyncMergeResult& syncer_merge_result, |
69 const base::TimeDelta& association_wait_time, | 63 const base::TimeDelta& association_wait_time, |
70 const base::TimeDelta& association_time) { | 64 const base::TimeDelta& association_time) { |
71 DCHECK_EQ(local_merge_result.model_type(), syncer_merge_result.model_type()); | 65 DCHECK_EQ(local_merge_result.model_type(), syncer_merge_result.model_type()); |
72 syncer::DataTypeAssociationStats stats; | 66 DataTypeAssociationStats stats; |
73 stats.had_error = | 67 stats.had_error = |
74 local_merge_result.error().IsSet() || syncer_merge_result.error().IsSet(); | 68 local_merge_result.error().IsSet() || syncer_merge_result.error().IsSet(); |
75 stats.num_local_items_before_association = | 69 stats.num_local_items_before_association = |
76 local_merge_result.num_items_before_association(); | 70 local_merge_result.num_items_before_association(); |
77 stats.num_sync_items_before_association = | 71 stats.num_sync_items_before_association = |
78 syncer_merge_result.num_items_before_association(); | 72 syncer_merge_result.num_items_before_association(); |
79 stats.num_local_items_after_association = | 73 stats.num_local_items_after_association = |
80 local_merge_result.num_items_after_association(); | 74 local_merge_result.num_items_after_association(); |
81 stats.num_sync_items_after_association = | 75 stats.num_sync_items_after_association = |
82 syncer_merge_result.num_items_after_association(); | 76 syncer_merge_result.num_items_after_association(); |
(...skipping 25 matching lines...) Expand all Loading... |
108 weak_ptr_factory_(this) { | 102 weak_ptr_factory_(this) { |
109 // Ensure all data type controllers are stopped. | 103 // Ensure all data type controllers are stopped. |
110 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 104 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
111 it != controllers_->end(); ++it) { | 105 it != controllers_->end(); ++it) { |
112 DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state()); | 106 DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state()); |
113 } | 107 } |
114 } | 108 } |
115 | 109 |
116 ModelAssociationManager::~ModelAssociationManager() {} | 110 ModelAssociationManager::~ModelAssociationManager() {} |
117 | 111 |
118 void ModelAssociationManager::Initialize(syncer::ModelTypeSet desired_types) { | 112 void ModelAssociationManager::Initialize(ModelTypeSet desired_types) { |
119 // state_ can be INITIALIZED if types are reconfigured when | 113 // state_ can be INITIALIZED if types are reconfigured when |
120 // data is being downloaded, so StartAssociationAsync() is never called for | 114 // data is being downloaded, so StartAssociationAsync() is never called for |
121 // the first configuration. | 115 // the first configuration. |
122 DCHECK_NE(ASSOCIATING, state_); | 116 DCHECK_NE(ASSOCIATING, state_); |
123 | 117 |
124 // Only keep types that have controllers. | 118 // Only keep types that have controllers. |
125 desired_types_.Clear(); | 119 desired_types_.Clear(); |
126 for (syncer::ModelTypeSet::Iterator it = desired_types.First(); it.Good(); | 120 for (ModelTypeSet::Iterator it = desired_types.First(); it.Good(); it.Inc()) { |
127 it.Inc()) { | |
128 if (controllers_->find(it.Get()) != controllers_->end()) | 121 if (controllers_->find(it.Get()) != controllers_->end()) |
129 desired_types_.Put(it.Get()); | 122 desired_types_.Put(it.Get()); |
130 } | 123 } |
131 | 124 |
132 DVLOG(1) << "ModelAssociationManager: Initializing for " | 125 DVLOG(1) << "ModelAssociationManager: Initializing for " |
133 << syncer::ModelTypeSetToString(desired_types_); | 126 << ModelTypeSetToString(desired_types_); |
134 | 127 |
135 state_ = INITIALIZED; | 128 state_ = INITIALIZED; |
136 notified_about_ready_for_configure_ = false; | 129 notified_about_ready_for_configure_ = false; |
137 | 130 |
138 StopDisabledTypes(); | 131 StopDisabledTypes(); |
139 LoadEnabledTypes(); | 132 LoadEnabledTypes(); |
140 } | 133 } |
141 | 134 |
142 void ModelAssociationManager::StopDatatype(const syncer::SyncError& error, | 135 void ModelAssociationManager::StopDatatype(const SyncError& error, |
143 DataTypeController* dtc) { | 136 DataTypeController* dtc) { |
144 loaded_types_.Remove(dtc->type()); | 137 loaded_types_.Remove(dtc->type()); |
145 associated_types_.Remove(dtc->type()); | 138 associated_types_.Remove(dtc->type()); |
146 associating_types_.Remove(dtc->type()); | 139 associating_types_.Remove(dtc->type()); |
147 | 140 |
148 if (error.IsSet() || dtc->state() != DataTypeController::NOT_RUNNING) { | 141 if (error.IsSet() || dtc->state() != DataTypeController::NOT_RUNNING) { |
149 // If an error was set, the delegate must be informed of the error. | 142 // If an error was set, the delegate must be informed of the error. |
150 delegate_->OnSingleDataTypeWillStop(dtc->type(), error); | 143 delegate_->OnSingleDataTypeWillStop(dtc->type(), error); |
151 dtc->Stop(); | 144 dtc->Stop(); |
152 } | 145 } |
153 } | 146 } |
154 | 147 |
155 void ModelAssociationManager::StopDisabledTypes() { | 148 void ModelAssociationManager::StopDisabledTypes() { |
156 DVLOG(1) << "ModelAssociationManager: Stopping disabled types."; | 149 DVLOG(1) << "ModelAssociationManager: Stopping disabled types."; |
157 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 150 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
158 it != controllers_->end(); ++it) { | 151 it != controllers_->end(); ++it) { |
159 DataTypeController* dtc = (*it).second.get(); | 152 DataTypeController* dtc = (*it).second.get(); |
160 if (dtc->state() != DataTypeController::NOT_RUNNING && | 153 if (dtc->state() != DataTypeController::NOT_RUNNING && |
161 !desired_types_.Has(dtc->type())) { | 154 !desired_types_.Has(dtc->type())) { |
162 DVLOG(1) << "ModelAssociationManager: stop " << dtc->name(); | 155 DVLOG(1) << "ModelAssociationManager: stop " << dtc->name(); |
163 StopDatatype(syncer::SyncError(), dtc); | 156 StopDatatype(SyncError(), dtc); |
164 } | 157 } |
165 } | 158 } |
166 } | 159 } |
167 | 160 |
168 void ModelAssociationManager::LoadEnabledTypes() { | 161 void ModelAssociationManager::LoadEnabledTypes() { |
169 // Load in kStartOrder. | 162 // Load in kStartOrder. |
170 for (size_t i = 0; i < arraysize(kStartOrder); i++) { | 163 for (size_t i = 0; i < arraysize(kStartOrder); i++) { |
171 syncer::ModelType type = kStartOrder[i]; | 164 ModelType type = kStartOrder[i]; |
172 if (!desired_types_.Has(type)) | 165 if (!desired_types_.Has(type)) |
173 continue; | 166 continue; |
174 | 167 |
175 DCHECK(controllers_->find(type) != controllers_->end()); | 168 DCHECK(controllers_->find(type) != controllers_->end()); |
176 DataTypeController* dtc = controllers_->find(type)->second.get(); | 169 DataTypeController* dtc = controllers_->find(type)->second.get(); |
177 if (dtc->state() == DataTypeController::NOT_RUNNING) { | 170 if (dtc->state() == DataTypeController::NOT_RUNNING) { |
178 DCHECK(!loaded_types_.Has(dtc->type())); | 171 DCHECK(!loaded_types_.Has(dtc->type())); |
179 DCHECK(!associated_types_.Has(dtc->type())); | 172 DCHECK(!associated_types_.Has(dtc->type())); |
180 dtc->LoadModels(base::Bind(&ModelAssociationManager::ModelLoadCallback, | 173 dtc->LoadModels(base::Bind(&ModelAssociationManager::ModelLoadCallback, |
181 weak_ptr_factory_.GetWeakPtr())); | 174 weak_ptr_factory_.GetWeakPtr())); |
182 } | 175 } |
183 } | 176 } |
184 NotifyDelegateIfReadyForConfigure(); | 177 NotifyDelegateIfReadyForConfigure(); |
185 } | 178 } |
186 | 179 |
187 void ModelAssociationManager::StartAssociationAsync( | 180 void ModelAssociationManager::StartAssociationAsync( |
188 const syncer::ModelTypeSet& types_to_associate) { | 181 const ModelTypeSet& types_to_associate) { |
189 DCHECK_EQ(INITIALIZED, state_); | 182 DCHECK_EQ(INITIALIZED, state_); |
190 DVLOG(1) << "Starting association for " | 183 DVLOG(1) << "Starting association for " |
191 << syncer::ModelTypeSetToString(types_to_associate); | 184 << ModelTypeSetToString(types_to_associate); |
192 state_ = ASSOCIATING; | 185 state_ = ASSOCIATING; |
193 | 186 |
194 association_start_time_ = base::TimeTicks::Now(); | 187 association_start_time_ = base::TimeTicks::Now(); |
195 | 188 |
196 requested_types_ = types_to_associate; | 189 requested_types_ = types_to_associate; |
197 | 190 |
198 associating_types_ = types_to_associate; | 191 associating_types_ = types_to_associate; |
199 associating_types_.RetainAll(desired_types_); | 192 associating_types_.RetainAll(desired_types_); |
200 associating_types_.RemoveAll(associated_types_); | 193 associating_types_.RemoveAll(associated_types_); |
201 | 194 |
202 // Assume success. | 195 // Assume success. |
203 configure_status_ = DataTypeManager::OK; | 196 configure_status_ = DataTypeManager::OK; |
204 | 197 |
205 // Done if no types to associate. | 198 // Done if no types to associate. |
206 if (associating_types_.Empty()) { | 199 if (associating_types_.Empty()) { |
207 ModelAssociationDone(INITIALIZED); | 200 ModelAssociationDone(INITIALIZED); |
208 return; | 201 return; |
209 } | 202 } |
210 | 203 |
211 timer_.Start(FROM_HERE, | 204 timer_.Start(FROM_HERE, |
212 base::TimeDelta::FromSeconds(kAssociationTimeOutInSeconds), | 205 base::TimeDelta::FromSeconds(kAssociationTimeOutInSeconds), |
213 base::Bind(&ModelAssociationManager::ModelAssociationDone, | 206 base::Bind(&ModelAssociationManager::ModelAssociationDone, |
214 weak_ptr_factory_.GetWeakPtr(), INITIALIZED)); | 207 weak_ptr_factory_.GetWeakPtr(), INITIALIZED)); |
215 | 208 |
216 // Start association of types that are loaded in specified order. | 209 // Start association of types that are loaded in specified order. |
217 for (size_t i = 0; i < arraysize(kStartOrder); i++) { | 210 for (size_t i = 0; i < arraysize(kStartOrder); i++) { |
218 syncer::ModelType type = kStartOrder[i]; | 211 ModelType type = kStartOrder[i]; |
219 if (!associating_types_.Has(type) || !loaded_types_.Has(type)) | 212 if (!associating_types_.Has(type) || !loaded_types_.Has(type)) |
220 continue; | 213 continue; |
221 | 214 |
222 DataTypeController* dtc = controllers_->find(type)->second.get(); | 215 DataTypeController* dtc = controllers_->find(type)->second.get(); |
223 DCHECK(DataTypeController::MODEL_LOADED == dtc->state() || | 216 DCHECK(DataTypeController::MODEL_LOADED == dtc->state() || |
224 DataTypeController::ASSOCIATING == dtc->state()); | 217 DataTypeController::ASSOCIATING == dtc->state()); |
225 if (dtc->state() == DataTypeController::MODEL_LOADED) { | 218 if (dtc->state() == DataTypeController::MODEL_LOADED) { |
226 TRACE_EVENT_ASYNC_BEGIN1("sync", "ModelAssociation", dtc, "DataType", | 219 TRACE_EVENT_ASYNC_BEGIN1("sync", "ModelAssociation", dtc, "DataType", |
227 ModelTypeToString(type)); | 220 ModelTypeToString(type)); |
228 | 221 |
229 dtc->StartAssociating(base::Bind( | 222 dtc->StartAssociating(base::Bind( |
230 &ModelAssociationManager::TypeStartCallback, | 223 &ModelAssociationManager::TypeStartCallback, |
231 weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); | 224 weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); |
232 } | 225 } |
233 } | 226 } |
234 } | 227 } |
235 | 228 |
236 void ModelAssociationManager::Stop() { | 229 void ModelAssociationManager::Stop() { |
237 // Ignore callbacks from controllers. | 230 // Ignore callbacks from controllers. |
238 weak_ptr_factory_.InvalidateWeakPtrs(); | 231 weak_ptr_factory_.InvalidateWeakPtrs(); |
239 | 232 |
240 // Stop started data types. | 233 // Stop started data types. |
241 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 234 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
242 it != controllers_->end(); ++it) { | 235 it != controllers_->end(); ++it) { |
243 DataTypeController* dtc = (*it).second.get(); | 236 DataTypeController* dtc = (*it).second.get(); |
244 if (dtc->state() != DataTypeController::NOT_RUNNING) { | 237 if (dtc->state() != DataTypeController::NOT_RUNNING) { |
245 StopDatatype(syncer::SyncError(), dtc); | 238 StopDatatype(SyncError(), dtc); |
246 DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name(); | 239 DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name(); |
247 } | 240 } |
248 } | 241 } |
249 | 242 |
250 desired_types_.Clear(); | 243 desired_types_.Clear(); |
251 loaded_types_.Clear(); | 244 loaded_types_.Clear(); |
252 associated_types_.Clear(); | 245 associated_types_.Clear(); |
253 | 246 |
254 if (state_ == ASSOCIATING) { | 247 if (state_ == ASSOCIATING) { |
255 if (configure_status_ == DataTypeManager::OK) | 248 if (configure_status_ == DataTypeManager::OK) |
256 configure_status_ = DataTypeManager::ABORTED; | 249 configure_status_ = DataTypeManager::ABORTED; |
257 DVLOG(1) << "ModelAssociationManager: Calling OnModelAssociationDone"; | 250 DVLOG(1) << "ModelAssociationManager: Calling OnModelAssociationDone"; |
258 ModelAssociationDone(IDLE); | 251 ModelAssociationDone(IDLE); |
259 } else { | 252 } else { |
260 DCHECK(associating_types_.Empty()); | 253 DCHECK(associating_types_.Empty()); |
261 DCHECK(requested_types_.Empty()); | 254 DCHECK(requested_types_.Empty()); |
262 state_ = IDLE; | 255 state_ = IDLE; |
263 } | 256 } |
264 } | 257 } |
265 | 258 |
266 void ModelAssociationManager::ModelLoadCallback( | 259 void ModelAssociationManager::ModelLoadCallback(ModelType type, |
267 syncer::ModelType type, | 260 const SyncError& error) { |
268 const syncer::SyncError& error) { | |
269 DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for " | 261 DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for " |
270 << syncer::ModelTypeToString(type); | 262 << ModelTypeToString(type); |
271 | 263 |
272 if (error.IsSet()) { | 264 if (error.IsSet()) { |
273 syncer::SyncMergeResult local_merge_result(type); | 265 SyncMergeResult local_merge_result(type); |
274 local_merge_result.set_error(error); | 266 local_merge_result.set_error(error); |
275 TypeStartCallback(type, base::TimeTicks::Now(), | 267 TypeStartCallback(type, base::TimeTicks::Now(), |
276 DataTypeController::ASSOCIATION_FAILED, | 268 DataTypeController::ASSOCIATION_FAILED, |
277 local_merge_result, syncer::SyncMergeResult(type)); | 269 local_merge_result, SyncMergeResult(type)); |
278 return; | 270 return; |
279 } | 271 } |
280 | 272 |
281 // This happens when slow loading type is disabled by new configuration. | 273 // This happens when slow loading type is disabled by new configuration. |
282 if (!desired_types_.Has(type)) | 274 if (!desired_types_.Has(type)) |
283 return; | 275 return; |
284 | 276 |
285 DCHECK(!loaded_types_.Has(type)); | 277 DCHECK(!loaded_types_.Has(type)); |
286 loaded_types_.Put(type); | 278 loaded_types_.Put(type); |
287 NotifyDelegateIfReadyForConfigure(); | 279 NotifyDelegateIfReadyForConfigure(); |
288 if (associating_types_.Has(type)) { | 280 if (associating_types_.Has(type)) { |
289 DataTypeController* dtc = controllers_->find(type)->second.get(); | 281 DataTypeController* dtc = controllers_->find(type)->second.get(); |
290 // If initial sync was done for this datatype then | 282 // If initial sync was done for this datatype then |
291 // NotifyDelegateIfReadyForConfigure possibly already triggered model | 283 // NotifyDelegateIfReadyForConfigure possibly already triggered model |
292 // association and StartAssociating was already called for this type. To | 284 // association and StartAssociating was already called for this type. To |
293 // ensure StartAssociating is called only once only make a call if state is | 285 // ensure StartAssociating is called only once only make a call if state is |
294 // MODEL_LOADED. | 286 // MODEL_LOADED. |
295 // TODO(pavely): Add test for this scenario in DataTypeManagerImpl | 287 // TODO(pavely): Add test for this scenario in DataTypeManagerImpl |
296 // unittests. | 288 // unittests. |
297 if (dtc->state() == DataTypeController::MODEL_LOADED) { | 289 if (dtc->state() == DataTypeController::MODEL_LOADED) { |
298 dtc->StartAssociating(base::Bind( | 290 dtc->StartAssociating(base::Bind( |
299 &ModelAssociationManager::TypeStartCallback, | 291 &ModelAssociationManager::TypeStartCallback, |
300 weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); | 292 weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); |
301 } | 293 } |
302 } | 294 } |
303 } | 295 } |
304 | 296 |
305 void ModelAssociationManager::TypeStartCallback( | 297 void ModelAssociationManager::TypeStartCallback( |
306 syncer::ModelType type, | 298 ModelType type, |
307 base::TimeTicks type_start_time, | 299 base::TimeTicks type_start_time, |
308 DataTypeController::ConfigureResult start_result, | 300 DataTypeController::ConfigureResult start_result, |
309 const syncer::SyncMergeResult& local_merge_result, | 301 const SyncMergeResult& local_merge_result, |
310 const syncer::SyncMergeResult& syncer_merge_result) { | 302 const SyncMergeResult& syncer_merge_result) { |
311 if (desired_types_.Has(type) && | 303 if (desired_types_.Has(type) && |
312 !DataTypeController::IsSuccessfulResult(start_result)) { | 304 !DataTypeController::IsSuccessfulResult(start_result)) { |
313 DVLOG(1) << "ModelAssociationManager: Type encountered an error."; | 305 DVLOG(1) << "ModelAssociationManager: Type encountered an error."; |
314 desired_types_.Remove(type); | 306 desired_types_.Remove(type); |
315 DataTypeController* dtc = controllers_->find(type)->second.get(); | 307 DataTypeController* dtc = controllers_->find(type)->second.get(); |
316 StopDatatype(local_merge_result.error(), dtc); | 308 StopDatatype(local_merge_result.error(), dtc); |
317 NotifyDelegateIfReadyForConfigure(); | 309 NotifyDelegateIfReadyForConfigure(); |
318 | 310 |
319 // Update configuration result. | 311 // Update configuration result. |
320 if (start_result == DataTypeController::UNRECOVERABLE_ERROR) | 312 if (start_result == DataTypeController::UNRECOVERABLE_ERROR) |
(...skipping 16 matching lines...) Expand all Loading... |
337 | 329 |
338 if (state_ != ASSOCIATING) | 330 if (state_ != ASSOCIATING) |
339 return; | 331 return; |
340 | 332 |
341 TRACE_EVENT_ASYNC_END1("sync", "ModelAssociation", | 333 TRACE_EVENT_ASYNC_END1("sync", "ModelAssociation", |
342 controllers_->find(type)->second.get(), "DataType", | 334 controllers_->find(type)->second.get(), "DataType", |
343 ModelTypeToString(type)); | 335 ModelTypeToString(type)); |
344 | 336 |
345 // Track the merge results if we succeeded or an association failure | 337 // Track the merge results if we succeeded or an association failure |
346 // occurred. | 338 // occurred. |
347 if (syncer::ProtocolTypes().Has(type)) { | 339 if (ProtocolTypes().Has(type)) { |
348 base::TimeDelta association_wait_time = | 340 base::TimeDelta association_wait_time = |
349 std::max(base::TimeDelta(), type_start_time - association_start_time_); | 341 std::max(base::TimeDelta(), type_start_time - association_start_time_); |
350 base::TimeDelta association_time = base::TimeTicks::Now() - type_start_time; | 342 base::TimeDelta association_time = base::TimeTicks::Now() - type_start_time; |
351 syncer::DataTypeAssociationStats stats = | 343 DataTypeAssociationStats stats = BuildAssociationStatsFromMergeResults( |
352 BuildAssociationStatsFromMergeResults( | 344 local_merge_result, syncer_merge_result, association_wait_time, |
353 local_merge_result, syncer_merge_result, association_wait_time, | 345 association_time); |
354 association_time); | |
355 delegate_->OnSingleDataTypeAssociationDone(type, stats); | 346 delegate_->OnSingleDataTypeAssociationDone(type, stats); |
356 } | 347 } |
357 | 348 |
358 associating_types_.Remove(type); | 349 associating_types_.Remove(type); |
359 | 350 |
360 if (associating_types_.Empty()) | 351 if (associating_types_.Empty()) |
361 ModelAssociationDone(INITIALIZED); | 352 ModelAssociationDone(INITIALIZED); |
362 } | 353 } |
363 | 354 |
364 void ModelAssociationManager::ModelAssociationDone(State new_state) { | 355 void ModelAssociationManager::ModelAssociationDone(State new_state) { |
365 DCHECK_NE(IDLE, state_); | 356 DCHECK_NE(IDLE, state_); |
366 | 357 |
367 if (state_ == INITIALIZED) { | 358 if (state_ == INITIALIZED) { |
368 // No associations are currently happening. Just reset the state. | 359 // No associations are currently happening. Just reset the state. |
369 state_ = new_state; | 360 state_ = new_state; |
370 return; | 361 return; |
371 } | 362 } |
372 | 363 |
373 DVLOG(1) << "Model association complete for " | 364 DVLOG(1) << "Model association complete for " |
374 << syncer::ModelTypeSetToString(requested_types_); | 365 << ModelTypeSetToString(requested_types_); |
375 | 366 |
376 timer_.Stop(); | 367 timer_.Stop(); |
377 | 368 |
378 // Treat any unfinished types as having errors. | 369 // Treat any unfinished types as having errors. |
379 desired_types_.RemoveAll(associating_types_); | 370 desired_types_.RemoveAll(associating_types_); |
380 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 371 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
381 it != controllers_->end(); ++it) { | 372 it != controllers_->end(); ++it) { |
382 DataTypeController* dtc = (*it).second.get(); | 373 DataTypeController* dtc = (*it).second.get(); |
383 if (associating_types_.Has(dtc->type()) && | 374 if (associating_types_.Has(dtc->type()) && |
384 dtc->state() != DataTypeController::NOT_RUNNING) { | 375 dtc->state() != DataTypeController::NOT_RUNNING) { |
385 UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed", | 376 UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed", |
386 ModelTypeToHistogramInt(dtc->type()), | 377 ModelTypeToHistogramInt(dtc->type()), |
387 syncer::MODEL_TYPE_COUNT); | 378 MODEL_TYPE_COUNT); |
388 StopDatatype( | 379 StopDatatype(SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, |
389 syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 380 "Association timed out.", dtc->type()), |
390 "Association timed out.", dtc->type()), | 381 dtc); |
391 dtc); | |
392 } | 382 } |
393 } | 383 } |
394 | 384 |
395 DataTypeManager::ConfigureResult result(configure_status_, requested_types_); | 385 DataTypeManager::ConfigureResult result(configure_status_, requested_types_); |
396 | 386 |
397 // Need to reset state before invoking delegate in order to avoid re-entrancy | 387 // Need to reset state before invoking delegate in order to avoid re-entrancy |
398 // issues (delegate may trigger a reconfiguration). | 388 // issues (delegate may trigger a reconfiguration). |
399 associating_types_.Clear(); | 389 associating_types_.Clear(); |
400 requested_types_.Clear(); | 390 requested_types_.Clear(); |
401 state_ = new_state; | 391 state_ = new_state; |
402 | 392 |
403 delegate_->OnModelAssociationDone(result); | 393 delegate_->OnModelAssociationDone(result); |
404 } | 394 } |
405 | 395 |
406 base::OneShotTimer* ModelAssociationManager::GetTimerForTesting() { | 396 base::OneShotTimer* ModelAssociationManager::GetTimerForTesting() { |
407 return &timer_; | 397 return &timer_; |
408 } | 398 } |
409 | 399 |
410 void ModelAssociationManager::NotifyDelegateIfReadyForConfigure() { | 400 void ModelAssociationManager::NotifyDelegateIfReadyForConfigure() { |
411 if (notified_about_ready_for_configure_) | 401 if (notified_about_ready_for_configure_) |
412 return; | 402 return; |
413 for (const auto& type_dtc_pair : *controllers_) { | 403 for (const auto& type_dtc_pair : *controllers_) { |
414 syncer::ModelType type = type_dtc_pair.first; | 404 ModelType type = type_dtc_pair.first; |
415 if (!desired_types_.Has(type)) | 405 if (!desired_types_.Has(type)) |
416 continue; | 406 continue; |
417 DataTypeController* dtc = type_dtc_pair.second.get(); | 407 DataTypeController* dtc = type_dtc_pair.second.get(); |
418 if (dtc->ShouldLoadModelBeforeConfigure() && !loaded_types_.Has(type)) { | 408 if (dtc->ShouldLoadModelBeforeConfigure() && !loaded_types_.Has(type)) { |
419 // At least one type is not ready. | 409 // At least one type is not ready. |
420 return; | 410 return; |
421 } | 411 } |
422 } | 412 } |
423 | 413 |
424 notified_about_ready_for_configure_ = true; | 414 notified_about_ready_for_configure_ = true; |
425 delegate_->OnAllDataTypesReadyForConfigure(); | 415 delegate_->OnAllDataTypesReadyForConfigure(); |
426 } | 416 } |
427 | 417 |
428 } // namespace sync_driver | 418 } // namespace syncer |
OLD | NEW |