Index: components/sync_driver/model_association_manager.cc |
diff --git a/components/sync_driver/model_association_manager.cc b/components/sync_driver/model_association_manager.cc |
deleted file mode 100644 |
index 0c69b7bb180f77ff8f1547ecd0d02954fe845e4c..0000000000000000000000000000000000000000 |
--- a/components/sync_driver/model_association_manager.cc |
+++ /dev/null |
@@ -1,462 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "components/sync_driver/model_association_manager.h" |
- |
-#include <stddef.h> |
-#include <stdint.h> |
- |
-#include <algorithm> |
-#include <functional> |
- |
-#include "base/logging.h" |
-#include "base/macros.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/metrics/histogram_macros.h" |
-#include "base/trace_event/trace_event.h" |
-#include "components/sync/api/sync_merge_result.h" |
-#include "components/sync/base/model_type.h" |
- |
-using syncer::ModelTypeSet; |
- |
-namespace sync_driver { |
- |
-namespace { |
- |
-static const syncer::ModelType kStartOrder[] = { |
- syncer::NIGORI, // Listed for completeness. |
- syncer::DEVICE_INFO, // Listed for completeness. |
- syncer::EXPERIMENTS, // Listed for completeness. |
- syncer::PROXY_TABS, // Listed for completeness. |
- |
- // Kick off the association of the non-UI types first so they can associate |
- // in parallel with the UI types. |
- syncer::PASSWORDS, |
- syncer::AUTOFILL, |
- syncer::AUTOFILL_PROFILE, |
- syncer::AUTOFILL_WALLET_DATA, |
- syncer::AUTOFILL_WALLET_METADATA, |
- syncer::EXTENSION_SETTINGS, |
- syncer::APP_SETTINGS, |
- syncer::TYPED_URLS, |
- syncer::HISTORY_DELETE_DIRECTIVES, |
- syncer::SYNCED_NOTIFICATIONS, |
- syncer::SYNCED_NOTIFICATION_APP_INFO, |
- |
- // UI thread data types. |
- syncer::BOOKMARKS, |
- syncer::SUPERVISED_USERS, // Syncing supervised users on initial login |
- // might block creating a new supervised user, |
- // so we want to do it early. |
- syncer::PREFERENCES, |
- syncer::PRIORITY_PREFERENCES, |
- syncer::EXTENSIONS, |
- syncer::APPS, |
- syncer::APP_LIST, |
- syncer::ARC_PACKAGE, |
- syncer::THEMES, |
- syncer::SEARCH_ENGINES, |
- syncer::SESSIONS, |
- syncer::APP_NOTIFICATIONS, |
- syncer::DICTIONARY, |
- syncer::FAVICON_IMAGES, |
- syncer::FAVICON_TRACKING, |
- syncer::SUPERVISED_USER_SETTINGS, |
- syncer::SUPERVISED_USER_SHARED_SETTINGS, |
- syncer::SUPERVISED_USER_WHITELISTS, |
- syncer::ARTICLES, |
- syncer::WIFI_CREDENTIALS, |
-}; |
- |
-static_assert(arraysize(kStartOrder) == |
- syncer::MODEL_TYPE_COUNT - syncer::FIRST_REAL_MODEL_TYPE, |
- "kStartOrder must have MODEL_TYPE_COUNT - " |
- "FIRST_REAL_MODEL_TYPE elements"); |
- |
-// 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. |
-const int64_t kAssociationTimeOutInSeconds = 600; |
- |
-syncer::DataTypeAssociationStats BuildAssociationStatsFromMergeResults( |
- const syncer::SyncMergeResult& local_merge_result, |
- const syncer::SyncMergeResult& syncer_merge_result, |
- const base::TimeDelta& association_wait_time, |
- const base::TimeDelta& association_time) { |
- DCHECK_EQ(local_merge_result.model_type(), syncer_merge_result.model_type()); |
- syncer::DataTypeAssociationStats stats; |
- stats.had_error = local_merge_result.error().IsSet() || |
- syncer_merge_result.error().IsSet(); |
- stats.num_local_items_before_association = |
- local_merge_result.num_items_before_association(); |
- stats.num_sync_items_before_association = |
- syncer_merge_result.num_items_before_association(); |
- stats.num_local_items_after_association = |
- local_merge_result.num_items_after_association(); |
- stats.num_sync_items_after_association = |
- syncer_merge_result.num_items_after_association(); |
- stats.num_local_items_added = |
- local_merge_result.num_items_added(); |
- stats.num_local_items_deleted = |
- local_merge_result.num_items_deleted(); |
- stats.num_local_items_modified = |
- local_merge_result.num_items_modified(); |
- stats.local_version_pre_association = |
- local_merge_result.pre_association_version(); |
- stats.num_sync_items_added = |
- syncer_merge_result.num_items_added(); |
- stats.num_sync_items_deleted = |
- syncer_merge_result.num_items_deleted(); |
- stats.num_sync_items_modified = |
- syncer_merge_result.num_items_modified(); |
- stats.sync_version_pre_association = |
- syncer_merge_result.pre_association_version(); |
- stats.association_wait_time = association_wait_time; |
- stats.association_time = association_time; |
- return stats; |
-} |
- |
-} // namespace |
- |
-ModelAssociationManager::ModelAssociationManager( |
- const DataTypeController::TypeMap* controllers, |
- ModelAssociationManagerDelegate* processor) |
- : state_(IDLE), |
- controllers_(controllers), |
- delegate_(processor), |
- configure_status_(DataTypeManager::UNKNOWN), |
- notified_about_ready_for_configure_(false), |
- weak_ptr_factory_(this) { |
- // Ensure all data type controllers are stopped. |
- for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
- it != controllers_->end(); ++it) { |
- DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state()); |
- } |
-} |
- |
-ModelAssociationManager::~ModelAssociationManager() { |
-} |
- |
-void ModelAssociationManager::Initialize(syncer::ModelTypeSet desired_types) { |
- // state_ can be INITIALIZED if types are reconfigured when |
- // data is being downloaded, so StartAssociationAsync() is never called for |
- // the first configuration. |
- DCHECK_NE(ASSOCIATING, state_); |
- |
- // Only keep types that have controllers. |
- desired_types_.Clear(); |
- for (syncer::ModelTypeSet::Iterator it = desired_types.First(); |
- it.Good(); it.Inc()) { |
- if (controllers_->find(it.Get()) != controllers_->end()) |
- desired_types_.Put(it.Get()); |
- } |
- |
- DVLOG(1) << "ModelAssociationManager: Initializing for " |
- << syncer::ModelTypeSetToString(desired_types_); |
- |
- state_ = INITIALIZED; |
- notified_about_ready_for_configure_ = false; |
- |
- StopDisabledTypes(); |
- 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()); |
- |
- 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(); |
- } |
-} |
- |
-void ModelAssociationManager::StopDisabledTypes() { |
- DVLOG(1) << "ModelAssociationManager: Stopping disabled types."; |
- for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); |
- it != controllers_->end(); ++it) { |
- DataTypeController* dtc = (*it).second.get(); |
- if (dtc->state() != DataTypeController::NOT_RUNNING && |
- !desired_types_.Has(dtc->type())) { |
- DVLOG(1) << "ModelAssociationManager: stop " << dtc->name(); |
- StopDatatype(syncer::SyncError(), dtc); |
- } |
- } |
-} |
- |
-void ModelAssociationManager::LoadEnabledTypes() { |
- // Load in kStartOrder. |
- for (size_t i = 0; i < arraysize(kStartOrder); i++) { |
- syncer::ModelType type = kStartOrder[i]; |
- if (!desired_types_.Has(type)) |
- continue; |
- |
- DCHECK(controllers_->find(type) != controllers_->end()); |
- DataTypeController* dtc = controllers_->find(type)->second.get(); |
- if (dtc->state() == DataTypeController::NOT_RUNNING) { |
- DCHECK(!loaded_types_.Has(dtc->type())); |
- DCHECK(!associated_types_.Has(dtc->type())); |
- dtc->LoadModels(base::Bind(&ModelAssociationManager::ModelLoadCallback, |
- weak_ptr_factory_.GetWeakPtr())); |
- } |
- } |
- NotifyDelegateIfReadyForConfigure(); |
-} |
- |
-void ModelAssociationManager::StartAssociationAsync( |
- const syncer::ModelTypeSet& types_to_associate) { |
- DCHECK_EQ(INITIALIZED, state_); |
- DVLOG(1) << "Starting association for " |
- << syncer::ModelTypeSetToString(types_to_associate); |
- state_ = ASSOCIATING; |
- |
- association_start_time_ = base::TimeTicks::Now(); |
- |
- requested_types_ = types_to_associate; |
- |
- associating_types_ = types_to_associate; |
- associating_types_.RetainAll(desired_types_); |
- associating_types_.RemoveAll(associated_types_); |
- |
- // Assume success. |
- configure_status_ = DataTypeManager::OK; |
- |
- // Done if no types to associate. |
- if (associating_types_.Empty()) { |
- ModelAssociationDone(INITIALIZED); |
- return; |
- } |
- |
- timer_.Start(FROM_HERE, |
- base::TimeDelta::FromSeconds(kAssociationTimeOutInSeconds), |
- base::Bind(&ModelAssociationManager::ModelAssociationDone, |
- weak_ptr_factory_.GetWeakPtr(), |
- INITIALIZED)); |
- |
- // Start association of types that are loaded in specified order. |
- for (size_t i = 0; i < arraysize(kStartOrder); i++) { |
- syncer::ModelType type = kStartOrder[i]; |
- if (!associating_types_.Has(type) || !loaded_types_.Has(type)) |
- continue; |
- |
- DataTypeController* dtc = controllers_->find(type)->second.get(); |
- DCHECK(DataTypeController::MODEL_LOADED == dtc->state() || |
- DataTypeController::ASSOCIATING == dtc->state()); |
- if (dtc->state() == DataTypeController::MODEL_LOADED) { |
- TRACE_EVENT_ASYNC_BEGIN1("sync", "ModelAssociation", |
- dtc, |
- "DataType", |
- ModelTypeToString(type)); |
- |
- dtc->StartAssociating( |
- base::Bind(&ModelAssociationManager::TypeStartCallback, |
- weak_ptr_factory_.GetWeakPtr(), |
- type, base::TimeTicks::Now())); |
- } |
- } |
-} |
- |
-void ModelAssociationManager::Stop() { |
- // Ignore callbacks from controllers. |
- weak_ptr_factory_.InvalidateWeakPtrs(); |
- |
- // 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); |
- DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name(); |
- } |
- } |
- |
- desired_types_.Clear(); |
- loaded_types_.Clear(); |
- associated_types_.Clear(); |
- |
- if (state_ == ASSOCIATING) { |
- if (configure_status_ == DataTypeManager::OK) |
- configure_status_ = DataTypeManager::ABORTED; |
- DVLOG(1) << "ModelAssociationManager: Calling OnModelAssociationDone"; |
- ModelAssociationDone(IDLE); |
- } else { |
- DCHECK(associating_types_.Empty()); |
- DCHECK(requested_types_.Empty()); |
- state_ = IDLE; |
- } |
-} |
- |
-void ModelAssociationManager::ModelLoadCallback(syncer::ModelType type, |
- syncer::SyncError error) { |
- DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for " |
- << syncer::ModelTypeToString(type); |
- |
- if (error.IsSet()) { |
- syncer::SyncMergeResult local_merge_result(type); |
- local_merge_result.set_error(error); |
- TypeStartCallback(type, |
- base::TimeTicks::Now(), |
- DataTypeController::ASSOCIATION_FAILED, |
- local_merge_result, |
- syncer::SyncMergeResult(type)); |
- return; |
- } |
- |
- // This happens when slow loading type is disabled by new configuration. |
- if (!desired_types_.Has(type)) |
- return; |
- |
- DCHECK(!loaded_types_.Has(type)); |
- loaded_types_.Put(type); |
- NotifyDelegateIfReadyForConfigure(); |
- if (associating_types_.Has(type)) { |
- DataTypeController* dtc = controllers_->find(type)->second.get(); |
- // If initial sync was done for this datatype then |
- // NotifyDelegateIfReadyForConfigure possibly already triggered model |
- // association and StartAssociating was already called for this type. To |
- // ensure StartAssociating is called only once only make a call if state is |
- // MODEL_LOADED. |
- // TODO(pavely): Add test for this scenario in DataTypeManagerImpl |
- // unittests. |
- if (dtc->state() == DataTypeController::MODEL_LOADED) { |
- dtc->StartAssociating(base::Bind( |
- &ModelAssociationManager::TypeStartCallback, |
- weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); |
- } |
- } |
-} |
- |
-void ModelAssociationManager::TypeStartCallback( |
- syncer::ModelType type, |
- base::TimeTicks type_start_time, |
- DataTypeController::ConfigureResult 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); |
- NotifyDelegateIfReadyForConfigure(); |
- |
- // Update configuration result. |
- if (start_result == DataTypeController::UNRECOVERABLE_ERROR) |
- configure_status_ = DataTypeManager::UNRECOVERABLE_ERROR; |
- } |
- |
- // 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_ == ASSOCIATING && associating_types_.Empty()) |
- ModelAssociationDone(INITIALIZED); |
- return; |
- } |
- |
- DCHECK(!associated_types_.Has(type)); |
- DCHECK(DataTypeController::IsSuccessfulResult(start_result)); |
- associated_types_.Put(type); |
- |
- if (state_ != ASSOCIATING) |
- return; |
- |
- TRACE_EVENT_ASYNC_END1("sync", "ModelAssociation", |
- controllers_->find(type)->second.get(), |
- "DataType", |
- ModelTypeToString(type)); |
- |
- // Track the merge results if we succeeded or an association failure |
- // occurred. |
- if (syncer::ProtocolTypes().Has(type)) { |
- base::TimeDelta association_wait_time = |
- std::max(base::TimeDelta(), type_start_time - association_start_time_); |
- base::TimeDelta association_time = |
- base::TimeTicks::Now() - type_start_time; |
- syncer::DataTypeAssociationStats stats = |
- BuildAssociationStatsFromMergeResults(local_merge_result, |
- syncer_merge_result, |
- association_wait_time, |
- association_time); |
- delegate_->OnSingleDataTypeAssociationDone(type, stats); |
- } |
- |
- associating_types_.Remove(type); |
- |
- if (associating_types_.Empty()) |
- ModelAssociationDone(INITIALIZED); |
-} |
- |
-void ModelAssociationManager::ModelAssociationDone(State new_state) { |
- DCHECK_NE(IDLE, state_); |
- |
- if (state_ == INITIALIZED) { |
- // No associations are currently happening. Just reset the state. |
- state_ = new_state; |
- return; |
- } |
- |
- DVLOG(1) << "Model association complete for " |
- << syncer::ModelTypeSetToString(requested_types_); |
- |
- 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); |
- } |
- } |
- |
- DataTypeManager::ConfigureResult result(configure_status_, |
- requested_types_); |
- |
- // Need to reset state before invoking delegate in order to avoid re-entrancy |
- // issues (delegate may trigger a reconfiguration). |
- associating_types_.Clear(); |
- requested_types_.Clear(); |
- state_ = new_state; |
- |
- delegate_->OnModelAssociationDone(result); |
-} |
- |
-base::OneShotTimer* ModelAssociationManager::GetTimerForTesting() { |
- return &timer_; |
-} |
- |
-void ModelAssociationManager::NotifyDelegateIfReadyForConfigure() { |
- if (notified_about_ready_for_configure_) |
- return; |
- for (const auto& type_dtc_pair : *controllers_) { |
- syncer::ModelType type = type_dtc_pair.first; |
- if (!desired_types_.Has(type)) |
- continue; |
- DataTypeController* dtc = type_dtc_pair.second.get(); |
- if (dtc->ShouldLoadModelBeforeConfigure() && !loaded_types_.Has(type)) { |
- // At least one type is not ready. |
- return; |
- } |
- } |
- |
- notified_about_ready_for_configure_ = true; |
- delegate_->OnAllDataTypesReadyForConfigure(); |
-} |
- |
-} // namespace sync_driver |