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_) { |
| 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 != POLL && purpose != NUDGE && purpose != CLEAR_USER_DATA) |
|
Nicolas Zea
2011/02/03 00:39:07
if (purpose == CONFIGURATION)?
tim (not reviewing)
2011/02/03 00:56:15
Done.
| |
| 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 default: | 164 default: |
| 165 NOTREACHED(); | |
| 165 return GetUpdatesCallerInfo::UNKNOWN; | 166 return GetUpdatesCallerInfo::UNKNOWN; |
| 166 } | 167 } |
| 167 } | 168 } |
| 168 | 169 |
| 169 // Functor for std::find_if to search by ModelSafeGroup. | 170 // Functor for std::find_if to search by ModelSafeGroup. |
| 170 struct WorkerGroupIs { | 171 struct WorkerGroupIs { |
| 171 explicit WorkerGroupIs(ModelSafeGroup group) : group(group) {} | 172 explicit WorkerGroupIs(ModelSafeGroup group) : group(group) {} |
| 172 bool operator()(ModelSafeWorker* w) { | 173 bool operator()(ModelSafeWorker* w) { |
| 173 return group == w->GetModelSafeGroup(); | 174 return group == w->GetModelSafeGroup(); |
| 174 } | 175 } |
| 175 ModelSafeGroup group; | 176 ModelSafeGroup group; |
| 176 }; | 177 }; |
| 177 } // namespace | 178 } // namespace |
| 178 | 179 |
| 180 void SyncerThread::ScheduleClearUserData() { | |
| 181 if (!thread_.IsRunning()) { | |
| 182 NOTREACHED(); | |
| 183 return; | |
| 184 } | |
| 185 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
| 186 this, &SyncerThread::ScheduleClearUserDataImpl)); | |
| 187 } | |
| 188 | |
| 179 void SyncerThread::ScheduleNudge(const TimeDelta& delay, | 189 void SyncerThread::ScheduleNudge(const TimeDelta& delay, |
| 180 NudgeSource source, const ModelTypeBitSet& types) { | 190 NudgeSource source, const ModelTypeBitSet& types) { |
| 181 if (!thread_.IsRunning()) { | 191 if (!thread_.IsRunning()) { |
| 182 NOTREACHED(); | 192 NOTREACHED(); |
| 183 return; | 193 return; |
| 184 } | 194 } |
| 185 | 195 |
| 186 TypePayloadMap types_with_payloads = | 196 TypePayloadMap types_with_payloads = |
| 187 sessions::MakeTypePayloadMapFromBitSet(types, std::string()); | 197 sessions::MakeTypePayloadMapFromBitSet(types, std::string()); |
| 188 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 198 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
| 189 this, &SyncerThread::ScheduleNudgeImpl, delay, source, | 199 this, &SyncerThread::ScheduleNudgeImpl, delay, source, |
| 190 types_with_payloads)); | 200 types_with_payloads)); |
| 191 } | 201 } |
| 192 | 202 |
| 193 void SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay, | 203 void SyncerThread::ScheduleNudgeWithPayloads(const TimeDelta& delay, |
| 194 NudgeSource source, const TypePayloadMap& types_with_payloads) { | 204 NudgeSource source, const TypePayloadMap& types_with_payloads) { |
| 195 if (!thread_.IsRunning()) { | 205 if (!thread_.IsRunning()) { |
| 196 NOTREACHED(); | 206 NOTREACHED(); |
| 197 return; | 207 return; |
| 198 } | 208 } |
| 199 | 209 |
| 200 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 210 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
| 201 this, &SyncerThread::ScheduleNudgeImpl, delay, source, | 211 this, &SyncerThread::ScheduleNudgeImpl, delay, source, |
| 202 types_with_payloads)); | 212 types_with_payloads)); |
| 203 } | 213 } |
| 204 | 214 |
| 215 void SyncerThread::ScheduleClearUserDataImpl() { | |
| 216 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); | |
| 217 SyncSession* session = new SyncSession(session_context_.get(), this, | |
| 218 SyncSourceInfo(), ModelSafeRoutingInfo(), | |
| 219 std::vector<ModelSafeWorker*>()); | |
| 220 ScheduleSyncSessionJob(TimeDelta::FromSeconds(0), CLEAR_USER_DATA, session); | |
| 221 } | |
| 222 | |
| 205 void SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay, | 223 void SyncerThread::ScheduleNudgeImpl(const TimeDelta& delay, |
| 206 NudgeSource source, const TypePayloadMap& types_with_payloads) { | 224 NudgeSource source, const TypePayloadMap& types_with_payloads) { |
| 207 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); | 225 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); |
| 208 TimeTicks rough_start = TimeTicks::Now() + delay; | 226 TimeTicks rough_start = TimeTicks::Now() + delay; |
| 209 if (!ShouldRunJob(NUDGE, rough_start)) | |
| 210 return; | |
| 211 | 227 |
| 212 // Note we currently nudge for all types regardless of the ones incurring | 228 // Note we currently nudge for all types regardless of the ones incurring |
| 213 // the nudge. Doing different would throw off some syncer commands like | 229 // the nudge. Doing different would throw off some syncer commands like |
| 214 // CleanupDisabledTypes. We may want to change this in the future. | 230 // CleanupDisabledTypes. We may want to change this in the future. |
| 215 ModelSafeRoutingInfo routes; | 231 ModelSafeRoutingInfo routes; |
| 216 std::vector<ModelSafeWorker*> workers; | 232 std::vector<ModelSafeWorker*> workers; |
| 217 session_context_->registrar()->GetModelSafeRoutingInfo(&routes); | 233 session_context_->registrar()->GetModelSafeRoutingInfo(&routes); |
| 218 session_context_->registrar()->GetWorkers(&workers); | 234 session_context_->registrar()->GetWorkers(&workers); |
| 219 SyncSourceInfo info(GetUpdatesFromNudgeSource(source), | 235 SyncSourceInfo info(GetUpdatesFromNudgeSource(source), |
| 220 types_with_payloads); | 236 types_with_payloads); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 SyncSessionJob job = {purpose, TimeTicks::Now() + delay, | 317 SyncSessionJob job = {purpose, TimeTicks::Now() + delay, |
| 302 make_linked_ptr(session)}; | 318 make_linked_ptr(session)}; |
| 303 if (purpose == NUDGE) { | 319 if (purpose == NUDGE) { |
| 304 DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session); | 320 DCHECK(!pending_nudge_.get() || pending_nudge_->session.get() == session); |
| 305 pending_nudge_.reset(new SyncSessionJob(job)); | 321 pending_nudge_.reset(new SyncSessionJob(job)); |
| 306 } | 322 } |
| 307 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this, | 323 MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableMethod(this, |
| 308 &SyncerThread::DoSyncSessionJob, job), delay.InMilliseconds()); | 324 &SyncerThread::DoSyncSessionJob, job), delay.InMilliseconds()); |
| 309 } | 325 } |
| 310 | 326 |
| 327 void SyncerThread::SetSyncerStepsForPurpose(SyncSessionJobPurpose purpose, | |
| 328 SyncerStep* start, SyncerStep* end) { | |
| 329 *start = SYNCER_BEGIN; | |
| 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 } | |
| 340 } | |
| 341 | |
| 311 void SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) { | 342 void SyncerThread::DoSyncSessionJob(const SyncSessionJob& job) { |
| 312 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); | 343 DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); |
| 313 | 344 |
| 314 if (job.purpose == NUDGE) { | 345 if (job.purpose == NUDGE) { |
| 315 DCHECK(pending_nudge_.get()); | 346 DCHECK(pending_nudge_.get()); |
| 316 if (pending_nudge_->session != job.session) | 347 if (pending_nudge_->session != job.session) |
| 317 return; // Another nudge must have been scheduled in in the meantime. | 348 return; // Another nudge must have been scheduled in in the meantime. |
| 318 pending_nudge_.reset(); | 349 pending_nudge_.reset(); |
| 319 } else if (job.purpose == CONFIGURATION) { | |
| 320 NOTIMPLEMENTED() << "TODO(tim): SyncShare [DOWNLOAD_UPDATES,APPLY_UPDATES]"; | |
| 321 } | 350 } |
| 322 | 351 |
| 352 SyncerStep begin(SYNCER_BEGIN); | |
| 353 SyncerStep end(SYNCER_END); | |
| 354 SetSyncerStepsForPurpose(job.purpose, &begin, &end); | |
| 355 | |
| 323 bool has_more_to_sync = true; | 356 bool has_more_to_sync = true; |
| 324 bool did_job = false; | 357 bool did_job = false; |
| 325 while (ShouldRunJob(job.purpose, job.scheduled_start) && has_more_to_sync) { | 358 while (ShouldRunJob(job.purpose, job.scheduled_start) && has_more_to_sync) { |
| 326 VLOG(1) << "SyncerThread: Calling SyncShare."; | 359 VLOG(1) << "SyncerThread: Calling SyncShare."; |
| 327 did_job = true; | 360 did_job = true; |
| 328 // Synchronously perform the sync session from this thread. | 361 // Synchronously perform the sync session from this thread. |
| 329 syncer_->SyncShare(job.session.get()); | 362 syncer_->SyncShare(job.session.get(), begin, end); |
| 330 has_more_to_sync = job.session->HasMoreToSync(); | 363 has_more_to_sync = job.session->HasMoreToSync(); |
| 331 if (has_more_to_sync) | 364 if (has_more_to_sync) |
| 332 job.session->ResetTransientState(); | 365 job.session->ResetTransientState(); |
| 333 } | 366 } |
| 334 VLOG(1) << "SyncerThread: Done SyncShare looping."; | 367 VLOG(1) << "SyncerThread: Done SyncShare looping."; |
| 335 if (did_job) | 368 if (did_job) |
| 336 FinishSyncSessionJob(job); | 369 FinishSyncSessionJob(job); |
| 337 } | 370 } |
| 338 | 371 |
| 339 void SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) { | 372 void SyncerThread::FinishSyncSessionJob(const SyncSessionJob& job) { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 368 // 500, is likely to have occurred during commit). | 401 // 500, is likely to have occurred during commit). |
| 369 const bool work_to_do = | 402 const bool work_to_do = |
| 370 old_job.session->status_controller()->num_server_changes_remaining() > 0 | 403 old_job.session->status_controller()->num_server_changes_remaining() > 0 |
| 371 || old_job.session->status_controller()->unsynced_handles().size() > 0; | 404 || old_job.session->status_controller()->unsynced_handles().size() > 0; |
| 372 VLOG(1) << "syncer has work to do: " << work_to_do; | 405 VLOG(1) << "syncer has work to do: " << work_to_do; |
| 373 | 406 |
| 374 AdjustPolling(&old_job); | 407 AdjustPolling(&old_job); |
| 375 | 408 |
| 376 // TODO(tim): Old impl had special code if notifications disabled. Needed? | 409 // TODO(tim): Old impl had special code if notifications disabled. Needed? |
| 377 if (!work_to_do) { | 410 if (!work_to_do) { |
| 378 wait_interval_.reset(); // Success implies backoff relief. | 411 // Success implies backoff relief. Note that if this was a "one-off" job |
| 412 // (i.e. purpose == CLEAR_USER_DATA), if there was work_to_do before it | |
| 413 // ran this wont have changed, as jobs like this don't run a full sync | |
| 414 // cycle. So we don't need special code here. | |
| 415 wait_interval_.reset(); | |
| 379 return; | 416 return; |
| 380 } | 417 } |
| 381 | 418 |
| 382 if (old_job.session->source().updates_source == | 419 if (old_job.session->source().updates_source == |
| 383 GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) { | 420 GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION) { |
| 384 // We don't seem to have made forward progress. Start or extend backoff. | 421 // We don't seem to have made forward progress. Start or extend backoff. |
| 385 HandleConsecutiveContinuationError(old_job); | 422 HandleConsecutiveContinuationError(old_job); |
| 386 } else if (IsBackingOff()) { | 423 } else if (IsBackingOff()) { |
| 387 // We weren't continuing but we're in backoff; must have been a nudge. | 424 // We weren't continuing but we're in backoff; must have been a nudge. |
| 388 DCHECK_EQ(NUDGE, old_job.purpose); | 425 DCHECK_EQ(NUDGE, old_job.purpose); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 const ServerConnectionEvent& event) { | 572 const ServerConnectionEvent& event) { |
| 536 NOTIMPLEMENTED(); | 573 NOTIMPLEMENTED(); |
| 537 } | 574 } |
| 538 | 575 |
| 539 void SyncerThread::set_notifications_enabled(bool notifications_enabled) { | 576 void SyncerThread::set_notifications_enabled(bool notifications_enabled) { |
| 540 session_context_->set_notifications_enabled(notifications_enabled); | 577 session_context_->set_notifications_enabled(notifications_enabled); |
| 541 } | 578 } |
| 542 | 579 |
| 543 } // s3 | 580 } // s3 |
| 544 } // browser_sync | 581 } // browser_sync |
| OLD | NEW |