| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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 #ifndef SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ | 5 #ifndef SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ |
| 6 #define SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ | 6 #define SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ |
| 7 | 7 |
| 8 #include <map> | 8 #include <map> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/cancelable_callback.h" | 12 #include "base/cancelable_callback.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/gtest_prod_util.h" | 14 #include "base/gtest_prod_util.h" |
| 15 #include "base/memory/linked_ptr.h" | 15 #include "base/memory/linked_ptr.h" |
| 16 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 17 #include "base/memory/weak_ptr.h" | 17 #include "base/memory/weak_ptr.h" |
| 18 #include "base/threading/non_thread_safe.h" | 18 #include "base/threading/non_thread_safe.h" |
| 19 #include "base/time.h" | 19 #include "base/time.h" |
| 20 #include "base/timer.h" | 20 #include "base/timer.h" |
| 21 #include "sync/base/sync_export.h" | 21 #include "sync/base/sync_export.h" |
| 22 #include "sync/engine/net/server_connection_manager.h" | 22 #include "sync/engine/net/server_connection_manager.h" |
| 23 #include "sync/engine/nudge_source.h" | 23 #include "sync/engine/nudge_source.h" |
| 24 #include "sync/engine/sync_scheduler.h" | 24 #include "sync/engine/sync_scheduler.h" |
| 25 #include "sync/engine/sync_session_job.h" | |
| 26 #include "sync/engine/syncer.h" | 25 #include "sync/engine/syncer.h" |
| 27 #include "sync/internal_api/public/base/model_type_invalidation_map.h" | 26 #include "sync/internal_api/public/base/model_type_invalidation_map.h" |
| 28 #include "sync/internal_api/public/engine/polling_constants.h" | 27 #include "sync/internal_api/public/engine/polling_constants.h" |
| 29 #include "sync/internal_api/public/util/weak_handle.h" | 28 #include "sync/internal_api/public/util/weak_handle.h" |
| 29 #include "sync/sessions/nudge_tracker.h" |
| 30 #include "sync/sessions/sync_session.h" | 30 #include "sync/sessions/sync_session.h" |
| 31 #include "sync/sessions/sync_session_context.h" | 31 #include "sync/sessions/sync_session_context.h" |
| 32 | 32 |
| 33 namespace syncer { | 33 namespace syncer { |
| 34 | 34 |
| 35 class BackoffDelayProvider; | 35 class BackoffDelayProvider; |
| 36 | 36 |
| 37 namespace sessions { |
| 38 struct ModelNeutralState; |
| 39 } |
| 40 |
| 37 class SYNC_EXPORT_PRIVATE SyncSchedulerImpl | 41 class SYNC_EXPORT_PRIVATE SyncSchedulerImpl |
| 38 : public SyncScheduler, | 42 : public SyncScheduler, |
| 39 public base::NonThreadSafe { | 43 public base::NonThreadSafe { |
| 40 public: | 44 public: |
| 41 // |name| is a display string to identify the syncer thread. Takes | 45 // |name| is a display string to identify the syncer thread. Takes |
| 42 // |ownership of |syncer| and |delay_provider|. | 46 // |ownership of |syncer| and |delay_provider|. |
| 43 SyncSchedulerImpl(const std::string& name, | 47 SyncSchedulerImpl(const std::string& name, |
| 44 BackoffDelayProvider* delay_provider, | 48 BackoffDelayProvider* delay_provider, |
| 45 sessions::SyncSessionContext* context, | 49 sessions::SyncSessionContext* context, |
| 46 Syncer* syncer); | 50 Syncer* syncer); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 76 const base::TimeDelta& new_interval) OVERRIDE; | 80 const base::TimeDelta& new_interval) OVERRIDE; |
| 77 virtual void OnReceivedLongPollIntervalUpdate( | 81 virtual void OnReceivedLongPollIntervalUpdate( |
| 78 const base::TimeDelta& new_interval) OVERRIDE; | 82 const base::TimeDelta& new_interval) OVERRIDE; |
| 79 virtual void OnReceivedSessionsCommitDelay( | 83 virtual void OnReceivedSessionsCommitDelay( |
| 80 const base::TimeDelta& new_delay) OVERRIDE; | 84 const base::TimeDelta& new_delay) OVERRIDE; |
| 81 virtual void OnShouldStopSyncingPermanently() OVERRIDE; | 85 virtual void OnShouldStopSyncingPermanently() OVERRIDE; |
| 82 virtual void OnSyncProtocolError( | 86 virtual void OnSyncProtocolError( |
| 83 const sessions::SyncSessionSnapshot& snapshot) OVERRIDE; | 87 const sessions::SyncSessionSnapshot& snapshot) OVERRIDE; |
| 84 | 88 |
| 85 private: | 89 private: |
| 86 enum JobProcessDecision { | |
| 87 // Indicates we should continue with the current job. | |
| 88 CONTINUE, | |
| 89 // Indicates that we should save it to be processed later. | |
| 90 SAVE, | |
| 91 // Indicates we should drop this job. | |
| 92 DROP, | |
| 93 }; | |
| 94 | |
| 95 enum JobPriority { | 90 enum JobPriority { |
| 96 // Non-canary jobs respect exponential backoff. | 91 // Non-canary jobs respect exponential backoff. |
| 97 NORMAL_PRIORITY, | 92 NORMAL_PRIORITY, |
| 98 // Canary jobs bypass exponential backoff, so use with extreme caution. | 93 // Canary jobs bypass exponential backoff, so use with extreme caution. |
| 99 CANARY_PRIORITY | 94 CANARY_PRIORITY |
| 100 }; | 95 }; |
| 101 | 96 |
| 102 friend class SyncSchedulerTest; | 97 friend class SyncSchedulerTest; |
| 103 friend class SyncSchedulerWhiteboxTest; | 98 friend class SyncSchedulerWhiteboxTest; |
| 104 friend class SyncerTest; | 99 friend class SyncerTest; |
| 105 | 100 |
| 101 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, NoNudgesInConfigureMode); |
| 106 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, | 102 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, |
| 107 DropNudgeWhileExponentialBackOff); | 103 DropNudgeWhileExponentialBackOff); |
| 108 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, SaveNudge); | 104 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, SaveNudge); |
| 109 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, | 105 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, |
| 110 SaveNudgeWhileTypeThrottled); | 106 SaveNudgeWhileTypeThrottled); |
| 111 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueNudge); | 107 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueNudge); |
| 112 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueConfiguration); | 108 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueConfiguration); |
| 113 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, | 109 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, |
| 114 SaveConfigurationWhileThrottled); | 110 SaveConfigurationWhileThrottled); |
| 115 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, | 111 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 138 WaitInterval(Mode mode, base::TimeDelta length); | 134 WaitInterval(Mode mode, base::TimeDelta length); |
| 139 | 135 |
| 140 static const char* GetModeString(Mode mode); | 136 static const char* GetModeString(Mode mode); |
| 141 | 137 |
| 142 Mode mode; | 138 Mode mode; |
| 143 base::TimeDelta length; | 139 base::TimeDelta length; |
| 144 }; | 140 }; |
| 145 | 141 |
| 146 static const char* GetModeString(Mode mode); | 142 static const char* GetModeString(Mode mode); |
| 147 | 143 |
| 148 static const char* GetDecisionString(JobProcessDecision decision); | |
| 149 | |
| 150 // Invoke the syncer to perform a non-POLL job. | |
| 151 bool DoSyncSessionJobImpl(scoped_ptr<SyncSessionJob> job, | |
| 152 JobPriority priority); | |
| 153 | |
| 154 // Invoke the syncer to perform a nudge job. | 144 // Invoke the syncer to perform a nudge job. |
| 155 void DoNudgeSyncSessionJob(JobPriority priority); | 145 void DoNudgeSyncSessionJob(JobPriority priority); |
| 156 | 146 |
| 157 // Invoke the syncer to perform a configuration job. | 147 // Invoke the syncer to perform a configuration job. |
| 158 bool DoConfigurationSyncSessionJob(JobPriority priority); | 148 bool DoConfigurationSyncSessionJob(JobPriority priority); |
| 159 | 149 |
| 160 // Returns whether or not it's safe to run a poll job at this time. | 150 // Helper function for Do{Nudge,Configuration}SyncSessionJob. |
| 161 bool ShouldPoll(); | 151 void HandleFailure( |
| 152 const sessions::ModelNeutralState& model_neutral_state); |
| 162 | 153 |
| 163 // Invoke the Syncer to perform a poll job. | 154 // Invoke the Syncer to perform a poll job. |
| 164 void DoPollSyncSessionJob(); | 155 void DoPollSyncSessionJob(); |
| 165 | 156 |
| 166 // Called after the Syncer has performed the sync represented by |job|, to | 157 // Returns the current desired poll rate. |
| 167 // reset our state. |exited_prematurely| is true if the Syncer did not | 158 base::TimeDelta GetDesiredPollRate(); |
| 168 // cycle from job.start_step() to job.end_step(), likely because the | |
| 169 // scheduler was forced to quit the job mid-way through. | |
| 170 bool FinishSyncSessionJob(SyncSessionJob* job, | |
| 171 bool exited_prematurely, | |
| 172 sessions::SyncSession* session); | |
| 173 | 159 |
| 174 // Helper to schedule retries of a failed configure or nudge job. | 160 // True if the desired poll interval does not match the poll timer's state. |
| 175 void ScheduleNextSync(scoped_ptr<SyncSessionJob> finished_job, | 161 bool DidPollRateChange(); |
| 176 sessions::SyncSession* session); | |
| 177 | 162 |
| 178 // Helper to configure polling intervals. Used by Start and ScheduleNextSync. | 163 // Restarts the poll timeout. |
| 179 void AdjustPolling(const SyncSessionJob* old_job); | 164 void RestartPollTimer(); |
| 165 |
| 166 // Adjusts the poll timer to account for new poll interval, if necessary. |
| 167 void RestartPollTimerIfRateChanged(); |
| 180 | 168 |
| 181 // Helper to restart waiting with |wait_interval_|'s timer. | 169 // Helper to restart waiting with |wait_interval_|'s timer. |
| 182 void RestartWaiting(); | 170 void RestartWaiting(); |
| 183 | 171 |
| 184 // Helper to ScheduleNextSync in case of consecutive sync errors. | 172 // Helper to adjust our wait interval when we expereince a transient failure. |
| 185 void HandleContinuationError(scoped_ptr<SyncSessionJob> old_job, | 173 void UpdateExponentialBackoff( |
| 186 sessions::SyncSession* session); | 174 const sessions::ModelNeutralState& model_neutral_state); |
| 187 | 175 |
| 188 // Decide whether we should CONTINUE, SAVE or DROP the job. | 176 // Determines if we're allowed to contact the server right now. |
| 189 JobProcessDecision DecideOnJob(const SyncSessionJob& job, | 177 bool CanRunJobNow(JobPriority priority); |
| 190 JobPriority priority); | |
| 191 | 178 |
| 192 // Decide on whether to CONTINUE, SAVE or DROP the job when we are in | 179 // Determines if we're allowed to contact the server right now. |
| 193 // backoff mode. | 180 bool CanRunNudgeJobNow(JobPriority priority); |
| 194 JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job, | |
| 195 JobPriority priority); | |
| 196 | 181 |
| 197 // 'Impl' here refers to real implementation of public functions, running on | 182 // 'Impl' here refers to real implementation of public functions. |
| 198 // |thread_|. | |
| 199 void StopImpl(const base::Closure& callback); | 183 void StopImpl(const base::Closure& callback); |
| 200 | 184 |
| 201 // If the scheduler's current state supports it, this will create a job based | 185 // If the scheduler's current state supports it, this will create a job based |
| 202 // on the passed in parameters and coalesce it with any other pending jobs, | 186 // on the passed in parameters and coalesce it with any other pending jobs, |
| 203 // then post a delayed task to run it. It may also choose to drop the job or | 187 // then post a delayed task to run it. It may also choose to drop the job or |
| 204 // save it for later, depending on the scheduler's current state. | 188 // save it for later, depending on the scheduler's current state. |
| 205 void ScheduleNudgeImpl( | 189 void ScheduleNudgeImpl( |
| 206 const base::TimeDelta& delay, | 190 const base::TimeDelta& delay, |
| 207 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source, | 191 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source, |
| 208 const ModelTypeInvalidationMap& invalidation_map, | 192 const ModelTypeInvalidationMap& invalidation_map, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 223 | 207 |
| 224 // Transitions out of the THROTTLED WaitInterval then calls TryCanaryJob(). | 208 // Transitions out of the THROTTLED WaitInterval then calls TryCanaryJob(). |
| 225 void Unthrottle(); | 209 void Unthrottle(); |
| 226 | 210 |
| 227 // Called when the root cause of the current connection error is fixed. | 211 // Called when the root cause of the current connection error is fixed. |
| 228 void OnServerConnectionErrorFixed(); | 212 void OnServerConnectionErrorFixed(); |
| 229 | 213 |
| 230 // Creates a session for a poll and performs the sync. | 214 // Creates a session for a poll and performs the sync. |
| 231 void PollTimerCallback(); | 215 void PollTimerCallback(); |
| 232 | 216 |
| 233 // Called once the first time thread_ is started to broadcast an initial | 217 // Called as we are started to broadcast an initial session snapshot |
| 234 // session snapshot containing data like initial_sync_ended. Important when | 218 // containing data like initial_sync_ended. Important when the client starts |
| 235 // the client starts up and does not need to perform an initial sync. | 219 // up and does not need to perform an initial sync. |
| 236 void SendInitialSnapshot(); | 220 void SendInitialSnapshot(); |
| 237 | 221 |
| 238 // This is used for histogramming and analysis of ScheduleNudge* APIs. | 222 // This is used for histogramming and analysis of ScheduleNudge* APIs. |
| 239 // SyncScheduler is the ultimate choke-point for all such invocations (with | 223 // SyncScheduler is the ultimate choke-point for all such invocations (with |
| 240 // and without InvalidationState variants, all NudgeSources, etc) and as such | 224 // and without InvalidationState variants, all NudgeSources, etc) and as such |
| 241 // is the most flexible place to do this bookkeeping. | 225 // is the most flexible place to do this bookkeeping. |
| 242 void UpdateNudgeTimeRecords(const sessions::SyncSourceInfo& info); | 226 void UpdateNudgeTimeRecords(const sessions::SyncSourceInfo& info); |
| 243 | 227 |
| 244 virtual void OnActionableError(const sessions::SyncSessionSnapshot& snapshot); | 228 virtual void OnActionableError(const sessions::SyncSessionSnapshot& snapshot); |
| 245 | 229 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 273 Mode mode_; | 257 Mode mode_; |
| 274 | 258 |
| 275 // Current wait state. Null if we're not in backoff and not throttled. | 259 // Current wait state. Null if we're not in backoff and not throttled. |
| 276 scoped_ptr<WaitInterval> wait_interval_; | 260 scoped_ptr<WaitInterval> wait_interval_; |
| 277 | 261 |
| 278 scoped_ptr<BackoffDelayProvider> delay_provider_; | 262 scoped_ptr<BackoffDelayProvider> delay_provider_; |
| 279 | 263 |
| 280 // The event that will wake us up. | 264 // The event that will wake us up. |
| 281 base::OneShotTimer<SyncSchedulerImpl> pending_wakeup_timer_; | 265 base::OneShotTimer<SyncSchedulerImpl> pending_wakeup_timer_; |
| 282 | 266 |
| 283 // Pending configure job storage. Note that | 267 // Storage for variables related to an in-progress configure request. Note |
| 284 // (mode_ != CONFIGURATION_MODE) \implies !pending_configure_job_. | 268 // that (mode_ != CONFIGURATION_MODE) \implies !pending_configure_params_. |
| 285 scoped_ptr<SyncSessionJob> pending_configure_job_; | 269 scoped_ptr<ConfigurationParams> pending_configure_params_; |
| 286 | 270 |
| 287 // Pending nudge job storage. These jobs can exist in CONFIGURATION_MODE, but | 271 // If we have a nudge pending to run soon, it will be listed here. |
| 288 // they will be run only in NORMAL_MODE. | 272 base::TimeTicks scheduled_nudge_time_; |
| 289 scoped_ptr<SyncSessionJob> pending_nudge_job_; | 273 |
| 274 // Keeps track of work that the syncer needs to handle. |
| 275 sessions::NudgeTracker nudge_tracker_; |
| 290 | 276 |
| 291 // Invoked to run through the sync cycle. | 277 // Invoked to run through the sync cycle. |
| 292 scoped_ptr<Syncer> syncer_; | 278 scoped_ptr<Syncer> syncer_; |
| 293 | 279 |
| 294 sessions::SyncSessionContext* session_context_; | 280 sessions::SyncSessionContext* session_context_; |
| 295 | 281 |
| 296 // A map tracking LOCAL NudgeSource invocations of ScheduleNudge* APIs, | 282 // A map tracking LOCAL NudgeSource invocations of ScheduleNudge* APIs, |
| 297 // organized by datatype. Each datatype that was part of the types requested | 283 // organized by datatype. Each datatype that was part of the types requested |
| 298 // in the call will have its TimeTicks value updated. | 284 // in the call will have its TimeTicks value updated. |
| 299 typedef std::map<ModelType, base::TimeTicks> ModelTypeTimeMap; | 285 typedef std::map<ModelType, base::TimeTicks> ModelTypeTimeMap; |
| 300 ModelTypeTimeMap last_local_nudges_by_model_type_; | 286 ModelTypeTimeMap last_local_nudges_by_model_type_; |
| 301 | 287 |
| 302 // Used as an "anti-reentrancy defensive assertion". | 288 // Used as an "anti-reentrancy defensive assertion". |
| 303 // While true, it is illegal for any new scheduling activity to take place. | 289 // While true, it is illegal for any new scheduling activity to take place. |
| 304 // Ensures that higher layers don't break this law in response to events that | 290 // Ensures that higher layers don't break this law in response to events that |
| 305 // take place during a sync cycle. We call this out because such violations | 291 // take place during a sync cycle. We call this out because such violations |
| 306 // could result in tight sync loops hitting sync servers. | 292 // could result in tight sync loops hitting sync servers. |
| 307 bool no_scheduling_allowed_; | 293 bool no_scheduling_allowed_; |
| 308 | 294 |
| 309 DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl); | 295 DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl); |
| 310 }; | 296 }; |
| 311 | 297 |
| 312 } // namespace syncer | 298 } // namespace syncer |
| 313 | 299 |
| 314 #endif // SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ | 300 #endif // SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ |
| OLD | NEW |