1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/process_commit_response_command.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer_proto_util.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer_util.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncproto.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/sessions/sync_session.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/directory_manager.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/syncable.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::ScopedDirLookup; 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::WriteTransaction; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::MutableEntry; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::Entry; 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::set; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::string; 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::vector; 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::BASE_VERSION; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::GET_BY_ID; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::ID; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::IS_DEL; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::IS_DIR; 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::IS_UNAPPLIED_UPDATE; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::IS_UNSYNCED; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::PARENT_ID; 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::SERVER_IS_DEL; 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::SERVER_PARENT_ID; 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::SERVER_POSITION_IN_PARENT; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::SERVER_VERSION; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::SYNCER; 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::SYNCING; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync { 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing sessions::OrderedCommitSet; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing sessions::StatusController; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing sessions::SyncSession; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing sessions::ConflictProgress; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid IncrementErrorCounters(StatusController* status) { 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->increment_num_consecutive_errors(); 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ResetErrorCounters(StatusController* status) { 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->set_num_consecutive_errors(0); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProcessCommitResponseCommand::ProcessCommitResponseCommand() {} 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProcessCommitResponseCommand::~ProcessCommitResponseCommand() {} 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ProcessCommitResponseCommand::ModelNeutralExecuteImpl( 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sessions::SyncSession* session) { 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedDirLookup dir(session->context()->directory_manager(), 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch session->context()->account_name()); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dir.good()) { 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Scoped dir lookup failed!"; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StatusController* status = session->status_controller(); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ClientToServerResponse& response(status->commit_response()); 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const vector<syncable::Id>& commit_ids(status->commit_ids()); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!response.has_commit()) { 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(sync): What if we didn't try to commit anything? 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "Commit response has no commit body!"; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementErrorCounters(status); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommitResponse& cr = response.commit(); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int commit_count = commit_ids.size(); 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cr.entryresponse_size() != commit_count) { 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Commit response has wrong number of entries! Expected:" << 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commit_count << " Got:" << cr.entryresponse_size(); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0 ; i < cr.entryresponse_size() ; i++) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Response #" << i << " Value: " << 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cr.entryresponse(i).response_type(); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cr.entryresponse(i).has_error_message()) 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << " " << cr.entryresponse(i).error_message(); 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementErrorCounters(status); 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ProcessCommitResponseCommand::ModelChangingExecuteImpl( 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncSession* session) { 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessCommitResponse(session); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionsActivityMonitor* monitor = session->context()->extensions_monitor(); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (session->status_controller()->HasBookmarkCommitActivity() && 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch session->status_controller()->syncer_status() 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch .num_successful_bookmark_commits == 0) { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch monitor->PutRecords(session->extensions_activity()); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch session->mutable_extensions_activity()->clear(); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ProcessCommitResponseCommand::ProcessCommitResponse( 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncSession* session) { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(sync): This function returns if it sees problems. We probably want 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to flag the need for an update or similar. 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedDirLookup dir(session->context()->directory_manager(), 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch session->context()->account_name()); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dir.good()) { 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Scoped dir lookup failed!"; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StatusController* status = session->status_controller(); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ClientToServerResponse& response(status->commit_response()); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommitResponse& cr = response.commit(); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::CommitMessage& commit_message = 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->commit_message().commit(); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we try to commit a parent and child together and the parent conflicts 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the child will have a bad parent causing an error. As this is not a 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // critical error, we trap it and don't LOG(ERROR). To enable this we keep 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a map of conflicting new folders. 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int transient_error_commits = 0; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int conflicting_commits = 0; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int error_commits = 0; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int successes = 0; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set<syncable::Id> conflicting_new_folder_ids; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set<syncable::Id> deleted_folders; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConflictProgress* conflict_progress = status->mutable_conflict_progress(); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OrderedCommitSet::Projection proj = status->commit_id_projection(); 138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!proj.empty()) { // Scope for WriteTransaction. 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WriteTransaction trans(dir, SYNCER, __FILE__, __LINE__); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < proj.size(); i++) { 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CommitResponse::ResponseType response_type = 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessSingleCommitResponse(&trans, cr.entryresponse(proj[i]), 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch commit_message.entries(proj[i]), 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->GetCommitIdAt(proj[i]), 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &conflicting_new_folder_ids, 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &deleted_folders); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (response_type) { 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CommitResponse::INVALID_MESSAGE: 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++error_commits; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CommitResponse::CONFLICT: 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++conflicting_commits; 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only server CONFLICT responses will activate conflict resolution. 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conflict_progress->AddConflictingItemById( 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->GetCommitIdAt(proj[i])); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CommitResponse::SUCCESS: 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(sync): worry about sync_rate_ rate calc? 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++successes; 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (status->GetCommitIdModelTypeAt(proj[i]) == syncable::BOOKMARKS) 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->increment_num_successful_bookmark_commits(); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->increment_num_successful_commits(); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CommitResponse::OVER_QUOTA: 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We handle over quota like a retry, which is same as transient. 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CommitResponse::RETRY: 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case CommitResponse::TRANSIENT_ERROR: 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(tim): Now that we have SyncSession::Delegate, we 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should plumb this directly for exponential backoff purposes rather 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // than trying to infer from HasMoreToSync(). See 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SyncerThread::CalculatePollingWaitTime. 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++transient_error_commits; 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(FATAL) << "Bad return from ProcessSingleCommitResponse"; 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(sync): move status reporting elsewhere. 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->increment_num_conflicting_commits_by(conflicting_commits); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (0 == successes) { 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->increment_num_consecutive_transient_error_commits_by( 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transient_error_commits); 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->increment_num_consecutive_errors_by(transient_error_commits); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->set_num_consecutive_transient_error_commits(0); 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->set_num_consecutive_errors(0); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int commit_count = static_cast<int>(proj.size()); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (commit_count != (conflicting_commits + error_commits + 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transient_error_commits)) { 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResetErrorCounters(status); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncerUtil::MarkDeletedChildrenSynced(dir, &deleted_folders); 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid LogServerError(const CommitResponse_EntryResponse& res) { 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (res.has_error_message()) 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << " " << res.error_message(); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << " No detailed error message returned from server"; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCommitResponse::ResponseType 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProcessCommitResponseCommand::ProcessSingleCommitResponse( 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::WriteTransaction* trans, 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::CommitResponse_EntryResponse& pb_server_entry, 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::SyncEntity& commit_request_entry, 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::Id& pre_commit_id, 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<syncable::Id>* conflicting_new_folder_ids, 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set<syncable::Id>* deleted_folders) { 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommitResponse_EntryResponse& server_entry = 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *static_cast<const CommitResponse_EntryResponse*>(&pb_server_entry); 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MutableEntry local_entry(trans, GET_BY_ID, pre_commit_id); 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(local_entry.good()); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool syncing_was_set = local_entry.Get(SYNCING); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry.Put(SYNCING, false); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CommitResponse::ResponseType response = (CommitResponse::ResponseType) 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch server_entry.response_type(); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!CommitResponse::ResponseType_IsValid(response)) { 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Commit response has unknown response type! Possibly out " 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "of date client?"; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CommitResponse::INVALID_MESSAGE; 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CommitResponse::TRANSIENT_ERROR == response) { 231731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Transient Error Committing: " << local_entry; 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogServerError(server_entry); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CommitResponse::TRANSIENT_ERROR; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CommitResponse::INVALID_MESSAGE == response) { 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Error Commiting: " << local_entry; 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogServerError(server_entry); 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return response; 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CommitResponse::CONFLICT == response) { 241731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Conflict Committing: " << local_entry; 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(nick): conflicting_new_folder_ids is a purposeless anachronism. 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pre_commit_id.ServerKnows() && local_entry.Get(IS_DIR)) { 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conflicting_new_folder_ids->insert(pre_commit_id); 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return response; 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CommitResponse::RETRY == response) { 249731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Retry Committing: " << local_entry; 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return response; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CommitResponse::OVER_QUOTA == response) { 253731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LOG(WARNING) << "Hit deprecated OVER_QUOTA Committing: " << local_entry; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return response; 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!server_entry.has_id_string()) { 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Commit response has no id"; 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CommitResponse::INVALID_MESSAGE; 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Implied by the IsValid call above, but here for clarity. 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(CommitResponse::SUCCESS, response) << response; 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check to see if we've been given the ID of an existing entry. If so treat 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it as an error response and retry later. 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pre_commit_id != server_entry.id()) { 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Entry e(trans, GET_BY_ID, server_entry.id()); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (e.good()) { 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Got duplicate id when commiting id: " << pre_commit_id << 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ". Treating as an error return"; 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CommitResponse::INVALID_MESSAGE; 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (server_entry.version() == 0) { 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "Server returned a zero version on a commit response."; 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessSuccessfulCommitResponse(commit_request_entry, server_entry, 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pre_commit_id, &local_entry, syncing_was_set, deleted_folders); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return response; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst string& ProcessCommitResponseCommand::GetResultingPostCommitName( 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::SyncEntity& committed_entry, 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommitResponse_EntryResponse& entry_response) { 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string& response_name = 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncerProtoUtil::NameFromCommitEntryResponse(entry_response); 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!response_name.empty()) 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return response_name; 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return SyncerProtoUtil::NameFromSyncEntity(committed_entry); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ProcessCommitResponseCommand::UpdateVersionAfterCommit( 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::SyncEntity& committed_entry, 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommitResponse_EntryResponse& entry_response, 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::Id& pre_commit_id, 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::MutableEntry* local_entry) { 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 old_version = local_entry->Get(BASE_VERSION); 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 new_version = entry_response.version(); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool bad_commit_version = false; 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (committed_entry.deleted() && 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !local_entry->Get(syncable::UNIQUE_CLIENT_TAG).empty()) { 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the item was deleted, and it's undeletable (uses the client tag), 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // change the version back to zero. We must set the version to zero so 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that the server knows to re-create the item if it gets committed 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // later for undeletion. 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_version = 0; 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (!pre_commit_id.ServerKnows()) { 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bad_commit_version = 0 == new_version; 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bad_commit_version = old_version > new_version; 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bad_commit_version) { 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Bad version in commit return for " << *local_entry 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << " new_id:" << entry_response.id() << " new_version:" 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << entry_response.version(); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the base version and server version. The base version must change 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // here, even if syncing_was_set is false; that's because local changes were 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // on top of the successfully committed version. 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(BASE_VERSION, new_version); 324731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Commit is changing base version of " << local_entry->Get(ID) 325731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << " to: " << new_version; 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(SERVER_VERSION, new_version); 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ProcessCommitResponseCommand::ChangeIdAfterCommit( 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommitResponse_EntryResponse& entry_response, 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::Id& pre_commit_id, 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::MutableEntry* local_entry) { 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::WriteTransaction* trans = local_entry->write_transaction(); 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry_response.id() != pre_commit_id) { 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pre_commit_id.ServerKnows()) { 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The server can sometimes generate a new ID on commit; for example, 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when committing an undeletion. 339731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << " ID changed while committing an old entry. " 340731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << pre_commit_id << " became " << entry_response.id() << "."; 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MutableEntry same_id(trans, GET_BY_ID, entry_response.id()); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We should trap this before this function. 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (same_id.good()) { 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "ID clash with id " << entry_response.id() 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << " during commit " << same_id; 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncerUtil::ChangeEntryIDAndUpdateChildren( 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch trans, local_entry, entry_response.id()); 351731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Changing ID to " << entry_response.id(); 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ProcessCommitResponseCommand::UpdateServerFieldsAfterCommit( 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::SyncEntity& committed_entry, 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommitResponse_EntryResponse& entry_response, 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::MutableEntry* local_entry) { 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We just committed an entry successfully, and now we want to make our view 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of the server state consistent with the server state. We must be careful; 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |entry_response| and |committed_entry| have some identically named 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // fields. We only want to consider fields from |committed_entry| when there 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is not an overriding field in the |entry_response|. We do not want to 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // update the server data from the local data in the entry -- it's possible 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that the local data changed during the commit, and even if not, the server 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // has the last word on the values of several properties. 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(SERVER_IS_DEL, committed_entry.deleted()); 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (committed_entry.deleted()) { 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't clobber any other fields of deleted objects. 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(syncable::SERVER_IS_DIR, 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (committed_entry.folder() || 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch committed_entry.bookmarkdata().bookmark_folder())); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(syncable::SERVER_SPECIFICS, 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch committed_entry.specifics()); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(syncable::SERVER_MTIME, 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch committed_entry.mtime()); 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(syncable::SERVER_CTIME, 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch committed_entry.ctime()); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(syncable::SERVER_POSITION_IN_PARENT, 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_response.position_in_parent()); 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(nick): The server doesn't set entry_response.server_parent_id in 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // practice; to update SERVER_PARENT_ID appropriately here we'd need to 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // get the post-commit ID of the parent indicated by 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // committed_entry.parent_id_string(). That should be inferrable from the 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // information we have, but it's a bit convoluted to pull it out directly. 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Getting this right is important: SERVER_PARENT_ID gets fed back into 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // old_parent_id during the next commit. 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(syncable::SERVER_PARENT_ID, 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Get(syncable::PARENT_ID)); 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(syncable::SERVER_NON_UNIQUE_NAME, 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetResultingPostCommitName(committed_entry, entry_response)); 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (local_entry->Get(IS_UNAPPLIED_UPDATE)) { 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This shouldn't happen; an unapplied update shouldn't be committed, and 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if it were, the commit should have failed. But if it does happen: we've 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // just overwritten the update info, so clear the flag. 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(IS_UNAPPLIED_UPDATE, false); 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ProcessCommitResponseCommand::OverrideClientFieldsAfterCommit( 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::SyncEntity& committed_entry, 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommitResponse_EntryResponse& entry_response, 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::MutableEntry* local_entry) { 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (committed_entry.deleted()) { 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If an entry's been deleted, nothing else matters. 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(local_entry->Get(IS_DEL)); 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the name. 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string& server_name = 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetResultingPostCommitName(committed_entry, entry_response); 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string& old_name = 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Get(syncable::NON_UNIQUE_NAME); 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!server_name.empty() && old_name != server_name) { 424731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "During commit, server changed name: " << old_name 425731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << " to new name: " << server_name; 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(syncable::NON_UNIQUE_NAME, server_name); 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The server has the final say on positioning, so apply the absolute 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // position that it returns. 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry_response.has_position_in_parent()) { 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The SERVER_ field should already have been written. 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(entry_response.position_in_parent(), 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Get(SERVER_POSITION_IN_PARENT)); 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We just committed successfully, so we assume that the position 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // value we got applies to the PARENT_ID we submitted. 438dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::Id new_prev = local_entry->ComputePrevIdFromServerPosition( 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Get(PARENT_ID)); 440731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!local_entry->PutPredecessor(new_prev)) 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "PutPredecessor failed after successful commit"; 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ProcessCommitResponseCommand::ProcessSuccessfulCommitResponse( 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::SyncEntity& committed_entry, 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommitResponse_EntryResponse& entry_response, 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::Id& pre_commit_id, syncable::MutableEntry* local_entry, 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool syncing_was_set, set<syncable::Id>* deleted_folders) { 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(local_entry->Get(IS_UNSYNCED)); 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update SERVER_VERSION and BASE_VERSION. 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!UpdateVersionAfterCommit(committed_entry, entry_response, pre_commit_id, 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry)) { 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Bad version in commit return for " << *local_entry 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << " new_id:" << entry_response.id() << " new_version:" 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << entry_response.version(); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the server gave us a new ID, apply it. 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ChangeIdAfterCommit(entry_response, pre_commit_id, local_entry)) { 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update our stored copy of the server state. 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateServerFieldsAfterCommit(committed_entry, entry_response, local_entry); 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the item doesn't need to be committed again (an item might need to be 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // committed again if it changed locally during the commit), we can remove 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it from the unsynced list. Also, we should change the locally- 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // visible properties to apply any canonicalizations or fixups 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that the server introduced during the commit. 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (syncing_was_set) { 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OverrideClientFieldsAfterCommit(committed_entry, entry_response, 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry); 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_entry->Put(IS_UNSYNCED, false); 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make a note of any deleted folders, whose children would have 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // been recursively deleted. 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(nick): Here, commit_message.deleted() would be more correct than 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // local_entry->Get(IS_DEL). For example, an item could be renamed, and then 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // deleted during the commit of the rename. Unit test & fix. 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (local_entry->Get(IS_DIR) && local_entry->Get(IS_DEL)) { 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deleted_folders->insert(local_entry->Get(ID)); 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace browser_sync 491