| 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 <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 11 #include "chrome/browser/sync/engine/syncer_proto_util.h" | 11 #include "chrome/browser/sync/engine/syncer_proto_util.h" |
| 12 #include "chrome/browser/sync/engine/syncer_session.h" | |
| 13 #include "chrome/browser/sync/engine/syncer_status.h" | |
| 14 #include "chrome/browser/sync/engine/syncer_util.h" | 12 #include "chrome/browser/sync/engine/syncer_util.h" |
| 15 #include "chrome/browser/sync/engine/syncproto.h" | 13 #include "chrome/browser/sync/engine/syncproto.h" |
| 14 #include "chrome/browser/sync/sessions/sync_session.h" |
| 16 #include "chrome/browser/sync/syncable/directory_manager.h" | 15 #include "chrome/browser/sync/syncable/directory_manager.h" |
| 17 #include "chrome/browser/sync/syncable/syncable.h" | 16 #include "chrome/browser/sync/syncable/syncable.h" |
| 18 | 17 |
| 19 using syncable::ScopedDirLookup; | 18 using syncable::ScopedDirLookup; |
| 20 using syncable::WriteTransaction; | 19 using syncable::WriteTransaction; |
| 21 using syncable::MutableEntry; | 20 using syncable::MutableEntry; |
| 22 using syncable::Entry; | 21 using syncable::Entry; |
| 23 | 22 |
| 24 using std::set; | 23 using std::set; |
| 25 using std::vector; | 24 using std::vector; |
| 26 | 25 |
| 27 using syncable::BASE_VERSION; | 26 using syncable::BASE_VERSION; |
| 28 using syncable::GET_BY_ID; | 27 using syncable::GET_BY_ID; |
| 29 using syncable::ID; | 28 using syncable::ID; |
| 30 using syncable::IS_DEL; | 29 using syncable::IS_DEL; |
| 31 using syncable::IS_DIR; | 30 using syncable::IS_DIR; |
| 32 using syncable::IS_UNAPPLIED_UPDATE; | 31 using syncable::IS_UNAPPLIED_UPDATE; |
| 33 using syncable::IS_UNSYNCED; | 32 using syncable::IS_UNSYNCED; |
| 34 using syncable::PARENT_ID; | 33 using syncable::PARENT_ID; |
| 35 using syncable::SERVER_PARENT_ID; | 34 using syncable::SERVER_PARENT_ID; |
| 36 using syncable::SERVER_POSITION_IN_PARENT; | 35 using syncable::SERVER_POSITION_IN_PARENT; |
| 37 using syncable::SYNCER; | 36 using syncable::SYNCER; |
| 38 using syncable::SYNCING; | 37 using syncable::SYNCING; |
| 39 | 38 |
| 40 namespace browser_sync { | 39 namespace browser_sync { |
| 41 | 40 |
| 42 void IncrementErrorCounters(SyncerStatus status) { | 41 using sessions::StatusController; |
| 43 status.increment_consecutive_problem_commits(); | 42 using sessions::SyncSession; |
| 44 status.increment_consecutive_errors(); | 43 using sessions::ConflictProgress; |
| 44 |
| 45 void IncrementErrorCounters(StatusController* status) { |
| 46 status->increment_num_consecutive_problem_commits(); |
| 47 status->increment_num_consecutive_errors(); |
| 45 } | 48 } |
| 46 void ResetErrorCounters(SyncerStatus status) { | 49 void ResetErrorCounters(StatusController* status) { |
| 47 status.zero_consecutive_problem_commits(); | 50 status->set_num_consecutive_problem_commits(0); |
| 48 status.zero_consecutive_errors(); | 51 status->set_num_consecutive_errors(0); |
| 49 } | 52 } |
| 50 | 53 |
| 51 ProcessCommitResponseCommand::ProcessCommitResponseCommand( | 54 ProcessCommitResponseCommand::ProcessCommitResponseCommand() {} |
| 52 ExtensionsActivityMonitor* monitor) : extensions_monitor_(monitor) {} | |
| 53 ProcessCommitResponseCommand::~ProcessCommitResponseCommand() {} | 55 ProcessCommitResponseCommand::~ProcessCommitResponseCommand() {} |
| 54 | 56 |
| 55 void ProcessCommitResponseCommand::ModelChangingExecuteImpl( | 57 void ProcessCommitResponseCommand::ModelChangingExecuteImpl( |
| 56 SyncerSession* session) { | 58 SyncSession* session) { |
| 57 ProcessCommitResponse(session); | 59 ProcessCommitResponse(session); |
| 58 if (!session->HadSuccessfulCommits()) | 60 ExtensionsActivityMonitor* monitor = session->context()->extensions_monitor(); |
| 59 extensions_monitor_->PutRecords(session->extensions_activity()); | 61 if (session->status_controller()->syncer_status().num_successful_commits == 0) |
| 62 monitor->PutRecords(session->extensions_activity()); |
| 60 } | 63 } |
| 61 | 64 |
| 62 void ProcessCommitResponseCommand::ProcessCommitResponse( | 65 void ProcessCommitResponseCommand::ProcessCommitResponse( |
| 63 SyncerSession* session) { | 66 SyncSession* session) { |
| 64 // TODO(sync): This function returns if it sees problems. We probably want | 67 // TODO(sync): This function returns if it sees problems. We probably want |
| 65 // to flag the need for an update or similar. | 68 // to flag the need for an update or similar. |
| 66 ScopedDirLookup dir(session->dirman(), session->account_name()); | 69 ScopedDirLookup dir(session->context()->directory_manager(), |
| 70 session->context()->account_name()); |
| 67 if (!dir.good()) { | 71 if (!dir.good()) { |
| 68 LOG(ERROR) << "Scoped dir lookup failed!"; | 72 LOG(ERROR) << "Scoped dir lookup failed!"; |
| 69 return; | 73 return; |
| 70 } | 74 } |
| 71 const ClientToServerResponse& response = session->commit_response(); | |
| 72 const vector<syncable::Id>& commit_ids = session->commit_ids(); | |
| 73 | 75 |
| 74 // TODO(sync): move counters out of here. | 76 StatusController* status = session->status_controller(); |
| 75 SyncerStatus status(session); | 77 const ClientToServerResponse& response(status->commit_response()); |
| 78 const vector<syncable::Id>& commit_ids(status->commit_ids()); |
| 76 | 79 |
| 77 if (!response.has_commit()) { | 80 if (!response.has_commit()) { |
| 78 // TODO(sync): What if we didn't try to commit anything? | 81 // TODO(sync): What if we didn't try to commit anything? |
| 79 LOG(WARNING) << "Commit response has no commit body!"; | 82 LOG(WARNING) << "Commit response has no commit body!"; |
| 80 IncrementErrorCounters(status); | 83 IncrementErrorCounters(status); |
| 81 return; | 84 return; |
| 82 } | 85 } |
| 83 | 86 |
| 84 const CommitResponse& cr = response.commit(); | 87 const CommitResponse& cr = response.commit(); |
| 85 int commit_count = commit_ids.size(); | 88 int commit_count = commit_ids.size(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 100 // the child will have a bad parent causing an error. As this is not a | 103 // the child will have a bad parent causing an error. As this is not a |
| 101 // critical error, we trap it and don't LOG(ERROR). To enable this we keep | 104 // critical error, we trap it and don't LOG(ERROR). To enable this we keep |
| 102 // a map of conflicting new folders. | 105 // a map of conflicting new folders. |
| 103 int transient_error_commits = 0; | 106 int transient_error_commits = 0; |
| 104 int conflicting_commits = 0; | 107 int conflicting_commits = 0; |
| 105 int error_commits = 0; | 108 int error_commits = 0; |
| 106 int successes = 0; | 109 int successes = 0; |
| 107 bool over_quota = false; | 110 bool over_quota = false; |
| 108 set<syncable::Id> conflicting_new_folder_ids; | 111 set<syncable::Id> conflicting_new_folder_ids; |
| 109 set<syncable::Id> deleted_folders; | 112 set<syncable::Id> deleted_folders; |
| 113 ConflictProgress* conflict_progress = status->mutable_conflict_progress(); |
| 110 { // Scope for WriteTransaction. | 114 { // Scope for WriteTransaction. |
| 111 WriteTransaction trans(dir, SYNCER, __FILE__, __LINE__); | 115 WriteTransaction trans(dir, SYNCER, __FILE__, __LINE__); |
| 112 for (int i = 0; i < cr.entryresponse_size(); i++) { | 116 for (int i = 0; i < cr.entryresponse_size(); i++) { |
| 113 CommitResponse::RESPONSE_TYPE response_type = | 117 CommitResponse::RESPONSE_TYPE response_type = |
| 114 ProcessSingleCommitResponse(&trans, cr.entryresponse(i), | 118 ProcessSingleCommitResponse(&trans, cr.entryresponse(i), |
| 115 commit_ids[i], | 119 commit_ids[i], |
| 116 &conflicting_new_folder_ids, | 120 &conflicting_new_folder_ids, |
| 117 &deleted_folders, session); | 121 &deleted_folders); |
| 118 switch (response_type) { | 122 switch (response_type) { |
| 119 case CommitResponse::INVALID_MESSAGE: | 123 case CommitResponse::INVALID_MESSAGE: |
| 120 ++error_commits; | 124 ++error_commits; |
| 121 break; | 125 break; |
| 122 case CommitResponse::CONFLICT: | 126 case CommitResponse::CONFLICT: |
| 123 ++conflicting_commits; | 127 ++conflicting_commits; |
| 124 // This is important to activate conflict resolution. | 128 // This is important to activate conflict resolution. |
| 125 session->AddCommitConflict(commit_ids[i]); | 129 conflict_progress->AddConflictingItemById(commit_ids[i]); |
| 126 break; | 130 break; |
| 127 case CommitResponse::SUCCESS: | 131 case CommitResponse::SUCCESS: |
| 128 // TODO(sync): worry about sync_rate_ rate calc? | 132 // TODO(sync): worry about sync_rate_ rate calc? |
| 129 ++successes; | 133 ++successes; |
| 130 status.increment_successful_commits(); | 134 status->increment_num_successful_commits(); |
| 131 break; | 135 break; |
| 132 case CommitResponse::OVER_QUOTA: | 136 case CommitResponse::OVER_QUOTA: |
| 133 over_quota = true; | 137 over_quota = true; |
| 134 // We handle over quota like a retry, which is same as transient. | 138 // We handle over quota like a retry, which is same as transient. |
| 135 case CommitResponse::RETRY: | 139 case CommitResponse::RETRY: |
| 136 case CommitResponse::TRANSIENT_ERROR: | 140 case CommitResponse::TRANSIENT_ERROR: |
| 141 // TODO(tim): Now that we have SyncSession::Delegate, we |
| 142 // should plumb this directly for exponential backoff purposes rather |
| 143 // than trying to infer from HasMoreToSync(). See |
| 144 // SyncerThread::CalculatePollingWaitTime. |
| 137 ++transient_error_commits; | 145 ++transient_error_commits; |
| 138 break; | 146 break; |
| 139 default: | 147 default: |
| 140 LOG(FATAL) << "Bad return from ProcessSingleCommitResponse"; | 148 LOG(FATAL) << "Bad return from ProcessSingleCommitResponse"; |
| 141 } | 149 } |
| 142 } | 150 } |
| 143 } | 151 } |
| 144 | 152 |
| 145 // TODO(sync): move status reporting elsewhere. | 153 // TODO(sync): move status reporting elsewhere. |
| 146 status.set_conflicting_commits(conflicting_commits); | 154 status->set_num_conflicting_commits(conflicting_commits); |
| 147 if (0 == successes) { | 155 if (0 == successes) { |
| 148 status.increment_consecutive_transient_error_commits_by( | 156 status->increment_num_consecutive_transient_error_commits_by( |
| 149 transient_error_commits); | 157 transient_error_commits); |
| 150 status.increment_consecutive_errors_by(transient_error_commits); | 158 status->increment_num_consecutive_errors_by(transient_error_commits); |
| 151 } else { | 159 } else { |
| 152 status.zero_consecutive_transient_error_commits(); | 160 status->set_num_consecutive_transient_error_commits(0); |
| 153 status.zero_consecutive_errors(); | 161 status->set_num_consecutive_errors(0); |
| 154 } | 162 } |
| 155 if (commit_count != (conflicting_commits + error_commits + | 163 if (commit_count != (conflicting_commits + error_commits + |
| 156 transient_error_commits)) { | 164 transient_error_commits)) { |
| 157 ResetErrorCounters(status); | 165 ResetErrorCounters(status); |
| 158 } | 166 } |
| 159 SyncerUtil::MarkDeletedChildrenSynced(dir, &deleted_folders); | 167 SyncerUtil::MarkDeletedChildrenSynced(dir, &deleted_folders); |
| 160 session->set_over_quota(over_quota); | 168 status->set_over_quota(over_quota); |
| 161 | 169 |
| 162 return; | 170 return; |
| 163 } | 171 } |
| 164 | 172 |
| 165 void LogServerError(const CommitResponse_EntryResponse& res) { | 173 void LogServerError(const CommitResponse_EntryResponse& res) { |
| 166 if (res.has_error_message()) | 174 if (res.has_error_message()) |
| 167 LOG(ERROR) << " " << res.error_message(); | 175 LOG(ERROR) << " " << res.error_message(); |
| 168 else | 176 else |
| 169 LOG(ERROR) << " No detailed error message returned from server"; | 177 LOG(ERROR) << " No detailed error message returned from server"; |
| 170 } | 178 } |
| 171 | 179 |
| 172 CommitResponse::RESPONSE_TYPE | 180 CommitResponse::RESPONSE_TYPE |
| 173 ProcessCommitResponseCommand::ProcessSingleCommitResponse( | 181 ProcessCommitResponseCommand::ProcessSingleCommitResponse( |
| 174 syncable::WriteTransaction* trans, | 182 syncable::WriteTransaction* trans, |
| 175 const sync_pb::CommitResponse_EntryResponse& pb_server_entry, | 183 const sync_pb::CommitResponse_EntryResponse& pb_server_entry, |
| 176 const syncable::Id& pre_commit_id, | 184 const syncable::Id& pre_commit_id, |
| 177 std::set<syncable::Id>* conflicting_new_folder_ids, | 185 std::set<syncable::Id>* conflicting_new_folder_ids, |
| 178 set<syncable::Id>* deleted_folders, | 186 set<syncable::Id>* deleted_folders) { |
| 179 SyncerSession* const session) { | |
| 180 | 187 |
| 181 const CommitResponse_EntryResponse& server_entry = | 188 const CommitResponse_EntryResponse& server_entry = |
| 182 *static_cast<const CommitResponse_EntryResponse*>(&pb_server_entry); | 189 *static_cast<const CommitResponse_EntryResponse*>(&pb_server_entry); |
| 183 MutableEntry local_entry(trans, GET_BY_ID, pre_commit_id); | 190 MutableEntry local_entry(trans, GET_BY_ID, pre_commit_id); |
| 184 CHECK(local_entry.good()); | 191 CHECK(local_entry.good()); |
| 185 bool syncing_was_set = local_entry.Get(SYNCING); | 192 bool syncing_was_set = local_entry.Get(SYNCING); |
| 186 local_entry.Put(SYNCING, false); | 193 local_entry.Put(SYNCING, false); |
| 187 | 194 |
| 188 CommitResponse::RESPONSE_TYPE response = (CommitResponse::RESPONSE_TYPE) | 195 CommitResponse::RESPONSE_TYPE response = (CommitResponse::RESPONSE_TYPE) |
| 189 server_entry.response_type(); | 196 server_entry.response_type(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 return CommitResponse::INVALID_MESSAGE; | 241 return CommitResponse::INVALID_MESSAGE; |
| 235 } | 242 } |
| 236 } | 243 } |
| 237 | 244 |
| 238 if (server_entry.version() == 0) { | 245 if (server_entry.version() == 0) { |
| 239 LOG(WARNING) << "Server returned a zero version on a commit response."; | 246 LOG(WARNING) << "Server returned a zero version on a commit response."; |
| 240 } | 247 } |
| 241 | 248 |
| 242 ProcessSuccessfulCommitResponse(trans, server_entry, pre_commit_id, | 249 ProcessSuccessfulCommitResponse(trans, server_entry, pre_commit_id, |
| 243 &local_entry, syncing_was_set, | 250 &local_entry, syncing_was_set, |
| 244 deleted_folders, session); | 251 deleted_folders); |
| 245 return response; | 252 return response; |
| 246 } | 253 } |
| 247 | 254 |
| 248 void ProcessCommitResponseCommand::ProcessSuccessfulCommitResponse( | 255 void ProcessCommitResponseCommand::ProcessSuccessfulCommitResponse( |
| 249 syncable::WriteTransaction* trans, | 256 syncable::WriteTransaction* trans, |
| 250 const CommitResponse_EntryResponse& server_entry, | 257 const CommitResponse_EntryResponse& server_entry, |
| 251 const syncable::Id& pre_commit_id, syncable::MutableEntry* local_entry, | 258 const syncable::Id& pre_commit_id, syncable::MutableEntry* local_entry, |
| 252 bool syncing_was_set, set<syncable::Id>* deleted_folders, | 259 bool syncing_was_set, set<syncable::Id>* deleted_folders) { |
| 253 SyncerSession* const session) { | |
| 254 int64 old_version = local_entry->Get(BASE_VERSION); | 260 int64 old_version = local_entry->Get(BASE_VERSION); |
| 255 int64 new_version = server_entry.version(); | 261 int64 new_version = server_entry.version(); |
| 256 bool bad_commit_version = false; | 262 bool bad_commit_version = false; |
| 257 // TODO(sync): The !server_entry.has_id_string() clauses below were | 263 // TODO(sync): The !server_entry.has_id_string() clauses below were |
| 258 // introduced when working with the new protocol. | 264 // introduced when working with the new protocol. |
| 259 if (!pre_commit_id.ServerKnows()) | 265 if (!pre_commit_id.ServerKnows()) |
| 260 bad_commit_version = 0 == new_version; | 266 bad_commit_version = 0 == new_version; |
| 261 else | 267 else |
| 262 bad_commit_version = old_version > new_version; | 268 bad_commit_version = old_version > new_version; |
| 263 if (bad_commit_version) { | 269 if (bad_commit_version) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 | 349 |
| 344 if (!server_name.empty() && old_name != server_name) { | 350 if (!server_name.empty() && old_name != server_name) { |
| 345 LOG(INFO) << "Server commit moved aside entry: " << old_name | 351 LOG(INFO) << "Server commit moved aside entry: " << old_name |
| 346 << " to new name " << server_name; | 352 << " to new name " << server_name; |
| 347 // Should be safe since we're in a "commit lock." | 353 // Should be safe since we're in a "commit lock." |
| 348 local_entry->Put(syncable::NON_UNIQUE_NAME, server_name); | 354 local_entry->Put(syncable::NON_UNIQUE_NAME, server_name); |
| 349 } | 355 } |
| 350 } | 356 } |
| 351 | 357 |
| 352 } // namespace browser_sync | 358 } // namespace browser_sync |
| OLD | NEW |