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

Unified Diff: components/sync/driver/data_type_manager_impl.cc

Issue 2563423005: [Sync] Move ConfigureDataTypes logic into DataTypeManagerImpl. (Closed)
Patch Set: Address comments. Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: components/sync/driver/data_type_manager_impl.cc
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index 15c30f157b0cfdd5e38582768f6fcaa6bc311064..071d4c42bd447bf55ce6432c90d7285eec89fed0 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <functional>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -52,7 +53,8 @@ DataTypeManagerImpl::DataTypeManagerImpl(
const DataTypeEncryptionHandler* encryption_handler,
ModelTypeConfigurer* configurer,
DataTypeManagerObserver* observer)
- : sync_client_(sync_client),
+ : downloaded_types_(initial_types),
+ sync_client_(sync_client),
configurer_(configurer),
controllers_(controllers),
state_(DataTypeManager::STOPPED),
@@ -165,12 +167,36 @@ void DataTypeManagerImpl::RegisterTypesWithBackend() {
// successfully. Such types shouldn't be in an error state at the same
// time.
DCHECK(!data_type_status_table_.GetFailedTypes().Has(dtc->type()));
- dtc->RegisterWithBackend(configurer_);
+ dtc->RegisterWithBackend(
+ base::Bind(&DataTypeManagerImpl::SetTypeDownloaded,
+ base::Unretained(this), dtc->type()),
+ configurer_);
}
}
}
-ModelTypeConfigurer::DataTypeConfigStateMap
+// static
+ModelTypeSet DataTypeManagerImpl::GetDataTypesInState(
+ DataTypeConfigState state,
+ const DataTypeConfigStateMap& state_map) {
+ ModelTypeSet types;
+ for (const auto& kv : state_map) {
+ if (kv.second == state)
+ types.Put(kv.first);
+ }
+ return types;
+}
+
+// static
+void DataTypeManagerImpl::SetDataTypesState(DataTypeConfigState state,
+ ModelTypeSet types,
+ DataTypeConfigStateMap* state_map) {
+ for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
+ (*state_map)[it.Get()] = state;
+ }
+}
+
+DataTypeManagerImpl::DataTypeConfigStateMap
DataTypeManagerImpl::BuildDataTypeConfigStateMap(
const ModelTypeSet& types_being_configured) const {
// 1. Get the failed types (due to fatal, crypto, and unready errors).
@@ -207,22 +233,14 @@ DataTypeManagerImpl::BuildDataTypeConfigStateMap(
DVLOG(1) << "Configuring: " << ModelTypeSetToString(to_configure);
DVLOG(1) << "Disabling: " << ModelTypeSetToString(disabled_types);
- ModelTypeConfigurer::DataTypeConfigStateMap config_state_map;
- ModelTypeConfigurer::SetDataTypesState(
- ModelTypeConfigurer::CONFIGURE_INACTIVE, enabled_types,
- &config_state_map);
- ModelTypeConfigurer::SetDataTypesState(ModelTypeConfigurer::CONFIGURE_ACTIVE,
- to_configure, &config_state_map);
- ModelTypeConfigurer::SetDataTypesState(ModelTypeConfigurer::CONFIGURE_CLEAN,
- clean_types, &config_state_map);
- ModelTypeConfigurer::SetDataTypesState(ModelTypeConfigurer::DISABLED,
- disabled_types, &config_state_map);
- ModelTypeConfigurer::SetDataTypesState(ModelTypeConfigurer::FATAL,
- fatal_types, &config_state_map);
- ModelTypeConfigurer::SetDataTypesState(ModelTypeConfigurer::CRYPTO,
- crypto_types, &config_state_map);
- ModelTypeConfigurer::SetDataTypesState(ModelTypeConfigurer::UNREADY,
- unready_types, &config_state_map);
+ DataTypeConfigStateMap config_state_map;
+ SetDataTypesState(CONFIGURE_INACTIVE, enabled_types, &config_state_map);
+ SetDataTypesState(CONFIGURE_ACTIVE, to_configure, &config_state_map);
+ SetDataTypesState(CONFIGURE_CLEAN, clean_types, &config_state_map);
+ SetDataTypesState(DISABLED, disabled_types, &config_state_map);
+ SetDataTypesState(FATAL, fatal_types, &config_state_map);
+ SetDataTypesState(CRYPTO, crypto_types, &config_state_map);
+ SetDataTypesState(UNREADY, unready_types, &config_state_map);
return config_state_map;
}
@@ -447,15 +465,21 @@ void DataTypeManagerImpl::StartNextDownload(
if (download_types_queue_.empty())
return;
- // Tell the backend about the new set of data types we wish to sync.
- // The task will be invoked when updates are downloaded.
- ModelTypeSet ready_types = configurer_->ConfigureDataTypes(
- last_configure_reason_,
- BuildDataTypeConfigStateMap(download_types_queue_.front()),
- base::Bind(&DataTypeManagerImpl::DownloadReady,
- weak_ptr_factory_.GetWeakPtr(), download_types_queue_.front()),
- base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
- weak_ptr_factory_.GetWeakPtr()));
+ ModelTypeConfigurer::ConfigureParams config_params;
+ ModelTypeSet ready_types = PrepareConfigureParams(&config_params);
+
+ // The engine's state was initially derived from the types detected to have
+ // been downloaded in the database. Afterwards it is modified only by this
+ // function. We expect |downloaded_types_| to remain consistent because
+ // configuration requests are never aborted; they are retried until they
+ // succeed or the engine is shut down.
+ //
+ // Only one configure is allowed at a time. This is guaranteed by our callers.
+ // The sync engine requests one configure as it is initializing and waits for
+ // it to complete. After engine initialization, all configurations pass
+ // through the DataTypeManager, and we are careful to never send a new
+ // configure request until the current request succeeds.
+ configurer_->ConfigureDataTypes(std::move(config_params));
AssociationTypesInfo association_info;
association_info.types = download_types_queue_.front();
@@ -469,6 +493,121 @@ void DataTypeManagerImpl::StartNextDownload(
StartNextAssociation(READY_AT_CONFIG);
}
+ModelTypeSet DataTypeManagerImpl::PrepareConfigureParams(
+ ModelTypeConfigurer::ConfigureParams* params) {
+ // Divide up the types into their corresponding actions:
+ // - Types which are newly enabled are downloaded.
+ // - Types which have encountered a fatal error (fatal_types) are deleted
+ // from the directory and journaled in the delete journal.
+ // - Types which have encountered a cryptographer error (crypto_types) are
+ // unapplied (local state is purged but sync state is not).
+ // - All other types not in the routing info (types just disabled) are deleted
+ // from the directory.
+ // - Everything else (enabled types and already disabled types) is not
+ // touched.
+ const DataTypeConfigStateMap config_state_map =
+ BuildDataTypeConfigStateMap(download_types_queue_.front());
+ const ModelTypeSet fatal_types = GetDataTypesInState(FATAL, config_state_map);
+ const ModelTypeSet crypto_types =
+ GetDataTypesInState(CRYPTO, config_state_map);
+ const ModelTypeSet unready_types =
+ GetDataTypesInState(UNREADY, config_state_map);
+ const ModelTypeSet active_types =
+ GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map);
+ const ModelTypeSet clean_types =
+ GetDataTypesInState(CONFIGURE_CLEAN, config_state_map);
+ const ModelTypeSet inactive_types =
+ GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map);
+
+ ModelTypeSet enabled_types = Union(active_types, clean_types);
+ ModelTypeSet disabled_types = GetDataTypesInState(DISABLED, config_state_map);
+ disabled_types.PutAll(fatal_types);
+ disabled_types.PutAll(crypto_types);
+ disabled_types.PutAll(unready_types);
+
+ DCHECK(Intersection(enabled_types, disabled_types).Empty());
+
+ // The sync engine's enabled types will be updated by adding |enabled_types|
+ // to the list then removing |disabled_types|. Any types which are not in
+ // either of those sets will remain untouched. Types which were not in
+ // |downloaded_types_| previously are not fully downloaded, so we must ask the
+ // engine to download them. Any newly supported datatypes won't have been in
+ // |downloaded_types_|, so they will also be downloaded if they are enabled.
+ ModelTypeSet types_to_download = Difference(enabled_types, downloaded_types_);
+ downloaded_types_.PutAll(enabled_types);
+ downloaded_types_.RemoveAll(disabled_types);
+
+ types_to_download.PutAll(clean_types);
+ types_to_download.RemoveAll(ProxyTypes());
+ if (!types_to_download.Empty())
+ types_to_download.Put(NIGORI);
+
+ // TODO(sync): crbug.com/137550.
+ // It's dangerous to configure types that have progress markers. Types with
+ // progress markers can trigger a MIGRATION_DONE response. We are not
+ // prepared to handle a migration during a configure, so we must ensure that
+ // all our types_to_download actually contain no data before we sync them.
+ //
+ // One common way to end up in this situation used to be types which
+ // downloaded some or all of their data but have not applied it yet. We avoid
+ // problems with those types by purging the data of any such partially synced
+ // types soon after we load the directory.
+ //
+ // Another possible scenario is that we have newly supported or newly enabled
+ // data types being downloaded here but the nigori type, which is always
+ // included in any GetUpdates request, requires migration. The server has
+ // code to detect this scenario based on the configure reason, the fact that
+ // the nigori type is the only requested type which requires migration, and
+ // that the requested types list includes at least one non-nigori type. It
+ // will not send a MIGRATION_DONE response in that case. We still need to be
+ // careful to not send progress markers for non-nigori types, though. If a
+ // non-nigori type in the request requires migration, a MIGRATION_DONE
+ // response will be sent.
+
+ ModelTypeSet types_to_purge =
+ Difference(ModelTypeSet::All(), downloaded_types_);
+ // Include clean_types in types_to_purge, they are part of
+ // |downloaded_types_|, but still need to be cleared.
+ DCHECK(downloaded_types_.HasAll(clean_types));
+ types_to_purge.PutAll(clean_types);
+ types_to_purge.RemoveAll(inactive_types);
+ types_to_purge.RemoveAll(unready_types);
+
+ // If a type has already been disabled and unapplied or journaled, it will
+ // not be part of the |types_to_purge| set, and therefore does not need
+ // to be acted on again.
+ ModelTypeSet types_to_journal = Intersection(fatal_types, types_to_purge);
+ ModelTypeSet unapply_types = Union(crypto_types, clean_types);
+ unapply_types.RetainAll(types_to_purge);
+
+ DCHECK(Intersection(downloaded_types_, types_to_journal).Empty());
+ DCHECK(Intersection(downloaded_types_, crypto_types).Empty());
+ // |downloaded_types_| was already updated to include all enabled types.
+ DCHECK(downloaded_types_.HasAll(types_to_download));
+
+ DVLOG(1) << "Types " << ModelTypeSetToString(types_to_download)
+ << " added; calling ConfigureDataTypes";
+
+ params->reason = last_configure_reason_;
+ params->enabled_types = enabled_types;
+ params->disabled_types = disabled_types;
+ params->to_download = types_to_download;
+ params->to_purge = types_to_purge;
+ params->to_journal = types_to_journal;
+ params->to_unapply = unapply_types;
+ params->ready_task =
+ base::Bind(&DataTypeManagerImpl::DownloadReady,
+ weak_ptr_factory_.GetWeakPtr(), download_types_queue_.front());
+ params->retry_callback = base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
+ weak_ptr_factory_.GetWeakPtr());
+
+ DCHECK(Intersection(active_types, types_to_purge).Empty());
+ DCHECK(Intersection(active_types, fatal_types).Empty());
+ DCHECK(Intersection(active_types, unapply_types).Empty());
+ DCHECK(Intersection(active_types, inactive_types).Empty());
+ return Difference(active_types, types_to_download);
+}
+
void DataTypeManagerImpl::StartNextAssociation(AssociationGroup group) {
CHECK(!association_types_queue_.empty());
@@ -701,4 +840,12 @@ ModelTypeSet DataTypeManagerImpl::GetEnabledTypes() const {
data_type_status_table_.GetFailedTypes());
}
+void DataTypeManagerImpl::SetTypeDownloaded(ModelType type, bool downloaded) {
+ if (downloaded) {
+ downloaded_types_.Put(type);
+ } else {
+ downloaded_types_.Remove(type);
+ }
+}
+
} // namespace syncer
« no previous file with comments | « components/sync/driver/data_type_manager_impl.h ('k') | components/sync/driver/data_type_manager_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698