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

Unified Diff: sync/engine/updater_list.cc

Issue 93433006: sync: Introduce ModelTypeRegistry and helpers (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Split the type manager Created 7 years 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: sync/engine/updater_list.cc
diff --git a/sync/engine/updater_list.cc b/sync/engine/updater_list.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8950a3dbb4f7bb573f0db812ea93513e1d173c87
--- /dev/null
+++ b/sync/engine/updater_list.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2013 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 "sync/engine/updater_list.h"
+
+#include <map>
+
+#include "sync/engine/sync_directory_update_handler.h"
+#include "sync/protocol/sync.pb.h"
+
+namespace syncer {
+
+typedef std::map<ModelType, size_t> TypeToIndexMap;
+
+UpdaterList::UpdaterList()
+ : update_handler_deleter_(&update_handler_map_) {}
+
+UpdaterList::~UpdaterList() {}
+
+void UpdaterList::SetEnabledSyncDirectoryTypes(
+ const std::vector<scoped_refptr<ModelSafeWorker> > workers,
+ const ModelSafeRoutingInfo& routing_info,
+ syncable::Directory* directory) {
+ std::map<ModelSafeGroup, scoped_refptr<ModelSafeWorker> > workers_map;
+ for (size_t i = 0u; i < workers.size(); ++i) {
+ workers_map.insert(
+ std::make_pair(workers[i]->GetModelSafeGroup(), workers[i]));
+ }
+
+ STLDeleteValues<UpdateHandlerMap>(&update_handler_map_);
+ for (ModelSafeRoutingInfo::const_iterator routing_iter = routing_info.begin();
+ routing_iter != routing_info.end(); ++routing_iter) {
+ ModelType type = routing_iter->first;
+ ModelSafeGroup group = routing_iter->second;
+ std::map<ModelSafeGroup, scoped_refptr<ModelSafeWorker> >::iterator
+ worker_it = workers_map.find(group);
+ DCHECK(worker_it != workers_map.end());
+ scoped_refptr<ModelSafeWorker> worker = worker_it->second;
+
+ SyncDirectoryUpdateHandler* handler =
+ new SyncDirectoryUpdateHandler(directory, type, worker);
+ update_handler_map_.insert(std::make_pair(type, handler));
+ }
+}
+
+void UpdaterList::PrepareGetUpdates(
+ ModelTypeSet gu_types,
+ sync_pb::GetUpdatesMessage* get_updates) {
+ for (ModelTypeSet::Iterator it = gu_types.First(); it.Good(); it.Inc()) {
+ UpdateHandlerMap::iterator handler_it = update_handler_map_.find(it.Get());
+ DCHECK(handler_it != update_handler_map_.end());
+ sync_pb::DataTypeProgressMarker* progress_marker =
+ get_updates->add_from_progress_marker();
+ handler_it->second->GetDownloadProgress(progress_marker);
+ }
+}
+
+namespace {
+
+// Given a GetUpdates response, iterates over all the returned items and
+// divides them according to their type. Outputs a map from model types to
+// received SyncEntities. The output map will have entries (possibly empty)
+// for all types in |requested_types|.
+void PartitionUpdatesByType(
+ const sync_pb::GetUpdatesResponse& updates,
+ ModelTypeSet requested_types,
+ TypeSyncEntityMap* updates_by_type) {
+ int update_count = updates.entries().size();
+ for (ModelTypeSet::Iterator it = requested_types.First();
+ it.Good(); it.Inc()) {
+ updates_by_type->insert(std::make_pair(it.Get(), SyncEntityList()));
+ }
+ for (int i = 0; i < update_count; ++i) {
+ const sync_pb::SyncEntity& update = updates.entries(i);
+ ModelType type = GetModelType(update);
+ if (!IsRealDataType(type)) {
+ NOTREACHED() << "Received update with invalid type.";
+ continue;
+ }
+
+ TypeSyncEntityMap::iterator it = updates_by_type->find(type);
+ if (it == updates_by_type->end()) {
+ DLOG(WARNING) << "Skipping update for unexpected type "
Nicolas Zea 2013/12/18 22:36:10 Should this be a NOTREACHED as well?
rlarocque 2014/01/03 01:46:41 Yes, probably. Updated.
+ << ModelTypeToString(type);
+ continue;
+ }
+
+ it->second.push_back(&update);
+ }
+}
+
+// Builds a map of ModelTypes to indices to progress markers in the given
+// |gu_response| message. The map is returned in the |index_map| parameter.
+void PartitionProgressMarkersByType(
+ const sync_pb::GetUpdatesResponse& gu_response,
+ ModelTypeSet request_types,
+ TypeToIndexMap* index_map) {
+ for (int i = 0; i < gu_response.new_progress_marker_size(); ++i) {
+ int field_number = gu_response.new_progress_marker(i).data_type_id();
+ ModelType model_type = GetModelTypeFromSpecificsFieldNumber(field_number);
+ if (!IsRealDataType(model_type)) {
+ DLOG(WARNING) << "Unknown field number " << field_number;
+ continue;
+ }
+ if (!request_types.Has(model_type)) {
+ DLOG(WARNING)
+ << "Skipping unexpected progress marker for non-enabled type "
+ << ModelTypeToString(model_type);
+ continue;
+ }
+ index_map->insert(std::make_pair(model_type, i));
+ }
+}
+
+} // namespace
+
+bool UpdaterList::ProcessGetUpdatesResponse(
+ ModelTypeSet gu_types,
+ const sync_pb::GetUpdatesResponse& gu_response,
+ sessions::StatusController* status_controller) {
+ TypeSyncEntityMap updates_by_type;
+ PartitionUpdatesByType(gu_response, gu_types, &updates_by_type);
+ DCHECK_EQ(gu_types.Size(), updates_by_type.size());
+
+ TypeToIndexMap progress_index_by_type;
+ PartitionProgressMarkersByType(gu_response,
+ gu_types,
+ &progress_index_by_type);
+ if (gu_types.Size() != progress_index_by_type.size()) {
+ NOTREACHED() << "Missing progress markers in GetUpdates response.";
+ return false;
+ }
+
+ // Iterate over these maps in parallel, processing updates for each type.
+ TypeToIndexMap::iterator progress_marker_iter =
+ progress_index_by_type.begin();
+ TypeSyncEntityMap::iterator updates_iter = updates_by_type.begin();
+ for ( ; (progress_marker_iter != progress_index_by_type.end()
Nicolas Zea 2013/12/18 22:36:10 nit: remove space before ;? (not sure what the sty
rlarocque 2014/01/03 01:46:41 Done.
+ && updates_iter != updates_by_type.end());
+ ++progress_marker_iter, ++updates_iter) {
+ DCHECK_EQ(progress_marker_iter->first, updates_iter->first);
+ ModelType type = progress_marker_iter->first;
+
+ UpdateHandlerMap::iterator update_handler_iter =
+ update_handler_map_.find(type);
+
+ if (update_handler_iter != update_handler_map_.end()) {
+ update_handler_iter->second->ProcessGetUpdatesResponse(
+ gu_response.new_progress_marker(progress_marker_iter->second),
+ updates_iter->second,
+ status_controller);
+ } else {
+ DLOG(WARNING)
+ << "Ignoring received updates of a type we can't handle. "
+ << "Type is: " << ModelTypeToString(type);
+ continue;
+ }
+ }
+ DCHECK(progress_marker_iter == progress_index_by_type.end()
+ && updates_iter == updates_by_type.end());
+
+ return true;
+}
+
+void UpdaterList::ApplyUpdatesForAllTypes(
+ sessions::StatusController* status_controller) {
+ for (UpdateHandlerMap::iterator it = update_handler_map_.begin();
+ it != update_handler_map_.end(); ++it) {
+ it->second->ApplyUpdates(status_controller);
+ }
+}
+
+void UpdaterList::RegisterTypeForTest(
+ ModelType type,
+ SyncDirectoryUpdateHandler* handler) {
+ bool inserted =
+ update_handler_map_.insert(std::make_pair(type, handler)).second;
+ DCHECK(inserted) << "Attempt to override existing type handler in map";
+}
+
+} // namespace syncer

Powered by Google App Engine
This is Rietveld 408576698