| Index: trunk/src/components/sync_driver/model_association_manager.cc
|
| ===================================================================
|
| --- trunk/src/components/sync_driver/model_association_manager.cc (revision 289114)
|
| +++ trunk/src/components/sync_driver/model_association_manager.cc (working copy)
|
| @@ -64,8 +64,8 @@
|
| kStartOrder_IncorrectSize);
|
|
|
| // The amount of time we wait for association to finish. If some types haven't
|
| -// finished association by the time, DataTypeManager is notified of the
|
| -// unfinished types.
|
| +// finished association by the time, configuration result will be
|
| +// PARTIAL_SUCCESS and DataTypeManager is notified of the unfinished types.
|
| const int64 kAssociationTimeOutInSeconds = 600;
|
|
|
| syncer::DataTypeAssociationStats BuildAssociationStatsFromMergeResults(
|
| @@ -134,6 +134,7 @@
|
|
|
| // Only keep types that have controllers.
|
| desired_types_.Clear();
|
| + slow_types_.Clear();
|
| for (syncer::ModelTypeSet::Iterator it = desired_types.First();
|
| it.Good(); it.Inc()) {
|
| if (controllers_->find(it.Get()) != controllers_->end())
|
| @@ -149,18 +150,13 @@
|
| LoadEnabledTypes();
|
| }
|
|
|
| -void ModelAssociationManager::StopDatatype(
|
| - const syncer::SyncError& error,
|
| - DataTypeController* dtc) {
|
| - loaded_types_.Remove(dtc->type());
|
| - associated_types_.Remove(dtc->type());
|
| - associating_types_.Remove(dtc->type());
|
| +void ModelAssociationManager::StopDatatype(DataTypeController* dtc) {
|
| + // First tell the sync backend that we no longer want to listen to
|
| + // changes for this type.
|
| + delegate_->OnSingleDataTypeWillStop(dtc->type());
|
|
|
| - if (error.IsSet() || dtc->state() != DataTypeController::NOT_RUNNING) {
|
| - // If an error was set, the delegate must be informed of the error.
|
| - delegate_->OnSingleDataTypeWillStop(dtc->type(), error);
|
| - dtc->Stop();
|
| - }
|
| + // Then tell all data type specific logic to shut down.
|
| + dtc->Stop();
|
| }
|
|
|
| void ModelAssociationManager::StopDisabledTypes() {
|
| @@ -169,9 +165,12 @@
|
| it != controllers_->end(); ++it) {
|
| DataTypeController* dtc = (*it).second.get();
|
| if (dtc->state() != DataTypeController::NOT_RUNNING &&
|
| - !desired_types_.Has(dtc->type())) {
|
| + (!desired_types_.Has(dtc->type()) ||
|
| + failed_data_types_info_.count(dtc->type()) > 0)) {
|
| DVLOG(1) << "ModelTypeToString: stop " << dtc->name();
|
| - StopDatatype(syncer::SyncError(), dtc);
|
| + StopDatatype(dtc);
|
| + loaded_types_.Remove(dtc->type());
|
| + associated_types_.Remove(dtc->type());
|
| }
|
| }
|
| }
|
| @@ -210,6 +209,13 @@
|
| // Assume success.
|
| configure_status_ = DataTypeManager::OK;
|
|
|
| + // Remove types that already failed.
|
| + for (std::map<syncer::ModelType, syncer::SyncError>::const_iterator it =
|
| + failed_data_types_info_.begin();
|
| + it != failed_data_types_info_.end(); ++it) {
|
| + associating_types_.Remove(it->first);
|
| + }
|
| +
|
| // Done if no types to associate.
|
| if (associating_types_.Empty()) {
|
| ModelAssociationDone();
|
| @@ -249,28 +255,30 @@
|
| // |loaded_types_| and |associated_types_| are not cleared. So
|
| // reconfiguration won't restart types that are already started.
|
| requested_types_.Clear();
|
| + failed_data_types_info_.clear();
|
| associating_types_.Clear();
|
| + needs_crypto_types_.Clear();
|
| }
|
|
|
| void ModelAssociationManager::Stop() {
|
| // Ignore callbacks from controllers.
|
| weak_ptr_factory_.InvalidateWeakPtrs();
|
|
|
| - desired_types_.Clear();
|
| - loaded_types_.Clear();
|
| - associated_types_.Clear();
|
| - associating_types_.Clear();
|
| -
|
| // Stop started data types.
|
| for (DataTypeController::TypeMap::const_iterator it = controllers_->begin();
|
| it != controllers_->end(); ++it) {
|
| DataTypeController* dtc = (*it).second.get();
|
| if (dtc->state() != DataTypeController::NOT_RUNNING) {
|
| - StopDatatype(syncer::SyncError(), dtc);
|
| + StopDatatype(dtc);
|
| DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name();
|
| }
|
| }
|
|
|
| + desired_types_.Clear();
|
| + loaded_types_.Clear();
|
| + associated_types_.Clear();
|
| + slow_types_.Clear();
|
| +
|
| if (state_ == CONFIGURING) {
|
| if (configure_status_ == DataTypeManager::OK)
|
| configure_status_ = DataTypeManager::ABORTED;
|
| @@ -283,11 +291,25 @@
|
| state_ = IDLE;
|
| }
|
|
|
| +void ModelAssociationManager::AppendToFailedDatatypesAndLogError(
|
| + const syncer::SyncError& error) {
|
| + failed_data_types_info_[error.model_type()] = error;
|
| + LOG(ERROR) << "Failed to associate models for "
|
| + << syncer::ModelTypeToString(error.model_type());
|
| + UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed",
|
| + ModelTypeToHistogramInt(error.model_type()),
|
| + syncer::MODEL_TYPE_COUNT);
|
| +}
|
| +
|
| void ModelAssociationManager::ModelLoadCallback(syncer::ModelType type,
|
| syncer::SyncError error) {
|
| DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for "
|
| << syncer::ModelTypeToString(type);
|
|
|
| + // TODO(haitaol): temporary fix for 335606.
|
| + if (slow_types_.Has(type))
|
| + return;
|
| +
|
| // This happens when slow loading type is disabled by new configuration.
|
| if (!desired_types_.Has(type))
|
| return;
|
| @@ -305,7 +327,7 @@
|
| }
|
|
|
| loaded_types_.Put(type);
|
| - if (associating_types_.Has(type)) {
|
| + if (associating_types_.Has(type) || slow_types_.Has(type)) {
|
| DataTypeController* dtc = controllers_->find(type)->second.get();
|
| dtc->StartAssociating(
|
| base::Bind(&ModelAssociationManager::TypeStartCallback,
|
| @@ -317,34 +339,41 @@
|
| void ModelAssociationManager::TypeStartCallback(
|
| syncer::ModelType type,
|
| base::TimeTicks type_start_time,
|
| - DataTypeController::ConfigureResult start_result,
|
| + DataTypeController::StartResult start_result,
|
| const syncer::SyncMergeResult& local_merge_result,
|
| const syncer::SyncMergeResult& syncer_merge_result) {
|
| - if (desired_types_.Has(type) &&
|
| - !DataTypeController::IsSuccessfulResult(start_result)) {
|
| - DVLOG(1) << "ModelAssociationManager: Type encountered an error.";
|
| - desired_types_.Remove(type);
|
| - DataTypeController* dtc = controllers_->find(type)->second.get();
|
| - StopDatatype(local_merge_result.error(), dtc);
|
| + // TODO(haitaol): temporary fix for 335606.
|
| + if (slow_types_.Has(type))
|
| + return;
|
|
|
| - // Update configuration result.
|
| - if (start_result == DataTypeController::UNRECOVERABLE_ERROR)
|
| - configure_status_ = DataTypeManager::UNRECOVERABLE_ERROR;
|
| - }
|
| + // This happens when slow associating type is disabled by new configuration.
|
| + if (!desired_types_.Has(type))
|
| + return;
|
|
|
| - // This happens when a slow associating type is disabled or if a type
|
| - // disables itself after initial configuration.
|
| - if (!desired_types_.Has(type)) {
|
| - // It's possible all types failed to associate, in which case association
|
| - // is complete.
|
| - if (state_ == CONFIGURING && associating_types_.Empty())
|
| - ModelAssociationDone();
|
| - return;
|
| - }
|
| + slow_types_.Remove(type);
|
|
|
| DCHECK(!associated_types_.Has(type));
|
| - DCHECK(DataTypeController::IsSuccessfulResult(start_result));
|
| - associated_types_.Put(type);
|
| + if (DataTypeController::IsSuccessfulResult(start_result)) {
|
| + associated_types_.Put(type);
|
| + } else if (state_ == IDLE) {
|
| + // For type that failed in IDLE mode, simply stop the controller. Next
|
| + // configuration will try to restart from scratch if the type is still
|
| + // enabled.
|
| + DataTypeController* dtc = controllers_->find(type)->second.get();
|
| + if (dtc->state() != DataTypeController::NOT_RUNNING)
|
| + StopDatatype(dtc);
|
| + loaded_types_.Remove(type);
|
| + } else {
|
| + // Record error in CONFIGURING or INITIALIZED_TO_CONFIGURE mode. The error
|
| + // will be reported when data types association finishes.
|
| + if (start_result == DataTypeController::NEEDS_CRYPTO) {
|
| + DVLOG(1) << "ModelAssociationManager: Encountered an undecryptable type";
|
| + needs_crypto_types_.Put(type);
|
| + } else {
|
| + DVLOG(1) << "ModelAssociationManager: Encountered a failed type";
|
| + AppendToFailedDatatypesAndLogError(local_merge_result.error());
|
| + }
|
| + }
|
|
|
| if (state_ != CONFIGURING)
|
| return;
|
| @@ -356,7 +385,9 @@
|
|
|
| // Track the merge results if we succeeded or an association failure
|
| // occurred.
|
| - if (syncer::ProtocolTypes().Has(type)) {
|
| + if ((DataTypeController::IsSuccessfulResult(start_result) ||
|
| + start_result == DataTypeController::ASSOCIATION_FAILED) &&
|
| + syncer::ProtocolTypes().Has(type)) {
|
| base::TimeDelta association_wait_time =
|
| std::max(base::TimeDelta(), type_start_time - association_start_time_);
|
| base::TimeDelta association_time =
|
| @@ -369,6 +400,14 @@
|
| delegate_->OnSingleDataTypeAssociationDone(type, stats);
|
| }
|
|
|
| + // Update configuration result.
|
| + if (configure_status_ == DataTypeManager::OK &&
|
| + start_result == DataTypeController::ASSOCIATION_FAILED) {
|
| + configure_status_ = DataTypeManager::PARTIAL_SUCCESS;
|
| + }
|
| + if (start_result == DataTypeController::UNRECOVERABLE_ERROR)
|
| + configure_status_ = DataTypeManager::UNRECOVERABLE_ERROR;
|
| +
|
| associating_types_.Remove(type);
|
|
|
| if (associating_types_.Empty())
|
| @@ -380,26 +419,34 @@
|
|
|
| timer_.Stop();
|
|
|
| - // Treat any unfinished types as having errors.
|
| - desired_types_.RemoveAll(associating_types_);
|
| - for (DataTypeController::TypeMap::const_iterator it = controllers_->begin();
|
| - it != controllers_->end(); ++it) {
|
| - DataTypeController* dtc = (*it).second.get();
|
| - if (associating_types_.Has(dtc->type()) &&
|
| - dtc->state() != DataTypeController::NOT_RUNNING) {
|
| - UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed",
|
| - ModelTypeToHistogramInt(dtc->type()),
|
| - syncer::MODEL_TYPE_COUNT);
|
| - StopDatatype(syncer::SyncError(FROM_HERE,
|
| - syncer::SyncError::DATATYPE_ERROR,
|
| - "Association timed out.",
|
| - dtc->type()),
|
| - dtc);
|
| - }
|
| + slow_types_.PutAll(associating_types_);
|
| +
|
| + // TODO(haitaol): temporary fix for 335606.
|
| + for (syncer::ModelTypeSet::Iterator it = associating_types_.First();
|
| + it.Good(); it.Inc()) {
|
| + AppendToFailedDatatypesAndLogError(
|
| + syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
|
| + "Association timed out.", it.Get()));
|
| }
|
|
|
| + // Stop controllers of failed types.
|
| + StopDisabledTypes();
|
| +
|
| + if (configure_status_ == DataTypeManager::OK &&
|
| + (!associating_types_.Empty() || !failed_data_types_info_.empty() ||
|
| + !needs_crypto_types_.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.
|
| + DVLOG(1) << "ModelAssociationManager: setting partial success";
|
| + configure_status_ = DataTypeManager::PARTIAL_SUCCESS;
|
| + }
|
| +
|
| DataTypeManager::ConfigureResult result(configure_status_,
|
| - requested_types_);
|
| + requested_types_,
|
| + failed_data_types_info_,
|
| + associating_types_,
|
| + needs_crypto_types_);
|
|
|
| // Reset state before notifying |delegate_| because that might
|
| // trigger a new round of configuration.
|
|
|