Index: chrome/browser/sync/glue/model_association_manager.cc |
diff --git a/chrome/browser/sync/glue/model_association_manager.cc b/chrome/browser/sync/glue/model_association_manager.cc |
index bd74db75890f8b7f8f2d0aa2e7e87b52bf222462..60699ef5a566bc28b9cd2fe115782fba8807df74 100644 |
--- a/chrome/browser/sync/glue/model_association_manager.cc |
+++ b/chrome/browser/sync/glue/model_association_manager.cc |
@@ -2,6 +2,15 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include <algorithm> |
+#include <functional> |
+ |
+#include "base/debug/trace_event.h" |
+ |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "base/metrics/histogram.h" |
+ |
#include "chrome/browser/sync/glue/model_association_manager.h" |
#include "content/public/browser/browser_thread.h" |
@@ -19,6 +28,11 @@ using content::BrowserThread; |
using syncable::ModelTypeSet; |
namespace browser_sync { |
+// The amount of time we wait for a datatype to load. If the type has |
+// not finished loading we move on to the next type. Once this type |
+// finishes loading we will do a configure to associate this type. Note |
+// that in most cases types finish loading before this timeout. |
+const int64 kDataTypeLoadWaitTimeInSeconds = 120; |
namespace { |
static const syncable::ModelType kStartOrder[] = { |
@@ -94,6 +108,25 @@ void ModelAssociationManager::Initialize( |
desired_types_ = desired_types; |
state_ = INITIAILIZED_TO_CONFIGURE; |
+ VLOG(0) << "ModelAssociationManager: Initializing"; |
+ |
+ // Stop the types that are still loading from the previous configuration. |
+ // If they are enabled we will start them here once again. |
+ for (std::vector<DataTypeController*>::const_iterator it = |
+ pending_model_load_.begin(); |
+ it != pending_model_load_.end(); |
+ ++it) { |
+ VLOG(0) << "ModelAssociationManager: Stopping " |
+ << (*it)->name() |
+ << " before initialization"; |
+ (*it)->Stop(); |
+ } |
+ |
+ pending_model_load_.clear(); |
+ waiting_to_associate_.clear(); |
+ currently_associating_ = NULL; |
+ |
tim (not reviewing)
2012/05/23 03:18:52
extra newline
lipalani1
2012/05/23 17:47:20
Done.
|
+ |
// We need to calculate our |needs_start_| and |needs_stop_| list. |
GetControllersNeedingStart(&needs_start_); |
// Sort these according to kStartOrder. |
@@ -112,7 +145,7 @@ void ModelAssociationManager::Initialize( |
dtc->state() == DataTypeController::RUNNING || |
dtc->state() == DataTypeController::DISABLED)) { |
needs_stop_.push_back(dtc); |
- DVLOG(1) << "Will stop " << dtc->name(); |
+ VLOG(0) << "ModelTypeToString: Will stop " << dtc->name(); |
} |
} |
// Sort these according to kStartOrder. |
@@ -124,12 +157,14 @@ void ModelAssociationManager::Initialize( |
void ModelAssociationManager::StartAssociationAsync() { |
DCHECK_EQ(state_, INITIAILIZED_TO_CONFIGURE); |
state_ = CONFIGURING; |
+ VLOG(0) << "ModelAssociationManager: Going to start model association"; |
LoadModelForNextType(); |
} |
void ModelAssociationManager::ResetForReconfiguration() { |
DCHECK_EQ(state_, INITIAILIZED_TO_CONFIGURE); |
state_ = IDLE; |
+ VLOG(0) << "ModelAssociationManager: Reseting for reconfiguration"; |
needs_start_.clear(); |
needs_stop_.clear(); |
failed_datatypes_info_.clear(); |
@@ -137,9 +172,10 @@ void ModelAssociationManager::ResetForReconfiguration() { |
void ModelAssociationManager::StopDisabledTypes() { |
DCHECK_EQ(state_, INITIAILIZED_TO_CONFIGURE); |
+ VLOG(0) << "ModelAssociationManager: Stopping disabled types."; |
tim (not reviewing)
2012/05/23 03:18:52
DVLOG(1) (here and elsewhere)?
lipalani1
2012/05/23 17:47:20
Done.
|
// Stop requested data types. |
for (size_t i = 0; i < needs_stop_.size(); ++i) { |
- DVLOG(1) << "Stopping " << needs_stop_[i]->name(); |
+ VLOG(0) << "ModelAssociationManager: Stopping " << needs_stop_[i]->name(); |
needs_stop_[i]->Stop(); |
} |
needs_stop_.clear(); |
@@ -147,7 +183,10 @@ void ModelAssociationManager::StopDisabledTypes() { |
void ModelAssociationManager::Stop() { |
bool need_to_call_model_association_done = false; |
+ VLOG(0) << "ModelAssociationManager: Stopping MAM"; |
if (state_ == CONFIGURING) { |
+ VLOG(0) << "ModelAssociationManager: In the middle of configuratio while" |
+ << " stopping"; |
state_ = ABORTED; |
DCHECK(currently_associating_ != NULL || |
needs_start_.size() > 0 || |
@@ -155,6 +194,8 @@ void ModelAssociationManager::Stop() { |
waiting_to_associate_.size() > 0); |
if (currently_associating_) { |
+ VLOG(0) << "ModelAssociationManager: stopping " |
+ << currently_associating_->name(); |
currently_associating_->Stop(); |
} else { |
// DTCs in other lists would be stopped below. |
@@ -177,14 +218,16 @@ void ModelAssociationManager::Stop() { |
if (dtc->state() != DataTypeController::NOT_RUNNING && |
dtc->state() != DataTypeController::STOPPING) { |
dtc->Stop(); |
- DVLOG(1) << "Stopped " << dtc->name(); |
+ VLOG(0) << "ModelAssociationManager: Stopped " << dtc->name(); |
} |
} |
if (need_to_call_model_association_done) { |
+ VLOG(0) << "ModelAssociationManager: Calling OnModelAssociationDone"; |
DataTypeManager::ConfigureResult result(DataTypeManager::ABORTED, |
desired_types_, |
- failed_datatypes_info_); |
+ failed_datatypes_info_, |
+ syncable::ModelTypeSet()); |
result_processor_->OnModelAssociationDone(result); |
} |
@@ -193,6 +236,7 @@ void ModelAssociationManager::Stop() { |
bool ModelAssociationManager::GetControllersNeedingStart( |
std::vector<DataTypeController*>* needs_start) { |
+ VLOG(0) << "ModelAssociationManager: GetControllersNeedingStart"; |
// Add any data type controllers into the needs_start_ list that are |
// currently NOT_RUNNING or STOPPING. |
bool found_any = false; |
@@ -207,7 +251,8 @@ bool ModelAssociationManager::GetControllersNeedingStart( |
if (needs_start) |
needs_start->push_back(dtc->second.get()); |
if (dtc->second->state() == DataTypeController::DISABLED) { |
- DVLOG(1) << "Found " << syncable::ModelTypeToString(dtc->second->type()) |
+ VLOG(0) << "ModelAssociationManager: Found "\ |
+ << syncable::ModelTypeToString(dtc->second->type()) |
<< " in disabled state."; |
} |
} |
@@ -215,14 +260,28 @@ bool ModelAssociationManager::GetControllersNeedingStart( |
return found_any; |
} |
+void ModelAssociationManager::HandleFailedTypes( |
tim (not reviewing)
2012/05/23 03:18:52
Actually, since this doesn't totally "handle" fail
lipalani1
2012/05/23 17:47:20
Done.
|
+ DataTypeController::StartResult result, |
+ const SyncError& error) { |
+ failed_datatypes_info_.push_back(error); |
+ LOG(ERROR) << "Failed to associate models for " |
+ << syncable::ModelTypeToString(error.type()); |
+ UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed", |
+ error.type(), |
+ syncable::MODEL_TYPE_COUNT); |
+} |
+ |
void ModelAssociationManager::TypeStartCallback( |
DataTypeController::StartResult result, |
const SyncError& error) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ VLOG(0) << "ModelAssociationManager: TypeStartCallback"; |
if (state_ == ABORTED) { |
// Now that we have finished with the current type we can stop |
// if abort was called. |
+ VLOG(0) << "ModelAssociationManager: Doing an early return" |
+ << " because of abort"; |
state_ = IDLE; |
return; |
} |
@@ -234,12 +293,8 @@ void ModelAssociationManager::TypeStartCallback( |
currently_associating_ = NULL; |
if (result == DataTypeController::ASSOCIATION_FAILED) { |
- failed_datatypes_info_.push_back(error); |
- LOG(ERROR) << "Failed to associate models for " |
- << syncable::ModelTypeToString(error.type()); |
- UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed", |
- error.type(), |
- syncable::MODEL_TYPE_COUNT); |
+ VLOG(0) << "ModelAssociationManager: Encountered a failed type"; |
+ HandleFailedTypes(result, error); |
} |
// If the type started normally, continue to the next type. |
@@ -250,6 +305,8 @@ void ModelAssociationManager::TypeStartCallback( |
result == DataTypeController::OK || |
result == DataTypeController::OK_FIRST_RUN || |
result == DataTypeController::ASSOCIATION_FAILED) { |
+ VLOG(0) << "ModelAssociationManager: type start callback returned " |
+ << result << " so calling LoadModelForNextType"; |
LoadModelForNextType(); |
return; |
} |
@@ -280,24 +337,34 @@ void ModelAssociationManager::TypeStartCallback( |
DataTypeManager::ConfigureResult configure_result(configure_status, |
desired_types_, |
- errors); |
+ errors, |
+ syncable::ModelTypeSet()); |
result_processor_->OnModelAssociationDone(configure_result); |
} |
void ModelAssociationManager::LoadModelForNextType() { |
+ VLOG(0) << "ModelAssociationManager: LoadModelForNextType"; |
if (!needs_start_.empty()) { |
- DVLOG(1) << "Starting " << needs_start_[0]->name(); |
+ VLOG(0) << "ModelAssociationManager: Starting " << needs_start_[0]->name(); |
DataTypeController* dtc = needs_start_[0]; |
needs_start_.erase(needs_start_.begin()); |
// Move from |needs_start_| to |pending_model_load_|. |
- pending_model_load_.push_back(dtc); |
+ pending_model_load_.insert(pending_model_load_.begin(), dtc); |
+ timer_.Start(FROM_HERE, |
+ base::TimeDelta::FromSeconds(kDataTypeLoadWaitTimeInSeconds), |
+ this, |
+ &ModelAssociationManager::LoadModelForNextType); |
dtc->LoadModels(base::Bind( |
&ModelAssociationManager::ModelLoadCallback, |
weak_ptr_factory_.GetWeakPtr())); |
+ |
return; |
} |
+ VLOG(0) << "ModelAssociationManager: All types have models loaded." |
+ << "Moving on to StartAssociatingNextType."; |
+ |
// If all controllers have their |LoadModels| invoked then pass onto |
// |StartAssociatingNextType|. |
StartAssociatingNextType(); |
@@ -305,37 +372,66 @@ void ModelAssociationManager::LoadModelForNextType() { |
void ModelAssociationManager::ModelLoadCallback( |
syncable::ModelType type, SyncError error) { |
- DCHECK_EQ(state_, CONFIGURING); |
- |
- for (std::vector<DataTypeController*>::iterator it = |
- pending_model_load_.begin(); |
- it != pending_model_load_.end(); |
- ++it) { |
- if ((*it)->type() == type) { |
- DataTypeController* dtc = *it; |
- pending_model_load_.erase(it); |
- if (!error.IsSet()) { |
- waiting_to_associate_.push_back(dtc); |
- StartAssociatingNextType(); |
- } else { |
- // Treat it like a regular error. |
- DCHECK(currently_associating_ == NULL); |
- currently_associating_ = dtc; |
- TypeStartCallback(DataTypeController::ASSOCIATION_FAILED, error); |
+ VLOG(0) << "ModelAssociationManager: ModelLoadCallback for " |
+ << syncable::ModelTypeToString(type); |
+ if (state_ == CONFIGURING) { |
+ VLOG(0) << "ModelAssociationManager: ModelLoadCallback while configuring"; |
+ for (std::vector<DataTypeController*>::iterator it = |
+ pending_model_load_.begin(); |
+ it != pending_model_load_.end(); |
+ ++it) { |
+ if ((*it)->type() == type) { |
+ // Each type is given |kDataTypeLoadWaitTimeInSeconds| time to load |
+ // (as controlled by the timer.). If the type does not load in that |
+ // time we move on to the next type. However if the type does |
+ // finish loading in that time we want to stop the timer. We stop |
+ // the timer, if the type that loaded is the same as the type that |
+ // we started the timer for(as indicated by the type on the head |
+ // of the list). |
+ // Note: Regardless of this timer value the associations will always |
+ // take place serially. The only thing this timer controls is how serial |
+ // the model load is. If this timer has a value of zero seconds then |
+ // the model loads will all be parallel. |
+ if (it == pending_model_load_.begin()) { |
+ VLOG(0) << "ModelAssociationManager: Stopping timer"; |
+ timer_.Stop(); |
+ } |
+ DataTypeController* dtc = *it; |
+ pending_model_load_.erase(it); |
+ if (!error.IsSet()) { |
+ VLOG(0) << "ModelAssociationManager:" |
+ << " Calling StartAssociatingNextType"; |
+ waiting_to_associate_.push_back(dtc); |
+ StartAssociatingNextType(); |
+ } else { |
+ VLOG(0) << "ModelAssociationManager: Encountered error loading"; |
+ // Treat it like a regular error. |
+ HandleFailedTypes(DataTypeController::ASSOCIATION_FAILED, error); |
+ } |
+ return; |
} |
- return; |
} |
+ NOTREACHED(); |
+ return; |
+ } else { |
+ VLOG(0) << "ModelAssociationManager: Models loaded after configure cycle" |
+ << "Informing DTM"; |
+ // This datatype finished loading after the deadline imposed by the |
+ // originating configuration cycle. Inform the DataTypeManager that the |
+ // type has loaded, so that association may begin. |
+ result_processor_->OnTypesLoaded(); |
} |
- NOTREACHED(); |
} |
- |
void ModelAssociationManager::StartAssociatingNextType() { |
DCHECK_EQ(state_, CONFIGURING); |
DCHECK_EQ(currently_associating_, static_cast<DataTypeController*>(NULL)); |
+ |
+ VLOG(0) << "ModelAssociationManager: StartAssociatingNextType"; |
if (!waiting_to_associate_.empty()) { |
- DVLOG(1) << "Starting " << waiting_to_associate_[0]->name(); |
+ VLOG(0) << "ModelAssociationManager: Starting " |
+ << waiting_to_associate_[0]->name(); |
TRACE_EVENT_BEGIN1("sync", "ModelAssociation", |
"DataType", |
ModelTypeToString(waiting_to_associate_[0]->type())); |
@@ -354,28 +450,53 @@ void ModelAssociationManager::StartAssociatingNextType() { |
// things like encryption, which may still need to be sorted out before we |
// can announce we're "Done" configuration entirely. |
if (GetControllersNeedingStart(NULL)) { |
- DVLOG(1) << "GetControllersNeedingStart returned true." |
- << " Blocking DataTypeManager"; |
+ VLOG(0) << "ModelAssociationManager: GetControllersNeedingStart" |
+ << " returned true. Blocking DataTypeManager"; |
DataTypeManager::ConfigureResult configure_result( |
DataTypeManager::CONFIGURE_BLOCKED, |
desired_types_, |
- failed_datatypes_info_); |
+ failed_datatypes_info_, |
+ syncable::ModelTypeSet()); |
state_ = IDLE; |
result_processor_->OnModelAssociationDone(configure_result); |
return; |
} |
DataTypeManager::ConfigureStatus configure_status = DataTypeManager::OK; |
- if (!failed_datatypes_info_.empty()) |
+ |
+ if (!failed_datatypes_info_.empty() || |
+ !GetTypesWaitingToLoad().Empty()) { |
+ // We have not configured all types that we have been asked to configure. |
+ // Either we have failed types or types that have not completed loading |
+ // yet. |
+ VLOG(0) << "ModelAssociationManager: setting partial success"; |
configure_status = DataTypeManager::PARTIAL_SUCCESS; |
+ } |
DataTypeManager::ConfigureResult result(configure_status, |
desired_types_, |
- failed_datatypes_info_); |
+ failed_datatypes_info_, |
+ GetTypesWaitingToLoad()); |
result_processor_->OnModelAssociationDone(result); |
return; |
} |
+syncable::ModelTypeSet ModelAssociationManager::GetTypesWaitingToLoad() { |
+ syncable::ModelTypeSet result; |
+ for (std::vector<DataTypeController*>::const_iterator it = |
+ pending_model_load_.begin(); |
+ it != pending_model_load_.end(); |
+ ++it) { |
+ result.Put((*it)->type()); |
+ } |
+ return result; |
+} |
+ |
+base::OneShotTimer<ModelAssociationManager>* |
+ ModelAssociationManager::GetTimerForTesting() { |
+ return &timer_; |
+} |
+ |
} // namespace browser_sync |