Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: sync/engine/sync_scheduler.h

Issue 10701046: sync: Remove SyncManager::TestingMode in favour of InternalComponentsFactory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: now with more scope Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 // A class to schedule syncer tasks intelligently. 5 // A class to schedule syncer tasks intelligently.
6 #ifndef SYNC_ENGINE_SYNC_SCHEDULER_H_ 6 #ifndef SYNC_ENGINE_SYNC_SCHEDULER_H_
7 #define SYNC_ENGINE_SYNC_SCHEDULER_H_ 7 #define SYNC_ENGINE_SYNC_SCHEDULER_H_
8 8
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"
14 #include "base/memory/linked_ptr.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/observer_list.h"
18 #include "base/time.h" 13 #include "base/time.h"
19 #include "base/timer.h"
20 #include "sync/engine/net/server_connection_manager.h"
21 #include "sync/engine/nudge_source.h" 14 #include "sync/engine/nudge_source.h"
22 #include "sync/engine/syncer.h"
23 #include "sync/internal_api/public/base/model_type_payload_map.h" 15 #include "sync/internal_api/public/base/model_type_payload_map.h"
24 #include "sync/internal_api/public/engine/polling_constants.h"
25 #include "sync/internal_api/public/util/weak_handle.h"
26 #include "sync/sessions/sync_session.h" 16 #include "sync/sessions/sync_session.h"
27 #include "sync/sessions/sync_session_context.h"
28 17
29 class MessageLoop; 18 class MessageLoop;
30 19
31 namespace tracked_objects { 20 namespace tracked_objects {
32 class Location; 21 class Location;
33 } // namespace tracked_objects 22 } // namespace tracked_objects
34 23
35 namespace syncer { 24 namespace syncer {
36 25
37 struct ServerConnectionEvent; 26 struct ServerConnectionEvent;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 // normal mode. 60 // normal mode.
72 CONFIGURATION_MODE, 61 CONFIGURATION_MODE,
73 // Resumes polling and allows nudges, drops configuration tasks. Runs 62 // Resumes polling and allows nudges, drops configuration tasks. Runs
74 // through entire sync cycle. 63 // through entire sync cycle.
75 NORMAL_MODE, 64 NORMAL_MODE,
76 }; 65 };
77 66
78 // All methods of SyncScheduler must be called on the same thread 67 // All methods of SyncScheduler must be called on the same thread
79 // (except for RequestEarlyExit()). 68 // (except for RequestEarlyExit()).
80 69
81 // |name| is a display string to identify the syncer thread. Takes 70 SyncScheduler();
82 // |ownership of |syncer|.
83 SyncScheduler(const std::string& name,
84 sessions::SyncSessionContext* context, Syncer* syncer);
85
86 // Calls Stop().
87 virtual ~SyncScheduler(); 71 virtual ~SyncScheduler();
88 72
89 // Start the scheduler with the given mode. If the scheduler is 73 // Start the scheduler with the given mode. If the scheduler is
90 // already started, switch to the given mode, although some 74 // already started, switch to the given mode, although some
91 // scheduled tasks from the old mode may still run. 75 // scheduled tasks from the old mode may still run.
92 virtual void Start(Mode mode); 76 virtual void Start(Mode mode) = 0;
93 77
94 // Schedules the configuration task specified by |params|. Returns true if 78 // Schedules the configuration task specified by |params|. Returns true if
95 // the configuration task executed immediately, false if it had to be 79 // the configuration task executed immediately, false if it had to be
96 // scheduled for a later attempt. |params.ready_task| is invoked whenever the 80 // scheduled for a later attempt. |params.ready_task| is invoked whenever the
97 // configuration task executes. 81 // configuration task executes.
98 // Note: must already be in CONFIGURATION mode. 82 // Note: must already be in CONFIGURATION mode.
99 virtual bool ScheduleConfiguration(const ConfigurationParams& params); 83 virtual bool ScheduleConfiguration(const ConfigurationParams& params) = 0;
100 84
101 // Request that any running syncer task stop as soon as possible and 85 // Request that any running syncer task stop as soon as possible and
102 // cancel all scheduled tasks. This function can be called from any thread, 86 // cancel all scheduled tasks. This function can be called from any thread,
103 // and should in fact be called from a thread that isn't the sync loop to 87 // and should in fact be called from a thread that isn't the sync loop to
104 // allow preempting ongoing sync cycles. 88 // allow preempting ongoing sync cycles.
105 // Invokes |callback| from the sync loop once syncer is idle and all tasks 89 // Invokes |callback| from the sync loop once syncer is idle and all tasks
106 // are cancelled. 90 // are cancelled.
107 void RequestStop(const base::Closure& callback); 91 virtual void RequestStop(const base::Closure& callback) = 0;
108 92
109 // The meat and potatoes. Both of these methods will post a delayed task 93 // The meat and potatoes. Both of these methods will post a delayed task
110 // to attempt the actual nudge (see ScheduleNudgeImpl). 94 // to attempt the actual nudge (see ScheduleNudgeImpl).
111 void ScheduleNudgeAsync(const base::TimeDelta& delay, NudgeSource source, 95 virtual void ScheduleNudgeAsync(
112 syncer::ModelTypeSet types, 96 const base::TimeDelta& delay,
113 const tracked_objects::Location& nudge_location); 97 NudgeSource source,
114 void ScheduleNudgeWithPayloadsAsync( 98 syncer::ModelTypeSet types,
99 const tracked_objects::Location& nudge_location) = 0;
100 virtual void ScheduleNudgeWithPayloadsAsync(
115 const base::TimeDelta& delay, NudgeSource source, 101 const base::TimeDelta& delay, NudgeSource source,
116 const syncer::ModelTypePayloadMap& types_with_payloads, 102 const syncer::ModelTypePayloadMap& types_with_payloads,
117 const tracked_objects::Location& nudge_location); 103 const tracked_objects::Location& nudge_location) = 0;
118
119 void CleanupDisabledTypes();
120 104
121 // Change status of notifications in the SyncSessionContext. 105 // Change status of notifications in the SyncSessionContext.
122 void set_notifications_enabled(bool notifications_enabled); 106 virtual void SetNotificationsEnabled(bool notifications_enabled) = 0;
123 107
124 base::TimeDelta sessions_commit_delay() const; 108 virtual base::TimeDelta GetSessionsCommitDelay() const = 0;
125
126 // DDOS avoidance function. Calculates how long we should wait before trying
127 // again after a failed sync attempt, where the last delay was |base_delay|.
128 // TODO(tim): Look at URLRequestThrottlerEntryInterface.
129 static base::TimeDelta GetRecommendedDelay(const base::TimeDelta& base_delay);
130 109
131 // Called when credentials are updated by the user. 110 // Called when credentials are updated by the user.
132 void OnCredentialsUpdated(); 111 virtual void OnCredentialsUpdated() = 0;
133 112
134 // Called when the network layer detects a connection status change. 113 // Called when the network layer detects a connection status change.
135 void OnConnectionStatusChange(); 114 virtual void OnConnectionStatusChange() = 0;
136
137 // SyncSession::Delegate implementation.
138 virtual void OnSilencedUntil(
139 const base::TimeTicks& silenced_until) OVERRIDE;
140 virtual bool IsSyncingCurrentlySilenced() OVERRIDE;
141 virtual void OnReceivedShortPollIntervalUpdate(
142 const base::TimeDelta& new_interval) OVERRIDE;
143 virtual void OnReceivedLongPollIntervalUpdate(
144 const base::TimeDelta& new_interval) OVERRIDE;
145 virtual void OnReceivedSessionsCommitDelay(
146 const base::TimeDelta& new_delay) OVERRIDE;
147 virtual void OnShouldStopSyncingPermanently() OVERRIDE;
148 virtual void OnSyncProtocolError(
149 const sessions::SyncSessionSnapshot& snapshot) OVERRIDE;
150
151 private:
152 enum JobProcessDecision {
153 // Indicates we should continue with the current job.
154 CONTINUE,
155 // Indicates that we should save it to be processed later.
156 SAVE,
157 // Indicates we should drop this job.
158 DROP,
159 };
160
161 struct SyncSessionJob {
162 // An enum used to describe jobs for scheduling purposes.
163 enum SyncSessionJobPurpose {
164 // Uninitialized state, should never be hit in practice.
165 UNKNOWN = -1,
166 // Our poll timer schedules POLL jobs periodically based on a server
167 // assigned poll interval.
168 POLL,
169 // A nudge task can come from a variety of components needing to force
170 // a sync. The source is inferable from |session.source()|.
171 NUDGE,
172 // Typically used for fetching updates for a subset of the enabled types
173 // during initial sync or reconfiguration. We don't run all steps of
174 // the sync cycle for these (e.g. CleanupDisabledTypes is skipped).
175 CONFIGURATION,
176 // The user disabled some types and we have to clean up the data
177 // for those.
178 CLEANUP_DISABLED_TYPES,
179 };
180 SyncSessionJob();
181 SyncSessionJob(SyncSessionJobPurpose purpose, base::TimeTicks start,
182 linked_ptr<sessions::SyncSession> session, bool is_canary_job,
183 const ConfigurationParams& config_params,
184 const tracked_objects::Location& nudge_location);
185 ~SyncSessionJob();
186 static const char* GetPurposeString(SyncSessionJobPurpose purpose);
187
188 SyncSessionJobPurpose purpose;
189 base::TimeTicks scheduled_start;
190 linked_ptr<sessions::SyncSession> session;
191 bool is_canary_job;
192 ConfigurationParams config_params;
193
194 // This is the location the job came from. Used for debugging.
195 // In case of multiple nudges getting coalesced this stores the
196 // first location that came in.
197 tracked_objects::Location from_here;
198 };
199 friend class SyncSchedulerTest;
200 friend class SyncSchedulerWhiteboxTest;
201 friend class SyncerTest;
202
203 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
204 DropNudgeWhileExponentialBackOff);
205 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, SaveNudge);
206 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
207 SaveNudgeWhileTypeThrottled);
208 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueNudge);
209 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, DropPoll);
210 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinuePoll);
211 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueConfiguration);
212 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
213 SaveConfigurationWhileThrottled);
214 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
215 SaveNudgeWhileThrottled);
216 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
217 ContinueCanaryJobConfig);
218 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
219 ContinueNudgeWhileExponentialBackOff);
220 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerTest, TransientPollFailure);
221
222 // A component used to get time delays associated with exponential backoff.
223 // Encapsulated into a class to facilitate testing.
224 class DelayProvider {
225 public:
226 DelayProvider();
227 virtual base::TimeDelta GetDelay(const base::TimeDelta& last_delay);
228 virtual ~DelayProvider();
229 private:
230 DISALLOW_COPY_AND_ASSIGN(DelayProvider);
231 };
232
233 struct WaitInterval {
234 enum Mode {
235 // Uninitialized state, should not be set in practice.
236 UNKNOWN = -1,
237 // A wait interval whose duration has been affected by exponential
238 // backoff.
239 // EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval.
240 EXPONENTIAL_BACKOFF,
241 // A server-initiated throttled interval. We do not allow any syncing
242 // during such an interval.
243 THROTTLED,
244 };
245 WaitInterval();
246 ~WaitInterval();
247 WaitInterval(Mode mode, base::TimeDelta length);
248
249 static const char* GetModeString(Mode mode);
250
251 Mode mode;
252
253 // This bool is set to true if we have observed a nudge during this
254 // interval and mode == EXPONENTIAL_BACKOFF.
255 bool had_nudge;
256 base::TimeDelta length;
257 base::OneShotTimer<SyncScheduler> timer;
258
259 // Configure jobs are saved only when backing off or throttling. So we
260 // expose the pointer here.
261 scoped_ptr<SyncSessionJob> pending_configure_job;
262 };
263
264 static const char* GetModeString(Mode mode);
265
266 static const char* GetDecisionString(JobProcessDecision decision);
267
268 // Assign |start| and |end| to appropriate SyncerStep values for the
269 // specified |purpose|.
270 static void SetSyncerStepsForPurpose(
271 SyncSessionJob::SyncSessionJobPurpose purpose,
272 SyncerStep* start, SyncerStep* end);
273
274 // Helpers that log before posting to |sync_loop_|. These will only post
275 // the task in between calls to Start/Stop.
276 void PostTask(const tracked_objects::Location& from_here,
277 const char* name,
278 const base::Closure& task);
279 void PostDelayedTask(const tracked_objects::Location& from_here,
280 const char* name,
281 const base::Closure& task,
282 base::TimeDelta delay);
283
284 // Helper to assemble a job and post a delayed task to sync.
285 void ScheduleSyncSessionJob(const SyncSessionJob& job);
286
287 // Invoke the Syncer to perform a sync.
288 void DoSyncSessionJob(const SyncSessionJob& job);
289
290 // Called after the Syncer has performed the sync represented by |job|, to
291 // reset our state.
292 void FinishSyncSessionJob(const SyncSessionJob& job);
293
294 // Record important state that might be needed in future syncs, such as which
295 // data types may require cleanup.
296 void UpdateCarryoverSessionState(const SyncSessionJob& old_job);
297
298 // Helper to FinishSyncSessionJob to schedule the next sync operation.
299 void ScheduleNextSync(const SyncSessionJob& old_job);
300
301 // Helper to configure polling intervals. Used by Start and ScheduleNextSync.
302 void AdjustPolling(const SyncSessionJob* old_job);
303
304 // Helper to restart waiting with |wait_interval_|'s timer.
305 void RestartWaiting();
306
307 // Helper to ScheduleNextSync in case of consecutive sync errors.
308 void HandleContinuationError(const SyncSessionJob& old_job);
309
310 // Determines if it is legal to run |job| by checking current
311 // operational mode, backoff or throttling, freshness
312 // (so we don't make redundant syncs), and connection.
313 bool ShouldRunJob(const SyncSessionJob& job);
314
315 // Decide whether we should CONTINUE, SAVE or DROP the job.
316 JobProcessDecision DecideOnJob(const SyncSessionJob& job);
317
318 // Decide on whether to CONTINUE, SAVE or DROP the job when we are in
319 // backoff mode.
320 JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job);
321
322 // Saves the job for future execution. Note: It drops all the poll jobs.
323 void SaveJob(const SyncSessionJob& job);
324
325 // Coalesces the current job with the pending nudge.
326 void InitOrCoalescePendingJob(const SyncSessionJob& job);
327
328 // 'Impl' here refers to real implementation of public functions, running on
329 // |thread_|.
330 void StopImpl(const base::Closure& callback);
331 void ScheduleNudgeImpl(
332 const base::TimeDelta& delay,
333 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
334 const syncer::ModelTypePayloadMap& types_with_payloads,
335 bool is_canary_job, const tracked_objects::Location& nudge_location);
336
337 // Returns true if the client is currently in exponential backoff.
338 bool IsBackingOff() const;
339
340 // Helper to signal all listeners registered with |session_context_|.
341 void Notify(SyncEngineEvent::EventCause cause);
342
343 // Callback to change backoff state.
344 void DoCanaryJob();
345 void Unthrottle();
346
347 // Executes the pending job. Called whenever an event occurs that may
348 // change conditions permitting a job to run. Like when network connection is
349 // re-established, mode changes etc.
350 void DoPendingJobIfPossible(bool is_canary_job);
351
352 // Called when the root cause of the current connection error is fixed.
353 void OnServerConnectionErrorFixed();
354
355 // The pointer is owned by the caller.
356 syncer::sessions::SyncSession* CreateSyncSession(
357 const syncer::sessions::SyncSourceInfo& info);
358
359 // Creates a session for a poll and performs the sync.
360 void PollTimerCallback();
361
362 // Used to update |connection_code_|, see below.
363 void UpdateServerConnectionManagerStatus(
364 HttpResponse::ServerConnectionCode code);
365
366 // Called once the first time thread_ is started to broadcast an initial
367 // session snapshot containing data like initial_sync_ended. Important when
368 // the client starts up and does not need to perform an initial sync.
369 void SendInitialSnapshot();
370
371 virtual void OnActionableError(const sessions::SyncSessionSnapshot& snapshot);
372
373 base::WeakPtrFactory<SyncScheduler> weak_ptr_factory_;
374
375 // A second factory specially for weak_handle_this_, to allow the handle
376 // to be const and alleviate threading concerns.
377 base::WeakPtrFactory<SyncScheduler> weak_ptr_factory_for_weak_handle_;
378
379 // For certain methods that need to worry about X-thread posting.
380 const WeakHandle<SyncScheduler> weak_handle_this_;
381
382 // Used for logging.
383 const std::string name_;
384
385 // The message loop this object is on. Almost all methods have to
386 // be called on this thread.
387 MessageLoop* const sync_loop_;
388
389 // Set in Start(), unset in Stop().
390 bool started_;
391
392 // Modifiable versions of kDefaultLongPollIntervalSeconds which can be
393 // updated by the server.
394 base::TimeDelta syncer_short_poll_interval_seconds_;
395 base::TimeDelta syncer_long_poll_interval_seconds_;
396
397 // Server-tweakable sessions commit delay.
398 base::TimeDelta sessions_commit_delay_;
399
400 // Periodic timer for polling. See AdjustPolling.
401 base::RepeatingTimer<SyncScheduler> poll_timer_;
402
403 // The mode of operation.
404 Mode mode_;
405
406 // TODO(tim): Bug 26339. This needs to track more than just time I think,
407 // since the nudges could be for different types. Current impl doesn't care.
408 base::TimeTicks last_sync_session_end_time_;
409
410 // The latest connection code we got while trying to connect.
411 HttpResponse::ServerConnectionCode connection_code_;
412
413 // Tracks in-flight nudges so we can coalesce.
414 scoped_ptr<SyncSessionJob> pending_nudge_;
415
416 // Current wait state. Null if we're not in backoff and not throttled.
417 scoped_ptr<WaitInterval> wait_interval_;
418
419 scoped_ptr<DelayProvider> delay_provider_;
420
421 // Invoked to run through the sync cycle.
422 scoped_ptr<Syncer> syncer_;
423
424 sessions::SyncSessionContext *session_context_;
425
426 DISALLOW_COPY_AND_ASSIGN(SyncScheduler);
427 }; 115 };
428 116
429 } // namespace syncer 117 } // namespace syncer
430 118
431 #endif // SYNC_ENGINE_SYNC_SCHEDULER_H_ 119 #endif // SYNC_ENGINE_SYNC_SCHEDULER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698