Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / sync / engine / get_updates_processor.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "sync/engine/get_updates_processor.h"
6
7 #include <map>
8
9 #include "sync/engine/get_updates_delegate.h"
10 #include "sync/engine/sync_directory_update_handler.h"
11 #include "sync/protocol/sync.pb.h"
12
13 namespace syncer {
14
15 typedef std::map<ModelType, size_t> TypeToIndexMap;
16
17 namespace {
18
19 // Given a GetUpdates response, iterates over all the returned items and
20 // divides them according to their type.  Outputs a map from model types to
21 // received SyncEntities.  The output map will have entries (possibly empty)
22 // for all types in |requested_types|.
23 void PartitionUpdatesByType(
24     const sync_pb::GetUpdatesResponse& updates,
25     ModelTypeSet requested_types,
26     TypeSyncEntityMap* updates_by_type) {
27   int update_count = updates.entries().size();
28   for (ModelTypeSet::Iterator it = requested_types.First();
29        it.Good(); it.Inc()) {
30     updates_by_type->insert(std::make_pair(it.Get(), SyncEntityList()));
31   }
32   for (int i = 0; i < update_count; ++i) {
33     const sync_pb::SyncEntity& update = updates.entries(i);
34     ModelType type = GetModelType(update);
35     if (!IsRealDataType(type)) {
36       NOTREACHED() << "Received update with invalid type.";
37       continue;
38     }
39
40     TypeSyncEntityMap::iterator it = updates_by_type->find(type);
41     if (it == updates_by_type->end()) {
42       NOTREACHED() << "Received update for unexpected type "
43                    << ModelTypeToString(type);
44       continue;
45     }
46
47     it->second.push_back(&update);
48   }
49 }
50
51 // Builds a map of ModelTypes to indices to progress markers in the given
52 // |gu_response| message.  The map is returned in the |index_map| parameter.
53 void PartitionProgressMarkersByType(
54     const sync_pb::GetUpdatesResponse& gu_response,
55     ModelTypeSet request_types,
56     TypeToIndexMap* index_map) {
57   for (int i = 0; i < gu_response.new_progress_marker_size(); ++i) {
58     int field_number = gu_response.new_progress_marker(i).data_type_id();
59     ModelType model_type = GetModelTypeFromSpecificsFieldNumber(field_number);
60     if (!IsRealDataType(model_type)) {
61       DLOG(WARNING) << "Unknown field number " << field_number;
62       continue;
63     }
64     if (!request_types.Has(model_type)) {
65       DLOG(WARNING)
66           << "Skipping unexpected progress marker for non-enabled type "
67           << ModelTypeToString(model_type);
68       continue;
69     }
70     index_map->insert(std::make_pair(model_type, i));
71   }
72 }
73
74 }  // namespace
75
76 GetUpdatesProcessor::GetUpdatesProcessor(UpdateHandlerMap* update_handler_map,
77                                          const GetUpdatesDelegate& delegate)
78     : update_handler_map_(update_handler_map), delegate_(delegate) {}
79
80 GetUpdatesProcessor::~GetUpdatesProcessor() {}
81
82 void GetUpdatesProcessor::PrepareGetUpdates(
83     ModelTypeSet gu_types,
84     sync_pb::GetUpdatesMessage* get_updates) {
85   for (ModelTypeSet::Iterator it = gu_types.First(); it.Good(); it.Inc()) {
86     UpdateHandlerMap::iterator handler_it = update_handler_map_->find(it.Get());
87     DCHECK(handler_it != update_handler_map_->end());
88     sync_pb::DataTypeProgressMarker* progress_marker =
89         get_updates->add_from_progress_marker();
90     handler_it->second->GetDownloadProgress(progress_marker);
91   }
92   delegate_.HelpPopulateGuMessage(get_updates);
93 }
94
95 bool GetUpdatesProcessor::ProcessGetUpdatesResponse(
96     ModelTypeSet gu_types,
97     const sync_pb::GetUpdatesResponse& gu_response,
98     sessions::StatusController* status_controller) {
99   TypeSyncEntityMap updates_by_type;
100   PartitionUpdatesByType(gu_response, gu_types, &updates_by_type);
101   DCHECK_EQ(gu_types.Size(), updates_by_type.size());
102
103   TypeToIndexMap progress_index_by_type;
104   PartitionProgressMarkersByType(gu_response,
105                                  gu_types,
106                                  &progress_index_by_type);
107   if (gu_types.Size() != progress_index_by_type.size()) {
108     NOTREACHED() << "Missing progress markers in GetUpdates response.";
109     return false;
110   }
111
112   // Iterate over these maps in parallel, processing updates for each type.
113   TypeToIndexMap::iterator progress_marker_iter =
114       progress_index_by_type.begin();
115   TypeSyncEntityMap::iterator updates_iter = updates_by_type.begin();
116   for (; (progress_marker_iter != progress_index_by_type.end()
117            && updates_iter != updates_by_type.end());
118        ++progress_marker_iter, ++updates_iter) {
119     DCHECK_EQ(progress_marker_iter->first, updates_iter->first);
120     ModelType type = progress_marker_iter->first;
121
122     UpdateHandlerMap::iterator update_handler_iter =
123         update_handler_map_->find(type);
124
125     if (update_handler_iter != update_handler_map_->end()) {
126       update_handler_iter->second->ProcessGetUpdatesResponse(
127           gu_response.new_progress_marker(progress_marker_iter->second),
128           updates_iter->second,
129           status_controller);
130     } else {
131       DLOG(WARNING)
132           << "Ignoring received updates of a type we can't handle.  "
133           << "Type is: " << ModelTypeToString(type);
134       continue;
135     }
136   }
137   DCHECK(progress_marker_iter == progress_index_by_type.end() &&
138          updates_iter == updates_by_type.end());
139
140   return true;
141 }
142
143 void GetUpdatesProcessor::ApplyUpdates(
144     sessions::StatusController* status_controller) {
145   delegate_.ApplyUpdates(status_controller, update_handler_map_);
146 }
147
148 }  // namespace syncer