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" |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/location.h" | 14 #include "base/location.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/time/default_clock.h" | |
| 17 #include "sync/engine/backoff_delay_provider.h" | 18 #include "sync/engine/backoff_delay_provider.h" |
| 18 #include "sync/engine/syncer.h" | 19 #include "sync/engine/syncer.h" |
| 19 #include "sync/notifier/object_id_invalidation_map.h" | 20 #include "sync/notifier/object_id_invalidation_map.h" |
| 20 #include "sync/protocol/proto_enum_conversions.h" | 21 #include "sync/protocol/proto_enum_conversions.h" |
| 21 #include "sync/protocol/sync.pb.h" | 22 #include "sync/protocol/sync.pb.h" |
| 22 #include "sync/util/data_type_histogram.h" | 23 #include "sync/util/data_type_histogram.h" |
| 23 #include "sync/util/logging.h" | 24 #include "sync/util/logging.h" |
| 24 | 25 |
| 25 using base::TimeDelta; | 26 using base::TimeDelta; |
| 26 using base::TimeTicks; | 27 using base::TimeTicks; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 : name_(name), | 159 : name_(name), |
| 159 started_(false), | 160 started_(false), |
| 160 syncer_short_poll_interval_seconds_( | 161 syncer_short_poll_interval_seconds_( |
| 161 TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)), | 162 TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)), |
| 162 syncer_long_poll_interval_seconds_( | 163 syncer_long_poll_interval_seconds_( |
| 163 TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)), | 164 TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)), |
| 164 sessions_commit_delay_( | 165 sessions_commit_delay_( |
| 165 TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds)), | 166 TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds)), |
| 166 mode_(NORMAL_MODE), | 167 mode_(NORMAL_MODE), |
| 167 delay_provider_(delay_provider), | 168 delay_provider_(delay_provider), |
| 169 nudge_tracker_(new base::DefaultClock), | |
| 168 syncer_(syncer), | 170 syncer_(syncer), |
| 169 session_context_(context), | 171 session_context_(context), |
| 170 no_scheduling_allowed_(false), | 172 no_scheduling_allowed_(false), |
| 171 do_poll_after_credentials_updated_(false), | 173 do_poll_after_credentials_updated_(false), |
| 172 next_sync_session_job_priority_(NORMAL_PRIORITY), | 174 next_sync_session_job_priority_(NORMAL_PRIORITY), |
| 173 weak_ptr_factory_(this), | 175 weak_ptr_factory_(this), |
| 174 weak_ptr_factory_for_weak_handle_(this) { | 176 weak_ptr_factory_for_weak_handle_(this) { |
| 175 weak_handle_this_ = MakeWeakHandle( | 177 weak_handle_this_ = MakeWeakHandle( |
| 176 weak_ptr_factory_for_weak_handle_.GetWeakPtr()); | 178 weak_ptr_factory_for_weak_handle_.GetWeakPtr()); |
| 177 } | 179 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 227 } | 229 } |
| 228 | 230 |
| 229 DCHECK(!session_context_->account_name().empty()); | 231 DCHECK(!session_context_->account_name().empty()); |
| 230 DCHECK(syncer_.get()); | 232 DCHECK(syncer_.get()); |
| 231 Mode old_mode = mode_; | 233 Mode old_mode = mode_; |
| 232 mode_ = mode; | 234 mode_ = mode; |
| 233 AdjustPolling(UPDATE_INTERVAL); // Will kick start poll timer if needed. | 235 AdjustPolling(UPDATE_INTERVAL); // Will kick start poll timer if needed. |
| 234 | 236 |
| 235 if (old_mode != mode_ && | 237 if (old_mode != mode_ && |
| 236 mode_ == NORMAL_MODE && | 238 mode_ == NORMAL_MODE && |
| 237 nudge_tracker_.IsSyncRequired() && | 239 (nudge_tracker_.IsSyncRequired() || nudge_tracker_.IsRetryRequired()) && |
| 238 CanRunNudgeJobNow(NORMAL_PRIORITY)) { | 240 CanRunNudgeJobNow(NORMAL_PRIORITY)) { |
| 239 // We just got back to normal mode. Let's try to run the work that was | 241 // We just got back to normal mode. Let's try to run the work that was |
| 240 // queued up while we were configuring. | 242 // queued up while we were configuring. |
| 241 TrySyncSessionJob(); | 243 TrySyncSessionJob(); |
| 242 } | 244 } |
| 243 } | 245 } |
| 244 | 246 |
| 245 ModelTypeSet SyncSchedulerImpl::GetEnabledAndUnthrottledTypes() { | 247 ModelTypeSet SyncSchedulerImpl::GetEnabledAndUnthrottledTypes() { |
| 246 ModelTypeSet enabled_types = session_context_->enabled_types(); | 248 ModelTypeSet enabled_types = session_context_->enabled_types(); |
| 247 ModelTypeSet throttled_types = nudge_tracker_.GetThrottledTypes(); | 249 ModelTypeSet throttled_types = nudge_tracker_.GetThrottledTypes(); |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 542 new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF, length)); | 544 new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF, length)); |
| 543 SDVLOG(2) << "Sync cycle failed. Will back off for " | 545 SDVLOG(2) << "Sync cycle failed. Will back off for " |
| 544 << wait_interval_->length.InMilliseconds() << "ms."; | 546 << wait_interval_->length.InMilliseconds() << "ms."; |
| 545 RestartWaiting(); | 547 RestartWaiting(); |
| 546 } | 548 } |
| 547 } | 549 } |
| 548 | 550 |
| 549 void SyncSchedulerImpl::DoPollSyncSessionJob() { | 551 void SyncSchedulerImpl::DoPollSyncSessionJob() { |
| 550 base::AutoReset<bool> protector(&no_scheduling_allowed_, true); | 552 base::AutoReset<bool> protector(&no_scheduling_allowed_, true); |
| 551 | 553 |
| 552 if (!CanRunJobNow(NORMAL_PRIORITY)) { | |
| 553 SDVLOG(2) << "Unable to run a poll job right now."; | |
| 554 return; | |
| 555 } | |
| 556 | |
| 557 if (mode_ != NORMAL_MODE) { | |
| 558 SDVLOG(2) << "Not running poll job in configure mode."; | |
| 559 return; | |
| 560 } | |
| 561 | |
| 562 SDVLOG(2) << "Polling with types " | 554 SDVLOG(2) << "Polling with types " |
| 563 << ModelTypeSetToString(session_context_->enabled_types()); | 555 << ModelTypeSetToString(GetEnabledAndUnthrottledTypes()); |
| 564 scoped_ptr<SyncSession> session(SyncSession::Build(session_context_, this)); | 556 scoped_ptr<SyncSession> session(SyncSession::Build(session_context_, this)); |
| 565 syncer_->PollSyncShare( | 557 syncer_->PollSyncShare( |
| 566 GetEnabledAndUnthrottledTypes(), | 558 GetEnabledAndUnthrottledTypes(), |
| 567 session.get()); | 559 session.get()); |
| 568 | 560 |
| 569 AdjustPolling(FORCE_RESET); | 561 AdjustPolling(FORCE_RESET); |
| 570 | 562 |
| 571 if (IsCurrentlyThrottled()) { | 563 if (IsCurrentlyThrottled()) { |
| 572 SDVLOG(2) << "Poll request got us throttled."; | 564 SDVLOG(2) << "Poll request got us throttled."; |
| 573 // The OnSilencedUntil() call set up the WaitInterval for us. All we need | 565 // The OnSilencedUntil() call set up the WaitInterval for us. All we need |
| 574 // to do is start the timer. | 566 // to do is start the timer. |
| 575 RestartWaiting(); | 567 RestartWaiting(); |
| 576 } | 568 } |
| 577 } | 569 } |
| 578 | 570 |
| 571 void SyncSchedulerImpl::DoRetrySyncSessionJob() { | |
| 572 DCHECK(CalledOnValidThread()); | |
| 573 DCHECK_EQ(mode_, NORMAL_MODE); | |
| 574 | |
| 575 base::AutoReset<bool> protector(&no_scheduling_allowed_, true); | |
| 576 | |
| 577 SDVLOG(2) << "Retrying with types " | |
| 578 << ModelTypeSetToString(GetEnabledAndUnthrottledTypes()); | |
| 579 scoped_ptr<SyncSession> session(SyncSession::Build(session_context_, this)); | |
| 580 if (syncer_->RetrySyncShare(GetEnabledAndUnthrottledTypes(), | |
| 581 session.get()) && | |
| 582 !sessions::HasSyncerError( | |
| 583 session->status_controller().model_neutral_state())) { | |
| 584 nudge_tracker_.RecordSuccessfulSyncCycle(); | |
| 585 } else { | |
| 586 HandleFailure(session->status_controller().model_neutral_state()); | |
| 587 } | |
| 588 } | |
| 589 | |
| 579 void SyncSchedulerImpl::UpdateNudgeTimeRecords(ModelTypeSet types) { | 590 void SyncSchedulerImpl::UpdateNudgeTimeRecords(ModelTypeSet types) { |
| 580 DCHECK(CalledOnValidThread()); | 591 DCHECK(CalledOnValidThread()); |
| 581 base::TimeTicks now = TimeTicks::Now(); | 592 base::TimeTicks now = TimeTicks::Now(); |
| 582 // Update timing information for how often datatypes are triggering nudges. | 593 // Update timing information for how often datatypes are triggering nudges. |
| 583 for (ModelTypeSet::Iterator iter = types.First(); iter.Good(); iter.Inc()) { | 594 for (ModelTypeSet::Iterator iter = types.First(); iter.Good(); iter.Inc()) { |
| 584 base::TimeTicks previous = last_local_nudges_by_model_type_[iter.Get()]; | 595 base::TimeTicks previous = last_local_nudges_by_model_type_[iter.Get()]; |
| 585 last_local_nudges_by_model_type_[iter.Get()] = now; | 596 last_local_nudges_by_model_type_[iter.Get()] = now; |
| 586 if (previous.is_null()) | 597 if (previous.is_null()) |
| 587 continue; | 598 continue; |
| 588 | 599 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 next_sync_session_job_priority_ = NORMAL_PRIORITY; | 689 next_sync_session_job_priority_ = NORMAL_PRIORITY; |
| 679 | 690 |
| 680 DCHECK(CalledOnValidThread()); | 691 DCHECK(CalledOnValidThread()); |
| 681 if (mode_ == CONFIGURATION_MODE) { | 692 if (mode_ == CONFIGURATION_MODE) { |
| 682 if (pending_configure_params_) { | 693 if (pending_configure_params_) { |
| 683 SDVLOG(2) << "Found pending configure job"; | 694 SDVLOG(2) << "Found pending configure job"; |
| 684 DoConfigurationSyncSessionJob(priority); | 695 DoConfigurationSyncSessionJob(priority); |
| 685 } | 696 } |
| 686 } else { | 697 } else { |
| 687 DCHECK(mode_ == NORMAL_MODE); | 698 DCHECK(mode_ == NORMAL_MODE); |
| 688 if (nudge_tracker_.IsSyncRequired() && CanRunNudgeJobNow(priority)) { | 699 if (!CanRunNudgeJobNow(priority)) |
| 700 return; | |
|
pavely
2014/01/08 00:59:56
Please don't do early return from this function. T
haitaol1
2014/01/08 19:06:38
Done.
| |
| 701 | |
| 702 if (nudge_tracker_.IsSyncRequired()) { | |
| 689 SDVLOG(2) << "Found pending nudge job"; | 703 SDVLOG(2) << "Found pending nudge job"; |
| 690 DoNudgeSyncSessionJob(priority); | 704 DoNudgeSyncSessionJob(priority); |
| 705 } else if (nudge_tracker_.IsRetryRequired()) { | |
| 706 DoRetrySyncSessionJob(); | |
| 691 } else if (do_poll_after_credentials_updated_ || | 707 } else if (do_poll_after_credentials_updated_ || |
| 692 ((base::TimeTicks::Now() - last_poll_reset_) >= GetPollInterval())) { | 708 ((base::TimeTicks::Now() - last_poll_reset_) >= GetPollInterval())) { |
| 693 DoPollSyncSessionJob(); | 709 DoPollSyncSessionJob(); |
| 694 // Poll timer fires infrequently. Usually by this time access token is | 710 // Poll timer fires infrequently. Usually by this time access token is |
| 695 // already expired and poll job will fail with auth error. Set flag to | 711 // already expired and poll job will fail with auth error. Set flag to |
| 696 // retry poll once ProfileSyncService gets new access token, TryCanaryJob | 712 // retry poll once ProfileSyncService gets new access token, TryCanaryJob |
| 697 // will be called after access token is retrieved. | 713 // will be called after access token is retrieved. |
| 698 if (HttpResponse::SYNC_AUTH_ERROR == | 714 if (HttpResponse::SYNC_AUTH_ERROR == |
| 699 session_context_->connection_manager()->server_status()) { | 715 session_context_->connection_manager()->server_status()) { |
| 700 do_poll_after_credentials_updated_ = true; | 716 do_poll_after_credentials_updated_ = true; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 730 // timer. If we find that no_scheduling_allowed_ is set here, then | 746 // timer. If we find that no_scheduling_allowed_ is set here, then |
| 731 // something is very wrong. Maybe someone mistakenly called us directly, or | 747 // something is very wrong. Maybe someone mistakenly called us directly, or |
| 732 // mishandled the book-keeping for no_scheduling_allowed_. | 748 // mishandled the book-keeping for no_scheduling_allowed_. |
| 733 NOTREACHED() << "Illegal to schedule job while session in progress."; | 749 NOTREACHED() << "Illegal to schedule job while session in progress."; |
| 734 return; | 750 return; |
| 735 } | 751 } |
| 736 | 752 |
| 737 TrySyncSessionJob(); | 753 TrySyncSessionJob(); |
| 738 } | 754 } |
| 739 | 755 |
| 756 void SyncSchedulerImpl::RetryTimerCallback() { | |
| 757 TrySyncSessionJob(); | |
| 758 } | |
| 759 | |
| 740 void SyncSchedulerImpl::Unthrottle() { | 760 void SyncSchedulerImpl::Unthrottle() { |
| 741 DCHECK(CalledOnValidThread()); | 761 DCHECK(CalledOnValidThread()); |
| 742 DCHECK_EQ(WaitInterval::THROTTLED, wait_interval_->mode); | 762 DCHECK_EQ(WaitInterval::THROTTLED, wait_interval_->mode); |
| 743 | 763 |
| 744 // We're no longer throttled, so clear the wait interval. | 764 // We're no longer throttled, so clear the wait interval. |
| 745 wait_interval_.reset(); | 765 wait_interval_.reset(); |
| 746 NotifyRetryTime(base::Time()); | 766 NotifyRetryTime(base::Time()); |
| 747 | 767 |
| 748 // We treat this as a 'canary' in the sense that it was originally scheduled | 768 // We treat this as a 'canary' in the sense that it was originally scheduled |
| 749 // to run some time ago, failed, and we now want to retry, versus a job that | 769 // to run some time ago, failed, and we now want to retry, versus a job that |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 883 DCHECK(CalledOnValidThread()); | 903 DCHECK(CalledOnValidThread()); |
| 884 if (ShouldRequestEarlyExit( | 904 if (ShouldRequestEarlyExit( |
| 885 snapshot.model_neutral_state().sync_protocol_error)) { | 905 snapshot.model_neutral_state().sync_protocol_error)) { |
| 886 SDVLOG(2) << "Sync Scheduler requesting early exit."; | 906 SDVLOG(2) << "Sync Scheduler requesting early exit."; |
| 887 Stop(); | 907 Stop(); |
| 888 } | 908 } |
| 889 if (IsActionableError(snapshot.model_neutral_state().sync_protocol_error)) | 909 if (IsActionableError(snapshot.model_neutral_state().sync_protocol_error)) |
| 890 OnActionableError(snapshot); | 910 OnActionableError(snapshot); |
| 891 } | 911 } |
| 892 | 912 |
| 913 void SyncSchedulerImpl::OnReceivedGuRetryDelaySeconds(int delay_seconds) { | |
| 914 nudge_tracker_.set_next_retry_time( | |
| 915 base::Time::Now() + base::TimeDelta::FromSeconds(delay_seconds)); | |
| 916 retry_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(delay_seconds), | |
| 917 this, &SyncSchedulerImpl::RetryTimerCallback); | |
| 918 } | |
| 919 | |
| 893 void SyncSchedulerImpl::SetNotificationsEnabled(bool notifications_enabled) { | 920 void SyncSchedulerImpl::SetNotificationsEnabled(bool notifications_enabled) { |
| 894 DCHECK(CalledOnValidThread()); | 921 DCHECK(CalledOnValidThread()); |
| 895 session_context_->set_notifications_enabled(notifications_enabled); | 922 session_context_->set_notifications_enabled(notifications_enabled); |
| 896 if (notifications_enabled) | 923 if (notifications_enabled) |
| 897 nudge_tracker_.OnInvalidationsEnabled(); | 924 nudge_tracker_.OnInvalidationsEnabled(); |
| 898 else | 925 else |
| 899 nudge_tracker_.OnInvalidationsDisabled(); | 926 nudge_tracker_.OnInvalidationsDisabled(); |
| 900 } | 927 } |
| 901 | 928 |
| 902 base::TimeDelta SyncSchedulerImpl::GetSessionsCommitDelay() const { | 929 base::TimeDelta SyncSchedulerImpl::GetSessionsCommitDelay() const { |
| 903 DCHECK(CalledOnValidThread()); | 930 DCHECK(CalledOnValidThread()); |
| 904 return sessions_commit_delay_; | 931 return sessions_commit_delay_; |
| 905 } | 932 } |
| 906 | 933 |
| 907 #undef SDVLOG_LOC | 934 #undef SDVLOG_LOC |
| 908 | 935 |
| 909 #undef SDVLOG | 936 #undef SDVLOG |
| 910 | 937 |
| 911 #undef SLOG | 938 #undef SLOG |
| 912 | 939 |
| 913 #undef ENUM_CASE | 940 #undef ENUM_CASE |
| 914 | 941 |
| 915 } // namespace syncer | 942 } // namespace syncer |
| OLD | NEW |