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