Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "sync/engine/sync_scheduler_impl.h" | 5 #include "sync/engine/sync_scheduler_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 | 9 |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 Mode old_mode = mode_; | 230 Mode old_mode = mode_; |
| 231 mode_ = mode; | 231 mode_ = mode; |
| 232 AdjustPolling(UPDATE_INTERVAL); // Will kick start poll timer if needed. | 232 AdjustPolling(UPDATE_INTERVAL); // Will kick start poll timer if needed. |
| 233 | 233 |
| 234 if (old_mode != mode_ && | 234 if (old_mode != mode_ && |
| 235 mode_ == NORMAL_MODE && | 235 mode_ == NORMAL_MODE && |
| 236 nudge_tracker_.IsSyncRequired() && | 236 nudge_tracker_.IsSyncRequired() && |
| 237 CanRunNudgeJobNow(NORMAL_PRIORITY)) { | 237 CanRunNudgeJobNow(NORMAL_PRIORITY)) { |
| 238 // We just got back to normal mode. Let's try to run the work that was | 238 // We just got back to normal mode. Let's try to run the work that was |
| 239 // queued up while we were configuring. | 239 // queued up while we were configuring. |
| 240 DoNudgeSyncSessionJob(NORMAL_PRIORITY); | 240 TryJob(NORMAL_PRIORITY); |
| 241 } | 241 } |
| 242 } | 242 } |
| 243 | 243 |
| 244 ModelTypeSet SyncSchedulerImpl::GetEnabledAndUnthrottledTypes() { | 244 ModelTypeSet SyncSchedulerImpl::GetEnabledAndUnthrottledTypes() { |
| 245 ModelTypeSet enabled_types = | 245 ModelTypeSet enabled_types = |
| 246 GetRoutingInfoTypes(session_context_->routing_info()); | 246 GetRoutingInfoTypes(session_context_->routing_info()); |
| 247 ModelTypeSet throttled_types = | 247 ModelTypeSet throttled_types = |
| 248 nudge_tracker_.GetThrottledTypes(); | 248 nudge_tracker_.GetThrottledTypes(); |
| 249 return Difference(enabled_types, throttled_types); | 249 return Difference(enabled_types, throttled_types); |
| 250 } | 250 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 292 | 292 |
| 293 ModelSafeRoutingInfo restricted_routes; | 293 ModelSafeRoutingInfo restricted_routes; |
| 294 BuildModelSafeParams(params.types_to_download, | 294 BuildModelSafeParams(params.types_to_download, |
| 295 params.routing_info, | 295 params.routing_info, |
| 296 &restricted_routes); | 296 &restricted_routes); |
| 297 session_context_->set_routing_info(restricted_routes); | 297 session_context_->set_routing_info(restricted_routes); |
| 298 | 298 |
| 299 // Only reconfigure if we have types to download. | 299 // Only reconfigure if we have types to download. |
| 300 if (!params.types_to_download.Empty()) { | 300 if (!params.types_to_download.Empty()) { |
| 301 pending_configure_params_.reset(new ConfigurationParams(params)); | 301 pending_configure_params_.reset(new ConfigurationParams(params)); |
| 302 DoConfigurationSyncSessionJob(NORMAL_PRIORITY); | 302 TryJob(NORMAL_PRIORITY); |
| 303 } else { | 303 } else { |
| 304 SDVLOG(2) << "No change in routing info, calling ready task directly."; | 304 SDVLOG(2) << "No change in routing info, calling ready task directly."; |
| 305 params.ready_task.Run(); | 305 params.ready_task.Run(); |
| 306 } | 306 } |
| 307 } | 307 } |
| 308 | 308 |
| 309 bool SyncSchedulerImpl::CanRunJobNow(JobPriority priority) { | 309 bool SyncSchedulerImpl::CanRunJobNow(JobPriority priority) { |
| 310 DCHECK(CalledOnValidThread()); | 310 DCHECK(CalledOnValidThread()); |
| 311 if (wait_interval_ && wait_interval_->mode == WaitInterval::THROTTLED) { | 311 if (wait_interval_ && wait_interval_->mode == WaitInterval::THROTTLED) { |
| 312 SDVLOG(1) << "Unable to run a job because we're throttled."; | 312 SDVLOG(1) << "Unable to run a job because we're throttled."; |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 565 return; | 565 return; |
| 566 } | 566 } |
| 567 | 567 |
| 568 SDVLOG(2) << "Polling with routes " | 568 SDVLOG(2) << "Polling with routes " |
| 569 << ModelSafeRoutingInfoToString(session_context_->routing_info()); | 569 << ModelSafeRoutingInfoToString(session_context_->routing_info()); |
| 570 scoped_ptr<SyncSession> session(SyncSession::Build(session_context_, this)); | 570 scoped_ptr<SyncSession> session(SyncSession::Build(session_context_, this)); |
| 571 syncer_->PollSyncShare( | 571 syncer_->PollSyncShare( |
| 572 GetEnabledAndUnthrottledTypes(), | 572 GetEnabledAndUnthrottledTypes(), |
| 573 session.get()); | 573 session.get()); |
| 574 | 574 |
| 575 AdjustPolling(UPDATE_INTERVAL); | 575 AdjustPolling(FORCE_RESET); |
| 576 | 576 |
| 577 if (IsCurrentlyThrottled()) { | 577 if (IsCurrentlyThrottled()) { |
| 578 SDVLOG(2) << "Poll request got us throttled."; | 578 SDVLOG(2) << "Poll request got us throttled."; |
| 579 // The OnSilencedUntil() call set up the WaitInterval for us. All we need | 579 // The OnSilencedUntil() call set up the WaitInterval for us. All we need |
| 580 // to do is start the timer. | 580 // to do is start the timer. |
| 581 RestartWaiting(); | 581 RestartWaiting(); |
| 582 } | 582 } |
| 583 } | 583 } |
| 584 | 584 |
| 585 void SyncSchedulerImpl::UpdateNudgeTimeRecords(ModelTypeSet types) { | 585 void SyncSchedulerImpl::UpdateNudgeTimeRecords(ModelTypeSet types) { |
| 586 DCHECK(CalledOnValidThread()); | 586 DCHECK(CalledOnValidThread()); |
| 587 base::TimeTicks now = TimeTicks::Now(); | 587 base::TimeTicks now = TimeTicks::Now(); |
| 588 // Update timing information for how often datatypes are triggering nudges. | 588 // Update timing information for how often datatypes are triggering nudges. |
| 589 for (ModelTypeSet::Iterator iter = types.First(); iter.Good(); iter.Inc()) { | 589 for (ModelTypeSet::Iterator iter = types.First(); iter.Good(); iter.Inc()) { |
| 590 base::TimeTicks previous = last_local_nudges_by_model_type_[iter.Get()]; | 590 base::TimeTicks previous = last_local_nudges_by_model_type_[iter.Get()]; |
| 591 last_local_nudges_by_model_type_[iter.Get()] = now; | 591 last_local_nudges_by_model_type_[iter.Get()] = now; |
| 592 if (previous.is_null()) | 592 if (previous.is_null()) |
| 593 continue; | 593 continue; |
| 594 | 594 |
| 595 #define PER_DATA_TYPE_MACRO(type_str) \ | 595 #define PER_DATA_TYPE_MACRO(type_str) \ |
| 596 SYNC_FREQ_HISTOGRAM("Sync.Freq" type_str, now - previous); | 596 SYNC_FREQ_HISTOGRAM("Sync.Freq" type_str, now - previous); |
| 597 SYNC_DATA_TYPE_HISTOGRAM(iter.Get()); | 597 SYNC_DATA_TYPE_HISTOGRAM(iter.Get()); |
| 598 #undef PER_DATA_TYPE_MACRO | 598 #undef PER_DATA_TYPE_MACRO |
| 599 } | 599 } |
| 600 } | 600 } |
| 601 | 601 |
| 602 TimeDelta SyncSchedulerImpl::GetPollInterval() { | |
| 603 return (!session_context_->notifications_enabled() || | |
| 604 !session_context_->ShouldFetchUpdatesBeforeCommit()) ? | |
| 605 syncer_short_poll_interval_seconds_ : | |
| 606 syncer_long_poll_interval_seconds_; | |
| 607 } | |
| 608 | |
| 602 void SyncSchedulerImpl::AdjustPolling(PollAdjustType type) { | 609 void SyncSchedulerImpl::AdjustPolling(PollAdjustType type) { |
| 603 DCHECK(CalledOnValidThread()); | 610 DCHECK(CalledOnValidThread()); |
| 604 | 611 |
| 605 TimeDelta poll = (!session_context_->notifications_enabled() || | 612 TimeDelta poll = GetPollInterval(); |
| 606 !session_context_->ShouldFetchUpdatesBeforeCommit()) ? | |
| 607 syncer_short_poll_interval_seconds_ : | |
| 608 syncer_long_poll_interval_seconds_; | |
| 609 bool rate_changed = !poll_timer_.IsRunning() || | 613 bool rate_changed = !poll_timer_.IsRunning() || |
| 610 poll != poll_timer_.GetCurrentDelay(); | 614 poll != poll_timer_.GetCurrentDelay(); |
| 611 | 615 |
| 612 if (type == FORCE_RESET && !rate_changed) | 616 if (type == FORCE_RESET) { |
| 613 poll_timer_.Reset(); | 617 last_poll_reset_ = base::TimeTicks::Now(); |
| 618 if (!rate_changed) | |
| 619 poll_timer_.Reset(); | |
| 620 } | |
| 614 | 621 |
| 615 if (!rate_changed) | 622 if (!rate_changed) |
| 616 return; | 623 return; |
| 617 | 624 |
| 618 // Adjust poll rate. | 625 // Adjust poll rate. |
| 619 poll_timer_.Stop(); | 626 poll_timer_.Stop(); |
| 620 poll_timer_.Start(FROM_HERE, poll, this, | 627 poll_timer_.Start(FROM_HERE, poll, this, |
| 621 &SyncSchedulerImpl::PollTimerCallback); | 628 &SyncSchedulerImpl::PollTimerCallback); |
| 622 } | 629 } |
| 623 | 630 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 653 poll_timer_.Stop(); | 660 poll_timer_.Stop(); |
| 654 pending_wakeup_timer_.Stop(); | 661 pending_wakeup_timer_.Stop(); |
| 655 pending_configure_params_.reset(); | 662 pending_configure_params_.reset(); |
| 656 if (started_) | 663 if (started_) |
| 657 started_ = false; | 664 started_ = false; |
| 658 } | 665 } |
| 659 | 666 |
| 660 // This is the only place where we invoke DoSyncSessionJob with canary | 667 // This is the only place where we invoke DoSyncSessionJob with canary |
| 661 // privileges. Everyone else should use NORMAL_PRIORITY. | 668 // privileges. Everyone else should use NORMAL_PRIORITY. |
| 662 void SyncSchedulerImpl::TryCanaryJob() { | 669 void SyncSchedulerImpl::TryCanaryJob() { |
| 663 DCHECK(CalledOnValidThread()); | 670 TryJob(CANARY_PRIORITY); |
| 664 | |
| 665 if (mode_ == CONFIGURATION_MODE && pending_configure_params_) { | |
| 666 SDVLOG(2) << "Found pending configure job; will run as canary"; | |
| 667 DoConfigurationSyncSessionJob(CANARY_PRIORITY); | |
| 668 } else if (mode_ == NORMAL_MODE && nudge_tracker_.IsSyncRequired() && | |
| 669 CanRunNudgeJobNow(CANARY_PRIORITY)) { | |
| 670 SDVLOG(2) << "Found pending nudge job; will run as canary"; | |
| 671 DoNudgeSyncSessionJob(CANARY_PRIORITY); | |
| 672 } else if (mode_ == NORMAL_MODE && CanRunJobNow(CANARY_PRIORITY) && | |
| 673 do_poll_after_credentials_updated_) { | |
| 674 // Retry poll if poll timer recently fired and ProfileSyncService received | |
| 675 // fresh access token. | |
| 676 DoPollSyncSessionJob(); | |
| 677 } else { | |
| 678 SDVLOG(2) << "Found no work to do; will not run a canary"; | |
| 679 } | |
| 680 // Don't run poll job till the next time poll timer fires. | 671 // Don't run poll job till the next time poll timer fires. |
| 681 do_poll_after_credentials_updated_ = false; | 672 do_poll_after_credentials_updated_ = false; |
| 682 } | 673 } |
| 683 | 674 |
| 675 void SyncSchedulerImpl::TryJob(JobPriority priority) { | |
|
tim (not reviewing)
2013/11/17 00:36:47
I like it. I've always been a fan of having a cons
pavely
2013/11/18 18:39:55
Done.
| |
| 676 DCHECK(CalledOnValidThread()); | |
| 677 if (mode_ == CONFIGURATION_MODE) { | |
| 678 if (pending_configure_params_) { | |
| 679 SDVLOG(2) << "Found pending configure job"; | |
| 680 DoConfigurationSyncSessionJob(priority); | |
| 681 } | |
| 682 } else { | |
| 683 DCHECK(mode_ == NORMAL_MODE); | |
| 684 if (nudge_tracker_.IsSyncRequired() && CanRunNudgeJobNow(priority)) { | |
| 685 SDVLOG(2) << "Found pending nudge job"; | |
| 686 DoNudgeSyncSessionJob(priority); | |
| 687 } else if (((base::TimeTicks::Now() - last_poll_reset_) | |
| 688 >= GetPollInterval()) || do_poll_after_credentials_updated_) { | |
|
tim (not reviewing)
2013/11/17 00:36:47
Whoa, this is hard to read. Consider pulling Now(
pavely
2013/11/18 18:39:55
I reordered conditions, decided not to extract sub
| |
| 689 DoPollSyncSessionJob(); | |
| 690 } | |
| 691 } | |
| 692 } | |
| 693 | |
| 684 void SyncSchedulerImpl::PollTimerCallback() { | 694 void SyncSchedulerImpl::PollTimerCallback() { |
| 685 DCHECK(CalledOnValidThread()); | 695 DCHECK(CalledOnValidThread()); |
| 686 if (no_scheduling_allowed_) { | 696 if (no_scheduling_allowed_) { |
| 687 // The no_scheduling_allowed_ flag is set by a function-scoped AutoReset in | 697 // The no_scheduling_allowed_ flag is set by a function-scoped AutoReset in |
| 688 // functions that are called only on the sync thread. This function is also | 698 // functions that are called only on the sync thread. This function is also |
| 689 // called only on the sync thread, and only when it is posted by an expiring | 699 // called only on the sync thread, and only when it is posted by an expiring |
| 690 // timer. If we find that no_scheduling_allowed_ is set here, then | 700 // timer. If we find that no_scheduling_allowed_ is set here, then |
| 691 // something is very wrong. Maybe someone mistakenly called us directly, or | 701 // something is very wrong. Maybe someone mistakenly called us directly, or |
| 692 // mishandled the book-keeping for no_scheduling_allowed_. | 702 // mishandled the book-keeping for no_scheduling_allowed_. |
| 693 NOTREACHED() << "Illegal to schedule job while session in progress."; | 703 NOTREACHED() << "Illegal to schedule job while session in progress."; |
| 694 return; | 704 return; |
| 695 } | 705 } |
| 696 | 706 |
| 697 DoPollSyncSessionJob(); | 707 TryJob(NORMAL_PRIORITY); |
| 698 // Poll timer fires infrequently. Usually by this time access token is already | 708 // Poll timer fires infrequently. Usually by this time access token is already |
| 699 // expired and poll job will fail with auth error. Set flag to retry poll once | 709 // expired and poll job will fail with auth error. Set flag to retry poll once |
| 700 // ProfileSyncService gets new access token, TryCanaryJob will be called in | 710 // ProfileSyncService gets new access token, TryCanaryJob will be called in |
| 701 // this case. | 711 // this case. |
| 702 if (HttpResponse::SYNC_AUTH_ERROR == | 712 if (HttpResponse::SYNC_AUTH_ERROR == |
| 703 session_context_->connection_manager()->server_status()) { | 713 session_context_->connection_manager()->server_status()) { |
| 704 do_poll_after_credentials_updated_ = true; | 714 do_poll_after_credentials_updated_ = true; |
| 705 } | 715 } |
| 706 } | 716 } |
| 707 | 717 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 732 type_unthrottle_timer_.Start( | 742 type_unthrottle_timer_.Start( |
| 733 FROM_HERE, | 743 FROM_HERE, |
| 734 time_until_next_unthrottle, | 744 time_until_next_unthrottle, |
| 735 base::Bind(&SyncSchedulerImpl::TypeUnthrottle, | 745 base::Bind(&SyncSchedulerImpl::TypeUnthrottle, |
| 736 weak_ptr_factory_.GetWeakPtr(), | 746 weak_ptr_factory_.GetWeakPtr(), |
| 737 unthrottle_time + time_until_next_unthrottle)); | 747 unthrottle_time + time_until_next_unthrottle)); |
| 738 } | 748 } |
| 739 | 749 |
| 740 // Maybe this is a good time to run a nudge job. Let's try it. | 750 // Maybe this is a good time to run a nudge job. Let's try it. |
| 741 if (nudge_tracker_.IsSyncRequired() && CanRunNudgeJobNow(NORMAL_PRIORITY)) | 751 if (nudge_tracker_.IsSyncRequired() && CanRunNudgeJobNow(NORMAL_PRIORITY)) |
| 742 DoNudgeSyncSessionJob(NORMAL_PRIORITY); | 752 TryJob(NORMAL_PRIORITY); |
| 743 } | 753 } |
| 744 | 754 |
| 745 void SyncSchedulerImpl::PerformDelayedNudge() { | 755 void SyncSchedulerImpl::PerformDelayedNudge() { |
| 746 // Circumstances may have changed since we scheduled this delayed nudge. | 756 // Circumstances may have changed since we scheduled this delayed nudge. |
| 747 // We must check to see if it's OK to run the job before we do so. | 757 // We must check to see if it's OK to run the job before we do so. |
| 748 if (CanRunNudgeJobNow(NORMAL_PRIORITY)) | 758 if (CanRunNudgeJobNow(NORMAL_PRIORITY)) |
| 749 DoNudgeSyncSessionJob(NORMAL_PRIORITY); | 759 TryJob(NORMAL_PRIORITY); |
| 750 | 760 |
| 751 // We're not responsible for setting up any retries here. The functions that | 761 // We're not responsible for setting up any retries here. The functions that |
| 752 // first put us into a state that prevents successful sync cycles (eg. global | 762 // first put us into a state that prevents successful sync cycles (eg. global |
| 753 // throttling, type throttling, network errors, transient errors) will also | 763 // throttling, type throttling, network errors, transient errors) will also |
| 754 // setup the appropriate retry logic (eg. retry after timeout, exponential | 764 // setup the appropriate retry logic (eg. retry after timeout, exponential |
| 755 // backoff, retry when the network changes). | 765 // backoff, retry when the network changes). |
| 756 } | 766 } |
| 757 | 767 |
| 758 void SyncSchedulerImpl::ExponentialBackoffRetry() { | 768 void SyncSchedulerImpl::ExponentialBackoffRetry() { |
| 759 TryCanaryJob(); | 769 TryCanaryJob(); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 886 | 896 |
| 887 #undef SDVLOG_LOC | 897 #undef SDVLOG_LOC |
| 888 | 898 |
| 889 #undef SDVLOG | 899 #undef SDVLOG |
| 890 | 900 |
| 891 #undef SLOG | 901 #undef SLOG |
| 892 | 902 |
| 893 #undef ENUM_CASE | 903 #undef ENUM_CASE |
| 894 | 904 |
| 895 } // namespace syncer | 905 } // namespace syncer |
| OLD | NEW |