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_thread2.h" | 5 #include "chrome/browser/sync/engine/syncer_thread2.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/rand_util.h" | 9 #include "base/rand_util.h" |
| 10 #include "chrome/browser/sync/engine/syncer.h" | 10 #include "chrome/browser/sync/engine/syncer.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 mode_ = mode; | 95 mode_ = mode; |
| 96 AdjustPolling(NULL); // Will kick start poll timer if needed. | 96 AdjustPolling(NULL); // Will kick start poll timer if needed. |
| 97 } | 97 } |
| 98 | 98 |
| 99 bool SyncerThread::ShouldRunJob(SyncSessionJobPurpose purpose, | 99 bool SyncerThread::ShouldRunJob(SyncSessionJobPurpose purpose, |
| 100 const TimeTicks& scheduled_start) { | 100 const TimeTicks& scheduled_start) { |
| 101 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); | 101 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); |
| 102 | 102 |
| 103 // Check wait interval. | 103 // Check wait interval. |
| 104 if (wait_interval_.get()) { | 104 if (wait_interval_.get()) { |
| 105 // TODO(tim): Consider different handling for CLEAR_USER_DATA (i.e. permit | |
| 106 // when throttled). | |
| 105 if (wait_interval_->mode == WaitInterval::THROTTLED) | 107 if (wait_interval_->mode == WaitInterval::THROTTLED) |
| 106 return false; | 108 return false; |
| 107 | 109 |
| 108 DCHECK_EQ(wait_interval_->mode, WaitInterval::EXPONENTIAL_BACKOFF); | 110 DCHECK_EQ(wait_interval_->mode, WaitInterval::EXPONENTIAL_BACKOFF); |
| 109 DCHECK(purpose == POLL || | 111 DCHECK(purpose == POLL || |
| 110 purpose == NUDGE); | 112 purpose == NUDGE); |
| 111 if ((purpose != NUDGE) || wait_interval_->had_nudge) | 113 if ((purpose != NUDGE) || wait_interval_->had_nudge) |
| 112 return false; | 114 return false; |
| 113 } | 115 } |
| 114 | 116 |
| 115 // Mode / purpose contract (See 'Mode' enum in header). Don't run jobs that | 117 // Mode / purpose contract (See 'Mode' enum in header). Don't run jobs that |
| 116 // were intended for a normal sync if we are in configuration mode, and vice | 118 // were intended for a normal sync if we are in configuration mode, and vice |
| 117 // versa. | 119 // versa. |
| 118 switch (mode_) { | 120 switch (mode_) { |
|
Raz Mathias
2011/02/03 01:42:17
It seems like you are switching on Purpose a bunch
tim (not reviewing)
2011/02/03 18:18:52
I like this suggestion, except that right now the
Raz Mathias
2011/02/03 19:21:17
What I meant here was implementing a method on the
| |
| 119 case CONFIGURATION_MODE: | 121 case CONFIGURATION_MODE: |
| 120 if (purpose != CONFIGURATION) | 122 if (purpose != CONFIGURATION) |
| 121 return false; | 123 return false; |
| 122 break; | 124 break; |
| 123 case NORMAL_MODE: | 125 case NORMAL_MODE: |
| 124 if (purpose != POLL && purpose != NUDGE) | 126 if (purpose == CONFIGURATION) |
| 125 return false; | 127 return false; |
| 126 break; | 128 break; |
| 127 default: | 129 default: |
| 128 NOTREACHED() << "Unknown SyncerThread Mode: " << mode_; | 130 NOTREACHED() << "Unknown SyncerThread Mode: " << mode_; |
| 129 return false; | 131 return false; |
| 130 } | 132 } |
| 131 | 133 |
| 132 // Continuation NUDGE tasks have priority over POLLs because they are the | 134 // Continuation NUDGE tasks have priority over POLLs because they are the |
| 133 // only tasks that trigger exponential backoff, so this prevents them from | 135 // only tasks that trigger exponential backoff, so this prevents them from |
| 134 // being starved from running (e.g. due to a very, very low poll interval, | 136 // being starved from running (e.g. due to a very, very low poll interval, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 151 namespace { | 153 namespace { |
| 152 GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource( | 154 GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource( |
| 153 NudgeSource source) { | 155 NudgeSource source) { |
| 154 switch (source) { | 156 switch (source) { |
| 155 case NUDGE_SOURCE_NOTIFICATION: | 157 case NUDGE_SOURCE_NOTIFICATION: |
| 156 return GetUpdatesCallerInfo::NOTIFICATION; | 158 return GetUpdatesCallerInfo::NOTIFICATION; |
| 157 case NUDGE_SOURCE_LOCAL: | 159 case NUDGE_SOURCE_LOCAL: |
| 158 return GetUpdatesCallerInfo::LOCAL; | 160 return GetUpdatesCallerInfo::LOCAL; |
| 159 case NUDGE_SOURCE_CONTINUATION: | 161 case NUDGE_SOURCE_CONTINUATION: |
| 160 return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION; | 162 return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION; |
| 161 case NUDGE_SOURCE_CLEAR_PRIVATE_DATA: | |
| 162 return GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA; | |
| 163 case NUDGE_SOURCE_UNKNOWN: | 163 case NUDGE_SOURCE_UNKNOWN: |
| 164 return GetUpdatesCallerInfo::UNKNOWN; | |
| 164 default: | 165 default: |
| 166 NOTREACHED(); | |
| 165 return GetUpdatesCallerInfo::UNKNOWN; | 167 return GetUpdatesCallerInfo::UNKNOWN; |
| 166 } | 168 } |
| 167 } | 169 } |
| 168 | 170 |
| 169 // Functor for std::find_if to search by ModelSafeGroup. | 171 // Functor for std::find_if to search by ModelSafeGroup. |
| 170 struct WorkerGroupIs { | 172 struct WorkerGroupIs { |
| 171 explicit WorkerGroupIs(ModelSafeGroup group) : group(group) {} | 173 explicit WorkerGroupIs(ModelSafeGroup group) : group(group) {} |
| 172 bool operator()(ModelSafeWorker* w) { | 174 bool operator()(ModelSafeWorker* w) { |
| 173 return group == w->GetModelSafeGroup(); | 175 return group == w->GetModelSafeGroup(); |
| 174 } | 176 } |
| 175 ModelSafeGroup group; | 177 ModelSafeGroup group; |
| 176 }; | 178 }; |
| 177 } // namespace | 179 } // namespace |
| 178 | 180 |
| 181 void SyncerThread::ScheduleClearUserData() { | |
| 182 if (!thread_.IsRunning()) { | |
| 183 NOTREACHED(); | |
| 184 return; | |
| 185 } | |
| 186 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
| 187 this, &SyncerThread::ScheduleClearUserDataImpl)); | |
| 188 } | |
| 189 | |
| 179 void SyncerThread::ScheduleNudge(const TimeDelta& delay, | 190 void SyncerThread::ScheduleNudge(const TimeDelta& delay, |
| 180 NudgeSource source, const ModelTypeBitSet& types) { | 191 NudgeSource source, const ModelTypeBitSet& types) { |
| 181 if (!thread_.IsRunning()) { | 192 if (!thread_.IsRunning()) { |
| 182 NOTREACHED(); | 193 NOTREACHED(); |
| 183 return; | 194 return; |
| 184 } | 195 } |
| 185 | 196 |
| 186 TypePayloadMap types_with_payloads = | 197 TypePayloadMap types_with_payloads = |
| 187 sessions::MakeTypePayloadMapFromBitSet(types, std::string()); | 198 sessions::MakeTypePayloadMapFromBitSet(types, std::string()); |
| 188 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 199 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
| 189 this, &SyncerThread::ScheduleNudgeImpl, delay, source, | 200 this, &SyncerThread::ScheduleNudgeImpl, delay, source, |
| 190 types_with_payloads)); | 201 types_with_payloads)); |
| 191 } | 202 } |
| 192 | 203 |
| 193 void SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay, | 204 void SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay, |
| 194 NudgeSource source, const TypePayloadMap& types_with_payloads) { | 205 NudgeSource source, const TypePayloadMap& types_with_payloads) { |
| 195 if (!thread_.IsRunning()) { | 206 if (!thread_.IsRunning()) { |
| 196 NOTREACHED(); | 207 NOTREACHED(); |
| 197 return; | 208 return; |
| 198 } | 209 } |
| 199 | 210 |
| 200 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 211 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
| 201 this, &SyncerThread::ScheduleNudgeImpl, delay, source, | 212 this, &SyncerThread::ScheduleNudgeImpl, delay, source, |
| 202 types_with_payloads)); | 213 types_with_payloads)); |
| 203 } | 214 } |
| 204 | 215 |
| 216 void SyncerThread::ScheduleClearUserDataImpl() { | |
| 217 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); | |
| 218 SyncSession* session = new SyncSession(session_context_.get(), this, | |
| 219 SyncSourceInfo(), ModelSafeRoutingInfo(), | |
| 220 std::vector<ModelSafeWorker*>()); | |
| 221 ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), CLEAR_USER_DATA, session); | |
| 222 } | |
| 223 | |
| 205 void SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay, | 224 void SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay, |
| 206 NudgeSource source, const TypePayloadMap& types_with_payloads) { | 225 NudgeSource source, const TypePayloadMap& types_with_payloads) { |
| 207 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); | 226 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); |
| 208 TimeTicks rough_start = TimeTicks::Now() + delay; | 227 TimeTicks rough_start = TimeTicks::Now() + delay; |
| 209 if (!ShouldRunJob(NUDGE, rough_start)) | |
| 210 return; | |
| 211 | 228 |
| 212 // Note we currently nudge for all types regardless of the ones incurring | 229 // Note we currently nudge for all types regardless of the ones incurring |
| 213 // the nudge. Doing different would throw off some syncer commands like | 230 // the nudge. Doing different would throw off some syncer commands like |
| 214 // CleanupDisabledTypes. We may want to change this in the future. | 231 // CleanupDisabledTypes. We may want to change this in the future. |
| 215 ModelSafeRoutingInfo routes; | 232 ModelSafeRoutingInfo routes; |
| 216 std::vector<ModelSafeWorker*> workers; | 233 std::vector<ModelSafeWorker*> workers; |
| 217 session_context_->registrar()->GetModelSafeRoutingInfo(&routes); | 234 session_context_->registrar()->GetModelSafeRoutingInfo(&routes); |
| 218 session_context_->registrar()->GetWorkers(&workers); | 235 session_context_->registrar()->GetWorkers(&workers); |
| 219 SyncSourceInfo info(GetUpdatesFromNudgeSource(source), | 236 SyncSourceInfo info(GetUpdatesFromNudgeSource(source), |
| 220 types_with_payloads); | 237 types_with_payloads); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 SyncSessionJob job = {purpose, TimeTicks::Now() + delay, | 318 SyncSessionJob job = {purpose, TimeTicks::Now() + delay, |
| 302 make_linked_ptr(session)}; | 319 make_linked_ptr(session)}; |
| 303 if (purpose == NUDGE) { | 320 if (purpose == NUDGE) { |
| 304 DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session); | 321 DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session); |
| 305 pending_nudge_.reset(new SyncSessionJob(job)); | 322 pending_nudge_.reset(new SyncSessionJob(job)); |
| 306 } | 323 } |
| 307 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this, | 324 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this, |
| 308 &SyncerThread::DoSyncSessionJob, job), delay.InMilliseconds()); | 325 &SyncerThread::DoSyncSessionJob, job), delay.InMilliseconds()); |
| 309 } | 326 } |
| 310 | 327 |
| 328 void SyncerThread::SetSyncerStepsForPurpose(SyncSessionJobPurpose purpose, | |
|
Raz Mathias
2011/02/03 01:42:17
It seems a little strange that the syncer, which s
tim (not reviewing)
2011/02/03 18:18:52
Did you mean SyncerThread vs Syncer? Because this
Raz Mathias
2011/02/03 19:21:17
Yes, sorry, SyncerThread -- This switch block with
| |
| 329 SyncerStep* start, SyncerStep* end) { | |
| 330 *end = SYNCER_END; | |
| 331 switch (purpose) { | |
| 332 case CONFIGURATION: | |
| 333 *start = DOWNLOAD_UPDATES; | |
| 334 *end = APPLY_UPDATES; | |
| 335 return; | |
| 336 case CLEAR_USER_DATA: | |
| 337 *start = CLEAR_PRIVATE_DATA; | |
| 338 return; | |
| 339 case NUDGE: | |
| 340 case POLL: | |
| 341 *start = SYNCER_BEGIN; | |
| 342 return; | |
| 343 default: | |
| 344 NOTREACHED(); | |
| 345 } | |
| 346 } | |
| 347 | |
| 311 void SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) { | 348 void SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) { |
| 312 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); | 349 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); |
| 313 | 350 |
| 314 if (job.purpose == NUDGE) { | 351 if (job.purpose == NUDGE) { |
| 315 DCHECK(pending_nudge_.get()); | 352 DCHECK(pending_nudge_.get()); |
| 316 if (pending_nudge_->session != job.session) | 353 if (pending_nudge_->session != job.session) |
| 317 return; // Another nudge must have been scheduled in in the meantime. | 354 return; // Another nudge must have been scheduled in in the meantime. |
| 318 pending_nudge_.reset(); | 355 pending_nudge_.reset(); |
| 319 } else if (job.purpose == CONFIGURATION) { | |
| 320 NOTIMPLEMENTED() << "TODO(tim): SyncShare [DOWNLOAD_UPDATES,APPLY_UPDATES]"; | |
| 321 } | 356 } |
| 322 | 357 |
| 358 SyncerStep begin(SYNCER_BEGIN); | |
| 359 SyncerStep end(SYNCER_END); | |
| 360 SetSyncerStepsForPurpose(job.purpose, &begin, &end); | |
| 361 | |
| 323 bool has_more_to_sync = true; | 362 bool has_more_to_sync = true; |
| 324 bool did_job = false; | 363 bool did_job = false; |
| 325 while (ShouldRunJob(job.purpose, job.scheduled_start) && has_more_to_sync) { | 364 while (ShouldRunJob(job.purpose, job.scheduled_start) && has_more_to_sync) { |
| 326 VLOG(1) << "SyncerThread: Calling SyncShare."; | 365 VLOG(1) << "SyncerThread: Calling SyncShare."; |
| 327 did_job = true; | 366 did_job = true; |
| 328 // Synchronously perform the sync session from this thread. | 367 // Synchronously perform the sync session from this thread. |
| 329 syncer_->SyncShare(job.session.get()); | 368 syncer_->SyncShare(job.session.get(), begin, end); |
| 330 has_more_to_sync = job.session->HasMoreToSync(); | 369 has_more_to_sync = job.session->HasMoreToSync(); |
| 331 if (has_more_to_sync) | 370 if (has_more_to_sync) |
| 332 job.session->ResetTransientState(); | 371 job.session->ResetTransientState(); |
| 333 } | 372 } |
| 334 VLOG(1) << "SyncerThread: Done SyncShare looping."; | 373 VLOG(1) << "SyncerThread: Done SyncShare looping."; |
| 335 if (did_job) | 374 if (did_job) |
| 336 FinishSyncSessionJob(job); | 375 FinishSyncSessionJob(job); |
| 337 } | 376 } |
| 338 | 377 |
| 339 void SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) { | 378 void SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 368 // 500, is likely to have occurred during commit). | 407 // 500, is likely to have occurred during commit). |
| 369 const bool work_to_do = | 408 const bool work_to_do = |
| 370 old_job.session->status_controller()->num_server_changes_remaining() > 0 | 409 old_job.session->status_controller()->num_server_changes_remaining() > 0 |
| 371 || old_job.session->status_controller()->unsynced_handles().size() > 0; | 410 || old_job.session->status_controller()->unsynced_handles().size() > 0; |
| 372 VLOG(1) << "syncer has work to do: " << work_to_do; | 411 VLOG(1) << "syncer has work to do: " << work_to_do; |
| 373 | 412 |
| 374 AdjustPolling(&old_job); | 413 AdjustPolling(&old_job); |
| 375 | 414 |
| 376 // TODO(tim): Old impl had special code if notifications disabled. Needed? | 415 // TODO(tim): Old impl had special code if notifications disabled. Needed? |
| 377 if (!work_to_do) { | 416 if (!work_to_do) { |
| 378 wait_interval_.reset(); // Success implies backoff relief. | 417 // Success implies backoff relief. Note that if this was a "one-off" job |
| 418 // (i.e. purpose == CLEAR_USER_DATA), if there was work_to_do before it | |
| 419 // ran this wont have changed, as jobs like this don't run a full sync | |
| 420 // cycle. So we don't need special code here. | |
| 421 wait_interval_.reset(); | |
| 379 return; | 422 return; |
| 380 } | 423 } |
| 381 | 424 |
| 382 if (old_job.session->source().updates_source == | 425 if (old_job.session->source().updates_source == |
| 383 GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) { | 426 GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) { |
| 384 // We don't seem to have made forward progress. Start or extend backoff. | 427 // We don't seem to have made forward progress. Start or extend backoff. |
| 385 HandleConsecutiveContinuationError(old_job); | 428 HandleConsecutiveContinuationError(old_job); |
| 386 } else if (IsBackingOff()) { | 429 } else if (IsBackingOff()) { |
| 387 // We weren't continuing but we're in backoff; must have been a nudge. | 430 // We weren't continuing but we're in backoff; must have been a nudge. |
| 388 DCHECK_EQ(NUDGE, old_job.purpose); | 431 DCHECK_EQ(NUDGE, old_job.purpose); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 const ServerConnectionEvent& event) { | 578 const ServerConnectionEvent& event) { |
| 536 NOTIMPLEMENTED(); | 579 NOTIMPLEMENTED(); |
| 537 } | 580 } |
| 538 | 581 |
| 539 void SyncerThread::set_notifications_enabled(bool notifications_enabled) { | 582 void SyncerThread::set_notifications_enabled(bool notifications_enabled) { |
| 540 session_context_->set_notifications_enabled(notifications_enabled); | 583 session_context_->set_notifications_enabled(notifications_enabled); |
| 541 } | 584 } |
| 542 | 585 |
| 543 } // s3 | 586 } // s3 |
| 544 } // browser_sync | 587 } // browser_sync |
| OLD | NEW |