Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1096)

Side by Side Diff: components/sync/engine_impl/sync_scheduler_impl.cc

Issue 2828423002: [Sync] Sync types never recovers from throttle (Closed)
Patch Set: rebase Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "components/sync/engine_impl/sync_scheduler_impl.h" 5 #include "components/sync/engine_impl/sync_scheduler_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cstring> 8 #include <cstring>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 mode_(CONFIGURATION_MODE), 142 mode_(CONFIGURATION_MODE),
143 delay_provider_(delay_provider), 143 delay_provider_(delay_provider),
144 syncer_(syncer), 144 syncer_(syncer),
145 cycle_context_(context), 145 cycle_context_(context),
146 next_sync_cycle_job_priority_(NORMAL_PRIORITY), 146 next_sync_cycle_job_priority_(NORMAL_PRIORITY),
147 ignore_auth_credentials_(ignore_auth_credentials), 147 ignore_auth_credentials_(ignore_auth_credentials),
148 weak_ptr_factory_(this) {} 148 weak_ptr_factory_(this) {}
149 149
150 SyncSchedulerImpl::~SyncSchedulerImpl() { 150 SyncSchedulerImpl::~SyncSchedulerImpl() {
151 DCHECK(CalledOnValidThread()); 151 DCHECK(CalledOnValidThread());
152
152 Stop(); 153 Stop();
153 } 154 }
154 155
155 void SyncSchedulerImpl::OnCredentialsUpdated() { 156 void SyncSchedulerImpl::OnCredentialsUpdated() {
156 DCHECK(CalledOnValidThread()); 157 DCHECK(CalledOnValidThread());
157 158
158 if (HttpResponse::SYNC_AUTH_ERROR == 159 if (HttpResponse::SYNC_AUTH_ERROR ==
159 cycle_context_->connection_manager()->server_status()) { 160 cycle_context_->connection_manager()->server_status()) {
160 OnServerConnectionErrorFixed(); 161 OnServerConnectionErrorFixed();
161 } 162 }
162 } 163 }
163 164
164 void SyncSchedulerImpl::OnConnectionStatusChange() { 165 void SyncSchedulerImpl::OnConnectionStatusChange() {
166 DCHECK(CalledOnValidThread());
167
165 if (HttpResponse::CONNECTION_UNAVAILABLE == 168 if (HttpResponse::CONNECTION_UNAVAILABLE ==
166 cycle_context_->connection_manager()->server_status()) { 169 cycle_context_->connection_manager()->server_status()) {
167 // Optimistically assume that the connection is fixed and try 170 // Optimistically assume that the connection is fixed and try
168 // connecting. 171 // connecting.
169 OnServerConnectionErrorFixed(); 172 OnServerConnectionErrorFixed();
170 } 173 }
171 } 174 }
172 175
173 void SyncSchedulerImpl::OnServerConnectionErrorFixed() { 176 void SyncSchedulerImpl::OnServerConnectionErrorFixed() {
174 // There could be a pending nudge or configuration job in several cases: 177 // There could be a pending nudge or configuration job in several cases:
175 // 178 //
176 // 1. We're in exponential backoff. 179 // 1. We're in exponential backoff.
177 // 2. We're silenced / throttled. 180 // 2. We're silenced / throttled.
178 // 3. A nudge was saved previously due to not having a valid auth token. 181 // 3. A nudge was saved previously due to not having a valid auth token.
179 // 4. A nudge was scheduled + saved while in configuration mode. 182 // 4. A nudge was scheduled + saved while in configuration mode.
180 // 183 //
181 // In all cases except (2), we want to retry contacting the server. We 184 // In all cases except (2), we want to retry contacting the server. We
182 // call TryCanaryJob to achieve this, and note that nothing -- not even a 185 // call TryCanaryJob to achieve this, and note that nothing -- not even a
183 // canary job -- can bypass a THROTTLED WaitInterval. The only thing that 186 // canary job -- can bypass a THROTTLED WaitInterval. The only thing that
184 // has the authority to do that is the Unthrottle timer. 187 // has the authority to do that is the Unthrottle timer.
185 TryCanaryJob(); 188 TryCanaryJob();
186 } 189 }
187 190
188 void SyncSchedulerImpl::Start(Mode mode, base::Time last_poll_time) { 191 void SyncSchedulerImpl::Start(Mode mode, base::Time last_poll_time) {
189 DCHECK(CalledOnValidThread()); 192 DCHECK(CalledOnValidThread());
193
190 std::string thread_name = base::PlatformThread::GetName(); 194 std::string thread_name = base::PlatformThread::GetName();
191 if (thread_name.empty()) 195 if (thread_name.empty())
192 thread_name = "<Main thread>"; 196 thread_name = "<Main thread>";
193 SDVLOG(2) << "Start called from thread " << thread_name << " with mode " 197 SDVLOG(2) << "Start called from thread " << thread_name << " with mode "
194 << GetModeString(mode); 198 << GetModeString(mode);
195 if (!started_) { 199 if (!started_) {
196 started_ = true; 200 started_ = true;
197 SendInitialSnapshot(); 201 SendInitialSnapshot();
198 } 202 }
199 203
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 ModelTypeSet SyncSchedulerImpl::GetEnabledAndUnblockedTypes() { 236 ModelTypeSet SyncSchedulerImpl::GetEnabledAndUnblockedTypes() {
233 ModelTypeSet enabled_types = cycle_context_->GetEnabledTypes(); 237 ModelTypeSet enabled_types = cycle_context_->GetEnabledTypes();
234 ModelTypeSet enabled_protocol_types = 238 ModelTypeSet enabled_protocol_types =
235 Intersection(ProtocolTypes(), enabled_types); 239 Intersection(ProtocolTypes(), enabled_types);
236 ModelTypeSet blocked_types = nudge_tracker_.GetBlockedTypes(); 240 ModelTypeSet blocked_types = nudge_tracker_.GetBlockedTypes();
237 return Difference(enabled_protocol_types, blocked_types); 241 return Difference(enabled_protocol_types, blocked_types);
238 } 242 }
239 243
240 void SyncSchedulerImpl::SendInitialSnapshot() { 244 void SyncSchedulerImpl::SendInitialSnapshot() {
241 DCHECK(CalledOnValidThread()); 245 DCHECK(CalledOnValidThread());
246
242 SyncCycleEvent event(SyncCycleEvent::STATUS_CHANGED); 247 SyncCycleEvent event(SyncCycleEvent::STATUS_CHANGED);
243 event.snapshot = SyncCycle(cycle_context_, this).TakeSnapshot(); 248 event.snapshot = SyncCycle(cycle_context_, this).TakeSnapshot();
244 for (auto& observer : *cycle_context_->listeners()) 249 for (auto& observer : *cycle_context_->listeners())
245 observer.OnSyncCycleEvent(event); 250 observer.OnSyncCycleEvent(event);
246 } 251 }
247 252
248 void SyncSchedulerImpl::ScheduleConfiguration( 253 void SyncSchedulerImpl::ScheduleConfiguration(
249 const ConfigurationParams& params) { 254 const ConfigurationParams& params) {
250 DCHECK(CalledOnValidThread()); 255 DCHECK(CalledOnValidThread());
251 DCHECK(IsConfigRelatedUpdateSourceValue(params.source)); 256 DCHECK(IsConfigRelatedUpdateSourceValue(params.source));
(...skipping 15 matching lines...) Expand all
267 params.ready_task.Run(); 272 params.ready_task.Run();
268 } 273 }
269 } 274 }
270 275
271 void SyncSchedulerImpl::ScheduleClearServerData(const ClearParams& params) { 276 void SyncSchedulerImpl::ScheduleClearServerData(const ClearParams& params) {
272 DCHECK(CalledOnValidThread()); 277 DCHECK(CalledOnValidThread());
273 DCHECK_EQ(CLEAR_SERVER_DATA_MODE, mode_); 278 DCHECK_EQ(CLEAR_SERVER_DATA_MODE, mode_);
274 DCHECK(!pending_configure_params_); 279 DCHECK(!pending_configure_params_);
275 DCHECK(!params.report_success_task.is_null()); 280 DCHECK(!params.report_success_task.is_null());
276 CHECK(started_) << "Scheduler must be running to clear."; 281 CHECK(started_) << "Scheduler must be running to clear.";
282
277 pending_clear_params_ = base::MakeUnique<ClearParams>(params); 283 pending_clear_params_ = base::MakeUnique<ClearParams>(params);
278 TrySyncCycleJob(); 284 TrySyncCycleJob();
279 } 285 }
280 286
281 bool SyncSchedulerImpl::CanRunJobNow(JobPriority priority) { 287 bool SyncSchedulerImpl::CanRunJobNow(JobPriority priority) {
282 DCHECK(CalledOnValidThread()); 288 DCHECK(CalledOnValidThread());
289
283 if (IsCurrentlyThrottled()) { 290 if (IsCurrentlyThrottled()) {
284 SDVLOG(1) << "Unable to run a job because we're throttled."; 291 SDVLOG(1) << "Unable to run a job because we're throttled.";
285 return false; 292 return false;
286 } 293 }
287 294
288 if (IsBackingOff() && priority != CANARY_PRIORITY) { 295 if (IsBackingOff() && priority != CANARY_PRIORITY) {
289 SDVLOG(1) << "Unable to run a job because we're backing off."; 296 SDVLOG(1) << "Unable to run a job because we're backing off.";
290 return false; 297 return false;
291 } 298 }
292 299
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 << "Dropping nudge, scheduler is not running."; 391 << "Dropping nudge, scheduler is not running.";
385 return; 392 return;
386 } 393 }
387 394
388 SDVLOG_LOC(nudge_location, 2) << "In ScheduleNudgeImpl with delay " 395 SDVLOG_LOC(nudge_location, 2) << "In ScheduleNudgeImpl with delay "
389 << delay.InMilliseconds() << " ms"; 396 << delay.InMilliseconds() << " ms";
390 397
391 if (!CanRunNudgeJobNow(NORMAL_PRIORITY)) 398 if (!CanRunNudgeJobNow(NORMAL_PRIORITY))
392 return; 399 return;
393 400
394 TimeTicks incoming_run_time = TimeTicks::Now() + delay; 401 if (!IsEarlierThanCurrentPendingJob(delay)) {
395 if (pending_wakeup_timer_.IsRunning() &&
396 (pending_wakeup_timer_.desired_run_time() < incoming_run_time)) {
397 // Old job arrives sooner than this one. Don't reschedule it. 402 // Old job arrives sooner than this one. Don't reschedule it.
398 return; 403 return;
399 } 404 }
400 405
401 // Either there is no existing nudge in flight or the incoming nudge should be 406 // Either there is no existing nudge in flight or the incoming nudge should be
402 // made to arrive first (preempt) the existing nudge. We reschedule in either 407 // made to arrive first (preempt) the existing nudge. We reschedule in either
403 // case. 408 // case.
404 SDVLOG_LOC(nudge_location, 2) << "Scheduling a nudge with " 409 SDVLOG_LOC(nudge_location, 2) << "Scheduling a nudge with "
405 << delay.InMilliseconds() << " ms delay"; 410 << delay.InMilliseconds() << " ms delay";
406 pending_wakeup_timer_.Start( 411 pending_wakeup_timer_.Start(
407 nudge_location, delay, base::Bind(&SyncSchedulerImpl::PerformDelayedNudge, 412 nudge_location, delay, base::Bind(&SyncSchedulerImpl::PerformDelayedNudge,
408 weak_ptr_factory_.GetWeakPtr())); 413 weak_ptr_factory_.GetWeakPtr()));
409 } 414 }
410 415
411 const char* SyncSchedulerImpl::GetModeString(SyncScheduler::Mode mode) { 416 const char* SyncSchedulerImpl::GetModeString(SyncScheduler::Mode mode) {
412 switch (mode) { 417 switch (mode) {
413 ENUM_CASE(CONFIGURATION_MODE); 418 ENUM_CASE(CONFIGURATION_MODE);
414 ENUM_CASE(CLEAR_SERVER_DATA_MODE); 419 ENUM_CASE(CLEAR_SERVER_DATA_MODE);
415 ENUM_CASE(NORMAL_MODE); 420 ENUM_CASE(NORMAL_MODE);
416 } 421 }
417 return ""; 422 return "";
418 } 423 }
419 424
420 void SyncSchedulerImpl::SetDefaultNudgeDelay(TimeDelta delay_ms) { 425 void SyncSchedulerImpl::SetDefaultNudgeDelay(TimeDelta delay_ms) {
421 DCHECK(CalledOnValidThread()); 426 DCHECK(CalledOnValidThread());
427
422 nudge_tracker_.SetDefaultNudgeDelay(delay_ms); 428 nudge_tracker_.SetDefaultNudgeDelay(delay_ms);
423 } 429 }
424 430
425 void SyncSchedulerImpl::DoNudgeSyncCycleJob(JobPriority priority) { 431 void SyncSchedulerImpl::DoNudgeSyncCycleJob(JobPriority priority) {
426 DCHECK(CalledOnValidThread()); 432 DCHECK(CalledOnValidThread());
427 DCHECK(CanRunNudgeJobNow(priority)); 433 DCHECK(CanRunNudgeJobNow(priority));
428 434
429 DVLOG(2) << "Will run normal mode sync cycle with types " 435 DVLOG(2) << "Will run normal mode sync cycle with types "
430 << ModelTypeSetToString(GetEnabledAndUnblockedTypes()); 436 << ModelTypeSetToString(GetEnabledAndUnblockedTypes());
431 SyncCycle cycle(cycle_context_, this); 437 SyncCycle cycle(cycle_context_, this);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 SDVLOG(2) << "Sync cycle failed. Will back off for " 530 SDVLOG(2) << "Sync cycle failed. Will back off for "
525 << wait_interval_->length.InMilliseconds() << "ms."; 531 << wait_interval_->length.InMilliseconds() << "ms.";
526 } else { 532 } else {
527 // Increase our backoff interval and schedule another retry. 533 // Increase our backoff interval and schedule another retry.
528 TimeDelta length = delay_provider_->GetDelay(wait_interval_->length); 534 TimeDelta length = delay_provider_->GetDelay(wait_interval_->length);
529 wait_interval_ = base::MakeUnique<WaitInterval>( 535 wait_interval_ = base::MakeUnique<WaitInterval>(
530 WaitInterval::EXPONENTIAL_BACKOFF, length); 536 WaitInterval::EXPONENTIAL_BACKOFF, length);
531 SDVLOG(2) << "Sync cycle failed. Will back off for " 537 SDVLOG(2) << "Sync cycle failed. Will back off for "
532 << wait_interval_->length.InMilliseconds() << "ms."; 538 << wait_interval_->length.InMilliseconds() << "ms.";
533 } 539 }
534 RestartWaiting();
535 } 540 }
536 541
537 void SyncSchedulerImpl::DoPollSyncCycleJob() { 542 void SyncSchedulerImpl::DoPollSyncCycleJob() {
538 SDVLOG(2) << "Polling with types " 543 SDVLOG(2) << "Polling with types "
539 << ModelTypeSetToString(GetEnabledAndUnblockedTypes()); 544 << ModelTypeSetToString(GetEnabledAndUnblockedTypes());
540 SyncCycle cycle(cycle_context_, this); 545 SyncCycle cycle(cycle_context_, this);
541 bool success = syncer_->PollSyncShare(GetEnabledAndUnblockedTypes(), &cycle); 546 bool success = syncer_->PollSyncShare(GetEnabledAndUnblockedTypes(), &cycle);
542 547
543 // Only restart the timer if the poll succeeded. Otherwise rely on normal 548 // Only restart the timer if the poll succeeded. Otherwise rely on normal
544 // failure handling to retry with backoff. 549 // failure handling to retry with backoff.
545 if (success) { 550 if (success) {
546 AdjustPolling(FORCE_RESET); 551 AdjustPolling(FORCE_RESET);
547 HandleSuccess(); 552 HandleSuccess();
548 } else { 553 } else {
549 HandleFailure(cycle.status_controller().model_neutral_state()); 554 HandleFailure(cycle.status_controller().model_neutral_state());
550 } 555 }
551 } 556 }
552 557
553 void SyncSchedulerImpl::UpdateNudgeTimeRecords(ModelTypeSet types) { 558 void SyncSchedulerImpl::UpdateNudgeTimeRecords(ModelTypeSet types) {
554 DCHECK(CalledOnValidThread()); 559 DCHECK(CalledOnValidThread());
560
555 TimeTicks now = TimeTicks::Now(); 561 TimeTicks now = TimeTicks::Now();
556 // Update timing information for how often datatypes are triggering nudges. 562 // Update timing information for how often datatypes are triggering nudges.
557 for (ModelTypeSet::Iterator iter = types.First(); iter.Good(); iter.Inc()) { 563 for (ModelTypeSet::Iterator iter = types.First(); iter.Good(); iter.Inc()) {
558 TimeTicks previous = last_local_nudges_by_model_type_[iter.Get()]; 564 TimeTicks previous = last_local_nudges_by_model_type_[iter.Get()];
559 last_local_nudges_by_model_type_[iter.Get()] = now; 565 last_local_nudges_by_model_type_[iter.Get()] = now;
560 if (previous.is_null()) 566 if (previous.is_null())
561 continue; 567 continue;
562 568
563 #define PER_DATA_TYPE_MACRO(type_str) \ 569 #define PER_DATA_TYPE_MACRO(type_str) \
564 SYNC_FREQ_HISTOGRAM("Sync.Freq" type_str, now - previous); 570 SYNC_FREQ_HISTOGRAM("Sync.Freq" type_str, now - previous);
565 SYNC_DATA_TYPE_HISTOGRAM(iter.Get()); 571 SYNC_DATA_TYPE_HISTOGRAM(iter.Get());
566 #undef PER_DATA_TYPE_MACRO 572 #undef PER_DATA_TYPE_MACRO
567 } 573 }
568 } 574 }
569 575
570 TimeDelta SyncSchedulerImpl::GetPollInterval() { 576 TimeDelta SyncSchedulerImpl::GetPollInterval() {
571 return (!cycle_context_->notifications_enabled() || 577 return (!cycle_context_->notifications_enabled() ||
572 !cycle_context_->ShouldFetchUpdatesBeforeCommit()) 578 !cycle_context_->ShouldFetchUpdatesBeforeCommit())
573 ? syncer_short_poll_interval_seconds_ 579 ? syncer_short_poll_interval_seconds_
574 : syncer_long_poll_interval_seconds_; 580 : syncer_long_poll_interval_seconds_;
575 } 581 }
576 582
577 void SyncSchedulerImpl::AdjustPolling(PollAdjustType type) { 583 void SyncSchedulerImpl::AdjustPolling(PollAdjustType type) {
578 DCHECK(CalledOnValidThread()); 584 DCHECK(CalledOnValidThread());
585
579 if (!started_) 586 if (!started_)
580 return; 587 return;
581 588
582 TimeDelta poll_interval = GetPollInterval(); 589 TimeDelta poll_interval = GetPollInterval();
583 TimeDelta poll_delay = poll_interval; 590 TimeDelta poll_delay = poll_interval;
584 const TimeTicks now = TimeTicks::Now(); 591 const TimeTicks now = TimeTicks::Now();
585 592
586 if (type == UPDATE_INTERVAL) { 593 if (type == UPDATE_INTERVAL) {
587 if (!last_poll_reset_.is_null()) { 594 if (!last_poll_reset_.is_null()) {
588 // Override the delay based on the last successful poll time (if it was 595 // Override the delay based on the last successful poll time (if it was
(...skipping 23 matching lines...) Expand all
612 SDVLOG(1) << "Updating polling delay to " << poll_delay.InMinutes() 619 SDVLOG(1) << "Updating polling delay to " << poll_delay.InMinutes()
613 << " minutes."; 620 << " minutes.";
614 621
615 // Adjust poll rate. Start will reset the timer if it was already running. 622 // Adjust poll rate. Start will reset the timer if it was already running.
616 poll_timer_.Start(FROM_HERE, poll_delay, this, 623 poll_timer_.Start(FROM_HERE, poll_delay, this,
617 &SyncSchedulerImpl::PollTimerCallback); 624 &SyncSchedulerImpl::PollTimerCallback);
618 } 625 }
619 626
620 void SyncSchedulerImpl::RestartWaiting() { 627 void SyncSchedulerImpl::RestartWaiting() {
621 if (wait_interval_.get()) { 628 if (wait_interval_.get()) {
622 // Global throttling or backoff 629 // Global throttling or backoff.
630 if (!IsEarlierThanCurrentPendingJob(wait_interval_->length)) {
631 // We check here because if we do not check here, and we already scheduled
632 // a global unblock job, we will schedule another unblock job which has
633 // same waiting time, then the job will be run later than expected. Even
634 // we did not schedule an unblock job when code reach here, it is ok since
635 // |TrySyncCycleJobImpl| will call this function after the scheduled job
636 // got run.
637 return;
638 }
623 NotifyRetryTime(base::Time::Now() + wait_interval_->length); 639 NotifyRetryTime(base::Time::Now() + wait_interval_->length);
624 SDVLOG(2) << "Starting WaitInterval timer of length " 640 SDVLOG(2) << "Starting WaitInterval timer of length "
625 << wait_interval_->length.InMilliseconds() << "ms."; 641 << wait_interval_->length.InMilliseconds() << "ms.";
626 if (wait_interval_->mode == WaitInterval::THROTTLED) { 642 if (wait_interval_->mode == WaitInterval::THROTTLED) {
627 pending_wakeup_timer_.Start(FROM_HERE, wait_interval_->length, 643 pending_wakeup_timer_.Start(FROM_HERE, wait_interval_->length,
628 base::Bind(&SyncSchedulerImpl::Unthrottle, 644 base::Bind(&SyncSchedulerImpl::Unthrottle,
629 weak_ptr_factory_.GetWeakPtr())); 645 weak_ptr_factory_.GetWeakPtr()));
630 } else { 646 } else {
631 pending_wakeup_timer_.Start( 647 pending_wakeup_timer_.Start(
632 FROM_HERE, wait_interval_->length, 648 FROM_HERE, wait_interval_->length,
633 base::Bind(&SyncSchedulerImpl::ExponentialBackoffRetry, 649 base::Bind(&SyncSchedulerImpl::ExponentialBackoffRetry,
634 weak_ptr_factory_.GetWeakPtr())); 650 weak_ptr_factory_.GetWeakPtr()));
635 } 651 }
636 } else if (nudge_tracker_.IsAnyTypeBlocked()) { 652 } else if (nudge_tracker_.IsAnyTypeBlocked()) {
637 // Per-datatype throttled or backed off. 653 // Per-datatype throttled or backed off.
638 TimeDelta time_until_next_unblock = 654 TimeDelta time_until_next_unblock =
639 nudge_tracker_.GetTimeUntilNextUnblock(); 655 nudge_tracker_.GetTimeUntilNextUnblock();
656 if (!IsEarlierThanCurrentPendingJob(time_until_next_unblock)) {
657 return;
658 }
640 pending_wakeup_timer_.Start(FROM_HERE, time_until_next_unblock, 659 pending_wakeup_timer_.Start(FROM_HERE, time_until_next_unblock,
641 base::Bind(&SyncSchedulerImpl::OnTypesUnblocked, 660 base::Bind(&SyncSchedulerImpl::OnTypesUnblocked,
642 weak_ptr_factory_.GetWeakPtr())); 661 weak_ptr_factory_.GetWeakPtr()));
643 } 662 }
644 } 663 }
645 664
646 void SyncSchedulerImpl::Stop() { 665 void SyncSchedulerImpl::Stop() {
647 DCHECK(CalledOnValidThread()); 666 DCHECK(CalledOnValidThread());
648 SDVLOG(2) << "Stop called"; 667 SDVLOG(2) << "Stop called";
649 668
(...skipping 19 matching lines...) Expand all
669 688
670 void SyncSchedulerImpl::TrySyncCycleJob() { 689 void SyncSchedulerImpl::TrySyncCycleJob() {
671 // Post call to TrySyncCycleJobImpl on current thread. Later request for 690 // Post call to TrySyncCycleJobImpl on current thread. Later request for
672 // access token will be here. 691 // access token will be here.
673 base::ThreadTaskRunnerHandle::Get()->PostTask( 692 base::ThreadTaskRunnerHandle::Get()->PostTask(
674 FROM_HERE, base::Bind(&SyncSchedulerImpl::TrySyncCycleJobImpl, 693 FROM_HERE, base::Bind(&SyncSchedulerImpl::TrySyncCycleJobImpl,
675 weak_ptr_factory_.GetWeakPtr())); 694 weak_ptr_factory_.GetWeakPtr()));
676 } 695 }
677 696
678 void SyncSchedulerImpl::TrySyncCycleJobImpl() { 697 void SyncSchedulerImpl::TrySyncCycleJobImpl() {
698 DCHECK(CalledOnValidThread());
699
679 JobPriority priority = next_sync_cycle_job_priority_; 700 JobPriority priority = next_sync_cycle_job_priority_;
680 next_sync_cycle_job_priority_ = NORMAL_PRIORITY; 701 next_sync_cycle_job_priority_ = NORMAL_PRIORITY;
681 702
682 nudge_tracker_.SetSyncCycleStartTime(TimeTicks::Now()); 703 nudge_tracker_.SetSyncCycleStartTime(TimeTicks::Now());
683 704
684 DCHECK(CalledOnValidThread());
685 if (mode_ == CONFIGURATION_MODE) { 705 if (mode_ == CONFIGURATION_MODE) {
686 if (pending_configure_params_) { 706 if (pending_configure_params_) {
687 SDVLOG(2) << "Found pending configure job"; 707 SDVLOG(2) << "Found pending configure job";
688 DoConfigurationSyncCycleJob(priority); 708 DoConfigurationSyncCycleJob(priority);
689 } 709 }
690 } else if (mode_ == CLEAR_SERVER_DATA_MODE) { 710 } else if (mode_ == CLEAR_SERVER_DATA_MODE) {
691 if (pending_clear_params_) { 711 if (pending_clear_params_) {
692 DoClearServerDataSyncCycleJob(priority); 712 DoClearServerDataSyncCycleJob(priority);
693 } 713 }
694 } else if (CanRunNudgeJobNow(priority)) { 714 } else if (CanRunNudgeJobNow(priority)) {
695 if (nudge_tracker_.IsSyncRequired()) { 715 if (nudge_tracker_.IsSyncRequired()) {
696 SDVLOG(2) << "Found pending nudge job"; 716 SDVLOG(2) << "Found pending nudge job";
697 DoNudgeSyncCycleJob(priority); 717 DoNudgeSyncCycleJob(priority);
698 } else if (((TimeTicks::Now() - last_poll_reset_) >= GetPollInterval())) { 718 } else if (((TimeTicks::Now() - last_poll_reset_) >= GetPollInterval())) {
699 SDVLOG(2) << "Found pending poll"; 719 SDVLOG(2) << "Found pending poll";
700 DoPollSyncCycleJob(); 720 DoPollSyncCycleJob();
701 } 721 }
702 } else { 722 } else {
703 // We must be in an error state. Transitioning out of each of these 723 // We must be in an error state. Transitioning out of each of these
704 // error states should trigger a canary job. 724 // error states should trigger a canary job.
705 DCHECK(IsCurrentlyThrottled() || IsBackingOff() || 725 DCHECK(IsCurrentlyThrottled() || IsBackingOff() ||
706 cycle_context_->connection_manager()->HasInvalidAuthToken()); 726 cycle_context_->connection_manager()->HasInvalidAuthToken());
707 } 727 }
708 728
709 if (IsBackingOff() && !pending_wakeup_timer_.IsRunning()) { 729 RestartWaiting();
710 // If we succeeded, our wait interval would have been cleared. If it hasn't
711 // been cleared, then we should increase our backoff interval and schedule
712 // another retry.
713 TimeDelta length = delay_provider_->GetDelay(wait_interval_->length);
714 wait_interval_ = base::MakeUnique<WaitInterval>(
715 WaitInterval::EXPONENTIAL_BACKOFF, length);
716 SDVLOG(2) << "Sync cycle failed. Will back off for "
717 << wait_interval_->length.InMilliseconds() << "ms.";
718 RestartWaiting();
719 }
720 } 730 }
721 731
722 void SyncSchedulerImpl::PollTimerCallback() { 732 void SyncSchedulerImpl::PollTimerCallback() {
723 DCHECK(CalledOnValidThread()); 733 DCHECK(CalledOnValidThread());
724 CHECK(!syncer_->IsSyncing()); 734 CHECK(!syncer_->IsSyncing());
725 735
726 TrySyncCycleJob(); 736 TrySyncCycleJob();
727 } 737 }
728 738
729 void SyncSchedulerImpl::RetryTimerCallback() { 739 void SyncSchedulerImpl::RetryTimerCallback() {
(...skipping 12 matching lines...) Expand all
742 // We treat this as a 'canary' in the sense that it was originally scheduled 752 // We treat this as a 'canary' in the sense that it was originally scheduled
743 // to run some time ago, failed, and we now want to retry, versus a job that 753 // to run some time ago, failed, and we now want to retry, versus a job that
744 // was just created (e.g via ScheduleNudgeImpl). The main implication is 754 // was just created (e.g via ScheduleNudgeImpl). The main implication is
745 // that we're careful to update routing info (etc) with such potentially 755 // that we're careful to update routing info (etc) with such potentially
746 // stale canary jobs. 756 // stale canary jobs.
747 TryCanaryJob(); 757 TryCanaryJob();
748 } 758 }
749 759
750 void SyncSchedulerImpl::OnTypesUnblocked() { 760 void SyncSchedulerImpl::OnTypesUnblocked() {
751 DCHECK(CalledOnValidThread()); 761 DCHECK(CalledOnValidThread());
762
752 nudge_tracker_.UpdateTypeThrottlingAndBackoffState(); 763 nudge_tracker_.UpdateTypeThrottlingAndBackoffState();
753 NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes()); 764 NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes());
754 765
755 RestartWaiting();
756
757 // Maybe this is a good time to run a nudge job. Let's try it. 766 // Maybe this is a good time to run a nudge job. Let's try it.
767 // If not a good time, reschedule a new run.
758 if (nudge_tracker_.IsSyncRequired() && CanRunNudgeJobNow(NORMAL_PRIORITY)) 768 if (nudge_tracker_.IsSyncRequired() && CanRunNudgeJobNow(NORMAL_PRIORITY))
759 TrySyncCycleJob(); 769 TrySyncCycleJob();
770 else
771 RestartWaiting();
760 } 772 }
761 773
762 void SyncSchedulerImpl::PerformDelayedNudge() { 774 void SyncSchedulerImpl::PerformDelayedNudge() {
763 // Circumstances may have changed since we scheduled this delayed nudge. 775 // Circumstances may have changed since we scheduled this delayed nudge.
764 // We must check to see if it's OK to run the job before we do so. 776 // We must check to see if it's OK to run the job before we do so.
765 if (CanRunNudgeJobNow(NORMAL_PRIORITY)) 777 if (CanRunNudgeJobNow(NORMAL_PRIORITY))
766 TrySyncCycleJob(); 778 TrySyncCycleJob();
767 779
768 // We're not responsible for setting up any retries here. The functions that 780 // We're not responsible for setting up any retries here. The functions that
769 // first put us into a state that prevents successful sync cycles (eg. global 781 // first put us into a state that prevents successful sync cycles (eg. global
(...skipping 26 matching lines...) Expand all
796 } 808 }
797 809
798 for (auto& observer : *cycle_context_->listeners()) { 810 for (auto& observer : *cycle_context_->listeners()) {
799 observer.OnThrottledTypesChanged(throttled_types); 811 observer.OnThrottledTypesChanged(throttled_types);
800 observer.OnBackedOffTypesChanged(backed_off_types); 812 observer.OnBackedOffTypesChanged(backed_off_types);
801 } 813 }
802 } 814 }
803 815
804 bool SyncSchedulerImpl::IsBackingOff() const { 816 bool SyncSchedulerImpl::IsBackingOff() const {
805 DCHECK(CalledOnValidThread()); 817 DCHECK(CalledOnValidThread());
818
806 return wait_interval_.get() && 819 return wait_interval_.get() &&
807 wait_interval_->mode == WaitInterval::EXPONENTIAL_BACKOFF; 820 wait_interval_->mode == WaitInterval::EXPONENTIAL_BACKOFF;
808 } 821 }
809 822
810 void SyncSchedulerImpl::OnThrottled(const TimeDelta& throttle_duration) { 823 void SyncSchedulerImpl::OnThrottled(const TimeDelta& throttle_duration) {
811 DCHECK(CalledOnValidThread()); 824 DCHECK(CalledOnValidThread());
825
812 wait_interval_ = base::MakeUnique<WaitInterval>(WaitInterval::THROTTLED, 826 wait_interval_ = base::MakeUnique<WaitInterval>(WaitInterval::THROTTLED,
813 throttle_duration); 827 throttle_duration);
814 NotifyRetryTime(base::Time::Now() + wait_interval_->length); 828 NotifyRetryTime(base::Time::Now() + wait_interval_->length);
815 829
816 for (auto& observer : *cycle_context_->listeners()) { 830 for (auto& observer : *cycle_context_->listeners()) {
817 observer.OnThrottledTypesChanged(ModelTypeSet::All()); 831 observer.OnThrottledTypesChanged(ModelTypeSet::All());
818 } 832 }
819 } 833 }
820 834
821 void SyncSchedulerImpl::OnTypesThrottled(ModelTypeSet types, 835 void SyncSchedulerImpl::OnTypesThrottled(ModelTypeSet types,
822 const TimeDelta& throttle_duration) { 836 const TimeDelta& throttle_duration) {
837 DCHECK(CalledOnValidThread());
838
823 TimeTicks now = TimeTicks::Now(); 839 TimeTicks now = TimeTicks::Now();
824 840
825 SDVLOG(1) << "Throttling " << ModelTypeSetToString(types) << " for " 841 SDVLOG(1) << "Throttling " << ModelTypeSetToString(types) << " for "
826 << throttle_duration.InMinutes() << " minutes."; 842 << throttle_duration.InMinutes() << " minutes.";
827 843
828 nudge_tracker_.SetTypesThrottledUntil(types, throttle_duration, now); 844 nudge_tracker_.SetTypesThrottledUntil(types, throttle_duration, now);
829 RestartWaiting();
830 NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes()); 845 NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes());
831 } 846 }
832 847
833 void SyncSchedulerImpl::OnTypesBackedOff(ModelTypeSet types) { 848 void SyncSchedulerImpl::OnTypesBackedOff(ModelTypeSet types) {
849 DCHECK(CalledOnValidThread());
850
834 TimeTicks now = TimeTicks::Now(); 851 TimeTicks now = TimeTicks::Now();
835 852
836 for (ModelTypeSet::Iterator type = types.First(); type.Good(); type.Inc()) { 853 for (ModelTypeSet::Iterator type = types.First(); type.Good(); type.Inc()) {
837 TimeDelta last_backoff_time = 854 TimeDelta last_backoff_time =
838 TimeDelta::FromSeconds(kInitialBackoffRetrySeconds); 855 TimeDelta::FromSeconds(kInitialBackoffRetrySeconds);
839 if (nudge_tracker_.GetTypeBlockingMode(type.Get()) == 856 if (nudge_tracker_.GetTypeBlockingMode(type.Get()) ==
840 WaitInterval::EXPONENTIAL_BACKOFF_RETRYING) { 857 WaitInterval::EXPONENTIAL_BACKOFF_RETRYING) {
841 last_backoff_time = nudge_tracker_.GetTypeLastBackoffInterval(type.Get()); 858 last_backoff_time = nudge_tracker_.GetTypeLastBackoffInterval(type.Get());
842 } 859 }
843 860
844 TimeDelta length = delay_provider_->GetDelay(last_backoff_time); 861 TimeDelta length = delay_provider_->GetDelay(last_backoff_time);
845 nudge_tracker_.SetTypeBackedOff(type.Get(), length, now); 862 nudge_tracker_.SetTypeBackedOff(type.Get(), length, now);
846 SDVLOG(1) << "Backing off " << ModelTypeToString(type.Get()) << " for " 863 SDVLOG(1) << "Backing off " << ModelTypeToString(type.Get()) << " for "
847 << length.InSeconds() << " second."; 864 << length.InSeconds() << " second.";
848 } 865 }
849 RestartWaiting();
850 NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes()); 866 NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes());
851 } 867 }
852 868
853 bool SyncSchedulerImpl::IsCurrentlyThrottled() { 869 bool SyncSchedulerImpl::IsCurrentlyThrottled() {
854 DCHECK(CalledOnValidThread()); 870 DCHECK(CalledOnValidThread());
871
855 return wait_interval_.get() && 872 return wait_interval_.get() &&
856 wait_interval_->mode == WaitInterval::THROTTLED; 873 wait_interval_->mode == WaitInterval::THROTTLED;
857 } 874 }
858 875
859 void SyncSchedulerImpl::OnReceivedShortPollIntervalUpdate( 876 void SyncSchedulerImpl::OnReceivedShortPollIntervalUpdate(
860 const TimeDelta& new_interval) { 877 const TimeDelta& new_interval) {
861 DCHECK(CalledOnValidThread()); 878 DCHECK(CalledOnValidThread());
879
862 if (new_interval == syncer_short_poll_interval_seconds_) 880 if (new_interval == syncer_short_poll_interval_seconds_)
863 return; 881 return;
864 SDVLOG(1) << "Updating short poll interval to " << new_interval.InMinutes() 882 SDVLOG(1) << "Updating short poll interval to " << new_interval.InMinutes()
865 << " minutes."; 883 << " minutes.";
866 syncer_short_poll_interval_seconds_ = new_interval; 884 syncer_short_poll_interval_seconds_ = new_interval;
867 AdjustPolling(UPDATE_INTERVAL); 885 AdjustPolling(UPDATE_INTERVAL);
868 } 886 }
869 887
870 void SyncSchedulerImpl::OnReceivedLongPollIntervalUpdate( 888 void SyncSchedulerImpl::OnReceivedLongPollIntervalUpdate(
871 const TimeDelta& new_interval) { 889 const TimeDelta& new_interval) {
872 DCHECK(CalledOnValidThread()); 890 DCHECK(CalledOnValidThread());
891
873 if (new_interval == syncer_long_poll_interval_seconds_) 892 if (new_interval == syncer_long_poll_interval_seconds_)
874 return; 893 return;
875 SDVLOG(1) << "Updating long poll interval to " << new_interval.InMinutes() 894 SDVLOG(1) << "Updating long poll interval to " << new_interval.InMinutes()
876 << " minutes."; 895 << " minutes.";
877 syncer_long_poll_interval_seconds_ = new_interval; 896 syncer_long_poll_interval_seconds_ = new_interval;
878 AdjustPolling(UPDATE_INTERVAL); 897 AdjustPolling(UPDATE_INTERVAL);
879 } 898 }
880 899
881 void SyncSchedulerImpl::OnReceivedCustomNudgeDelays( 900 void SyncSchedulerImpl::OnReceivedCustomNudgeDelays(
882 const std::map<ModelType, TimeDelta>& nudge_delays) { 901 const std::map<ModelType, TimeDelta>& nudge_delays) {
883 DCHECK(CalledOnValidThread()); 902 DCHECK(CalledOnValidThread());
903
884 nudge_tracker_.OnReceivedCustomNudgeDelays(nudge_delays); 904 nudge_tracker_.OnReceivedCustomNudgeDelays(nudge_delays);
885 } 905 }
886 906
887 void SyncSchedulerImpl::OnReceivedClientInvalidationHintBufferSize(int size) { 907 void SyncSchedulerImpl::OnReceivedClientInvalidationHintBufferSize(int size) {
908 DCHECK(CalledOnValidThread());
909
888 if (size > 0) 910 if (size > 0)
889 nudge_tracker_.SetHintBufferSize(size); 911 nudge_tracker_.SetHintBufferSize(size);
890 else 912 else
891 NOTREACHED() << "Hint buffer size should be > 0."; 913 NOTREACHED() << "Hint buffer size should be > 0.";
892 } 914 }
893 915
894 void SyncSchedulerImpl::OnSyncProtocolError( 916 void SyncSchedulerImpl::OnSyncProtocolError(
895 const SyncProtocolError& sync_protocol_error) { 917 const SyncProtocolError& sync_protocol_error) {
896 DCHECK(CalledOnValidThread()); 918 DCHECK(CalledOnValidThread());
919
897 if (ShouldRequestEarlyExit(sync_protocol_error)) { 920 if (ShouldRequestEarlyExit(sync_protocol_error)) {
898 SDVLOG(2) << "Sync Scheduler requesting early exit."; 921 SDVLOG(2) << "Sync Scheduler requesting early exit.";
899 Stop(); 922 Stop();
900 } 923 }
901 if (IsActionableError(sync_protocol_error)) { 924 if (IsActionableError(sync_protocol_error)) {
902 SDVLOG(2) << "OnActionableError"; 925 SDVLOG(2) << "OnActionableError";
903 for (auto& observer : *cycle_context_->listeners()) 926 for (auto& observer : *cycle_context_->listeners())
904 observer.OnActionableError(sync_protocol_error); 927 observer.OnActionableError(sync_protocol_error);
905 } 928 }
906 } 929 }
907 930
908 void SyncSchedulerImpl::OnReceivedGuRetryDelay(const TimeDelta& delay) { 931 void SyncSchedulerImpl::OnReceivedGuRetryDelay(const TimeDelta& delay) {
932 DCHECK(CalledOnValidThread());
933
909 nudge_tracker_.SetNextRetryTime(TimeTicks::Now() + delay); 934 nudge_tracker_.SetNextRetryTime(TimeTicks::Now() + delay);
910 retry_timer_.Start(FROM_HERE, delay, this, 935 retry_timer_.Start(FROM_HERE, delay, this,
911 &SyncSchedulerImpl::RetryTimerCallback); 936 &SyncSchedulerImpl::RetryTimerCallback);
912 } 937 }
913 938
914 void SyncSchedulerImpl::OnReceivedMigrationRequest(ModelTypeSet types) { 939 void SyncSchedulerImpl::OnReceivedMigrationRequest(ModelTypeSet types) {
940 DCHECK(CalledOnValidThread());
941
915 for (auto& observer : *cycle_context_->listeners()) 942 for (auto& observer : *cycle_context_->listeners())
916 observer.OnMigrationRequested(types); 943 observer.OnMigrationRequested(types);
917 } 944 }
918 945
919 void SyncSchedulerImpl::SetNotificationsEnabled(bool notifications_enabled) { 946 void SyncSchedulerImpl::SetNotificationsEnabled(bool notifications_enabled) {
920 DCHECK(CalledOnValidThread()); 947 DCHECK(CalledOnValidThread());
948
921 cycle_context_->set_notifications_enabled(notifications_enabled); 949 cycle_context_->set_notifications_enabled(notifications_enabled);
922 if (notifications_enabled) 950 if (notifications_enabled)
923 nudge_tracker_.OnInvalidationsEnabled(); 951 nudge_tracker_.OnInvalidationsEnabled();
924 else 952 else
925 nudge_tracker_.OnInvalidationsDisabled(); 953 nudge_tracker_.OnInvalidationsDisabled();
926 } 954 }
927 955
956 bool SyncSchedulerImpl::IsEarlierThanCurrentPendingJob(const TimeDelta& delay) {
957 TimeTicks incoming_run_time = TimeTicks::Now() + delay;
958 if (pending_wakeup_timer_.IsRunning() &&
959 (pending_wakeup_timer_.desired_run_time() < incoming_run_time)) {
960 // Old job arrives sooner than this one.
961 return false;
962 }
963 return true;
964 }
965
928 #undef SDVLOG_LOC 966 #undef SDVLOG_LOC
929 967
930 #undef SDVLOG 968 #undef SDVLOG
931 969
932 #undef SLOG 970 #undef SLOG
933 971
934 #undef ENUM_CASE 972 #undef ENUM_CASE
935 973
936 } // namespace syncer 974 } // namespace syncer
OLDNEW
« no previous file with comments | « components/sync/engine_impl/sync_scheduler_impl.h ('k') | components/sync/engine_impl/sync_scheduler_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698