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

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: Fix progress marker fetching 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
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());
Nicolas Zea 2013/10/29 22:50:18 DCHECK that handler_it != handler_map->end()?
rlarocque 2013/10/30 00:32:22 Done.
131 continue;
132 sync_pb::DataTypeProgressMarker* progress_marker = 134 sync_pb::DataTypeProgressMarker* progress_marker =
133 get_updates->add_from_progress_marker(); 135 get_updates->add_from_progress_marker();
134 dir->GetDownloadProgress(it.Get(), progress_marker); 136 handler_it->second->GetDownloadProgress(progress_marker);
135 } 137 }
136 } 138 }
137 139
140 // Builds a map of ModelTypes to indices to progress markers in the given
141 // |gu_response| message. The map is returned in the |index_map| parameter.
142 void PartitionProgressMarkersByType(
143 const sync_pb::GetUpdatesResponse& gu_response,
144 ModelTypeSet request_types,
145 TypeToIndexMap* index_map) {
146 for (int i = 0; i < gu_response.new_progress_marker_size(); ++i) {
147 int field_number = gu_response.new_progress_marker(i).data_type_id();
148 ModelType model_type = GetModelTypeFromSpecificsFieldNumber(field_number);
149 if (!IsRealDataType(model_type)) {
150 DLOG(WARNING) << "Unknown field number " << field_number;
151 continue;
152 }
153 if (!request_types.Has(model_type)) {
154 DLOG(WARNING)
155 << "Skipping unexpected progress marker for non-enabled type "
156 << ModelTypeToString(model_type);
157 continue;
158 }
159 index_map->insert(std::make_pair(model_type, i));
160 }
161 }
162
163 // Examines the contents of the GetUpdates response message and forwards
164 // relevant data to the UpdateHandlers for processing and persisting.
165 bool ProcessUpdateResponseMessage(
166 const sync_pb::GetUpdatesResponse& gu_response,
167 ModelTypeSet proto_request_types,
168 UpdateHandlerMap* handler_map,
169 StatusController* status) {
170 TypeSyncEntityMap updates_by_type;
171 PartitionUpdatesByType(gu_response, proto_request_types, &updates_by_type);
172 DCHECK_EQ(proto_request_types.Size(), updates_by_type.size());
173
174 TypeToIndexMap progress_index_by_type;
175 PartitionProgressMarkersByType(gu_response,
176 proto_request_types,
177 &progress_index_by_type);
178 if (proto_request_types.Size() != progress_index_by_type.size()) {
179 NOTREACHED() << "Missing progress markers in GetUpdates response.";
180 return false;
181 }
182
183 // Iterate over these maps in parallel, processing updates for each type.
184 TypeToIndexMap::iterator progress_marker_iter =
185 progress_index_by_type.begin();
186 TypeSyncEntityMap::iterator updates_iter = updates_by_type.begin();
187 for ( ; (progress_marker_iter != progress_index_by_type.end()
188 && updates_iter != updates_by_type.end());
189 ++progress_marker_iter, ++updates_iter) {
190 DCHECK_EQ(progress_marker_iter->first, updates_iter->first);
191 ModelType type = progress_marker_iter->first;
192
193 UpdateHandlerMap::iterator update_handler_iter = handler_map->find(type);
194
195 if (update_handler_iter != handler_map->end()) {
196 update_handler_iter->second->ProcessGetUpdatesResponse(
197 gu_response.new_progress_marker(progress_marker_iter->second),
198 updates_iter->second,
199 status);
200 } else {
201 DLOG(WARNING)
202 << "Ignoring received updates of a type we can't handle. "
203 << "Type is: " << ModelTypeToString(type);
204 continue;
205 }
206 }
207 DCHECK(progress_marker_iter == progress_index_by_type.end()
208 && updates_iter == updates_by_type.end());
209
210 return true;
211 }
212
138 } // namespace 213 } // namespace
139 214
140 void BuildNormalDownloadUpdates( 215 void BuildNormalDownloadUpdates(
141 SyncSession* session, 216 SyncSession* session,
142 bool create_mobile_bookmarks_folder, 217 bool create_mobile_bookmarks_folder,
143 ModelTypeSet request_types, 218 ModelTypeSet request_types,
144 const sessions::NudgeTracker& nudge_tracker, 219 const sessions::NudgeTracker& nudge_tracker,
145 sync_pb::ClientToServerMessage* client_to_server_message) { 220 sync_pb::ClientToServerMessage* client_to_server_message) {
146 InitDownloadUpdatesRequest( 221 InitDownloadUpdatesRequest(
147 session, 222 session,
148 create_mobile_bookmarks_folder, 223 create_mobile_bookmarks_folder,
149 client_to_server_message, 224 client_to_server_message,
150 request_types); 225 Intersection(request_types, ProtocolTypes()));
151 sync_pb::GetUpdatesMessage* get_updates = 226 sync_pb::GetUpdatesMessage* get_updates =
152 client_to_server_message->mutable_get_updates(); 227 client_to_server_message->mutable_get_updates();
153 228
154 // Request updates for all requested types. 229 // Request updates for all requested types.
155 DVLOG(1) << "Getting updates for types " 230 DVLOG(1) << "Getting updates for types "
156 << ModelTypeSetToString(request_types); 231 << ModelTypeSetToString(request_types);
157 DCHECK(!request_types.Empty()); 232 DCHECK(!request_types.Empty());
158 233
159 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. 234 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
160 get_updates->mutable_caller_info()->set_source( 235 get_updates->mutable_caller_info()->set_source(
(...skipping 22 matching lines...) Expand all
183 void BuildDownloadUpdatesForConfigure( 258 void BuildDownloadUpdatesForConfigure(
184 SyncSession* session, 259 SyncSession* session,
185 bool create_mobile_bookmarks_folder, 260 bool create_mobile_bookmarks_folder,
186 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source, 261 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
187 ModelTypeSet request_types, 262 ModelTypeSet request_types,
188 sync_pb::ClientToServerMessage* client_to_server_message) { 263 sync_pb::ClientToServerMessage* client_to_server_message) {
189 InitDownloadUpdatesRequest( 264 InitDownloadUpdatesRequest(
190 session, 265 session,
191 create_mobile_bookmarks_folder, 266 create_mobile_bookmarks_folder,
192 client_to_server_message, 267 client_to_server_message,
193 request_types); 268 Intersection(request_types, ProtocolTypes()));
194 sync_pb::GetUpdatesMessage* get_updates = 269 sync_pb::GetUpdatesMessage* get_updates =
195 client_to_server_message->mutable_get_updates(); 270 client_to_server_message->mutable_get_updates();
196 271
197 // Request updates for all enabled types. 272 // Request updates for all enabled types.
198 DVLOG(1) << "Initial download for types " 273 DVLOG(1) << "Initial download for types "
199 << ModelTypeSetToString(request_types); 274 << ModelTypeSetToString(request_types);
200 DCHECK(!request_types.Empty()); 275 DCHECK(!request_types.Empty());
201 276
202 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. 277 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
203 get_updates->mutable_caller_info()->set_source(source); 278 get_updates->mutable_caller_info()->set_source(source);
204 279
205 // Set the new and improved version of source, too. 280 // Set the new and improved version of source, too.
206 sync_pb::SyncEnums::GetUpdatesOrigin origin = 281 sync_pb::SyncEnums::GetUpdatesOrigin origin =
207 ConvertConfigureSourceToOrigin(source); 282 ConvertConfigureSourceToOrigin(source);
208 get_updates->set_get_updates_origin(origin); 283 get_updates->set_get_updates_origin(origin);
209 } 284 }
210 285
211 void BuildDownloadUpdatesForPoll( 286 void BuildDownloadUpdatesForPoll(
212 SyncSession* session, 287 SyncSession* session,
213 bool create_mobile_bookmarks_folder, 288 bool create_mobile_bookmarks_folder,
214 ModelTypeSet request_types, 289 ModelTypeSet request_types,
215 sync_pb::ClientToServerMessage* client_to_server_message) { 290 sync_pb::ClientToServerMessage* client_to_server_message) {
216 InitDownloadUpdatesRequest( 291 InitDownloadUpdatesRequest(
217 session, 292 session,
218 create_mobile_bookmarks_folder, 293 create_mobile_bookmarks_folder,
219 client_to_server_message, 294 client_to_server_message,
220 request_types); 295 Intersection(request_types, ProtocolTypes()));
221 sync_pb::GetUpdatesMessage* get_updates = 296 sync_pb::GetUpdatesMessage* get_updates =
222 client_to_server_message->mutable_get_updates(); 297 client_to_server_message->mutable_get_updates();
223 298
224 DVLOG(1) << "Polling for types " 299 DVLOG(1) << "Polling for types "
225 << ModelTypeSetToString(request_types); 300 << ModelTypeSetToString(request_types);
226 DCHECK(!request_types.Empty()); 301 DCHECK(!request_types.Empty());
227 302
228 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. 303 // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
229 get_updates->mutable_caller_info()->set_source( 304 get_updates->mutable_caller_info()->set_source(
230 sync_pb::GetUpdatesCallerInfo::PERIODIC); 305 sync_pb::GetUpdatesCallerInfo::PERIODIC);
231 306
232 // Set the new and improved version of source, too. 307 // Set the new and improved version of source, too.
233 get_updates->set_get_updates_origin(sync_pb::SyncEnums::PERIODIC); 308 get_updates->set_get_updates_origin(sync_pb::SyncEnums::PERIODIC);
234 } 309 }
235 310
236 SyncerError ExecuteDownloadUpdates( 311 SyncerError ExecuteDownloadUpdates(
312 ModelTypeSet request_types,
237 SyncSession* session, 313 SyncSession* session,
238 sync_pb::ClientToServerMessage* msg) { 314 sync_pb::ClientToServerMessage* msg) {
239 sync_pb::ClientToServerResponse update_response; 315 sync_pb::ClientToServerResponse update_response;
240 StatusController* status = session->mutable_status_controller(); 316 StatusController* status = session->mutable_status_controller();
241 bool need_encryption_key = ShouldRequestEncryptionKey(session->context()); 317 bool need_encryption_key = ShouldRequestEncryptionKey(session->context());
242 318
243 SyncerError result = SyncerProtoUtil::PostClientToServerMessage( 319 SyncerError result = SyncerProtoUtil::PostClientToServerMessage(
244 msg, 320 msg,
245 &update_response, 321 &update_response,
246 session); 322 session);
247 323
248 DVLOG(2) << SyncerProtoUtil::ClientToServerResponseDebugString( 324 DVLOG(2) << SyncerProtoUtil::ClientToServerResponseDebugString(
249 update_response); 325 update_response);
250 326
251 if (result != SYNCER_OK) { 327 if (result != SYNCER_OK) {
252 status->mutable_updates_response()->Clear(); 328 status->mutable_updates_response()->Clear();
253 LOG(ERROR) << "PostClientToServerMessage() failed during GetUpdates"; 329 LOG(ERROR) << "PostClientToServerMessage() failed during GetUpdates";
254 } else { 330 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 } 331 }
270 332
271 ProcessUpdatesCommand process_updates; 333 status->mutable_updates_response()->CopyFrom(update_response);
272 process_updates.Execute(session);
273 334
274 StoreTimestampsCommand store_timestamps; 335 DVLOG(1) << "GetUpdates "
275 store_timestamps.Execute(session); 336 << " returned " << update_response.get_updates().entries_size()
337 << " updates and indicated "
338 << update_response.get_updates().changes_remaining()
339 << " updates left on server.";
276 340
277 return result; 341 if (need_encryption_key ||
342 update_response.get_updates().encryption_keys_size() > 0) {
343 syncable::Directory* dir = session->context()->directory();
344 status->set_last_get_key_result(
345 HandleGetEncryptionKeyResponse(update_response, dir));
346 }
347
348 const sync_pb::GetUpdatesResponse& gu_response =
349 update_response.get_updates();
350 status->increment_num_updates_downloaded_by(gu_response.entries_size());
351 DCHECK(gu_response.has_changes_remaining());
352 status->set_num_server_changes_remaining(gu_response.changes_remaining());
353
354 const ModelTypeSet proto_request_types =
355 Intersection(request_types, ProtocolTypes());
356
357 if (!ProcessUpdateResponseMessage(gu_response,
358 proto_request_types,
359 session->context()->update_handler_map(),
360 status)) {
361 return SERVER_RESPONSE_VALIDATION_FAILED;
362 } else {
363 return result;
364 }
278 } 365 }
279 366
280 } // namespace syncer 367 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698