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

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

Issue 10735041: Remove syncproto.h (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Improve DCHECKing, fix tests Created 8 years, 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/process_commit_response_command.h" 5 #include "sync/engine/process_commit_response_command.h"
6 6
7 #include <cstddef> 7 #include <cstddef>
8 #include <set> 8 #include <set>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/basictypes.h" 12 #include "base/basictypes.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "sync/engine/syncer_proto_util.h" 14 #include "sync/engine/syncer_proto_util.h"
15 #include "sync/engine/syncer_util.h" 15 #include "sync/engine/syncer_util.h"
16 #include "sync/engine/syncproto.h"
17 #include "sync/sessions/sync_session.h" 16 #include "sync/sessions/sync_session.h"
18 #include "sync/syncable/entry.h" 17 #include "sync/syncable/entry.h"
19 #include "sync/syncable/mutable_entry.h" 18 #include "sync/syncable/mutable_entry.h"
20 #include "sync/syncable/read_transaction.h" 19 #include "sync/syncable/read_transaction.h"
20 #include "sync/syncable/syncable_proto_util.h"
21 #include "sync/syncable/syncable_util.h" 21 #include "sync/syncable/syncable_util.h"
22 #include "sync/syncable/write_transaction.h" 22 #include "sync/syncable/write_transaction.h"
23 #include "sync/util/time.h" 23 #include "sync/util/time.h"
24 24
25 using std::set; 25 using std::set;
26 using std::string; 26 using std::string;
27 using std::vector; 27 using std::vector;
28 using sync_pb::CommitResponse;
28 29
29 namespace syncer { 30 namespace syncer {
30 31
31 using sessions::OrderedCommitSet; 32 using sessions::OrderedCommitSet;
32 using sessions::StatusController; 33 using sessions::StatusController;
33 using sessions::SyncSession; 34 using sessions::SyncSession;
34 using sessions::ConflictProgress; 35 using sessions::ConflictProgress;
35 using syncable::WriteTransaction; 36 using syncable::WriteTransaction;
36 using syncable::MutableEntry; 37 using syncable::MutableEntry;
37 using syncable::Entry; 38 using syncable::Entry;
38 using syncable::BASE_VERSION; 39 using syncable::BASE_VERSION;
39 using syncable::GET_BY_ID; 40 using syncable::GET_BY_ID;
40 using syncable::ID; 41 using syncable::ID;
41 using syncable::IS_DEL; 42 using syncable::IS_DEL;
42 using syncable::IS_DIR; 43 using syncable::IS_DIR;
43 using syncable::IS_UNAPPLIED_UPDATE; 44 using syncable::IS_UNAPPLIED_UPDATE;
44 using syncable::IS_UNSYNCED; 45 using syncable::IS_UNSYNCED;
45 using syncable::PARENT_ID; 46 using syncable::PARENT_ID;
46 using syncable::SERVER_IS_DEL; 47 using syncable::SERVER_IS_DEL;
47 using syncable::SERVER_PARENT_ID; 48 using syncable::SERVER_PARENT_ID;
48 using syncable::SERVER_POSITION_IN_PARENT; 49 using syncable::SERVER_POSITION_IN_PARENT;
49 using syncable::SERVER_VERSION; 50 using syncable::SERVER_VERSION;
50 using syncable::SYNCER; 51 using syncable::SYNCER;
51 using syncable::SYNCING; 52 using syncable::SYNCING;
52 53
53 ProcessCommitResponseCommand::ProcessCommitResponseCommand( 54 ProcessCommitResponseCommand::ProcessCommitResponseCommand(
54 const sessions::OrderedCommitSet& commit_set, 55 const sessions::OrderedCommitSet& commit_set,
55 const ClientToServerMessage& commit_message, 56 const sync_pb::ClientToServerMessage& commit_message,
56 const ClientToServerResponse& commit_response) 57 const sync_pb::ClientToServerResponse& commit_response)
57 : commit_set_(commit_set), 58 : commit_set_(commit_set),
58 commit_message_(commit_message), 59 commit_message_(commit_message),
59 commit_response_(commit_response) { 60 commit_response_(commit_response) {
60 } 61 }
61 62
62 ProcessCommitResponseCommand::~ProcessCommitResponseCommand() {} 63 ProcessCommitResponseCommand::~ProcessCommitResponseCommand() {}
63 64
64 std::set<ModelSafeGroup> ProcessCommitResponseCommand::GetGroupsToChange( 65 std::set<ModelSafeGroup> ProcessCommitResponseCommand::GetGroupsToChange(
65 const sessions::SyncSession& session) const { 66 const sessions::SyncSession& session) const {
66 std::set<ModelSafeGroup> groups_with_commits; 67 std::set<ModelSafeGroup> groups_with_commits;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 // 183 //
183 // TODO: Remove this option when the CONFLICT return value is fully 184 // TODO: Remove this option when the CONFLICT return value is fully
184 // deprecated. 185 // deprecated.
185 return SERVER_RETURN_TRANSIENT_ERROR; 186 return SERVER_RETURN_TRANSIENT_ERROR;
186 } else { 187 } else {
187 LOG(FATAL) << "Inconsistent counts when processing commit response"; 188 LOG(FATAL) << "Inconsistent counts when processing commit response";
188 return SYNCER_OK; 189 return SYNCER_OK;
189 } 190 }
190 } 191 }
191 192
192 void LogServerError(const CommitResponse_EntryResponse& res) { 193 void LogServerError(const sync_pb::CommitResponse_EntryResponse& res) {
193 if (res.has_error_message()) 194 if (res.has_error_message())
194 LOG(WARNING) << " " << res.error_message(); 195 LOG(WARNING) << " " << res.error_message();
195 else 196 else
196 LOG(WARNING) << " No detailed error message returned from server"; 197 LOG(WARNING) << " No detailed error message returned from server";
197 } 198 }
198 199
199 CommitResponse::ResponseType 200 CommitResponse::ResponseType
200 ProcessCommitResponseCommand::ProcessSingleCommitResponse( 201 ProcessCommitResponseCommand::ProcessSingleCommitResponse(
201 syncable::WriteTransaction* trans, 202 syncable::WriteTransaction* trans,
202 const sync_pb::CommitResponse_EntryResponse& pb_server_entry, 203 const sync_pb::CommitResponse_EntryResponse& pb_server_entry,
203 const sync_pb::SyncEntity& commit_request_entry, 204 const sync_pb::SyncEntity& commit_request_entry,
204 const syncable::Id& pre_commit_id, 205 const syncable::Id& pre_commit_id,
205 set<syncable::Id>* deleted_folders) { 206 set<syncable::Id>* deleted_folders) {
206 207
207 const CommitResponse_EntryResponse& server_entry = 208 const sync_pb::CommitResponse_EntryResponse& server_entry =
208 *static_cast<const CommitResponse_EntryResponse*>(&pb_server_entry); 209 *static_cast<const sync_pb::CommitResponse_EntryResponse*>(
akalin 2012/07/11 01:42:22 static cast not needed anymore?
rlarocque 2012/07/11 19:22:16 Done.
210 &pb_server_entry);
209 MutableEntry local_entry(trans, GET_BY_ID, pre_commit_id); 211 MutableEntry local_entry(trans, GET_BY_ID, pre_commit_id);
210 CHECK(local_entry.good()); 212 CHECK(local_entry.good());
211 bool syncing_was_set = local_entry.Get(SYNCING); 213 bool syncing_was_set = local_entry.Get(SYNCING);
212 local_entry.Put(SYNCING, false); 214 local_entry.Put(SYNCING, false);
213 215
214 CommitResponse::ResponseType response = (CommitResponse::ResponseType) 216 CommitResponse::ResponseType response = (CommitResponse::ResponseType)
215 server_entry.response_type(); 217 server_entry.response_type();
216 if (!CommitResponse::ResponseType_IsValid(response)) { 218 if (!CommitResponse::ResponseType_IsValid(response)) {
217 LOG(ERROR) << "Commit response has unknown response type! Possibly out " 219 LOG(ERROR) << "Commit response has unknown response type! Possibly out "
218 "of date client?"; 220 "of date client?";
(...skipping 23 matching lines...) Expand all
242 } 244 }
243 if (!server_entry.has_id_string()) { 245 if (!server_entry.has_id_string()) {
244 LOG(ERROR) << "Commit response has no id"; 246 LOG(ERROR) << "Commit response has no id";
245 return CommitResponse::INVALID_MESSAGE; 247 return CommitResponse::INVALID_MESSAGE;
246 } 248 }
247 249
248 // Implied by the IsValid call above, but here for clarity. 250 // Implied by the IsValid call above, but here for clarity.
249 DCHECK_EQ(CommitResponse::SUCCESS, response) << response; 251 DCHECK_EQ(CommitResponse::SUCCESS, response) << response;
250 // Check to see if we've been given the ID of an existing entry. If so treat 252 // Check to see if we've been given the ID of an existing entry. If so treat
251 // it as an error response and retry later. 253 // it as an error response and retry later.
252 if (pre_commit_id != server_entry.id()) { 254 syncable::Id server_entry_id = SyncableIdFromProto(server_entry.id_string());
253 Entry e(trans, GET_BY_ID, server_entry.id()); 255 if (pre_commit_id != server_entry_id) {
256 Entry e(trans, GET_BY_ID, server_entry_id);
254 if (e.good()) { 257 if (e.good()) {
255 LOG(ERROR) << "Got duplicate id when commiting id: " << pre_commit_id << 258 LOG(ERROR) << "Got duplicate id when commiting id: " << pre_commit_id <<
256 ". Treating as an error return"; 259 ". Treating as an error return";
257 return CommitResponse::INVALID_MESSAGE; 260 return CommitResponse::INVALID_MESSAGE;
258 } 261 }
259 } 262 }
260 263
261 if (server_entry.version() == 0) { 264 if (server_entry.version() == 0) {
262 LOG(WARNING) << "Server returned a zero version on a commit response."; 265 LOG(WARNING) << "Server returned a zero version on a commit response.";
263 } 266 }
264 267
265 ProcessSuccessfulCommitResponse(commit_request_entry, server_entry, 268 ProcessSuccessfulCommitResponse(commit_request_entry, server_entry,
266 pre_commit_id, &local_entry, syncing_was_set, deleted_folders); 269 pre_commit_id, &local_entry, syncing_was_set, deleted_folders);
267 return response; 270 return response;
268 } 271 }
269 272
270 const string& ProcessCommitResponseCommand::GetResultingPostCommitName( 273 const string& ProcessCommitResponseCommand::GetResultingPostCommitName(
271 const sync_pb::SyncEntity& committed_entry, 274 const sync_pb::SyncEntity& committed_entry,
272 const CommitResponse_EntryResponse& entry_response) { 275 const sync_pb::CommitResponse_EntryResponse& entry_response) {
273 const string& response_name = 276 const string& response_name =
274 SyncerProtoUtil::NameFromCommitEntryResponse(entry_response); 277 SyncerProtoUtil::NameFromCommitEntryResponse(entry_response);
275 if (!response_name.empty()) 278 if (!response_name.empty())
276 return response_name; 279 return response_name;
277 return SyncerProtoUtil::NameFromSyncEntity(committed_entry); 280 return SyncerProtoUtil::NameFromSyncEntity(committed_entry);
278 } 281 }
279 282
280 bool ProcessCommitResponseCommand::UpdateVersionAfterCommit( 283 bool ProcessCommitResponseCommand::UpdateVersionAfterCommit(
281 const sync_pb::SyncEntity& committed_entry, 284 const sync_pb::SyncEntity& committed_entry,
282 const CommitResponse_EntryResponse& entry_response, 285 const sync_pb::CommitResponse_EntryResponse& entry_response,
283 const syncable::Id& pre_commit_id, 286 const syncable::Id& pre_commit_id,
284 syncable::MutableEntry* local_entry) { 287 syncable::MutableEntry* local_entry) {
285 int64 old_version = local_entry->Get(BASE_VERSION); 288 int64 old_version = local_entry->Get(BASE_VERSION);
286 int64 new_version = entry_response.version(); 289 int64 new_version = entry_response.version();
287 bool bad_commit_version = false; 290 bool bad_commit_version = false;
288 if (committed_entry.deleted() && 291 if (committed_entry.deleted() &&
289 !local_entry->Get(syncable::UNIQUE_CLIENT_TAG).empty()) { 292 !local_entry->Get(syncable::UNIQUE_CLIENT_TAG).empty()) {
290 // If the item was deleted, and it's undeletable (uses the client tag), 293 // If the item was deleted, and it's undeletable (uses the client tag),
291 // change the version back to zero. We must set the version to zero so 294 // change the version back to zero. We must set the version to zero so
292 // that the server knows to re-create the item if it gets committed 295 // that the server knows to re-create the item if it gets committed
293 // later for undeletion. 296 // later for undeletion.
294 new_version = 0; 297 new_version = 0;
295 } else if (!pre_commit_id.ServerKnows()) { 298 } else if (!pre_commit_id.ServerKnows()) {
296 bad_commit_version = 0 == new_version; 299 bad_commit_version = 0 == new_version;
297 } else { 300 } else {
298 bad_commit_version = old_version > new_version; 301 bad_commit_version = old_version > new_version;
299 } 302 }
300 if (bad_commit_version) { 303 if (bad_commit_version) {
301 LOG(ERROR) << "Bad version in commit return for " << *local_entry 304 LOG(ERROR) << "Bad version in commit return for " << *local_entry
302 << " new_id:" << entry_response.id() << " new_version:" 305 << " new_id:" << SyncableIdFromProto(entry_response.id_string())
303 << entry_response.version(); 306 << " new_version:" << entry_response.version();
304 return false; 307 return false;
305 } 308 }
306 309
307 // Update the base version and server version. The base version must change 310 // Update the base version and server version. The base version must change
308 // here, even if syncing_was_set is false; that's because local changes were 311 // here, even if syncing_was_set is false; that's because local changes were
309 // on top of the successfully committed version. 312 // on top of the successfully committed version.
310 local_entry->Put(BASE_VERSION, new_version); 313 local_entry->Put(BASE_VERSION, new_version);
311 DVLOG(1) << "Commit is changing base version of " << local_entry->Get(ID) 314 DVLOG(1) << "Commit is changing base version of " << local_entry->Get(ID)
312 << " to: " << new_version; 315 << " to: " << new_version;
313 local_entry->Put(SERVER_VERSION, new_version); 316 local_entry->Put(SERVER_VERSION, new_version);
314 return true; 317 return true;
315 } 318 }
316 319
317 bool ProcessCommitResponseCommand::ChangeIdAfterCommit( 320 bool ProcessCommitResponseCommand::ChangeIdAfterCommit(
318 const CommitResponse_EntryResponse& entry_response, 321 const sync_pb::CommitResponse_EntryResponse& entry_response,
319 const syncable::Id& pre_commit_id, 322 const syncable::Id& pre_commit_id,
320 syncable::MutableEntry* local_entry) { 323 syncable::MutableEntry* local_entry) {
321 syncable::WriteTransaction* trans = local_entry->write_transaction(); 324 syncable::WriteTransaction* trans = local_entry->write_transaction();
322 if (entry_response.id() != pre_commit_id) { 325 syncable::Id entry_response_id =
326 SyncableIdFromProto(entry_response.id_string());
327 if (entry_response_id != pre_commit_id) {
323 if (pre_commit_id.ServerKnows()) { 328 if (pre_commit_id.ServerKnows()) {
324 // The server can sometimes generate a new ID on commit; for example, 329 // The server can sometimes generate a new ID on commit; for example,
325 // when committing an undeletion. 330 // when committing an undeletion.
326 DVLOG(1) << " ID changed while committing an old entry. " 331 DVLOG(1) << " ID changed while committing an old entry. "
327 << pre_commit_id << " became " << entry_response.id() << "."; 332 << pre_commit_id << " became " << entry_response_id << ".";
328 } 333 }
329 MutableEntry same_id(trans, GET_BY_ID, entry_response.id()); 334 MutableEntry same_id(trans, GET_BY_ID, entry_response_id);
330 // We should trap this before this function. 335 // We should trap this before this function.
331 if (same_id.good()) { 336 if (same_id.good()) {
332 LOG(ERROR) << "ID clash with id " << entry_response.id() 337 LOG(ERROR) << "ID clash with id " << entry_response_id
333 << " during commit " << same_id; 338 << " during commit " << same_id;
334 return false; 339 return false;
335 } 340 }
336 ChangeEntryIDAndUpdateChildren(trans, local_entry, entry_response.id()); 341 ChangeEntryIDAndUpdateChildren(trans, local_entry, entry_response_id);
337 DVLOG(1) << "Changing ID to " << entry_response.id(); 342 DVLOG(1) << "Changing ID to " << entry_response_id;
338 } 343 }
339 return true; 344 return true;
340 } 345 }
341 346
342 void ProcessCommitResponseCommand::UpdateServerFieldsAfterCommit( 347 void ProcessCommitResponseCommand::UpdateServerFieldsAfterCommit(
343 const sync_pb::SyncEntity& committed_entry, 348 const sync_pb::SyncEntity& committed_entry,
344 const CommitResponse_EntryResponse& entry_response, 349 const sync_pb::CommitResponse_EntryResponse& entry_response,
345 syncable::MutableEntry* local_entry) { 350 syncable::MutableEntry* local_entry) {
346 351
347 // We just committed an entry successfully, and now we want to make our view 352 // We just committed an entry successfully, and now we want to make our view
348 // of the server state consistent with the server state. We must be careful; 353 // of the server state consistent with the server state. We must be careful;
349 // |entry_response| and |committed_entry| have some identically named 354 // |entry_response| and |committed_entry| have some identically named
350 // fields. We only want to consider fields from |committed_entry| when there 355 // fields. We only want to consider fields from |committed_entry| when there
351 // is not an overriding field in the |entry_response|. We do not want to 356 // is not an overriding field in the |entry_response|. We do not want to
352 // update the server data from the local data in the entry -- it's possible 357 // update the server data from the local data in the entry -- it's possible
353 // that the local data changed during the commit, and even if not, the server 358 // that the local data changed during the commit, and even if not, the server
354 // has the last word on the values of several properties. 359 // has the last word on the values of several properties.
(...skipping 30 matching lines...) Expand all
385 if (local_entry->Get(IS_UNAPPLIED_UPDATE)) { 390 if (local_entry->Get(IS_UNAPPLIED_UPDATE)) {
386 // This shouldn't happen; an unapplied update shouldn't be committed, and 391 // This shouldn't happen; an unapplied update shouldn't be committed, and
387 // if it were, the commit should have failed. But if it does happen: we've 392 // if it were, the commit should have failed. But if it does happen: we've
388 // just overwritten the update info, so clear the flag. 393 // just overwritten the update info, so clear the flag.
389 local_entry->Put(IS_UNAPPLIED_UPDATE, false); 394 local_entry->Put(IS_UNAPPLIED_UPDATE, false);
390 } 395 }
391 } 396 }
392 397
393 void ProcessCommitResponseCommand::OverrideClientFieldsAfterCommit( 398 void ProcessCommitResponseCommand::OverrideClientFieldsAfterCommit(
394 const sync_pb::SyncEntity& committed_entry, 399 const sync_pb::SyncEntity& committed_entry,
395 const CommitResponse_EntryResponse& entry_response, 400 const sync_pb::CommitResponse_EntryResponse& entry_response,
396 syncable::MutableEntry* local_entry) { 401 syncable::MutableEntry* local_entry) {
397 if (committed_entry.deleted()) { 402 if (committed_entry.deleted()) {
398 // If an entry's been deleted, nothing else matters. 403 // If an entry's been deleted, nothing else matters.
399 DCHECK(local_entry->Get(IS_DEL)); 404 DCHECK(local_entry->Get(IS_DEL));
400 return; 405 return;
401 } 406 }
402 407
403 // Update the name. 408 // Update the name.
404 const string& server_name = 409 const string& server_name =
405 GetResultingPostCommitName(committed_entry, entry_response); 410 GetResultingPostCommitName(committed_entry, entry_response);
(...skipping 19 matching lines...) Expand all
425 local_entry->Get(PARENT_ID)); 430 local_entry->Get(PARENT_ID));
426 if (!local_entry->PutPredecessor(new_prev)) { 431 if (!local_entry->PutPredecessor(new_prev)) {
427 // TODO(lipalani) : Propagate the error to caller. crbug.com/100444. 432 // TODO(lipalani) : Propagate the error to caller. crbug.com/100444.
428 NOTREACHED(); 433 NOTREACHED();
429 } 434 }
430 } 435 }
431 } 436 }
432 437
433 void ProcessCommitResponseCommand::ProcessSuccessfulCommitResponse( 438 void ProcessCommitResponseCommand::ProcessSuccessfulCommitResponse(
434 const sync_pb::SyncEntity& committed_entry, 439 const sync_pb::SyncEntity& committed_entry,
435 const CommitResponse_EntryResponse& entry_response, 440 const sync_pb::CommitResponse_EntryResponse& entry_response,
436 const syncable::Id& pre_commit_id, syncable::MutableEntry* local_entry, 441 const syncable::Id& pre_commit_id, syncable::MutableEntry* local_entry,
437 bool syncing_was_set, set<syncable::Id>* deleted_folders) { 442 bool syncing_was_set, set<syncable::Id>* deleted_folders) {
438 DCHECK(local_entry->Get(IS_UNSYNCED)); 443 DCHECK(local_entry->Get(IS_UNSYNCED));
439 444
440 // Update SERVER_VERSION and BASE_VERSION. 445 // Update SERVER_VERSION and BASE_VERSION.
441 if (!UpdateVersionAfterCommit(committed_entry, entry_response, pre_commit_id, 446 if (!UpdateVersionAfterCommit(committed_entry, entry_response, pre_commit_id,
442 local_entry)) { 447 local_entry)) {
443 LOG(ERROR) << "Bad version in commit return for " << *local_entry 448 LOG(ERROR) << "Bad version in commit return for " << *local_entry
444 << " new_id:" << entry_response.id() << " new_version:" 449 << " new_id:" << SyncableIdFromProto(entry_response.id_string())
445 << entry_response.version(); 450 << " new_version:" << entry_response.version();
446 return; 451 return;
447 } 452 }
448 453
449 // If the server gave us a new ID, apply it. 454 // If the server gave us a new ID, apply it.
450 if (!ChangeIdAfterCommit(entry_response, pre_commit_id, local_entry)) { 455 if (!ChangeIdAfterCommit(entry_response, pre_commit_id, local_entry)) {
451 return; 456 return;
452 } 457 }
453 458
454 // Update our stored copy of the server state. 459 // Update our stored copy of the server state.
455 UpdateServerFieldsAfterCommit(committed_entry, entry_response, local_entry); 460 UpdateServerFieldsAfterCommit(committed_entry, entry_response, local_entry);
(...skipping 13 matching lines...) Expand all
469 // been recursively deleted. 474 // been recursively deleted.
470 // TODO(nick): Here, commit_message.deleted() would be more correct than 475 // TODO(nick): Here, commit_message.deleted() would be more correct than
471 // local_entry->Get(IS_DEL). For example, an item could be renamed, and then 476 // local_entry->Get(IS_DEL). For example, an item could be renamed, and then
472 // deleted during the commit of the rename. Unit test & fix. 477 // deleted during the commit of the rename. Unit test & fix.
473 if (local_entry->Get(IS_DIR) && local_entry->Get(IS_DEL)) { 478 if (local_entry->Get(IS_DIR) && local_entry->Get(IS_DEL)) {
474 deleted_folders->insert(local_entry->Get(ID)); 479 deleted_folders->insert(local_entry->Get(ID));
475 } 480 }
476 } 481 }
477 482
478 } // namespace syncer 483 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698