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

Side by Side Diff: sync/engine/download.cc

Issue 38803003: sync: Implement per-type update processing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review fixes Created 7 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sync/engine/download.h ('k') | sync/engine/process_updates_command.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sync/engine/download.h" 5 #include "sync/engine/download.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "sync/engine/process_updates_command.h" 10 #include "sync/engine/process_updates_util.h"
11 #include "sync/engine/store_timestamps_command.h" 11 #include "sync/engine/sync_directory_update_handler.h"
12 #include "sync/engine/syncer.h" 12 #include "sync/engine/syncer.h"
13 #include "sync/engine/syncer_proto_util.h" 13 #include "sync/engine/syncer_proto_util.h"
14 #include "sync/sessions/nudge_tracker.h" 14 #include "sync/sessions/nudge_tracker.h"
15 #include "sync/syncable/directory.h" 15 #include "sync/syncable/directory.h"
16 #include "sync/syncable/nigori_handler.h" 16 #include "sync/syncable/nigori_handler.h"
17 #include "sync/syncable/syncable_read_transaction.h" 17 #include "sync/syncable/syncable_read_transaction.h"
18 18
19 using sync_pb::DebugInfo; 19 using sync_pb::DebugInfo;
20 20
21 namespace syncer { 21 namespace syncer {
22 22
23 using sessions::StatusController; 23 using sessions::StatusController;
24 using sessions::SyncSession; 24 using sessions::SyncSession;
25 using sessions::SyncSessionContext; 25 using sessions::SyncSessionContext;
26 using std::string; 26 using std::string;
27 27
28 namespace { 28 namespace {
29 29
30 typedef std::map<ModelType, size_t> TypeToIndexMap;
31
30 SyncerError HandleGetEncryptionKeyResponse( 32 SyncerError HandleGetEncryptionKeyResponse(
31 const sync_pb::ClientToServerResponse& update_response, 33 const sync_pb::ClientToServerResponse& update_response,
32 syncable::Directory* dir) { 34 syncable::Directory* dir) {
33 bool success = false; 35 bool success = false;
34 if (update_response.get_updates().encryption_keys_size() == 0) { 36 if (update_response.get_updates().encryption_keys_size() == 0) {
35 LOG(ERROR) << "Failed to receive encryption key from server."; 37 LOG(ERROR) << "Failed to receive encryption key from server.";
36 return SERVER_RESPONSE_VALIDATION_FAILED; 38 return SERVER_RESPONSE_VALIDATION_FAILED;
37 } 39 }
38 syncable::ReadTransaction trans(FROM_HERE, dir); 40 syncable::ReadTransaction trans(FROM_HERE, dir);
39 syncable::NigoriHandler* nigori_handler = dir->GetNigoriHandler(); 41 syncable::NigoriHandler* nigori_handler = dir->GetNigoriHandler();
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 debug_info); 93 debug_info);
92 } 94 }
93 session->mutable_status_controller()->set_debug_info_sent(); 95 session->mutable_status_controller()->set_debug_info_sent();
94 } 96 }
95 } 97 }
96 98
97 void InitDownloadUpdatesRequest( 99 void InitDownloadUpdatesRequest(
98 SyncSession* session, 100 SyncSession* session,
99 bool create_mobile_bookmarks_folder, 101 bool create_mobile_bookmarks_folder,
100 sync_pb::ClientToServerMessage* message, 102 sync_pb::ClientToServerMessage* message,
101 ModelTypeSet request_types) { 103 ModelTypeSet proto_request_types) {
102 message->set_share(session->context()->account_name()); 104 message->set_share(session->context()->account_name());
103 message->set_message_contents(sync_pb::ClientToServerMessage::GET_UPDATES); 105 message->set_message_contents(sync_pb::ClientToServerMessage::GET_UPDATES);
104 106
105 sync_pb::GetUpdatesMessage* get_updates = message->mutable_get_updates(); 107 sync_pb::GetUpdatesMessage* get_updates = message->mutable_get_updates();
106 108
107 // We want folders for our associated types, always. If we were to set 109 // We want folders for our associated types, always. If we were to set
108 // this to false, the server would send just the non-container items 110 // this to false, the server would send just the non-container items
109 // (e.g. Bookmark URLs but not their containing folders). 111 // (e.g. Bookmark URLs but not their containing folders).
110 get_updates->set_fetch_folders(true); 112 get_updates->set_fetch_folders(true);
111 113
112 DebugInfo* debug_info = message->mutable_debug_info(); 114 DebugInfo* debug_info = message->mutable_debug_info();
113 AppendClientDebugInfoIfNeeded(session, debug_info); 115 AppendClientDebugInfoIfNeeded(session, debug_info);
114 116
115 get_updates->set_create_mobile_bookmarks_folder( 117 get_updates->set_create_mobile_bookmarks_folder(
116 create_mobile_bookmarks_folder); 118 create_mobile_bookmarks_folder);
117 bool need_encryption_key = ShouldRequestEncryptionKey(session->context()); 119 bool need_encryption_key = ShouldRequestEncryptionKey(session->context());
118 get_updates->set_need_encryption_key(need_encryption_key); 120 get_updates->set_need_encryption_key(need_encryption_key);
119 121
120 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. 122 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
121 get_updates->mutable_caller_info()->set_notifications_enabled( 123 get_updates->mutable_caller_info()->set_notifications_enabled(
122 session->context()->notifications_enabled()); 124 session->context()->notifications_enabled());
123 125
124 StatusController* status = session->mutable_status_controller(); 126 StatusController* status = session->mutable_status_controller();
125 status->set_updates_request_types(request_types); 127 status->set_updates_request_types(proto_request_types);
126 128
127 syncable::Directory* dir = session->context()->directory(); 129 UpdateHandlerMap* handler_map = session->context()->update_handler_map();
128 for (ModelTypeSet::Iterator it = request_types.First(); 130
131 for (ModelTypeSet::Iterator it = proto_request_types.First();
129 it.Good(); it.Inc()) { 132 it.Good(); it.Inc()) {
130 if (ProxyTypes().Has(it.Get())) 133 UpdateHandlerMap::iterator handler_it = handler_map->find(it.Get());
131 continue; 134 DCHECK(handler_it != handler_map->end());
132 sync_pb::DataTypeProgressMarker* progress_marker = 135 sync_pb::DataTypeProgressMarker* progress_marker =
133 get_updates->add_from_progress_marker(); 136 get_updates->add_from_progress_marker();
134 dir->GetDownloadProgress(it.Get(), progress_marker); 137 handler_it->second->GetDownloadProgress(progress_marker);
135 } 138 }
136 } 139 }
137 140
141 // Builds a map of ModelTypes to indices to progress markers in the given
142 // |gu_response| message. The map is returned in the |index_map| parameter.
143 void PartitionProgressMarkersByType(
144 const sync_pb::GetUpdatesResponse& gu_response,
145 ModelTypeSet request_types,
146 TypeToIndexMap* index_map) {
147 for (int i = 0; i < gu_response.new_progress_marker_size(); ++i) {
148 int field_number = gu_response.new_progress_marker(i).data_type_id();
149 ModelType model_type = GetModelTypeFromSpecificsFieldNumber(field_number);
150 if (!IsRealDataType(model_type)) {
151 DLOG(WARNING) << "Unknown field number " << field_number;
152 continue;
153 }
154 if (!request_types.Has(model_type)) {
155 DLOG(WARNING)
156 << "Skipping unexpected progress marker for non-enabled type "
157 << ModelTypeToString(model_type);
158 continue;
159 }
160 index_map->insert(std::make_pair(model_type, i));
161 }
162 }
163
164 // Examines the contents of the GetUpdates response message and forwards
165 // relevant data to the UpdateHandlers for processing and persisting.
166 bool ProcessUpdateResponseMessage(
167 const sync_pb::GetUpdatesResponse& gu_response,
168 ModelTypeSet proto_request_types,
169 UpdateHandlerMap* handler_map,
170 StatusController* status) {
171 TypeSyncEntityMap updates_by_type;
172 PartitionUpdatesByType(gu_response, proto_request_types, &updates_by_type);
173 DCHECK_EQ(proto_request_types.Size(), updates_by_type.size());
174
175 TypeToIndexMap progress_index_by_type;
176 PartitionProgressMarkersByType(gu_response,
177 proto_request_types,
178 &progress_index_by_type);
179 if (proto_request_types.Size() != progress_index_by_type.size()) {
180 NOTREACHED() << "Missing progress markers in GetUpdates response.";
181 return false;
182 }
183
184 // Iterate over these maps in parallel, processing updates for each type.
185 TypeToIndexMap::iterator progress_marker_iter =
186 progress_index_by_type.begin();
187 TypeSyncEntityMap::iterator updates_iter = updates_by_type.begin();
188 for ( ; (progress_marker_iter != progress_index_by_type.end()
189 && updates_iter != updates_by_type.end());
190 ++progress_marker_iter, ++updates_iter) {
191 DCHECK_EQ(progress_marker_iter->first, updates_iter->first);
192 ModelType type = progress_marker_iter->first;
193
194 UpdateHandlerMap::iterator update_handler_iter = handler_map->find(type);
195
196 if (update_handler_iter != handler_map->end()) {
197 update_handler_iter->second->ProcessGetUpdatesResponse(
198 gu_response.new_progress_marker(progress_marker_iter->second),
199 updates_iter->second,
200 status);
201 } else {
202 DLOG(WARNING)
203 << "Ignoring received updates of a type we can't handle. "
204 << "Type is: " << ModelTypeToString(type);
205 continue;
206 }
207 }
208 DCHECK(progress_marker_iter == progress_index_by_type.end()
209 && updates_iter == updates_by_type.end());
210
211 return true;
212 }
213
138 } // namespace 214 } // namespace
139 215
140 void BuildNormalDownloadUpdates( 216 void BuildNormalDownloadUpdates(
141 SyncSession* session, 217 SyncSession* session,
142 bool create_mobile_bookmarks_folder, 218 bool create_mobile_bookmarks_folder,
143 ModelTypeSet request_types, 219 ModelTypeSet request_types,
144 const sessions::NudgeTracker& nudge_tracker, 220 const sessions::NudgeTracker& nudge_tracker,
145 sync_pb::ClientToServerMessage* client_to_server_message) { 221 sync_pb::ClientToServerMessage* client_to_server_message) {
146 InitDownloadUpdatesRequest( 222 InitDownloadUpdatesRequest(
147 session, 223 session,
148 create_mobile_bookmarks_folder, 224 create_mobile_bookmarks_folder,
149 client_to_server_message, 225 client_to_server_message,
150 request_types); 226 Intersection(request_types, ProtocolTypes()));
151 sync_pb::GetUpdatesMessage* get_updates = 227 sync_pb::GetUpdatesMessage* get_updates =
152 client_to_server_message->mutable_get_updates(); 228 client_to_server_message->mutable_get_updates();
153 229
154 // Request updates for all requested types. 230 // Request updates for all requested types.
155 DVLOG(1) << "Getting updates for types " 231 DVLOG(1) << "Getting updates for types "
156 << ModelTypeSetToString(request_types); 232 << ModelTypeSetToString(request_types);
157 DCHECK(!request_types.Empty()); 233 DCHECK(!request_types.Empty());
158 234
159 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. 235 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
160 get_updates->mutable_caller_info()->set_source( 236 get_updates->mutable_caller_info()->set_source(
(...skipping 22 matching lines...) Expand all
183 void BuildDownloadUpdatesForConfigure( 259 void BuildDownloadUpdatesForConfigure(
184 SyncSession* session, 260 SyncSession* session,
185 bool create_mobile_bookmarks_folder, 261 bool create_mobile_bookmarks_folder,
186 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source, 262 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
187 ModelTypeSet request_types, 263 ModelTypeSet request_types,
188 sync_pb::ClientToServerMessage* client_to_server_message) { 264 sync_pb::ClientToServerMessage* client_to_server_message) {
189 InitDownloadUpdatesRequest( 265 InitDownloadUpdatesRequest(
190 session, 266 session,
191 create_mobile_bookmarks_folder, 267 create_mobile_bookmarks_folder,
192 client_to_server_message, 268 client_to_server_message,
193 request_types); 269 Intersection(request_types, ProtocolTypes()));
194 sync_pb::GetUpdatesMessage* get_updates = 270 sync_pb::GetUpdatesMessage* get_updates =
195 client_to_server_message->mutable_get_updates(); 271 client_to_server_message->mutable_get_updates();
196 272
197 // Request updates for all enabled types. 273 // Request updates for all enabled types.
198 DVLOG(1) << "Initial download for types " 274 DVLOG(1) << "Initial download for types "
199 << ModelTypeSetToString(request_types); 275 << ModelTypeSetToString(request_types);
200 DCHECK(!request_types.Empty()); 276 DCHECK(!request_types.Empty());
201 277
202 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. 278 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
203 get_updates->mutable_caller_info()->set_source(source); 279 get_updates->mutable_caller_info()->set_source(source);
204 280
205 // Set the new and improved version of source, too. 281 // Set the new and improved version of source, too.
206 sync_pb::SyncEnums::GetUpdatesOrigin origin = 282 sync_pb::SyncEnums::GetUpdatesOrigin origin =
207 ConvertConfigureSourceToOrigin(source); 283 ConvertConfigureSourceToOrigin(source);
208 get_updates->set_get_updates_origin(origin); 284 get_updates->set_get_updates_origin(origin);
209 } 285 }
210 286
211 void BuildDownloadUpdatesForPoll( 287 void BuildDownloadUpdatesForPoll(
212 SyncSession* session, 288 SyncSession* session,
213 bool create_mobile_bookmarks_folder, 289 bool create_mobile_bookmarks_folder,
214 ModelTypeSet request_types, 290 ModelTypeSet request_types,
215 sync_pb::ClientToServerMessage* client_to_server_message) { 291 sync_pb::ClientToServerMessage* client_to_server_message) {
216 InitDownloadUpdatesRequest( 292 InitDownloadUpdatesRequest(
217 session, 293 session,
218 create_mobile_bookmarks_folder, 294 create_mobile_bookmarks_folder,
219 client_to_server_message, 295 client_to_server_message,
220 request_types); 296 Intersection(request_types, ProtocolTypes()));
221 sync_pb::GetUpdatesMessage* get_updates = 297 sync_pb::GetUpdatesMessage* get_updates =
222 client_to_server_message->mutable_get_updates(); 298 client_to_server_message->mutable_get_updates();
223 299
224 DVLOG(1) << "Polling for types " 300 DVLOG(1) << "Polling for types "
225 << ModelTypeSetToString(request_types); 301 << ModelTypeSetToString(request_types);
226 DCHECK(!request_types.Empty()); 302 DCHECK(!request_types.Empty());
227 303
228 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. 304 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
229 get_updates->mutable_caller_info()->set_source( 305 get_updates->mutable_caller_info()->set_source(
230 sync_pb::GetUpdatesCallerInfo::PERIODIC); 306 sync_pb::GetUpdatesCallerInfo::PERIODIC);
231 307
232 // Set the new and improved version of source, too. 308 // Set the new and improved version of source, too.
233 get_updates->set_get_updates_origin(sync_pb::SyncEnums::PERIODIC); 309 get_updates->set_get_updates_origin(sync_pb::SyncEnums::PERIODIC);
234 } 310 }
235 311
236 SyncerError ExecuteDownloadUpdates( 312 SyncerError ExecuteDownloadUpdates(
313 ModelTypeSet request_types,
237 SyncSession* session, 314 SyncSession* session,
238 sync_pb::ClientToServerMessage* msg) { 315 sync_pb::ClientToServerMessage* msg) {
239 sync_pb::ClientToServerResponse update_response; 316 sync_pb::ClientToServerResponse update_response;
240 StatusController* status = session->mutable_status_controller(); 317 StatusController* status = session->mutable_status_controller();
241 bool need_encryption_key = ShouldRequestEncryptionKey(session->context()); 318 bool need_encryption_key = ShouldRequestEncryptionKey(session->context());
242 319
243 SyncerError result = SyncerProtoUtil::PostClientToServerMessage( 320 SyncerError result = SyncerProtoUtil::PostClientToServerMessage(
244 msg, 321 msg,
245 &update_response, 322 &update_response,
246 session); 323 session);
247 324
248 DVLOG(2) << SyncerProtoUtil::ClientToServerResponseDebugString( 325 DVLOG(2) << SyncerProtoUtil::ClientToServerResponseDebugString(
249 update_response); 326 update_response);
250 327
251 if (result != SYNCER_OK) { 328 if (result != SYNCER_OK) {
252 status->mutable_updates_response()->Clear(); 329 status->mutable_updates_response()->Clear();
253 LOG(ERROR) << "PostClientToServerMessage() failed during GetUpdates"; 330 LOG(ERROR) << "PostClientToServerMessage() failed during GetUpdates";
254 } else { 331 return result;
255 status->mutable_updates_response()->CopyFrom(update_response);
256
257 DVLOG(1) << "GetUpdates "
258 << " returned " << update_response.get_updates().entries_size()
259 << " updates and indicated "
260 << update_response.get_updates().changes_remaining()
261 << " updates left on server.";
262
263 if (need_encryption_key ||
264 update_response.get_updates().encryption_keys_size() > 0) {
265 syncable::Directory* dir = session->context()->directory();
266 status->set_last_get_key_result(
267 HandleGetEncryptionKeyResponse(update_response, dir));
268 }
269 } 332 }
270 333
271 ProcessUpdatesCommand process_updates; 334 status->mutable_updates_response()->CopyFrom(update_response);
272 process_updates.Execute(session);
273 335
274 StoreTimestampsCommand store_timestamps; 336 DVLOG(1) << "GetUpdates "
275 store_timestamps.Execute(session); 337 << " returned " << update_response.get_updates().entries_size()
338 << " updates and indicated "
339 << update_response.get_updates().changes_remaining()
340 << " updates left on server.";
276 341
277 return result; 342 if (need_encryption_key ||
343 update_response.get_updates().encryption_keys_size() > 0) {
344 syncable::Directory* dir = session->context()->directory();
345 status->set_last_get_key_result(
346 HandleGetEncryptionKeyResponse(update_response, dir));
347 }
348
349 const sync_pb::GetUpdatesResponse& gu_response =
350 update_response.get_updates();
351 status->increment_num_updates_downloaded_by(gu_response.entries_size());
352 DCHECK(gu_response.has_changes_remaining());
353 status->set_num_server_changes_remaining(gu_response.changes_remaining());
354
355 const ModelTypeSet proto_request_types =
356 Intersection(request_types, ProtocolTypes());
357
358 if (!ProcessUpdateResponseMessage(gu_response,
359 proto_request_types,
360 session->context()->update_handler_map(),
361 status)) {
362 return SERVER_RESPONSE_VALIDATION_FAILED;
363 } else {
364 return result;
365 }
278 } 366 }
279 367
280 } // namespace syncer 368 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/engine/download.h ('k') | sync/engine/process_updates_command.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698