| 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/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
| 15 #include "base/rand_util.h" | 15 #include "sync/engine/backoff_delay_provider.h" |
| 16 #include "sync/engine/syncer.h" | 16 #include "sync/engine/syncer.h" |
| 17 #include "sync/engine/throttled_data_type_tracker.h" | 17 #include "sync/engine/throttled_data_type_tracker.h" |
| 18 #include "sync/protocol/proto_enum_conversions.h" | 18 #include "sync/protocol/proto_enum_conversions.h" |
| 19 #include "sync/protocol/sync.pb.h" | 19 #include "sync/protocol/sync.pb.h" |
| 20 #include "sync/util/data_type_histogram.h" | 20 #include "sync/util/data_type_histogram.h" |
| 21 #include "sync/util/logging.h" | 21 #include "sync/util/logging.h" |
| 22 | 22 |
| 23 using base::TimeDelta; | 23 using base::TimeDelta; |
| 24 using base::TimeTicks; | 24 using base::TimeTicks; |
| 25 | 25 |
| 26 namespace syncer { | 26 namespace syncer { |
| 27 | 27 |
| 28 using sessions::SyncSession; | 28 using sessions::SyncSession; |
| 29 using sessions::SyncSessionSnapshot; | 29 using sessions::SyncSessionSnapshot; |
| 30 using sessions::SyncSourceInfo; | 30 using sessions::SyncSourceInfo; |
| 31 using sync_pb::GetUpdatesCallerInfo; | 31 using sync_pb::GetUpdatesCallerInfo; |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 // For integration tests only. Override initial backoff value. | |
| 36 // TODO(tim): Remove this egregiousness, use command line flag and plumb | |
| 37 // through. Done this way to reduce diffs in hotfix. | |
| 38 static bool g_force_short_retry = false; | |
| 39 | |
| 40 bool ShouldRequestEarlyExit(const SyncProtocolError& error) { | 35 bool ShouldRequestEarlyExit(const SyncProtocolError& error) { |
| 41 switch (error.error_type) { | 36 switch (error.error_type) { |
| 42 case SYNC_SUCCESS: | 37 case SYNC_SUCCESS: |
| 43 case MIGRATION_DONE: | 38 case MIGRATION_DONE: |
| 44 case THROTTLED: | 39 case THROTTLED: |
| 45 case TRANSIENT_ERROR: | 40 case TRANSIENT_ERROR: |
| 46 return false; | 41 return false; |
| 47 case NOT_MY_BIRTHDAY: | 42 case NOT_MY_BIRTHDAY: |
| 48 case CLEAR_PENDING: | 43 case CLEAR_PENDING: |
| 49 // If we send terminate sync early then |sync_cycle_ended| notification | 44 // If we send terminate sync early then |sync_cycle_ended| notification |
| (...skipping 28 matching lines...) Expand all Loading... |
| 78 const ModelSafeRoutingInfo& routing_info, | 73 const ModelSafeRoutingInfo& routing_info, |
| 79 const base::Closure& ready_task) | 74 const base::Closure& ready_task) |
| 80 : source(source), | 75 : source(source), |
| 81 types_to_download(types_to_download), | 76 types_to_download(types_to_download), |
| 82 routing_info(routing_info), | 77 routing_info(routing_info), |
| 83 ready_task(ready_task) { | 78 ready_task(ready_task) { |
| 84 DCHECK(!ready_task.is_null()); | 79 DCHECK(!ready_task.is_null()); |
| 85 } | 80 } |
| 86 ConfigurationParams::~ConfigurationParams() {} | 81 ConfigurationParams::~ConfigurationParams() {} |
| 87 | 82 |
| 88 SyncSchedulerImpl::DelayProvider::DelayProvider() {} | |
| 89 SyncSchedulerImpl::DelayProvider::~DelayProvider() {} | |
| 90 | |
| 91 SyncSchedulerImpl::WaitInterval::WaitInterval() | 83 SyncSchedulerImpl::WaitInterval::WaitInterval() |
| 92 : mode(UNKNOWN), | 84 : mode(UNKNOWN), |
| 93 had_nudge(false) { | 85 had_nudge(false) { |
| 94 } | 86 } |
| 95 | 87 |
| 96 SyncSchedulerImpl::WaitInterval::~WaitInterval() {} | 88 SyncSchedulerImpl::WaitInterval::~WaitInterval() {} |
| 97 | 89 |
| 98 #define ENUM_CASE(x) case x: return #x; break; | 90 #define ENUM_CASE(x) case x: return #x; break; |
| 99 | 91 |
| 100 const char* SyncSchedulerImpl::WaitInterval::GetModeString(Mode mode) { | 92 const char* SyncSchedulerImpl::WaitInterval::GetModeString(Mode mode) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 switch (purpose) { | 125 switch (purpose) { |
| 134 ENUM_CASE(UNKNOWN); | 126 ENUM_CASE(UNKNOWN); |
| 135 ENUM_CASE(POLL); | 127 ENUM_CASE(POLL); |
| 136 ENUM_CASE(NUDGE); | 128 ENUM_CASE(NUDGE); |
| 137 ENUM_CASE(CONFIGURATION); | 129 ENUM_CASE(CONFIGURATION); |
| 138 } | 130 } |
| 139 NOTREACHED(); | 131 NOTREACHED(); |
| 140 return ""; | 132 return ""; |
| 141 } | 133 } |
| 142 | 134 |
| 143 TimeDelta SyncSchedulerImpl::DelayProvider::GetDelay( | |
| 144 const base::TimeDelta& last_delay) { | |
| 145 return SyncSchedulerImpl::GetRecommendedDelay(last_delay); | |
| 146 } | |
| 147 | |
| 148 GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource( | 135 GetUpdatesCallerInfo::GetUpdatesSource GetUpdatesFromNudgeSource( |
| 149 NudgeSource source) { | 136 NudgeSource source) { |
| 150 switch (source) { | 137 switch (source) { |
| 151 case NUDGE_SOURCE_NOTIFICATION: | 138 case NUDGE_SOURCE_NOTIFICATION: |
| 152 return GetUpdatesCallerInfo::NOTIFICATION; | 139 return GetUpdatesCallerInfo::NOTIFICATION; |
| 153 case NUDGE_SOURCE_LOCAL: | 140 case NUDGE_SOURCE_LOCAL: |
| 154 return GetUpdatesCallerInfo::LOCAL; | 141 return GetUpdatesCallerInfo::LOCAL; |
| 155 case NUDGE_SOURCE_CONTINUATION: | 142 case NUDGE_SOURCE_CONTINUATION: |
| 156 return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION; | 143 return GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION; |
| 157 case NUDGE_SOURCE_LOCAL_REFRESH: | 144 case NUDGE_SOURCE_LOCAL_REFRESH: |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 case GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE: | 177 case GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE: |
| 191 return true; | 178 return true; |
| 192 default: | 179 default: |
| 193 return false; | 180 return false; |
| 194 } | 181 } |
| 195 } | 182 } |
| 196 | 183 |
| 197 } // namespace | 184 } // namespace |
| 198 | 185 |
| 199 SyncSchedulerImpl::SyncSchedulerImpl(const std::string& name, | 186 SyncSchedulerImpl::SyncSchedulerImpl(const std::string& name, |
| 187 BackoffDelayProvider* delay_provider, |
| 200 sessions::SyncSessionContext* context, | 188 sessions::SyncSessionContext* context, |
| 201 Syncer* syncer) | 189 Syncer* syncer) |
| 202 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 190 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 203 weak_ptr_factory_for_weak_handle_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 191 weak_ptr_factory_for_weak_handle_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 204 weak_handle_this_(MakeWeakHandle( | 192 weak_handle_this_(MakeWeakHandle( |
| 205 weak_ptr_factory_for_weak_handle_.GetWeakPtr())), | 193 weak_ptr_factory_for_weak_handle_.GetWeakPtr())), |
| 206 name_(name), | 194 name_(name), |
| 207 sync_loop_(MessageLoop::current()), | 195 sync_loop_(MessageLoop::current()), |
| 208 started_(false), | 196 started_(false), |
| 209 syncer_short_poll_interval_seconds_( | 197 syncer_short_poll_interval_seconds_( |
| 210 TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)), | 198 TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds)), |
| 211 syncer_long_poll_interval_seconds_( | 199 syncer_long_poll_interval_seconds_( |
| 212 TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)), | 200 TimeDelta::FromSeconds(kDefaultLongPollIntervalSeconds)), |
| 213 sessions_commit_delay_( | 201 sessions_commit_delay_( |
| 214 TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds)), | 202 TimeDelta::FromSeconds(kDefaultSessionsCommitDelaySeconds)), |
| 215 mode_(NORMAL_MODE), | 203 mode_(NORMAL_MODE), |
| 216 // Start with assuming everything is fine with the connection. | 204 // Start with assuming everything is fine with the connection. |
| 217 // At the end of the sync cycle we would have the correct status. | 205 // At the end of the sync cycle we would have the correct status. |
| 218 connection_code_(HttpResponse::SERVER_CONNECTION_OK), | 206 connection_code_(HttpResponse::SERVER_CONNECTION_OK), |
| 219 delay_provider_(new DelayProvider()), | 207 delay_provider_(delay_provider), |
| 220 syncer_(syncer), | 208 syncer_(syncer), |
| 221 session_context_(context) { | 209 session_context_(context) { |
| 222 DCHECK(sync_loop_); | 210 DCHECK(sync_loop_); |
| 223 } | 211 } |
| 224 | 212 |
| 225 SyncSchedulerImpl::~SyncSchedulerImpl() { | 213 SyncSchedulerImpl::~SyncSchedulerImpl() { |
| 226 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 214 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
| 227 StopImpl(base::Closure()); | 215 StopImpl(base::Closure()); |
| 228 } | 216 } |
| 229 | 217 |
| (...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 896 &SyncSchedulerImpl::PollTimerCallback); | 884 &SyncSchedulerImpl::PollTimerCallback); |
| 897 } | 885 } |
| 898 | 886 |
| 899 void SyncSchedulerImpl::RestartWaiting() { | 887 void SyncSchedulerImpl::RestartWaiting() { |
| 900 CHECK(wait_interval_.get()); | 888 CHECK(wait_interval_.get()); |
| 901 wait_interval_->timer.Stop(); | 889 wait_interval_->timer.Stop(); |
| 902 wait_interval_->timer.Start(FROM_HERE, wait_interval_->length, | 890 wait_interval_->timer.Start(FROM_HERE, wait_interval_->length, |
| 903 this, &SyncSchedulerImpl::DoCanaryJob); | 891 this, &SyncSchedulerImpl::DoCanaryJob); |
| 904 } | 892 } |
| 905 | 893 |
| 906 namespace { | |
| 907 // TODO(tim): Move this function to syncer_error.h. | |
| 908 // Return true if the command in question was attempted and did not complete | |
| 909 // successfully. | |
| 910 bool IsError(SyncerError error) { | |
| 911 return error != UNSET && error != SYNCER_OK; | |
| 912 } | |
| 913 } // namespace | |
| 914 | |
| 915 // static | |
| 916 void SyncSchedulerImpl::ForceShortInitialBackoffRetry() { | |
| 917 g_force_short_retry = true; | |
| 918 } | |
| 919 | |
| 920 TimeDelta SyncSchedulerImpl::GetInitialBackoffDelay( | |
| 921 const sessions::ModelNeutralState& state) const { | |
| 922 // TODO(tim): Remove this, provide integration-test-only mechanism | |
| 923 // for override. | |
| 924 if (g_force_short_retry) { | |
| 925 return TimeDelta::FromSeconds(kInitialBackoffShortRetrySeconds); | |
| 926 } | |
| 927 | |
| 928 if (IsError(state.last_get_key_result)) | |
| 929 return TimeDelta::FromSeconds(kInitialBackoffRetrySeconds); | |
| 930 // Note: If we received a MIGRATION_DONE on download updates, then commit | |
| 931 // should not have taken place. Moreover, if we receive a MIGRATION_DONE | |
| 932 // on commit, it means that download updates succeeded. Therefore, we only | |
| 933 // need to check if either code is equal to SERVER_RETURN_MIGRATION_DONE, | |
| 934 // and not if there were any more serious errors requiring the long retry. | |
| 935 if (state.last_download_updates_result == SERVER_RETURN_MIGRATION_DONE || | |
| 936 state.commit_result == SERVER_RETURN_MIGRATION_DONE) { | |
| 937 return TimeDelta::FromSeconds(kInitialBackoffShortRetrySeconds); | |
| 938 } | |
| 939 | |
| 940 return TimeDelta::FromSeconds(kInitialBackoffRetrySeconds); | |
| 941 } | |
| 942 | |
| 943 void SyncSchedulerImpl::HandleContinuationError( | 894 void SyncSchedulerImpl::HandleContinuationError( |
| 944 const SyncSessionJob& old_job) { | 895 const SyncSessionJob& old_job) { |
| 945 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 896 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
| 946 if (DCHECK_IS_ON()) { | 897 if (DCHECK_IS_ON()) { |
| 947 if (IsBackingOff()) { | 898 if (IsBackingOff()) { |
| 948 DCHECK(wait_interval_->timer.IsRunning() || old_job.is_canary_job); | 899 DCHECK(wait_interval_->timer.IsRunning() || old_job.is_canary_job); |
| 949 } | 900 } |
| 950 } | 901 } |
| 951 | 902 |
| 952 TimeDelta length = delay_provider_->GetDelay( | 903 TimeDelta length = delay_provider_->GetDelay( |
| 953 IsBackingOff() ? wait_interval_->length : | 904 IsBackingOff() ? wait_interval_->length : |
| 954 GetInitialBackoffDelay( | 905 delay_provider_->GetInitialDelay( |
| 955 old_job.session->status_controller().model_neutral_state())); | 906 old_job.session->status_controller().model_neutral_state())); |
| 956 | 907 |
| 957 SDVLOG(2) << "In handle continuation error with " | 908 SDVLOG(2) << "In handle continuation error with " |
| 958 << SyncSessionJob::GetPurposeString(old_job.purpose) | 909 << SyncSessionJob::GetPurposeString(old_job.purpose) |
| 959 << " job. The time delta(ms) is " | 910 << " job. The time delta(ms) is " |
| 960 << length.InMilliseconds(); | 911 << length.InMilliseconds(); |
| 961 | 912 |
| 962 // This will reset the had_nudge variable as well. | 913 // This will reset the had_nudge variable as well. |
| 963 wait_interval_.reset(new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF, | 914 wait_interval_.reset(new WaitInterval(WaitInterval::EXPONENTIAL_BACKOFF, |
| 964 length)); | 915 length)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 977 // We are not in configuration mode. So wait_interval's pending job | 928 // We are not in configuration mode. So wait_interval's pending job |
| 978 // should be null. | 929 // should be null. |
| 979 DCHECK(wait_interval_->pending_configure_job.get() == NULL); | 930 DCHECK(wait_interval_->pending_configure_job.get() == NULL); |
| 980 | 931 |
| 981 // TODO(lipalani) - handle clear user data. | 932 // TODO(lipalani) - handle clear user data. |
| 982 InitOrCoalescePendingJob(old_job); | 933 InitOrCoalescePendingJob(old_job); |
| 983 } | 934 } |
| 984 RestartWaiting(); | 935 RestartWaiting(); |
| 985 } | 936 } |
| 986 | 937 |
| 987 // static | |
| 988 TimeDelta SyncSchedulerImpl::GetRecommendedDelay(const TimeDelta& last_delay) { | |
| 989 if (last_delay.InSeconds() >= kMaxBackoffSeconds) | |
| 990 return TimeDelta::FromSeconds(kMaxBackoffSeconds); | |
| 991 | |
| 992 // This calculates approx. base_delay_seconds * 2 +/- base_delay_seconds / 2 | |
| 993 int64 backoff_s = | |
| 994 std::max(static_cast<int64>(1), | |
| 995 last_delay.InSeconds() * kBackoffRandomizationFactor); | |
| 996 | |
| 997 // Flip a coin to randomize backoff interval by +/- 50%. | |
| 998 int rand_sign = base::RandInt(0, 1) * 2 - 1; | |
| 999 | |
| 1000 // Truncation is adequate for rounding here. | |
| 1001 backoff_s = backoff_s + | |
| 1002 (rand_sign * (last_delay.InSeconds() / kBackoffRandomizationFactor)); | |
| 1003 | |
| 1004 // Cap the backoff interval. | |
| 1005 backoff_s = std::max(static_cast<int64>(1), | |
| 1006 std::min(backoff_s, kMaxBackoffSeconds)); | |
| 1007 | |
| 1008 return TimeDelta::FromSeconds(backoff_s); | |
| 1009 } | |
| 1010 | |
| 1011 void SyncSchedulerImpl::RequestStop(const base::Closure& callback) { | 938 void SyncSchedulerImpl::RequestStop(const base::Closure& callback) { |
| 1012 syncer_->RequestEarlyExit(); // Safe to call from any thread. | 939 syncer_->RequestEarlyExit(); // Safe to call from any thread. |
| 1013 DCHECK(weak_handle_this_.IsInitialized()); | 940 DCHECK(weak_handle_this_.IsInitialized()); |
| 1014 SDVLOG(3) << "Posting StopImpl"; | 941 SDVLOG(3) << "Posting StopImpl"; |
| 1015 weak_handle_this_.Call(FROM_HERE, | 942 weak_handle_this_.Call(FROM_HERE, |
| 1016 &SyncSchedulerImpl::StopImpl, | 943 &SyncSchedulerImpl::StopImpl, |
| 1017 callback); | 944 callback); |
| 1018 } | 945 } |
| 1019 | 946 |
| 1020 void SyncSchedulerImpl::StopImpl(const base::Closure& callback) { | 947 void SyncSchedulerImpl::StopImpl(const base::Closure& callback) { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1192 | 1119 |
| 1193 #undef SDVLOG_LOC | 1120 #undef SDVLOG_LOC |
| 1194 | 1121 |
| 1195 #undef SDVLOG | 1122 #undef SDVLOG |
| 1196 | 1123 |
| 1197 #undef SLOG | 1124 #undef SLOG |
| 1198 | 1125 |
| 1199 #undef ENUM_CASE | 1126 #undef ENUM_CASE |
| 1200 | 1127 |
| 1201 } // namespace syncer | 1128 } // namespace syncer |
| OLD | NEW |