Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/syncer.h" | 5 #include "chrome/browser/sync/engine/syncer.h" |
| 6 | 6 |
| 7 #include "base/debug/trace_event.h" | |
| 7 #include "base/location.h" | 8 #include "base/location.h" |
| 8 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 9 #include "base/time.h" | 10 #include "base/time.h" |
| 10 #include "chrome/browser/sync/engine/apply_updates_command.h" | 11 #include "chrome/browser/sync/engine/apply_updates_command.h" |
| 11 #include "chrome/browser/sync/engine/build_and_process_conflict_sets_command.h" | 12 #include "chrome/browser/sync/engine/build_and_process_conflict_sets_command.h" |
| 12 #include "chrome/browser/sync/engine/build_commit_command.h" | 13 #include "chrome/browser/sync/engine/build_commit_command.h" |
| 13 #include "chrome/browser/sync/engine/cleanup_disabled_types_command.h" | 14 #include "chrome/browser/sync/engine/cleanup_disabled_types_command.h" |
| 14 #include "chrome/browser/sync/engine/clear_data_command.h" | 15 #include "chrome/browser/sync/engine/clear_data_command.h" |
| 15 #include "chrome/browser/sync/engine/conflict_resolver.h" | 16 #include "chrome/browser/sync/engine/conflict_resolver.h" |
| 16 #include "chrome/browser/sync/engine/download_updates_command.h" | 17 #include "chrome/browser/sync/engine/download_updates_command.h" |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 47 using syncable::ScopedDirLookup; | 48 using syncable::ScopedDirLookup; |
| 48 using syncable::WriteTransaction; | 49 using syncable::WriteTransaction; |
| 49 | 50 |
| 50 namespace browser_sync { | 51 namespace browser_sync { |
| 51 | 52 |
| 52 using sessions::ScopedSessionContextConflictResolver; | 53 using sessions::ScopedSessionContextConflictResolver; |
| 53 using sessions::StatusController; | 54 using sessions::StatusController; |
| 54 using sessions::SyncSession; | 55 using sessions::SyncSession; |
| 55 using sessions::ConflictProgress; | 56 using sessions::ConflictProgress; |
| 56 | 57 |
| 58 #define ENUM_CASE(x) case x: return #x; break | |
| 59 const char* SyncerStepToString(const SyncerStep step) | |
| 60 { | |
| 61 switch (step) { | |
| 62 ENUM_CASE(SYNCER_BEGIN); | |
| 63 ENUM_CASE(CLEANUP_DISABLED_TYPES); | |
| 64 ENUM_CASE(DOWNLOAD_UPDATES); | |
| 65 ENUM_CASE(PROCESS_CLIENT_COMMAND); | |
| 66 ENUM_CASE(VERIFY_UPDATES); | |
| 67 ENUM_CASE(PROCESS_UPDATES); | |
| 68 ENUM_CASE(STORE_TIMESTAMPS); | |
| 69 ENUM_CASE(APPLY_UPDATES); | |
| 70 ENUM_CASE(BUILD_COMMIT_REQUEST); | |
| 71 ENUM_CASE(POST_COMMIT_MESSAGE); | |
| 72 ENUM_CASE(PROCESS_COMMIT_RESPONSE); | |
| 73 ENUM_CASE(BUILD_AND_PROCESS_CONFLICT_SETS); | |
| 74 ENUM_CASE(RESOLVE_CONFLICTS); | |
| 75 ENUM_CASE(APPLY_UPDATES_TO_RESOLVE_CONFLICTS); | |
| 76 ENUM_CASE(CLEAR_PRIVATE_DATA); | |
| 77 ENUM_CASE(SYNCER_END); | |
| 78 } | |
| 79 } | |
| 80 #undef ENUM_CASE | |
| 81 | |
| 57 Syncer::ScopedSyncStartStopTracker::ScopedSyncStartStopTracker( | 82 Syncer::ScopedSyncStartStopTracker::ScopedSyncStartStopTracker( |
| 58 sessions::SyncSession* session) : session_(session) { | 83 sessions::SyncSession* session) : session_(session) { |
| 59 session_->status_controller()->SetSyncInProgressAndUpdateStartTime(true); | 84 session_->status_controller()->SetSyncInProgressAndUpdateStartTime(true); |
| 60 } | 85 } |
| 61 | 86 |
| 62 Syncer::ScopedSyncStartStopTracker::~ScopedSyncStartStopTracker() { | 87 Syncer::ScopedSyncStartStopTracker::~ScopedSyncStartStopTracker() { |
| 63 session_->status_controller()->SetSyncInProgressAndUpdateStartTime(false); | 88 session_->status_controller()->SetSyncInProgressAndUpdateStartTime(false); |
| 64 } | 89 } |
| 65 | 90 |
| 66 Syncer::Syncer() | 91 Syncer::Syncer() |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 91 } | 116 } |
| 92 | 117 |
| 93 ScopedSessionContextConflictResolver scoped(session->context(), | 118 ScopedSessionContextConflictResolver scoped(session->context(), |
| 94 &resolver_); | 119 &resolver_); |
| 95 | 120 |
| 96 ScopedSyncStartStopTracker start_stop_tracker(session); | 121 ScopedSyncStartStopTracker start_stop_tracker(session); |
| 97 SyncerStep current_step = first_step; | 122 SyncerStep current_step = first_step; |
| 98 | 123 |
| 99 SyncerStep next_step = current_step; | 124 SyncerStep next_step = current_step; |
| 100 while (!ExitRequested()) { | 125 while (!ExitRequested()) { |
| 126 TRACE_EVENT_BEGIN1("sync", "SyncerStateMachine", | |
|
jbates
2011/11/16 00:46:57
If you change this to TRACE_EVENT1 instead of TRAC
rlarocque
2011/11/16 01:03:40
I had considered that, but decided against it. I
| |
| 127 "state", SyncerStepToString(current_step)); | |
| 128 VLOG(1) << "Syncer step:" << SyncerStepToString(current_step); | |
| 129 | |
| 101 switch (current_step) { | 130 switch (current_step) { |
| 102 case SYNCER_BEGIN: | 131 case SYNCER_BEGIN: |
| 103 VLOG(1) << "Syncer Begin"; | |
| 104 // This isn't perfect, as we can end up bundling extensions activity | 132 // This isn't perfect, as we can end up bundling extensions activity |
| 105 // intended for the next session into the current one. We could do a | 133 // intended for the next session into the current one. We could do a |
| 106 // test-and-reset as with the source, but note that also falls short if | 134 // test-and-reset as with the source, but note that also falls short if |
| 107 // the commit request fails (e.g. due to lost connection), as we will | 135 // the commit request fails (e.g. due to lost connection), as we will |
| 108 // fall all the way back to the syncer thread main loop in that case, | 136 // fall all the way back to the syncer thread main loop in that case, |
| 109 // creating a new session when a connection is established, losing the | 137 // creating a new session when a connection is established, losing the |
| 110 // records set here on the original attempt. This should provide us | 138 // records set here on the original attempt. This should provide us |
| 111 // with the right data "most of the time", and we're only using this | 139 // with the right data "most of the time", and we're only using this |
| 112 // for analysis purposes, so Law of Large Numbers FTW. | 140 // for analysis purposes, so Law of Large Numbers FTW. |
| 113 session->context()->extensions_monitor()->GetAndClearRecords( | 141 session->context()->extensions_monitor()->GetAndClearRecords( |
| 114 session->mutable_extensions_activity()); | 142 session->mutable_extensions_activity()); |
| 115 next_step = CLEANUP_DISABLED_TYPES; | 143 next_step = CLEANUP_DISABLED_TYPES; |
| 116 break; | 144 break; |
| 117 case CLEANUP_DISABLED_TYPES: { | 145 case CLEANUP_DISABLED_TYPES: { |
| 118 VLOG(1) << "Cleaning up disabled types"; | |
| 119 CleanupDisabledTypesCommand cleanup; | 146 CleanupDisabledTypesCommand cleanup; |
| 120 cleanup.Execute(session); | 147 cleanup.Execute(session); |
| 121 next_step = DOWNLOAD_UPDATES; | 148 next_step = DOWNLOAD_UPDATES; |
| 122 break; | 149 break; |
| 123 } | 150 } |
| 124 case DOWNLOAD_UPDATES: { | 151 case DOWNLOAD_UPDATES: { |
| 125 VLOG(1) << "Downloading Updates"; | |
| 126 DownloadUpdatesCommand download_updates; | 152 DownloadUpdatesCommand download_updates; |
| 127 download_updates.Execute(session); | 153 download_updates.Execute(session); |
| 128 next_step = PROCESS_CLIENT_COMMAND; | 154 next_step = PROCESS_CLIENT_COMMAND; |
| 129 break; | 155 break; |
| 130 } | 156 } |
| 131 case PROCESS_CLIENT_COMMAND: { | 157 case PROCESS_CLIENT_COMMAND: { |
| 132 VLOG(1) << "Processing Client Command"; | |
| 133 ProcessClientCommand(session); | 158 ProcessClientCommand(session); |
| 134 next_step = VERIFY_UPDATES; | 159 next_step = VERIFY_UPDATES; |
| 135 break; | 160 break; |
| 136 } | 161 } |
| 137 case VERIFY_UPDATES: { | 162 case VERIFY_UPDATES: { |
| 138 VLOG(1) << "Verifying Updates"; | |
| 139 VerifyUpdatesCommand verify_updates; | 163 VerifyUpdatesCommand verify_updates; |
| 140 verify_updates.Execute(session); | 164 verify_updates.Execute(session); |
| 141 next_step = PROCESS_UPDATES; | 165 next_step = PROCESS_UPDATES; |
| 142 break; | 166 break; |
| 143 } | 167 } |
| 144 case PROCESS_UPDATES: { | 168 case PROCESS_UPDATES: { |
| 145 VLOG(1) << "Processing Updates"; | |
| 146 ProcessUpdatesCommand process_updates; | 169 ProcessUpdatesCommand process_updates; |
| 147 process_updates.Execute(session); | 170 process_updates.Execute(session); |
| 148 next_step = STORE_TIMESTAMPS; | 171 next_step = STORE_TIMESTAMPS; |
| 149 break; | 172 break; |
| 150 } | 173 } |
| 151 case STORE_TIMESTAMPS: { | 174 case STORE_TIMESTAMPS: { |
| 152 VLOG(1) << "Storing timestamps"; | |
| 153 StoreTimestampsCommand store_timestamps; | 175 StoreTimestampsCommand store_timestamps; |
| 154 store_timestamps.Execute(session); | 176 store_timestamps.Execute(session); |
| 155 // We should download all of the updates before attempting to process | 177 // We should download all of the updates before attempting to process |
| 156 // them. | 178 // them. |
| 157 if (session->status_controller()->ServerSaysNothingMoreToDownload() || | 179 if (session->status_controller()->ServerSaysNothingMoreToDownload() || |
| 158 !session->status_controller()->download_updates_succeeded()) { | 180 !session->status_controller()->download_updates_succeeded()) { |
| 159 next_step = APPLY_UPDATES; | 181 next_step = APPLY_UPDATES; |
| 160 } else { | 182 } else { |
| 161 next_step = DOWNLOAD_UPDATES; | 183 next_step = DOWNLOAD_UPDATES; |
| 162 } | 184 } |
| 163 break; | 185 break; |
| 164 } | 186 } |
| 165 case APPLY_UPDATES: { | 187 case APPLY_UPDATES: { |
| 166 VLOG(1) << "Applying Updates"; | |
| 167 ApplyUpdatesCommand apply_updates; | 188 ApplyUpdatesCommand apply_updates; |
| 168 apply_updates.Execute(session); | 189 apply_updates.Execute(session); |
| 169 if (last_step == APPLY_UPDATES) { | 190 if (last_step == APPLY_UPDATES) { |
| 170 // We're in configuration mode, but we still need to run the | 191 // We're in configuration mode, but we still need to run the |
| 171 // SYNCER_END step. | 192 // SYNCER_END step. |
| 172 last_step = SYNCER_END; | 193 last_step = SYNCER_END; |
| 173 next_step = SYNCER_END; | 194 next_step = SYNCER_END; |
| 174 } else { | 195 } else { |
| 175 next_step = BUILD_COMMIT_REQUEST; | 196 next_step = BUILD_COMMIT_REQUEST; |
| 176 } | 197 } |
| 177 break; | 198 break; |
| 178 } | 199 } |
| 179 // These two steps are combined since they are executed within the same | 200 // These two steps are combined since they are executed within the same |
| 180 // write transaction. | 201 // write transaction. |
| 181 case BUILD_COMMIT_REQUEST: { | 202 case BUILD_COMMIT_REQUEST: { |
| 182 VLOG(1) << "Processing Commit Request"; | |
| 183 ScopedDirLookup dir(session->context()->directory_manager(), | 203 ScopedDirLookup dir(session->context()->directory_manager(), |
| 184 session->context()->account_name()); | 204 session->context()->account_name()); |
| 185 if (!dir.good()) { | 205 if (!dir.good()) { |
| 186 LOG(ERROR) << "Scoped dir lookup failed!"; | 206 LOG(ERROR) << "Scoped dir lookup failed!"; |
| 187 return; | 207 return; |
| 188 } | 208 } |
| 189 WriteTransaction trans(FROM_HERE, SYNCER, dir); | 209 WriteTransaction trans(FROM_HERE, SYNCER, dir); |
| 190 sessions::ScopedSetSessionWriteTransaction set_trans(session, &trans); | 210 sessions::ScopedSetSessionWriteTransaction set_trans(session, &trans); |
| 191 | 211 |
| 192 VLOG(1) << "Getting the Commit IDs"; | 212 VLOG(1) << "Getting the Commit IDs"; |
| 193 GetCommitIdsCommand get_commit_ids_command( | 213 GetCommitIdsCommand get_commit_ids_command( |
| 194 session->context()->max_commit_batch_size()); | 214 session->context()->max_commit_batch_size()); |
| 195 get_commit_ids_command.Execute(session); | 215 get_commit_ids_command.Execute(session); |
| 196 | 216 |
| 197 if (!session->status_controller()->commit_ids().empty()) { | 217 if (!session->status_controller()->commit_ids().empty()) { |
| 198 VLOG(1) << "Building a commit message"; | 218 VLOG(1) << "Building a commit message"; |
| 199 BuildCommitCommand build_commit_command; | 219 BuildCommitCommand build_commit_command; |
| 200 build_commit_command.Execute(session); | 220 build_commit_command.Execute(session); |
| 201 | 221 |
| 202 next_step = POST_COMMIT_MESSAGE; | 222 next_step = POST_COMMIT_MESSAGE; |
| 203 } else { | 223 } else { |
| 204 next_step = BUILD_AND_PROCESS_CONFLICT_SETS; | 224 next_step = BUILD_AND_PROCESS_CONFLICT_SETS; |
| 205 } | 225 } |
| 206 | 226 |
| 207 break; | 227 break; |
| 208 } | 228 } |
| 209 case POST_COMMIT_MESSAGE: { | 229 case POST_COMMIT_MESSAGE: { |
| 210 VLOG(1) << "Posting a commit request"; | |
| 211 PostCommitMessageCommand post_commit_command; | 230 PostCommitMessageCommand post_commit_command; |
| 212 post_commit_command.Execute(session); | 231 post_commit_command.Execute(session); |
| 213 next_step = PROCESS_COMMIT_RESPONSE; | 232 next_step = PROCESS_COMMIT_RESPONSE; |
| 214 break; | 233 break; |
| 215 } | 234 } |
| 216 case PROCESS_COMMIT_RESPONSE: { | 235 case PROCESS_COMMIT_RESPONSE: { |
| 217 VLOG(1) << "Processing the commit response"; | |
| 218 session->status_controller()->reset_num_conflicting_commits(); | 236 session->status_controller()->reset_num_conflicting_commits(); |
| 219 ProcessCommitResponseCommand process_response_command; | 237 ProcessCommitResponseCommand process_response_command; |
| 220 process_response_command.Execute(session); | 238 process_response_command.Execute(session); |
| 221 next_step = BUILD_AND_PROCESS_CONFLICT_SETS; | 239 next_step = BUILD_AND_PROCESS_CONFLICT_SETS; |
| 222 break; | 240 break; |
| 223 } | 241 } |
| 224 case BUILD_AND_PROCESS_CONFLICT_SETS: { | 242 case BUILD_AND_PROCESS_CONFLICT_SETS: { |
| 225 VLOG(1) << "Building and Processing Conflict Sets"; | |
| 226 BuildAndProcessConflictSetsCommand build_process_conflict_sets; | 243 BuildAndProcessConflictSetsCommand build_process_conflict_sets; |
| 227 build_process_conflict_sets.Execute(session); | 244 build_process_conflict_sets.Execute(session); |
| 228 if (session->status_controller()->conflict_sets_built()) | 245 if (session->status_controller()->conflict_sets_built()) |
| 229 next_step = SYNCER_END; | 246 next_step = SYNCER_END; |
| 230 else | 247 else |
| 231 next_step = RESOLVE_CONFLICTS; | 248 next_step = RESOLVE_CONFLICTS; |
| 232 break; | 249 break; |
| 233 } | 250 } |
| 234 case RESOLVE_CONFLICTS: { | 251 case RESOLVE_CONFLICTS: { |
| 235 VLOG(1) << "Resolving Conflicts"; | |
| 236 | 252 |
| 237 // Trigger the pre_conflict_resolution_closure_, which is a testing | 253 // Trigger the pre_conflict_resolution_closure_, which is a testing |
| 238 // hook for the unit tests, if it is non-NULL. | 254 // hook for the unit tests, if it is non-NULL. |
| 239 if (pre_conflict_resolution_closure_) { | 255 if (pre_conflict_resolution_closure_) { |
| 240 pre_conflict_resolution_closure_->Run(); | 256 pre_conflict_resolution_closure_->Run(); |
| 241 } | 257 } |
| 242 | 258 |
| 243 StatusController* status = session->status_controller(); | 259 StatusController* status = session->status_controller(); |
| 244 status->reset_conflicts_resolved(); | 260 status->reset_conflicts_resolved(); |
| 245 ResolveConflictsCommand resolve_conflicts_command; | 261 ResolveConflictsCommand resolve_conflicts_command; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 268 status->TotalNumBlockingConflictingItems(); | 284 status->TotalNumBlockingConflictingItems(); |
| 269 status->update_conflicts_resolved(before_blocking_conflicting_updates > | 285 status->update_conflicts_resolved(before_blocking_conflicting_updates > |
| 270 after_blocking_conflicting_updates); | 286 after_blocking_conflicting_updates); |
| 271 if (status->conflicts_resolved()) | 287 if (status->conflicts_resolved()) |
| 272 next_step = RESOLVE_CONFLICTS; | 288 next_step = RESOLVE_CONFLICTS; |
| 273 else | 289 else |
| 274 next_step = SYNCER_END; | 290 next_step = SYNCER_END; |
| 275 break; | 291 break; |
| 276 } | 292 } |
| 277 case CLEAR_PRIVATE_DATA: { | 293 case CLEAR_PRIVATE_DATA: { |
| 278 VLOG(1) << "Clear Private Data"; | |
| 279 ClearDataCommand clear_data_command; | 294 ClearDataCommand clear_data_command; |
| 280 clear_data_command.Execute(session); | 295 clear_data_command.Execute(session); |
| 281 next_step = SYNCER_END; | 296 next_step = SYNCER_END; |
| 282 break; | 297 break; |
| 283 } | 298 } |
| 284 case SYNCER_END: { | 299 case SYNCER_END: { |
| 285 VLOG(1) << "Syncer End"; | |
| 286 SyncerEndCommand syncer_end_command; | 300 SyncerEndCommand syncer_end_command; |
| 287 syncer_end_command.Execute(session); | 301 syncer_end_command.Execute(session); |
| 288 next_step = SYNCER_END; | 302 next_step = SYNCER_END; |
| 289 break; | 303 break; |
| 290 } | 304 } |
| 291 default: | 305 default: |
| 292 LOG(ERROR) << "Unknown command: " << current_step; | 306 LOG(ERROR) << "Unknown command: " << current_step; |
| 293 } | 307 } |
| 294 VLOG(2) << "last step: " << last_step << ", current step: " | 308 VLOG(2) << "last step: " << SyncerStepToString(last_step) << ", " |
| 295 << current_step << ", next step: " | 309 << "current step: " << SyncerStepToString(current_step) << ", " |
| 296 << next_step << ", snapshot: " | 310 << "next step: " << SyncerStepToString(next_step) << ", " |
| 297 << session->TakeSnapshot().ToString(); | 311 << "snapshot: " << session->TakeSnapshot().ToString(); |
| 312 TRACE_EVENT_END1("sync", "SyncerStateMachine", | |
|
jbates
2011/11/16 00:46:57
Could remove this as mentioned above.
| |
| 313 "state", SyncerStepToString(current_step)); | |
| 298 if (last_step == current_step) | 314 if (last_step == current_step) |
| 299 break; | 315 break; |
| 300 current_step = next_step; | 316 current_step = next_step; |
| 301 } | 317 } |
| 302 } | 318 } |
| 303 | 319 |
| 304 void Syncer::ProcessClientCommand(sessions::SyncSession* session) { | 320 void Syncer::ProcessClientCommand(sessions::SyncSession* session) { |
| 305 const ClientToServerResponse& response = | 321 const ClientToServerResponse& response = |
| 306 session->status_controller()->updates_response(); | 322 session->status_controller()->updates_response(); |
| 307 if (!response.has_client_command()) | 323 if (!response.has_client_command()) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 348 entry->Put(SERVER_CTIME, Time()); | 364 entry->Put(SERVER_CTIME, Time()); |
| 349 entry->Put(SERVER_VERSION, 0); | 365 entry->Put(SERVER_VERSION, 0); |
| 350 entry->Put(SERVER_IS_DIR, false); | 366 entry->Put(SERVER_IS_DIR, false); |
| 351 entry->Put(SERVER_IS_DEL, false); | 367 entry->Put(SERVER_IS_DEL, false); |
| 352 entry->Put(IS_UNAPPLIED_UPDATE, false); | 368 entry->Put(IS_UNAPPLIED_UPDATE, false); |
| 353 entry->Put(SERVER_SPECIFICS, sync_pb::EntitySpecifics::default_instance()); | 369 entry->Put(SERVER_SPECIFICS, sync_pb::EntitySpecifics::default_instance()); |
| 354 entry->Put(SERVER_POSITION_IN_PARENT, 0); | 370 entry->Put(SERVER_POSITION_IN_PARENT, 0); |
| 355 } | 371 } |
| 356 | 372 |
| 357 } // namespace browser_sync | 373 } // namespace browser_sync |
| OLD | NEW |