| Index: trunk/src/components/sync_driver/data_type_manager_impl.cc
|
| ===================================================================
|
| --- trunk/src/components/sync_driver/data_type_manager_impl.cc (revision 289114)
|
| +++ trunk/src/components/sync_driver/data_type_manager_impl.cc (working copy)
|
| @@ -88,9 +88,7 @@
|
| if (syncer::IsControlType(type.Get()) ||
|
| iter != controllers_->end()) {
|
| if (iter != controllers_->end()) {
|
| - if (!iter->second->ReadyForStart() &&
|
| - !failed_data_types_handler_->GetUnreadyErrorTypes().Has(
|
| - type.Get())) {
|
| + if (!iter->second->ReadyForStart()) {
|
| // Add the type to the unready types set to prevent purging it. It's
|
| // up to the datatype controller to, if necessary, explicitly
|
| // mark the type as broken to trigger a purge.
|
| @@ -101,7 +99,7 @@
|
| std::map<syncer::ModelType, syncer::SyncError> errors;
|
| errors[type.Get()] = error;
|
| failed_data_types_handler_->UpdateFailedDataTypes(errors);
|
| - } else if (iter->second->ReadyForStart()) {
|
| + } else {
|
| failed_data_types_handler_->ResetUnreadyErrorFor(type.Get());
|
| }
|
| }
|
| @@ -347,18 +345,14 @@
|
| if (!failed_configuration_types.Empty()) {
|
| if (!unrecoverable_error_method_.is_null())
|
| unrecoverable_error_method_.Run();
|
| - FailedDataTypesHandler::TypeErrorMap errors;
|
| - for (syncer::ModelTypeSet::Iterator iter =
|
| - failed_configuration_types.First(); iter.Good(); iter.Inc()) {
|
| - syncer::SyncError error(
|
| - FROM_HERE,
|
| - syncer::SyncError::UNRECOVERABLE_ERROR,
|
| - "Backend failed to download type.",
|
| - iter.Get());
|
| - errors[iter.Get()] = error;
|
| - }
|
| - failed_data_types_handler_->UpdateFailedDataTypes(errors);
|
| - Abort(UNRECOVERABLE_ERROR);
|
| + std::string error_msg =
|
| + "Configuration failed for types " +
|
| + syncer::ModelTypeSetToString(failed_configuration_types);
|
| + syncer::SyncError error(FROM_HERE,
|
| + syncer::SyncError::UNRECOVERABLE_ERROR,
|
| + error_msg,
|
| + failed_configuration_types.First().Get());
|
| + Abort(UNRECOVERABLE_ERROR, error);
|
| return;
|
| }
|
|
|
| @@ -406,24 +400,8 @@
|
| }
|
|
|
| void DataTypeManagerImpl::OnSingleDataTypeWillStop(
|
| - syncer::ModelType type,
|
| - const syncer::SyncError& error) {
|
| + syncer::ModelType type) {
|
| configurer_->DeactivateDataType(type);
|
| - if (error.IsSet()) {
|
| - FailedDataTypesHandler::TypeErrorMap failed_types;
|
| - failed_types[type] = error;
|
| - failed_data_types_handler_->UpdateFailedDataTypes(
|
| - failed_types);
|
| -
|
| - // Unrecoverable errors will shut down the entire backend, so no need to
|
| - // reconfigure.
|
| - if (error.error_type() != syncer::SyncError::UNRECOVERABLE_ERROR) {
|
| - needs_reconfigure_ = true;
|
| - ProcessReconfigure();
|
| - } else {
|
| - DCHECK_EQ(state_, CONFIGURING);
|
| - }
|
| - }
|
| }
|
|
|
| void DataTypeManagerImpl::OnSingleDataTypeAssociationDone(
|
| @@ -471,6 +449,25 @@
|
| if (state_ == STOPPING)
|
| return;
|
|
|
| + // Don't reconfigure due to failed data types if we have an unrecoverable
|
| + // error or have already aborted.
|
| + if (result.status == PARTIAL_SUCCESS) {
|
| + if (!result.needs_crypto.Empty()) {
|
| + needs_reconfigure_ = true;
|
| + syncer::ModelTypeSet encrypted_types = result.needs_crypto;
|
| + encrypted_types.RemoveAll(
|
| + failed_data_types_handler_->GetCryptoErrorTypes());
|
| + FailedDataTypesHandler::TypeErrorMap crypto_errors =
|
| + GenerateCryptoErrorsForTypes(encrypted_types);
|
| + failed_data_types_handler_->UpdateFailedDataTypes(crypto_errors);
|
| + }
|
| + if (!result.failed_data_types.empty()) {
|
| + needs_reconfigure_ = true;
|
| + failed_data_types_handler_->UpdateFailedDataTypes(
|
| + result.failed_data_types);
|
| + }
|
| + }
|
| +
|
| // Ignore abort/unrecoverable error if we need to reconfigure anyways.
|
| if (needs_reconfigure_) {
|
| association_types_queue_ = std::queue<AssociationTypesInfo>();
|
| @@ -479,18 +476,38 @@
|
| }
|
|
|
| if (result.status == ABORTED || result.status == UNRECOVERABLE_ERROR) {
|
| - Abort(result.status);
|
| + Abort(result.status, result.failed_data_types.size() >= 1 ?
|
| + result.failed_data_types.begin()->second :
|
| + syncer::SyncError());
|
| return;
|
| }
|
|
|
| - DCHECK(result.status == OK);
|
| + DCHECK(result.status == PARTIAL_SUCCESS || result.status == OK);
|
| + DCHECK(result.status != OK ||
|
| + (result.needs_crypto.Empty() && result.failed_data_types.empty()));
|
|
|
| + // It's possible this is a retry to disable failed types, in which case
|
| + // the association would be SUCCESS, but the overall configuration should
|
| + // still be PARTIAL_SUCCESS.
|
| + syncer::ModelTypeSet failed_data_types =
|
| + failed_data_types_handler_->GetFailedTypes();
|
| + ConfigureStatus status = result.status;
|
| + if (!syncer::Intersection(last_requested_types_,
|
| + failed_data_types).Empty() && result.status == OK) {
|
| + status = PARTIAL_SUCCESS;
|
| + }
|
| +
|
| association_types_queue_.pop();
|
| if (!association_types_queue_.empty()) {
|
| StartNextAssociation();
|
| } else if (download_types_queue_.empty()) {
|
| state_ = CONFIGURED;
|
| - NotifyDone(result);
|
| + ConfigureResult configure_result(status,
|
| + result.requested_types,
|
| + failed_data_types_handler_->GetAllErrors(),
|
| + result.unfinished_data_types,
|
| + result.needs_crypto);
|
| + NotifyDone(configure_result);
|
| }
|
| }
|
|
|
| @@ -504,19 +521,29 @@
|
|
|
| if (need_to_notify) {
|
| ConfigureResult result(ABORTED,
|
| - last_requested_types_);
|
| + last_requested_types_,
|
| + std::map<syncer::ModelType, syncer::SyncError>(),
|
| + syncer::ModelTypeSet(),
|
| + syncer::ModelTypeSet());
|
| NotifyDone(result);
|
| }
|
| }
|
|
|
| -void DataTypeManagerImpl::Abort(ConfigureStatus status) {
|
| +void DataTypeManagerImpl::Abort(ConfigureStatus status,
|
| + const syncer::SyncError& error) {
|
| DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);
|
|
|
| StopImpl();
|
|
|
| DCHECK_NE(OK, status);
|
| + std::map<syncer::ModelType, syncer::SyncError> errors;
|
| + if (error.IsSet())
|
| + errors[error.model_type()] = error;
|
| ConfigureResult result(status,
|
| - last_requested_types_);
|
| + last_requested_types_,
|
| + errors,
|
| + syncer::ModelTypeSet(),
|
| + syncer::ModelTypeSet());
|
| NotifyDone(result);
|
| }
|
|
|
| @@ -566,7 +593,12 @@
|
| UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.UNRECOVERABLE_ERROR",
|
| configure_time_delta_);
|
| break;
|
| - case DataTypeManager::UNKNOWN:
|
| + case DataTypeManager::PARTIAL_SUCCESS:
|
| + DVLOG(1) << "NotifyDone called with result: PARTIAL_SUCCESS";
|
| + UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.PARTIAL_SUCCESS",
|
| + configure_time_delta_);
|
| + break;
|
| + default:
|
| NOTREACHED();
|
| break;
|
| }
|
|
|