| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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 "chrome/browser/sync/engine/process_commit_response_command.h" | 5 #include "chrome/browser/sync/engine/process_commit_response_command.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 using std::vector; | 26 using std::vector; |
| 27 | 27 |
| 28 using syncable::BASE_VERSION; | 28 using syncable::BASE_VERSION; |
| 29 using syncable::GET_BY_ID; | 29 using syncable::GET_BY_ID; |
| 30 using syncable::ID; | 30 using syncable::ID; |
| 31 using syncable::IS_DEL; | 31 using syncable::IS_DEL; |
| 32 using syncable::IS_DIR; | 32 using syncable::IS_DIR; |
| 33 using syncable::IS_UNAPPLIED_UPDATE; | 33 using syncable::IS_UNAPPLIED_UPDATE; |
| 34 using syncable::IS_UNSYNCED; | 34 using syncable::IS_UNSYNCED; |
| 35 using syncable::PARENT_ID; | 35 using syncable::PARENT_ID; |
| 36 using syncable::SERVER_IS_DEL; |
| 36 using syncable::SERVER_PARENT_ID; | 37 using syncable::SERVER_PARENT_ID; |
| 37 using syncable::SERVER_POSITION_IN_PARENT; | 38 using syncable::SERVER_POSITION_IN_PARENT; |
| 39 using syncable::SERVER_VERSION; |
| 38 using syncable::SYNCER; | 40 using syncable::SYNCER; |
| 39 using syncable::SYNCING; | 41 using syncable::SYNCING; |
| 40 | 42 |
| 41 namespace browser_sync { | 43 namespace browser_sync { |
| 42 | 44 |
| 43 using sessions::OrderedCommitSet; | 45 using sessions::OrderedCommitSet; |
| 44 using sessions::StatusController; | 46 using sessions::StatusController; |
| 45 using sessions::SyncSession; | 47 using sessions::SyncSession; |
| 46 using sessions::ConflictProgress; | 48 using sessions::ConflictProgress; |
| 47 | 49 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 ScopedDirLookup dir(session->context()->directory_manager(), | 113 ScopedDirLookup dir(session->context()->directory_manager(), |
| 112 session->context()->account_name()); | 114 session->context()->account_name()); |
| 113 if (!dir.good()) { | 115 if (!dir.good()) { |
| 114 LOG(ERROR) << "Scoped dir lookup failed!"; | 116 LOG(ERROR) << "Scoped dir lookup failed!"; |
| 115 return; | 117 return; |
| 116 } | 118 } |
| 117 | 119 |
| 118 StatusController* status = session->status_controller(); | 120 StatusController* status = session->status_controller(); |
| 119 const ClientToServerResponse& response(status->commit_response()); | 121 const ClientToServerResponse& response(status->commit_response()); |
| 120 const CommitResponse& cr = response.commit(); | 122 const CommitResponse& cr = response.commit(); |
| 123 const sync_pb::CommitMessage& commit_message = |
| 124 status->commit_message().commit(); |
| 121 | 125 |
| 122 // If we try to commit a parent and child together and the parent conflicts | 126 // If we try to commit a parent and child together and the parent conflicts |
| 123 // the child will have a bad parent causing an error. As this is not a | 127 // the child will have a bad parent causing an error. As this is not a |
| 124 // critical error, we trap it and don't LOG(ERROR). To enable this we keep | 128 // critical error, we trap it and don't LOG(ERROR). To enable this we keep |
| 125 // a map of conflicting new folders. | 129 // a map of conflicting new folders. |
| 126 int transient_error_commits = 0; | 130 int transient_error_commits = 0; |
| 127 int conflicting_commits = 0; | 131 int conflicting_commits = 0; |
| 128 int error_commits = 0; | 132 int error_commits = 0; |
| 129 int successes = 0; | 133 int successes = 0; |
| 130 bool over_quota = false; | 134 bool over_quota = false; |
| 131 set<syncable::Id> conflicting_new_folder_ids; | 135 set<syncable::Id> conflicting_new_folder_ids; |
| 132 set<syncable::Id> deleted_folders; | 136 set<syncable::Id> deleted_folders; |
| 133 ConflictProgress* conflict_progress = status->mutable_conflict_progress(); | 137 ConflictProgress* conflict_progress = status->mutable_conflict_progress(); |
| 134 OrderedCommitSet::Projection proj = status->commit_id_projection(); | 138 OrderedCommitSet::Projection proj = status->commit_id_projection(); |
| 135 { // Scope for WriteTransaction. | 139 { // Scope for WriteTransaction. |
| 136 WriteTransaction trans(dir, SYNCER, __FILE__, __LINE__); | 140 WriteTransaction trans(dir, SYNCER, __FILE__, __LINE__); |
| 137 for (size_t i = 0; i < proj.size(); i++) { | 141 for (size_t i = 0; i < proj.size(); i++) { |
| 138 CommitResponse::ResponseType response_type = | 142 CommitResponse::ResponseType response_type = |
| 139 ProcessSingleCommitResponse(&trans, cr.entryresponse(proj[i]), | 143 ProcessSingleCommitResponse(&trans, cr.entryresponse(proj[i]), |
| 144 commit_message.entries(proj[i]), |
| 140 status->GetCommitIdAt(proj[i]), | 145 status->GetCommitIdAt(proj[i]), |
| 141 &conflicting_new_folder_ids, | 146 &conflicting_new_folder_ids, |
| 142 &deleted_folders); | 147 &deleted_folders); |
| 143 switch (response_type) { | 148 switch (response_type) { |
| 144 case CommitResponse::INVALID_MESSAGE: | 149 case CommitResponse::INVALID_MESSAGE: |
| 145 ++error_commits; | 150 ++error_commits; |
| 146 break; | 151 break; |
| 147 case CommitResponse::CONFLICT: | 152 case CommitResponse::CONFLICT: |
| 148 ++conflicting_commits; | 153 ++conflicting_commits; |
| 149 // Only server CONFLICT responses will activate conflict resolution. | 154 // Only server CONFLICT responses will activate conflict resolution. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 if (res.has_error_message()) | 204 if (res.has_error_message()) |
| 200 LOG(WARNING) << " " << res.error_message(); | 205 LOG(WARNING) << " " << res.error_message(); |
| 201 else | 206 else |
| 202 LOG(WARNING) << " No detailed error message returned from server"; | 207 LOG(WARNING) << " No detailed error message returned from server"; |
| 203 } | 208 } |
| 204 | 209 |
| 205 CommitResponse::ResponseType | 210 CommitResponse::ResponseType |
| 206 ProcessCommitResponseCommand::ProcessSingleCommitResponse( | 211 ProcessCommitResponseCommand::ProcessSingleCommitResponse( |
| 207 syncable::WriteTransaction* trans, | 212 syncable::WriteTransaction* trans, |
| 208 const sync_pb::CommitResponse_EntryResponse& pb_server_entry, | 213 const sync_pb::CommitResponse_EntryResponse& pb_server_entry, |
| 214 const sync_pb::SyncEntity& commit_request_entry, |
| 209 const syncable::Id& pre_commit_id, | 215 const syncable::Id& pre_commit_id, |
| 210 std::set<syncable::Id>* conflicting_new_folder_ids, | 216 std::set<syncable::Id>* conflicting_new_folder_ids, |
| 211 set<syncable::Id>* deleted_folders) { | 217 set<syncable::Id>* deleted_folders) { |
| 212 | 218 |
| 213 const CommitResponse_EntryResponse& server_entry = | 219 const CommitResponse_EntryResponse& server_entry = |
| 214 *static_cast<const CommitResponse_EntryResponse*>(&pb_server_entry); | 220 *static_cast<const CommitResponse_EntryResponse*>(&pb_server_entry); |
| 215 MutableEntry local_entry(trans, GET_BY_ID, pre_commit_id); | 221 MutableEntry local_entry(trans, GET_BY_ID, pre_commit_id); |
| 216 CHECK(local_entry.good()); | 222 CHECK(local_entry.good()); |
| 217 bool syncing_was_set = local_entry.Get(SYNCING); | 223 bool syncing_was_set = local_entry.Get(SYNCING); |
| 218 local_entry.Put(SYNCING, false); | 224 local_entry.Put(SYNCING, false); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 229 LogServerError(server_entry); | 235 LogServerError(server_entry); |
| 230 return CommitResponse::TRANSIENT_ERROR; | 236 return CommitResponse::TRANSIENT_ERROR; |
| 231 } | 237 } |
| 232 if (CommitResponse::INVALID_MESSAGE == response) { | 238 if (CommitResponse::INVALID_MESSAGE == response) { |
| 233 LOG(ERROR) << "Error Commiting: " << local_entry; | 239 LOG(ERROR) << "Error Commiting: " << local_entry; |
| 234 LogServerError(server_entry); | 240 LogServerError(server_entry); |
| 235 return response; | 241 return response; |
| 236 } | 242 } |
| 237 if (CommitResponse::CONFLICT == response) { | 243 if (CommitResponse::CONFLICT == response) { |
| 238 LOG(INFO) << "Conflict Committing: " << local_entry; | 244 LOG(INFO) << "Conflict Committing: " << local_entry; |
| 245 // TODO(nick): conflicting_new_folder_ids is a purposeless anachronism. |
| 239 if (!pre_commit_id.ServerKnows() && local_entry.Get(IS_DIR)) { | 246 if (!pre_commit_id.ServerKnows() && local_entry.Get(IS_DIR)) { |
| 240 conflicting_new_folder_ids->insert(pre_commit_id); | 247 conflicting_new_folder_ids->insert(pre_commit_id); |
| 241 } | 248 } |
| 242 return response; | 249 return response; |
| 243 } | 250 } |
| 244 if (CommitResponse::RETRY == response) { | 251 if (CommitResponse::RETRY == response) { |
| 245 LOG(INFO) << "Retry Committing: " << local_entry; | 252 LOG(INFO) << "Retry Committing: " << local_entry; |
| 246 return response; | 253 return response; |
| 247 } | 254 } |
| 248 if (CommitResponse::OVER_QUOTA == response) { | 255 if (CommitResponse::OVER_QUOTA == response) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 264 LOG(ERROR) << "Got duplicate id when commiting id: " << pre_commit_id << | 271 LOG(ERROR) << "Got duplicate id when commiting id: " << pre_commit_id << |
| 265 ". Treating as an error return"; | 272 ". Treating as an error return"; |
| 266 return CommitResponse::INVALID_MESSAGE; | 273 return CommitResponse::INVALID_MESSAGE; |
| 267 } | 274 } |
| 268 } | 275 } |
| 269 | 276 |
| 270 if (server_entry.version() == 0) { | 277 if (server_entry.version() == 0) { |
| 271 LOG(WARNING) << "Server returned a zero version on a commit response."; | 278 LOG(WARNING) << "Server returned a zero version on a commit response."; |
| 272 } | 279 } |
| 273 | 280 |
| 274 ProcessSuccessfulCommitResponse(trans, server_entry, pre_commit_id, | 281 ProcessSuccessfulCommitResponse(commit_request_entry, server_entry, |
| 275 &local_entry, syncing_was_set, | 282 pre_commit_id, &local_entry, syncing_was_set, deleted_folders); |
| 276 deleted_folders); | |
| 277 return response; | 283 return response; |
| 278 } | 284 } |
| 279 | 285 |
| 280 void ProcessCommitResponseCommand::ProcessSuccessfulCommitResponse( | 286 const string& ProcessCommitResponseCommand::GetResultingPostCommitName( |
| 281 syncable::WriteTransaction* trans, | 287 const sync_pb::SyncEntity& committed_entry, |
| 282 const CommitResponse_EntryResponse& server_entry, | 288 const CommitResponse_EntryResponse& entry_response) { |
| 283 const syncable::Id& pre_commit_id, syncable::MutableEntry* local_entry, | 289 const string& response_name = |
| 284 bool syncing_was_set, set<syncable::Id>* deleted_folders) { | 290 SyncerProtoUtil::NameFromCommitEntryResponse(entry_response); |
| 291 if (!response_name.empty()) |
| 292 return response_name; |
| 293 return SyncerProtoUtil::NameFromSyncEntity(committed_entry); |
| 294 } |
| 295 |
| 296 bool ProcessCommitResponseCommand::UpdateVersionAfterCommit( |
| 297 const sync_pb::SyncEntity& committed_entry, |
| 298 const CommitResponse_EntryResponse& entry_response, |
| 299 const syncable::Id& pre_commit_id, |
| 300 syncable::MutableEntry* local_entry) { |
| 285 int64 old_version = local_entry->Get(BASE_VERSION); | 301 int64 old_version = local_entry->Get(BASE_VERSION); |
| 286 int64 new_version = server_entry.version(); | 302 int64 new_version = entry_response.version(); |
| 287 bool bad_commit_version = false; | 303 bool bad_commit_version = false; |
| 288 // TODO(sync): The !server_entry.has_id_string() clauses below were | 304 if (committed_entry.deleted() && |
| 289 // introduced when working with the new protocol. | 305 !local_entry->Get(syncable::UNIQUE_CLIENT_TAG).empty()) { |
| 290 if (!pre_commit_id.ServerKnows()) | 306 // If the item was deleted, and it's undeletable (uses the client tag), |
| 307 // change the version back to zero. We must set the version to zero so |
| 308 // that the server knows to re-create the item if it gets committed |
| 309 // later for undeletion. |
| 310 new_version = 0; |
| 311 } else if (!pre_commit_id.ServerKnows()) { |
| 291 bad_commit_version = 0 == new_version; | 312 bad_commit_version = 0 == new_version; |
| 292 else | 313 } else { |
| 293 bad_commit_version = old_version > new_version; | 314 bad_commit_version = old_version > new_version; |
| 315 } |
| 294 if (bad_commit_version) { | 316 if (bad_commit_version) { |
| 295 LOG(ERROR) << "Bad version in commit return for " << *local_entry << | 317 LOG(ERROR) << "Bad version in commit return for " << *local_entry |
| 296 " new_id:" << server_entry.id() << " new_version:" << | 318 << " new_id:" << entry_response.id() << " new_version:" |
| 297 server_entry.version(); | 319 << entry_response.version(); |
| 298 return; | 320 return false; |
| 299 } | 321 } |
| 300 if (server_entry.id() != pre_commit_id) { | 322 |
| 323 // Update the base version and server version. The base version must change |
| 324 // here, even if syncing_was_set is false; that's because local changes were |
| 325 // on top of the successfully committed version. |
| 326 local_entry->Put(BASE_VERSION, new_version); |
| 327 LOG(INFO) << "Commit is changing base version of " |
| 328 << local_entry->Get(ID) << " to: " << new_version; |
| 329 local_entry->Put(SERVER_VERSION, new_version); |
| 330 return true; |
| 331 } |
| 332 |
| 333 bool ProcessCommitResponseCommand::ChangeIdAfterCommit( |
| 334 const CommitResponse_EntryResponse& entry_response, |
| 335 const syncable::Id& pre_commit_id, |
| 336 syncable::MutableEntry* local_entry) { |
| 337 syncable::WriteTransaction* trans = local_entry->write_transaction(); |
| 338 if (entry_response.id() != pre_commit_id) { |
| 301 if (pre_commit_id.ServerKnows()) { | 339 if (pre_commit_id.ServerKnows()) { |
| 302 // TODO(sync): In future it's possible that we'll want the opportunity | 340 // The server can sometimes generate a new ID on commit; for example, |
| 303 // to do a server triggered move aside here. | 341 // when committing an undeletion. |
| 304 LOG(ERROR) << " ID change but not committing a new entry. " << | 342 LOG(INFO) << " ID changed while committing an old entry. " |
| 305 pre_commit_id << " became " << server_entry.id() << "."; | 343 << pre_commit_id << " became " << entry_response.id() << "."; |
| 306 return; | |
| 307 } | 344 } |
| 308 if (!server_entry.id().ServerKnows()) { | 345 MutableEntry same_id(trans, GET_BY_ID, entry_response.id()); |
| 309 LOG(ERROR) << " New entries id < 0." << pre_commit_id << " became " << | 346 // We should trap this before this function. |
| 310 server_entry.id() << "."; | 347 if (same_id.good()) { |
| 311 return; | 348 LOG(ERROR) << "ID clash with id " << entry_response.id() |
| 349 << " during commit " << same_id; |
| 350 return false; |
| 312 } | 351 } |
| 313 MutableEntry same_id(trans, GET_BY_ID, server_entry.id()); | |
| 314 // We should trap this before this function. | |
| 315 CHECK(!same_id.good()) << "ID clash with id " << server_entry.id() << | |
| 316 " during commit " << same_id; | |
| 317 SyncerUtil::ChangeEntryIDAndUpdateChildren( | 352 SyncerUtil::ChangeEntryIDAndUpdateChildren( |
| 318 trans, local_entry, server_entry.id()); | 353 trans, local_entry, entry_response.id()); |
| 319 LOG(INFO) << "Changing ID to " << server_entry.id(); | 354 LOG(INFO) << "Changing ID to " << entry_response.id(); |
| 320 } | 355 } |
| 321 | 356 return true; |
| 322 local_entry->Put(BASE_VERSION, new_version); | 357 } |
| 323 LOG(INFO) << "Commit is changing base version of " << | 358 |
| 324 local_entry->Get(ID) << " to: " << new_version; | 359 void ProcessCommitResponseCommand::UpdateServerFieldsAfterCommit( |
| 360 const sync_pb::SyncEntity& committed_entry, |
| 361 const CommitResponse_EntryResponse& entry_response, |
| 362 syncable::MutableEntry* local_entry) { |
| 363 |
| 364 // We just committed an entry successfully, and now we want to make our view |
| 365 // of the server state consistent with the server state. We must be careful; |
| 366 // |entry_response| and |committed_entry| have some identically named |
| 367 // fields. We only want to consider fields from |committed_entry| when there |
| 368 // is not an overriding field in the |entry_response|. We do not want to |
| 369 // update the server data from the local data in the entry -- it's possible |
| 370 // that the local data changed during the commit, and even if not, the server |
| 371 // has the last word on the values of several properties. |
| 372 |
| 373 local_entry->Put(SERVER_IS_DEL, committed_entry.deleted()); |
| 374 if (committed_entry.deleted()) { |
| 375 // Don't clobber any other fields of deleted objects. |
| 376 return; |
| 377 } |
| 378 |
| 379 local_entry->Put(syncable::SERVER_IS_DIR, |
| 380 (committed_entry.folder() || |
| 381 committed_entry.bookmarkdata().bookmark_folder())); |
| 382 local_entry->Put(syncable::SERVER_SPECIFICS, |
| 383 committed_entry.specifics()); |
| 384 local_entry->Put(syncable::SERVER_MTIME, |
| 385 committed_entry.mtime()); |
| 386 local_entry->Put(syncable::SERVER_CTIME, |
| 387 committed_entry.ctime()); |
| 388 local_entry->Put(syncable::SERVER_POSITION_IN_PARENT, |
| 389 entry_response.position_in_parent()); |
| 390 // TODO(nick): The server doesn't set entry_response.server_parent_id in |
| 391 // practice; to update SERVER_PARENT_ID appropriately here we'd need to |
| 392 // get the post-commit ID of the parent indicated by |
| 393 // committed_entry.parent_id_string(). That should be inferrable from the |
| 394 // information we have, but it's a bit convoluted to pull it out directly. |
| 395 // Getting this right is important: SERVER_PARENT_ID gets fed back into |
| 396 // old_parent_id during the next commit. |
| 397 local_entry->Put(syncable::SERVER_PARENT_ID, |
| 398 local_entry->Get(syncable::PARENT_ID)); |
| 399 local_entry->Put(syncable::SERVER_NON_UNIQUE_NAME, |
| 400 GetResultingPostCommitName(committed_entry, entry_response)); |
| 325 | 401 |
| 326 if (local_entry->Get(IS_UNAPPLIED_UPDATE)) { | 402 if (local_entry->Get(IS_UNAPPLIED_UPDATE)) { |
| 327 // This is possible, but very unlikely. | 403 // This shouldn't happen; an unapplied update shouldn't be committed, and |
| 404 // if it were, the commit should have failed. But if it does happen: we've |
| 405 // just overwritten the update info, so clear the flag. |
| 328 local_entry->Put(IS_UNAPPLIED_UPDATE, false); | 406 local_entry->Put(IS_UNAPPLIED_UPDATE, false); |
| 329 } | 407 } |
| 330 | 408 } |
| 331 if (server_entry.has_name()) { | 409 |
| 332 if (syncing_was_set) { | 410 void ProcessCommitResponseCommand::OverrideClientFieldsAfterCommit( |
| 333 PerformCommitTimeNameAside(trans, server_entry, local_entry); | 411 const sync_pb::SyncEntity& committed_entry, |
| 334 } else { | 412 const CommitResponse_EntryResponse& entry_response, |
| 335 // IS_UNSYNCED will ensure that this entry gets committed again, even if | 413 syncable::MutableEntry* local_entry) { |
| 336 // we skip this name aside. IS_UNSYNCED was probably previously set, but | 414 if (committed_entry.deleted()) { |
| 337 // let's just set it anyway. | 415 // If an entry's been deleted, nothing else matters. |
| 338 local_entry->Put(IS_UNSYNCED, true); | 416 DCHECK(local_entry->Get(IS_DEL)); |
| 339 LOG(INFO) << "Skipping commit time name aside because" << | 417 return; |
| 340 " entry was changed during commit."; | 418 } |
| 341 } | 419 |
| 342 } | 420 // Update the name. |
| 343 | 421 const string& server_name = |
| 344 if (syncing_was_set && server_entry.has_position_in_parent()) { | 422 GetResultingPostCommitName(committed_entry, entry_response); |
| 345 // The server has the final say on positioning, so apply the absolute | 423 const string& old_name = |
| 346 // position that it returns. | 424 local_entry->Get(syncable::NON_UNIQUE_NAME); |
| 347 local_entry->Put(SERVER_POSITION_IN_PARENT, | 425 |
| 348 server_entry.position_in_parent()); | 426 if (!server_name.empty() && old_name != server_name) { |
| 427 LOG(INFO) << "During commit, server changed name: " << old_name |
| 428 << " to new name: " << server_name; |
| 429 local_entry->Put(syncable::NON_UNIQUE_NAME, server_name); |
| 430 } |
| 431 |
| 432 // The server has the final say on positioning, so apply the absolute |
| 433 // position that it returns. |
| 434 if (entry_response.has_position_in_parent()) { |
| 435 // The SERVER_ field should already have been written. |
| 436 DCHECK_EQ(entry_response.position_in_parent(), |
| 437 local_entry->Get(SERVER_POSITION_IN_PARENT)); |
| 349 | 438 |
| 350 // We just committed successfully, so we assume that the position | 439 // We just committed successfully, so we assume that the position |
| 351 // value we got applies to the PARENT_ID we submitted. | 440 // value we got applies to the PARENT_ID we submitted. |
| 352 syncable::Id new_prev = SyncerUtil::ComputePrevIdFromServerPosition( | 441 syncable::Id new_prev = SyncerUtil::ComputePrevIdFromServerPosition( |
| 353 trans, local_entry, local_entry->Get(PARENT_ID)); | 442 local_entry->write_transaction(), local_entry, |
| 443 local_entry->Get(PARENT_ID)); |
| 354 if (!local_entry->PutPredecessor(new_prev)) { | 444 if (!local_entry->PutPredecessor(new_prev)) { |
| 355 LOG(WARNING) << "PutPredecessor failed after successful commit"; | 445 LOG(WARNING) << "PutPredecessor failed after successful commit"; |
| 356 } | 446 } |
| 357 } | 447 } |
| 358 | 448 } |
| 449 |
| 450 void ProcessCommitResponseCommand::ProcessSuccessfulCommitResponse( |
| 451 const sync_pb::SyncEntity& committed_entry, |
| 452 const CommitResponse_EntryResponse& entry_response, |
| 453 const syncable::Id& pre_commit_id, syncable::MutableEntry* local_entry, |
| 454 bool syncing_was_set, set<syncable::Id>* deleted_folders) { |
| 455 DCHECK(local_entry->Get(IS_UNSYNCED)); |
| 456 |
| 457 // Update SERVER_VERSION and BASE_VERSION. |
| 458 if (!UpdateVersionAfterCommit(committed_entry, entry_response, pre_commit_id, |
| 459 local_entry)) { |
| 460 LOG(ERROR) << "Bad version in commit return for " << *local_entry |
| 461 << " new_id:" << entry_response.id() << " new_version:" |
| 462 << entry_response.version(); |
| 463 return; |
| 464 } |
| 465 |
| 466 // If the server gave us a new ID, apply it. |
| 467 if (!ChangeIdAfterCommit(entry_response, pre_commit_id, local_entry)) { |
| 468 return; |
| 469 } |
| 470 |
| 471 // Update our stored copy of the server state. |
| 472 UpdateServerFieldsAfterCommit(committed_entry, entry_response, local_entry); |
| 473 |
| 474 // If the item doesn't need to be committed again (a situation that |
| 475 // happens if it changed locally during the commit), we can remove |
| 476 // it from the unsynced list. Also, we should change the locally- |
| 477 // visible properties to apply any canonicalizations or fixups |
| 478 // that the server introduced during the commit. |
| 359 if (syncing_was_set) { | 479 if (syncing_was_set) { |
| 480 OverrideClientFieldsAfterCommit(committed_entry, entry_response, |
| 481 local_entry); |
| 360 local_entry->Put(IS_UNSYNCED, false); | 482 local_entry->Put(IS_UNSYNCED, false); |
| 361 } | 483 } |
| 484 |
| 485 // Make a note of any deleted folders, whose children would have |
| 486 // been recursively deleted. |
| 487 // TODO(nick): Here, commit_message.deleted() would be more correct than |
| 488 // local_entry->Get(IS_DEL). For example, an item could be renamed, and then |
| 489 // deleted during the commit of the rename. Unit test & fix. |
| 362 if (local_entry->Get(IS_DIR) && local_entry->Get(IS_DEL)) { | 490 if (local_entry->Get(IS_DIR) && local_entry->Get(IS_DEL)) { |
| 363 deleted_folders->insert(local_entry->Get(ID)); | 491 deleted_folders->insert(local_entry->Get(ID)); |
| 364 } | 492 } |
| 365 } | 493 } |
| 366 | 494 |
| 367 void ProcessCommitResponseCommand::PerformCommitTimeNameAside( | |
| 368 syncable::WriteTransaction* trans, | |
| 369 const CommitResponse_EntryResponse& server_entry, | |
| 370 syncable::MutableEntry* local_entry) { | |
| 371 string old_name = local_entry->Get(syncable::NON_UNIQUE_NAME); | |
| 372 const string server_name = | |
| 373 SyncerProtoUtil::NameFromCommitEntryResponse(server_entry); | |
| 374 | |
| 375 if (!server_name.empty() && old_name != server_name) { | |
| 376 LOG(INFO) << "Server commit moved aside entry: " << old_name | |
| 377 << " to new name " << server_name; | |
| 378 // Should be safe since we're in a "commit lock." | |
| 379 local_entry->Put(syncable::NON_UNIQUE_NAME, server_name); | |
| 380 } | |
| 381 } | |
| 382 | |
| 383 } // namespace browser_sync | 495 } // namespace browser_sync |
| OLD | NEW |