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 #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/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/gtest_prod_util.h" | 13 #include "base/gtest_prod_util.h" |
14 #include "base/memory/linked_ptr.h" | 14 #include "base/memory/linked_ptr.h" |
15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
16 #include "base/memory/weak_ptr.h" | 16 #include "base/memory/weak_ptr.h" |
17 #include "base/observer_list.h" | 17 #include "base/observer_list.h" |
18 #include "base/time.h" | 18 #include "base/time.h" |
19 #include "base/timer.h" | 19 #include "base/timer.h" |
20 #include "sync/engine/net/server_connection_manager.h" | 20 #include "sync/engine/net/server_connection_manager.h" |
21 #include "sync/engine/nudge_source.h" | 21 #include "sync/engine/nudge_source.h" |
22 #include "sync/engine/sync_scheduler.h" | 22 #include "sync/engine/sync_scheduler.h" |
23 #include "sync/engine/sync_session_job.h" | |
24 #include "sync/engine/syncer.h" | 23 #include "sync/engine/syncer.h" |
25 #include "sync/internal_api/public/base/model_type_invalidation_map.h" | 24 #include "sync/internal_api/public/base/model_type_invalidation_map.h" |
26 #include "sync/internal_api/public/engine/polling_constants.h" | 25 #include "sync/internal_api/public/engine/polling_constants.h" |
27 #include "sync/internal_api/public/util/weak_handle.h" | 26 #include "sync/internal_api/public/util/weak_handle.h" |
28 #include "sync/sessions/sync_session.h" | 27 #include "sync/sessions/sync_session.h" |
29 #include "sync/sessions/sync_session_context.h" | 28 #include "sync/sessions/sync_session_context.h" |
30 | 29 |
31 namespace syncer { | 30 namespace syncer { |
32 | 31 |
33 class BackoffDelayProvider; | 32 class BackoffDelayProvider; |
34 | 33 |
35 class SyncSchedulerImpl : public SyncScheduler { | 34 class SyncSchedulerImpl : public SyncScheduler { |
36 public: | 35 public: |
37 // |name| is a display string to identify the syncer thread. Takes | 36 // |name| is a display string to identify the syncer thread. Takes |
38 // |ownership of |syncer| and |delay_provider|. | 37 // |ownership of |syncer| and |delay_provider|. |
39 SyncSchedulerImpl(const std::string& name, | 38 SyncSchedulerImpl(const std::string& name, |
40 BackoffDelayProvider* delay_provider, | 39 BackoffDelayProvider* delay_provider, |
41 sessions::SyncSessionContext* context, | 40 sessions::SyncSessionContext* context, |
42 Syncer* syncer); | 41 Syncer* syncer); |
43 | 42 |
44 // Calls Stop(). | 43 // Calls Stop(). |
45 virtual ~SyncSchedulerImpl(); | 44 virtual ~SyncSchedulerImpl(); |
46 | 45 |
47 virtual void Start(Mode mode) OVERRIDE; | 46 virtual void Start(Mode mode) OVERRIDE; |
48 virtual bool ScheduleConfiguration( | 47 virtual bool ScheduleConfiguration( |
49 const ConfigurationParams& params) OVERRIDE; | 48 const ConfigurationParams& params) OVERRIDE; |
50 virtual void RequestStop(const base::Closure& callback) OVERRIDE; | 49 virtual void RequestStop(const base::Closure& callback) OVERRIDE; |
51 virtual void ScheduleNudgeAsync( | 50 virtual void ScheduleNudgeAsync( |
52 const base::TimeDelta& desired_delay, | 51 const base::TimeDelta& delay, |
53 NudgeSource source, | 52 NudgeSource source, |
54 ModelTypeSet types, | 53 ModelTypeSet types, |
55 const tracked_objects::Location& nudge_location) OVERRIDE; | 54 const tracked_objects::Location& nudge_location) OVERRIDE; |
56 virtual void ScheduleNudgeWithStatesAsync( | 55 virtual void ScheduleNudgeWithStatesAsync( |
57 const base::TimeDelta& desired_delay, NudgeSource source, | 56 const base::TimeDelta& delay, NudgeSource source, |
58 const ModelTypeInvalidationMap& invalidation_map, | 57 const ModelTypeInvalidationMap& invalidation_map, |
59 const tracked_objects::Location& nudge_location) OVERRIDE; | 58 const tracked_objects::Location& nudge_location) OVERRIDE; |
60 virtual void SetNotificationsEnabled(bool notifications_enabled) OVERRIDE; | 59 virtual void SetNotificationsEnabled(bool notifications_enabled) OVERRIDE; |
61 | 60 |
62 virtual base::TimeDelta GetSessionsCommitDelay() const OVERRIDE; | 61 virtual base::TimeDelta GetSessionsCommitDelay() const OVERRIDE; |
63 | 62 |
64 virtual void OnCredentialsUpdated() OVERRIDE; | 63 virtual void OnCredentialsUpdated() OVERRIDE; |
65 virtual void OnConnectionStatusChange() OVERRIDE; | 64 virtual void OnConnectionStatusChange() OVERRIDE; |
66 | 65 |
67 // SyncSession::Delegate implementation. | 66 // SyncSession::Delegate implementation. |
(...skipping 13 matching lines...) Expand all Loading... |
81 private: | 80 private: |
82 enum JobProcessDecision { | 81 enum JobProcessDecision { |
83 // Indicates we should continue with the current job. | 82 // Indicates we should continue with the current job. |
84 CONTINUE, | 83 CONTINUE, |
85 // Indicates that we should save it to be processed later. | 84 // Indicates that we should save it to be processed later. |
86 SAVE, | 85 SAVE, |
87 // Indicates we should drop this job. | 86 // Indicates we should drop this job. |
88 DROP, | 87 DROP, |
89 }; | 88 }; |
90 | 89 |
| 90 struct SyncSessionJob { |
| 91 // An enum used to describe jobs for scheduling purposes. |
| 92 enum SyncSessionJobPurpose { |
| 93 // Uninitialized state, should never be hit in practice. |
| 94 UNKNOWN = -1, |
| 95 // Our poll timer schedules POLL jobs periodically based on a server |
| 96 // assigned poll interval. |
| 97 POLL, |
| 98 // A nudge task can come from a variety of components needing to force |
| 99 // a sync. The source is inferable from |session.source()|. |
| 100 NUDGE, |
| 101 // Typically used for fetching updates for a subset of the enabled types |
| 102 // during initial sync or reconfiguration. |
| 103 CONFIGURATION, |
| 104 }; |
| 105 SyncSessionJob(); |
| 106 SyncSessionJob(SyncSessionJobPurpose purpose, base::TimeTicks start, |
| 107 linked_ptr<sessions::SyncSession> session, bool is_canary_job, |
| 108 const ConfigurationParams& config_params, |
| 109 const tracked_objects::Location& nudge_location); |
| 110 ~SyncSessionJob(); |
| 111 static const char* GetPurposeString(SyncSessionJobPurpose purpose); |
| 112 |
| 113 SyncSessionJobPurpose purpose; |
| 114 base::TimeTicks scheduled_start; |
| 115 linked_ptr<sessions::SyncSession> session; |
| 116 bool is_canary_job; |
| 117 ConfigurationParams config_params; |
| 118 |
| 119 // This is the location the job came from. Used for debugging. |
| 120 // In case of multiple nudges getting coalesced this stores the |
| 121 // first location that came in. |
| 122 tracked_objects::Location from_here; |
| 123 }; |
91 friend class SyncSchedulerTest; | 124 friend class SyncSchedulerTest; |
92 friend class SyncSchedulerWhiteboxTest; | 125 friend class SyncSchedulerWhiteboxTest; |
93 friend class SyncerTest; | 126 friend class SyncerTest; |
94 | 127 |
95 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, | 128 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, |
96 DropNudgeWhileExponentialBackOff); | 129 DropNudgeWhileExponentialBackOff); |
97 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, SaveNudge); | 130 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, SaveNudge); |
98 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, | 131 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, |
99 SaveNudgeWhileTypeThrottled); | 132 SaveNudgeWhileTypeThrottled); |
100 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueNudge); | 133 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueNudge); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 | 165 |
133 Mode mode; | 166 Mode mode; |
134 | 167 |
135 // This bool is set to true if we have observed a nudge during this | 168 // This bool is set to true if we have observed a nudge during this |
136 // interval and mode == EXPONENTIAL_BACKOFF. | 169 // interval and mode == EXPONENTIAL_BACKOFF. |
137 bool had_nudge; | 170 bool had_nudge; |
138 base::TimeDelta length; | 171 base::TimeDelta length; |
139 base::OneShotTimer<SyncSchedulerImpl> timer; | 172 base::OneShotTimer<SyncSchedulerImpl> timer; |
140 | 173 |
141 // Configure jobs are saved only when backing off or throttling. So we | 174 // Configure jobs are saved only when backing off or throttling. So we |
142 // expose the pointer here (does not own, similar to pending_nudge). | 175 // expose the pointer here. |
143 SyncSessionJob* pending_configure_job; | 176 scoped_ptr<SyncSessionJob> pending_configure_job; |
144 }; | 177 }; |
145 | 178 |
146 static const char* GetModeString(Mode mode); | 179 static const char* GetModeString(Mode mode); |
147 | 180 |
148 static const char* GetDecisionString(JobProcessDecision decision); | 181 static const char* GetDecisionString(JobProcessDecision decision); |
149 | 182 |
| 183 // Assign |start| and |end| to appropriate SyncerStep values for the |
| 184 // specified |purpose|. |
| 185 static void SetSyncerStepsForPurpose( |
| 186 SyncSessionJob::SyncSessionJobPurpose purpose, |
| 187 SyncerStep* start, SyncerStep* end); |
| 188 |
150 // Helpers that log before posting to |sync_loop_|. These will only post | 189 // Helpers that log before posting to |sync_loop_|. These will only post |
151 // the task in between calls to Start/Stop. | 190 // the task in between calls to Start/Stop. |
152 void PostTask(const tracked_objects::Location& from_here, | 191 void PostTask(const tracked_objects::Location& from_here, |
153 const char* name, | 192 const char* name, |
154 const base::Closure& task); | 193 const base::Closure& task); |
155 void PostDelayedTask(const tracked_objects::Location& from_here, | 194 void PostDelayedTask(const tracked_objects::Location& from_here, |
156 const char* name, | 195 const char* name, |
157 const base::Closure& task, | 196 const base::Closure& task, |
158 base::TimeDelta delay); | 197 base::TimeDelta delay); |
159 | 198 |
160 // Helper to assemble a job and post a delayed task to sync. | 199 // Helper to assemble a job and post a delayed task to sync. |
161 void ScheduleSyncSessionJob(scoped_ptr<SyncSessionJob> job); | 200 void ScheduleSyncSessionJob(const SyncSessionJob& job); |
162 | 201 |
163 // Invoke the Syncer to perform a sync. | 202 // Invoke the Syncer to perform a sync. |
164 bool DoSyncSessionJob(scoped_ptr<SyncSessionJob> job); | 203 void DoSyncSessionJob(const SyncSessionJob& job); |
165 | 204 |
166 // Called after the Syncer has performed the sync represented by |job|, to | 205 // Called after the Syncer has performed the sync represented by |job|, to |
167 // reset our state. |exited_prematurely| is true if the Syncer did not | 206 // reset our state. |
168 // cycle from job.start_step() to job.end_step(), likely because the | 207 void FinishSyncSessionJob(const SyncSessionJob& job); |
169 // scheduler was forced to quit the job mid-way through. | |
170 bool FinishSyncSessionJob(scoped_ptr<SyncSessionJob> job, | |
171 bool exited_prematurely); | |
172 | 208 |
173 // Helper to FinishSyncSessionJob to schedule the next sync operation. | 209 // Helper to FinishSyncSessionJob to schedule the next sync operation. |
174 // |succeeded| carries the return value of |old_job|->Finish. | 210 void ScheduleNextSync(const SyncSessionJob& old_job); |
175 void ScheduleNextSync(scoped_ptr<SyncSessionJob> finished_job, | |
176 bool succeeded); | |
177 | 211 |
178 // Helper to configure polling intervals. Used by Start and ScheduleNextSync. | 212 // Helper to configure polling intervals. Used by Start and ScheduleNextSync. |
179 void AdjustPolling(const SyncSessionJob* old_job); | 213 void AdjustPolling(const SyncSessionJob* old_job); |
180 | 214 |
181 // Helper to restart waiting with |wait_interval_|'s timer. | 215 // Helper to restart waiting with |wait_interval_|'s timer. |
182 void RestartWaiting(scoped_ptr<SyncSessionJob> job); | 216 void RestartWaiting(); |
183 | 217 |
184 // Helper to ScheduleNextSync in case of consecutive sync errors. | 218 // Helper to ScheduleNextSync in case of consecutive sync errors. |
185 void HandleContinuationError(scoped_ptr<SyncSessionJob> old_job); | 219 void HandleContinuationError(const SyncSessionJob& old_job); |
| 220 |
| 221 // Determines if it is legal to run |job| by checking current |
| 222 // operational mode, backoff or throttling, freshness |
| 223 // (so we don't make redundant syncs), and connection. |
| 224 bool ShouldRunJob(const SyncSessionJob& job); |
186 | 225 |
187 // Decide whether we should CONTINUE, SAVE or DROP the job. | 226 // Decide whether we should CONTINUE, SAVE or DROP the job. |
188 JobProcessDecision DecideOnJob(const SyncSessionJob& job); | 227 JobProcessDecision DecideOnJob(const SyncSessionJob& job); |
189 | 228 |
190 // If DecideOnJob decides that |job| should be SAVEd, this function will | |
191 // carry out the task of actually "saving" (or coalescing) the job. | |
192 void HandleSaveJobDecision(scoped_ptr<SyncSessionJob> job); | |
193 | |
194 // Decide on whether to CONTINUE, SAVE or DROP the job when we are in | 229 // Decide on whether to CONTINUE, SAVE or DROP the job when we are in |
195 // backoff mode. | 230 // backoff mode. |
196 JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job); | 231 JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job); |
197 | 232 |
| 233 // Saves the job for future execution. Note: It drops all the poll jobs. |
| 234 void SaveJob(const SyncSessionJob& job); |
| 235 |
| 236 // Coalesces the current job with the pending nudge. |
| 237 void InitOrCoalescePendingJob(const SyncSessionJob& job); |
| 238 |
198 // 'Impl' here refers to real implementation of public functions, running on | 239 // 'Impl' here refers to real implementation of public functions, running on |
199 // |thread_|. | 240 // |thread_|. |
200 void StopImpl(const base::Closure& callback); | 241 void StopImpl(const base::Closure& callback); |
201 void ScheduleNudgeImpl( | 242 void ScheduleNudgeImpl( |
202 const base::TimeDelta& delay, | 243 const base::TimeDelta& delay, |
203 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source, | 244 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source, |
204 const ModelTypeInvalidationMap& invalidation_map, | 245 const ModelTypeInvalidationMap& invalidation_map, |
205 const tracked_objects::Location& nudge_location); | 246 bool is_canary_job, const tracked_objects::Location& nudge_location); |
206 | 247 |
207 // Returns true if the client is currently in exponential backoff. | 248 // Returns true if the client is currently in exponential backoff. |
208 bool IsBackingOff() const; | 249 bool IsBackingOff() const; |
209 | 250 |
210 // Helper to signal all listeners registered with |session_context_|. | 251 // Helper to signal all listeners registered with |session_context_|. |
211 void Notify(SyncEngineEvent::EventCause cause); | 252 void Notify(SyncEngineEvent::EventCause cause); |
212 | 253 |
213 // Callback to change backoff state. |to_be_canary| in both cases is the job | 254 // Callback to change backoff state. |
214 // that should be granted canary privileges. Note: it is possible that the | 255 void DoCanaryJob(); |
215 // job that gets scheduled when this callback is scheduled is different from | 256 void Unthrottle(); |
216 // the job that will actually get executed, because other jobs may have been | |
217 // scheduled while we were waiting for the callback. | |
218 void DoCanaryJob(scoped_ptr<SyncSessionJob> to_be_canary); | |
219 void Unthrottle(scoped_ptr<SyncSessionJob> to_be_canary); | |
220 | 257 |
221 // Returns a pending job that has potential to run given the state of the | 258 // Executes the pending job. Called whenever an event occurs that may |
222 // scheduler, if it exists. Useful whenever an event occurs that may | 259 // change conditions permitting a job to run. Like when network connection is |
223 // change conditions that permit a job to run, such as re-establishing | 260 // re-established, mode changes etc. |
224 // network connection, auth refresh, mode changes etc. Note that the returned | 261 void DoPendingJobIfPossible(bool is_canary_job); |
225 // job may have been scheduled to run at a later time, or may have been | |
226 // unscheduled. In the former case, this will result in abandoning the old | |
227 // job and effectively cancelling it. | |
228 scoped_ptr<SyncSessionJob> TakePendingJobForCurrentMode(); | |
229 | 262 |
230 // Called when the root cause of the current connection error is fixed. | 263 // Called when the root cause of the current connection error is fixed. |
231 void OnServerConnectionErrorFixed(); | 264 void OnServerConnectionErrorFixed(); |
232 | 265 |
233 scoped_ptr<sessions::SyncSession> CreateSyncSession( | 266 // The pointer is owned by the caller. |
| 267 sessions::SyncSession* CreateSyncSession( |
234 const sessions::SyncSourceInfo& info); | 268 const sessions::SyncSourceInfo& info); |
235 | 269 |
236 // Creates a session for a poll and performs the sync. | 270 // Creates a session for a poll and performs the sync. |
237 void PollTimerCallback(); | 271 void PollTimerCallback(); |
238 | 272 |
239 // Used to update |connection_code_|, see below. | 273 // Used to update |connection_code_|, see below. |
240 void UpdateServerConnectionManagerStatus( | 274 void UpdateServerConnectionManagerStatus( |
241 HttpResponse::ServerConnectionCode code); | 275 HttpResponse::ServerConnectionCode code); |
242 | 276 |
243 // Called once the first time thread_ is started to broadcast an initial | 277 // Called once the first time thread_ is started to broadcast an initial |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 | 316 |
283 // Periodic timer for polling. See AdjustPolling. | 317 // Periodic timer for polling. See AdjustPolling. |
284 base::RepeatingTimer<SyncSchedulerImpl> poll_timer_; | 318 base::RepeatingTimer<SyncSchedulerImpl> poll_timer_; |
285 | 319 |
286 // The mode of operation. | 320 // The mode of operation. |
287 Mode mode_; | 321 Mode mode_; |
288 | 322 |
289 // The latest connection code we got while trying to connect. | 323 // The latest connection code we got while trying to connect. |
290 HttpResponse::ServerConnectionCode connection_code_; | 324 HttpResponse::ServerConnectionCode connection_code_; |
291 | 325 |
292 // Tracks (does not own) in-flight nudges (scheduled or unscheduled), | 326 // Tracks in-flight nudges so we can coalesce. |
293 // so we can coalesce. NULL if there is no pending nudge. | 327 scoped_ptr<SyncSessionJob> pending_nudge_; |
294 SyncSessionJob* pending_nudge_; | |
295 | |
296 // There are certain situations where we want to remember a nudge, but | |
297 // there is no well defined moment in time in the future when that nudge | |
298 // should run, e.g. if it requires a mode switch or updated auth credentials. | |
299 // This member will own NUDGE jobs in those cases, until an external event | |
300 // (mode switch or fixed auth) occurs to trigger a retry. Should be treated | |
301 // as opaque / not interacted with (i.e. we could build a wrapper to | |
302 // hide the type, but that's probably overkill). | |
303 scoped_ptr<SyncSessionJob> unscheduled_nudge_storage_; | |
304 | 328 |
305 // Current wait state. Null if we're not in backoff and not throttled. | 329 // Current wait state. Null if we're not in backoff and not throttled. |
306 scoped_ptr<WaitInterval> wait_interval_; | 330 scoped_ptr<WaitInterval> wait_interval_; |
307 | 331 |
308 scoped_ptr<BackoffDelayProvider> delay_provider_; | 332 scoped_ptr<BackoffDelayProvider> delay_provider_; |
309 | 333 |
310 // Invoked to run through the sync cycle. | 334 // Invoked to run through the sync cycle. |
311 scoped_ptr<Syncer> syncer_; | 335 scoped_ptr<Syncer> syncer_; |
312 | 336 |
313 sessions::SyncSessionContext* session_context_; | 337 sessions::SyncSessionContext* session_context_; |
(...skipping 10 matching lines...) Expand all Loading... |
324 // take place during a sync cycle. We call this out because such violations | 348 // take place during a sync cycle. We call this out because such violations |
325 // could result in tight sync loops hitting sync servers. | 349 // could result in tight sync loops hitting sync servers. |
326 bool no_scheduling_allowed_; | 350 bool no_scheduling_allowed_; |
327 | 351 |
328 DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl); | 352 DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl); |
329 }; | 353 }; |
330 | 354 |
331 } // namespace syncer | 355 } // namespace syncer |
332 | 356 |
333 #endif // SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ | 357 #endif // SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ |
OLD | NEW |