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

Side by Side Diff: chrome/browser/sync/glue/model_association_manager.cc

Issue 10387144: [Sync] - Implement isolated model association. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: For review. Created 8 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <algorithm> 5 #include <algorithm>
6 #include <functional> 6 #include <functional>
7 7
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 13
14 #include "chrome/browser/sync/glue/model_association_manager.h" 14 #include "chrome/browser/sync/glue/model_association_manager.h"
15 15
16 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
17 17
18 using content::BrowserThread; 18 using content::BrowserThread;
19 using syncable::ModelTypeSet; 19 using syncable::ModelTypeSet;
20 20
21 namespace browser_sync { 21 namespace browser_sync {
22 const int64 kDataTypeLoadWaitTimeInSeconds = 120;
22 namespace { 23 namespace {
23 24
24 static const syncable::ModelType kStartOrder[] = { 25 static const syncable::ModelType kStartOrder[] = {
25 syncable::NIGORI, // Listed for completeness. 26 syncable::NIGORI, // Listed for completeness.
26 syncable::BOOKMARKS, 27 syncable::BOOKMARKS,
27 syncable::PREFERENCES, 28 syncable::PREFERENCES,
28 syncable::AUTOFILL, 29 syncable::AUTOFILL,
29 syncable::AUTOFILL_PROFILE, 30 syncable::AUTOFILL_PROFILE,
30 syncable::EXTENSION_SETTINGS, 31 syncable::EXTENSION_SETTINGS,
31 syncable::EXTENSIONS, 32 syncable::EXTENSIONS,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 // Build a ModelType -> order map for sorting. 81 // Build a ModelType -> order map for sorting.
81 for (int i = 0; i < static_cast<int>(arraysize(kStartOrder)); i++) 82 for (int i = 0; i < static_cast<int>(arraysize(kStartOrder)); i++)
82 start_order_[kStartOrder[i]] = i; 83 start_order_[kStartOrder[i]] = i;
83 } 84 }
84 85
85 ModelAssociationManager::~ModelAssociationManager() { 86 ModelAssociationManager::~ModelAssociationManager() {
86 } 87 }
87 88
88 void ModelAssociationManager::Initialize( 89 void ModelAssociationManager::Initialize(
89 syncable::ModelTypeSet desired_types) { 90 syncable::ModelTypeSet desired_types) {
90 DCHECK(state_ == IDLE); 91 DCHECK(state_ == IDLE);
tim (not reviewing) 2012/05/21 23:18:57 DCHECK_EQ
lipalani1 2012/05/22 01:23:58 Done.
91 needs_start_.clear(); 92 needs_start_.clear();
92 needs_stop_.clear(); 93 needs_stop_.clear();
93 failed_datatypes_info_.clear(); 94 failed_datatypes_info_.clear();
94 desired_types_ = desired_types; 95 desired_types_ = desired_types;
95 state_ = INITIAILIZED_TO_CONFIGURE; 96 state_ = INITIAILIZED_TO_CONFIGURE;
96 97
98 // Stop the types that are still loading from the previous configuration.
99 // If they are enabled we will start them here once again.
100
101 for (std::vector<DataTypeController*>::const_iterator it =
102 pending_model_load_.begin();
103 it != pending_model_load_.end();
104 ++it) {
105 (*it)->Stop();
106 }
107
108 pending_model_load_.clear();
109 waiting_to_associate_.clear();
110 currently_associating_ = NULL;
111
112
97 // We need to calculate our |needs_start_| and |needs_stop_| list. 113 // We need to calculate our |needs_start_| and |needs_stop_| list.
98 GetControllersNeedingStart(&needs_start_); 114 GetControllersNeedingStart(&needs_start_);
99 // Sort these according to kStartOrder. 115 // Sort these according to kStartOrder.
100 std::sort(needs_start_.begin(), 116 std::sort(needs_start_.begin(),
101 needs_start_.end(), 117 needs_start_.end(),
102 SortComparator(&start_order_)); 118 SortComparator(&start_order_));
103 119
104 // Add any data type controllers into that needs_stop_ list that are 120 // Add any data type controllers into that needs_stop_ list that are
105 // currently MODEL_STARTING, ASSOCIATING, RUNNING or DISABLED. 121 // currently MODEL_STARTING, ASSOCIATING, RUNNING or DISABLED.
106 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); 122 for (DataTypeController::TypeMap::const_iterator it = controllers_->begin();
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 if (dtc->state() != DataTypeController::NOT_RUNNING && 187 if (dtc->state() != DataTypeController::NOT_RUNNING &&
172 dtc->state() != DataTypeController::STOPPING) { 188 dtc->state() != DataTypeController::STOPPING) {
173 dtc->Stop(); 189 dtc->Stop();
174 DVLOG(1) << "Stopped " << dtc->name(); 190 DVLOG(1) << "Stopped " << dtc->name();
175 } 191 }
176 } 192 }
177 193
178 if (need_to_call_model_association_done) { 194 if (need_to_call_model_association_done) {
179 DataTypeManager::ConfigureResult result(DataTypeManager::ABORTED, 195 DataTypeManager::ConfigureResult result(DataTypeManager::ABORTED,
180 desired_types_, 196 desired_types_,
181 failed_datatypes_info_); 197 failed_datatypes_info_,
198 syncable::ModelTypeSet());
182 result_processor_->OnModelAssociationDone(result); 199 result_processor_->OnModelAssociationDone(result);
183 } 200 }
184 201
185 failed_datatypes_info_.clear(); 202 failed_datatypes_info_.clear();
186 } 203 }
187 204
188 bool ModelAssociationManager::GetControllersNeedingStart( 205 bool ModelAssociationManager::GetControllersNeedingStart(
189 std::vector<DataTypeController*>* needs_start) { 206 std::vector<DataTypeController*>* needs_start) {
190 // Add any data type controllers into the needs_start_ list that are 207 // Add any data type controllers into the needs_start_ list that are
191 // currently NOT_RUNNING or STOPPING. 208 // currently NOT_RUNNING or STOPPING.
(...skipping 10 matching lines...) Expand all
202 needs_start->push_back(dtc->second.get()); 219 needs_start->push_back(dtc->second.get());
203 if (dtc->second->state() == DataTypeController::DISABLED) { 220 if (dtc->second->state() == DataTypeController::DISABLED) {
204 DVLOG(1) << "Found " << syncable::ModelTypeToString(dtc->second->type()) 221 DVLOG(1) << "Found " << syncable::ModelTypeToString(dtc->second->type())
205 << " in disabled state."; 222 << " in disabled state.";
206 } 223 }
207 } 224 }
208 } 225 }
209 return found_any; 226 return found_any;
210 } 227 }
211 228
229 void ModelAssociationManager::HandleFailedTypes(
230 DataTypeController::StartResult result,
231 const SyncError& error) {
232 failed_datatypes_info_.push_back(error);
233 LOG(ERROR) << "Failed to associate models for "
234 << syncable::ModelTypeToString(error.type());
235 UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed",
236 error.type(),
237 syncable::MODEL_TYPE_COUNT);
238
239 }
240
212 void ModelAssociationManager::TypeStartCallback( 241 void ModelAssociationManager::TypeStartCallback(
213 DataTypeController::StartResult result, 242 DataTypeController::StartResult result,
214 const SyncError& error) { 243 const SyncError& error) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
216 245
217 if (state_ == ABORT) { 246 if (state_ == ABORT) {
218 // Now that we have finished with the current type we can stop 247 // Now that we have finished with the current type we can stop
219 // if abort was called. 248 // if abort was called.
220 state_ = IDLE; 249 state_ = IDLE;
221 return; 250 return;
222 } 251 }
223 252
224 DCHECK(state_ == CONFIGURING); 253 DCHECK(state_ == CONFIGURING);
225 254
226 // We are done with this type. Clear it. 255 // We are done with this type. Clear it.
227 DataTypeController* started_dtc = currently_associating_; 256 DataTypeController* started_dtc = currently_associating_;
228 currently_associating_ = NULL; 257 currently_associating_ = NULL;
229 258
230 if (result == DataTypeController::ASSOCIATION_FAILED) { 259 if (result == DataTypeController::ASSOCIATION_FAILED) {
231 failed_datatypes_info_.push_back(error); 260 HandleFailedTypes(result, error);
232 LOG(ERROR) << "Failed to associate models for "
233 << syncable::ModelTypeToString(error.type());
234 UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed",
235 error.type(),
236 syncable::MODEL_TYPE_COUNT);
237 } 261 }
238 262
239 // If the type started normally, continue to the next type. 263 // If the type started normally, continue to the next type.
240 // If the type is waiting for the cryptographer, continue to the next type. 264 // If the type is waiting for the cryptographer, continue to the next type.
241 // Once the cryptographer is ready, we'll attempt to restart this type. 265 // Once the cryptographer is ready, we'll attempt to restart this type.
242 // If this type encountered a type specific error continue to the next type. 266 // If this type encountered a type specific error continue to the next type.
243 if (result == DataTypeController::NEEDS_CRYPTO || 267 if (result == DataTypeController::NEEDS_CRYPTO ||
244 result == DataTypeController::OK || 268 result == DataTypeController::OK ||
245 result == DataTypeController::OK_FIRST_RUN || 269 result == DataTypeController::OK_FIRST_RUN ||
246 result == DataTypeController::ASSOCIATION_FAILED) { 270 result == DataTypeController::ASSOCIATION_FAILED) {
(...skipping 20 matching lines...) Expand all
267 } 291 }
268 292
269 std::list<SyncError> errors; 293 std::list<SyncError> errors;
270 errors.push_back(error); 294 errors.push_back(error);
271 295
272 // Put our state to idle. 296 // Put our state to idle.
273 state_ = IDLE; 297 state_ = IDLE;
274 298
275 DataTypeManager::ConfigureResult configure_result(configure_status, 299 DataTypeManager::ConfigureResult configure_result(configure_status,
276 desired_types_, 300 desired_types_,
277 errors); 301 errors,
302 syncable::ModelTypeSet());
278 result_processor_->OnModelAssociationDone(configure_result); 303 result_processor_->OnModelAssociationDone(configure_result);
279 } 304 }
280 305
281 void ModelAssociationManager::LoadModelForNextType() { 306 void ModelAssociationManager::LoadModelForNextType() {
282 if (!needs_start_.empty()) { 307 if (!needs_start_.empty()) {
283 DVLOG(1) << "Starting " << needs_start_[0]->name(); 308 DVLOG(1) << "Starting " << needs_start_[0]->name();
284 309
285 DataTypeController* dtc = needs_start_[0]; 310 DataTypeController* dtc = needs_start_[0];
286 needs_start_.erase(needs_start_.begin()); 311 needs_start_.erase(needs_start_.begin());
287 // Move from |needs_start_| to |pending_model_load_|. 312 // Move from |needs_start_| to |pending_model_load_|.
288 pending_model_load_.push_back(dtc); 313 pending_model_load_.insert(pending_model_load_.begin(), dtc);
314 timer_.Start(FROM_HERE,
315 base::TimeDelta::FromSeconds(kDataTypeLoadWaitTimeInSeconds),
316 this,
317 &ModelAssociationManager::ModelLoadTimedOut);
289 dtc->LoadModels(base::Bind( 318 dtc->LoadModels(base::Bind(
290 &ModelAssociationManager::ModelLoadCallback, 319 &ModelAssociationManager::ModelLoadCallback,
291 weak_ptr_factory_.GetWeakPtr())); 320 weak_ptr_factory_.GetWeakPtr()));
321
292 return; 322 return;
293 } 323 }
294 324
295 // If all controllers have their |LoadModels| invoked then pass onto 325 // If all controllers have their |LoadModels| invoked then pass onto
296 // |StartAssociatingNextType|. 326 // |StartAssociatingNextType|.
297 StartAssociatingNextType(); 327 StartAssociatingNextType();
298 } 328 }
299 329
300 void ModelAssociationManager::ModelLoadCallback( 330 void ModelAssociationManager::ModelLoadCallback(
301 syncable::ModelType type, SyncError error) { 331 syncable::ModelType type, SyncError error) {
302 DCHECK_EQ(state_, CONFIGURING); 332 if (state_ == CONFIGURING) {
303 333 for (std::vector<DataTypeController*>::iterator it =
304 for (std::vector<DataTypeController*>::iterator it = 334 pending_model_load_.begin();
305 pending_model_load_.begin(); 335 it != pending_model_load_.end();
306 it != pending_model_load_.end(); 336 ++it) {
307 ++it) { 337 if ((*it)->type() == type) {
308 if ((*it)->type() == type) { 338 // If the type that got loaded was the type that was started
tim (not reviewing) 2012/05/21 23:18:57 'If the type that just finished loading was the la
lipalani1 2012/05/22 01:23:58 Done.
309 DataTypeController* dtc = *it; 339 // last, then we could stop the timer.
310 pending_model_load_.erase(it); 340 if (it == pending_model_load_.begin()) {
311 if (!error.IsSet()) { 341 timer_.Stop();
312 waiting_to_associate_.push_back(dtc); 342 }
313 StartAssociatingNextType(); 343 DataTypeController* dtc = *it;
314 } else { 344 pending_model_load_.erase(it);
315 // Treat it like a regular error. 345 if (!error.IsSet()) {
316 DCHECK(currently_associating_ == NULL); 346 waiting_to_associate_.push_back(dtc);
317 currently_associating_ = dtc; 347 StartAssociatingNextType();
318 TypeStartCallback(DataTypeController::ASSOCIATION_FAILED, error); 348 } else {
319 } 349 // Treat it like a regular error.
320 return; 350 HandleFailedTypes(DataTypeController::ASSOCIATION_FAILED, error);
351 }
352 return;
353 }
321 } 354 }
355 NOTREACHED();
356 return;
357 }
358 else {
359 // We got a callback on type that we started loading during the
tim (not reviewing) 2012/05/21 23:18:57 "This data type finished loading after the deadlin
lipalani1 2012/05/22 01:23:58 Done.
360 // previous configuration. Inform the DTM that the type has loaded.
361 result_processor_->OnTypesLoaded();
322 } 362 }
323 363
324 NOTREACHED();
325 } 364 }
326 365
327 366
328 void ModelAssociationManager::StartAssociatingNextType() { 367 void ModelAssociationManager::StartAssociatingNextType() {
329 DCHECK(state_ == CONFIGURING); 368 DCHECK(state_ == CONFIGURING);
330 DCHECK(currently_associating_ == NULL); 369 DCHECK(currently_associating_ == NULL);
331 if (!waiting_to_associate_.empty()) { 370 if (!waiting_to_associate_.empty()) {
332 DVLOG(1) << "Starting " << waiting_to_associate_[0]->name(); 371 DVLOG(1) << "Starting " << waiting_to_associate_[0]->name();
333 TRACE_EVENT_BEGIN1("sync", "ModelAssociation", 372 TRACE_EVENT_BEGIN1("sync", "ModelAssociation",
334 "DataType", 373 "DataType",
(...skipping 10 matching lines...) Expand all
345 state_ = IDLE; 384 state_ = IDLE;
346 // Do a fresh calculation to see if controllers need starting to account for 385 // Do a fresh calculation to see if controllers need starting to account for
347 // things like encryption, which may still need to be sorted out before we 386 // things like encryption, which may still need to be sorted out before we
348 // can announce we're "Done" configuration entirely. 387 // can announce we're "Done" configuration entirely.
349 if (GetControllersNeedingStart(NULL)) { 388 if (GetControllersNeedingStart(NULL)) {
350 DVLOG(1) << "GetControllersNeedingStart returned true. DTM blocked"; 389 DVLOG(1) << "GetControllersNeedingStart returned true. DTM blocked";
351 390
352 DataTypeManager::ConfigureResult configure_result( 391 DataTypeManager::ConfigureResult configure_result(
353 DataTypeManager::CONFIGURE_BLOCKED, 392 DataTypeManager::CONFIGURE_BLOCKED,
354 desired_types_, 393 desired_types_,
355 failed_datatypes_info_); 394 failed_datatypes_info_,
395 syncable::ModelTypeSet());
356 state_ = IDLE; 396 state_ = IDLE;
357 result_processor_->OnModelAssociationDone(configure_result); 397 result_processor_->OnModelAssociationDone(configure_result);
358 return; 398 return;
359 } 399 }
360 400
361 DataTypeManager::ConfigureStatus configure_status = DataTypeManager::OK; 401 DataTypeManager::ConfigureStatus configure_status = DataTypeManager::OK;
362 if (!failed_datatypes_info_.empty()) { 402 if (!failed_datatypes_info_.empty() ||
403 !GetTypesWaitingToLoad().Empty()) {
363 configure_status = DataTypeManager::PARTIAL_SUCCESS; 404 configure_status = DataTypeManager::PARTIAL_SUCCESS;
364 } 405 }
365 DataTypeManager::ConfigureResult result(configure_status, 406 DataTypeManager::ConfigureResult result(configure_status,
366 desired_types_, 407 desired_types_,
367 failed_datatypes_info_); 408 failed_datatypes_info_,
409 GetTypesWaitingToLoad());
368 result_processor_->OnModelAssociationDone(result); 410 result_processor_->OnModelAssociationDone(result);
369 return; 411 return;
370 } 412 }
371 413
414 void ModelAssociationManager::ModelLoadTimedOut() {
tim (not reviewing) 2012/05/21 23:18:57 Is this method actually needed?
lipalani1 2012/05/22 01:23:58 Just for clarity purpose... Compiler probably opti
tim (not reviewing) 2012/05/22 16:50:05 Hmm, to me the extra indirection makes it less cle
lipalani1 2012/05/22 20:20:46 Done.
415 LoadModelForNextType();
416 }
417
418 syncable::ModelTypeSet ModelAssociationManager::GetTypesWaitingToLoad() {
419 syncable::ModelTypeSet result;
420 for (std::vector<DataTypeController*>::const_iterator it =
421 pending_model_load_.begin();
422 it != pending_model_load_.end();
423 ++it) {
424 result.Put((*it)->type());
425 }
426 return result;
427 }
428
429 void ModelAssociationManager::TestSimulateDataTypeLoadTimeout() {
tim (not reviewing) 2012/05/21 23:18:57 I think there is a way to do this that doesn't req
lipalani1 2012/05/22 01:23:58 I think the eventual direction you are advocating
tim (not reviewing) 2012/05/22 16:50:05 It sounds like we're in agreement that it would be
lipalani1 2012/05/22 20:20:46 I have addressed this. Let me know what you think.
430 timer_.Stop();
431 ModelLoadTimedOut();
432 }
433
434
435
372 } // namespace browser_sync 436 } // namespace browser_sync
373 437
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698