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

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

Issue 10917234: sync: make scheduling logic and job ownership more obvious. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address review Created 8 years, 1 month 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 #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"
23 #include "sync/engine/syncer.h" 24 #include "sync/engine/syncer.h"
24 #include "sync/internal_api/public/base/model_type_invalidation_map.h" 25 #include "sync/internal_api/public/base/model_type_invalidation_map.h"
25 #include "sync/internal_api/public/engine/polling_constants.h" 26 #include "sync/internal_api/public/engine/polling_constants.h"
26 #include "sync/internal_api/public/util/weak_handle.h" 27 #include "sync/internal_api/public/util/weak_handle.h"
27 #include "sync/sessions/sync_session.h" 28 #include "sync/sessions/sync_session.h"
28 #include "sync/sessions/sync_session_context.h" 29 #include "sync/sessions/sync_session_context.h"
29 30
30 namespace syncer { 31 namespace syncer {
31 32
32 class BackoffDelayProvider; 33 class BackoffDelayProvider;
33 34
34 class SyncSchedulerImpl : public SyncScheduler { 35 class SyncSchedulerImpl : public SyncScheduler {
35 public: 36 public:
36 // |name| is a display string to identify the syncer thread. Takes 37 // |name| is a display string to identify the syncer thread. Takes
37 // |ownership of |syncer| and |delay_provider|. 38 // |ownership of |syncer| and |delay_provider|.
38 SyncSchedulerImpl(const std::string& name, 39 SyncSchedulerImpl(const std::string& name,
39 BackoffDelayProvider* delay_provider, 40 BackoffDelayProvider* delay_provider,
40 sessions::SyncSessionContext* context, 41 sessions::SyncSessionContext* context,
41 Syncer* syncer); 42 Syncer* syncer);
42 43
43 // Calls Stop(). 44 // Calls Stop().
44 virtual ~SyncSchedulerImpl(); 45 virtual ~SyncSchedulerImpl();
45 46
46 virtual void Start(Mode mode) OVERRIDE; 47 virtual void Start(Mode mode) OVERRIDE;
47 virtual bool ScheduleConfiguration( 48 virtual bool ScheduleConfiguration(
48 const ConfigurationParams& params) OVERRIDE; 49 const ConfigurationParams& params) OVERRIDE;
49 virtual void RequestStop(const base::Closure& callback) OVERRIDE; 50 virtual void RequestStop(const base::Closure& callback) OVERRIDE;
50 virtual void ScheduleNudgeAsync( 51 virtual void ScheduleNudgeAsync(
51 const base::TimeDelta& delay, 52 const base::TimeDelta& desired_delay,
52 NudgeSource source, 53 NudgeSource source,
53 ModelTypeSet types, 54 ModelTypeSet types,
54 const tracked_objects::Location& nudge_location) OVERRIDE; 55 const tracked_objects::Location& nudge_location) OVERRIDE;
55 virtual void ScheduleNudgeWithStatesAsync( 56 virtual void ScheduleNudgeWithStatesAsync(
56 const base::TimeDelta& delay, NudgeSource source, 57 const base::TimeDelta& desired_delay, NudgeSource source,
57 const ModelTypeInvalidationMap& invalidation_map, 58 const ModelTypeInvalidationMap& invalidation_map,
58 const tracked_objects::Location& nudge_location) OVERRIDE; 59 const tracked_objects::Location& nudge_location) OVERRIDE;
59 virtual void SetNotificationsEnabled(bool notifications_enabled) OVERRIDE; 60 virtual void SetNotificationsEnabled(bool notifications_enabled) OVERRIDE;
60 61
61 virtual base::TimeDelta GetSessionsCommitDelay() const OVERRIDE; 62 virtual base::TimeDelta GetSessionsCommitDelay() const OVERRIDE;
62 63
63 virtual void OnCredentialsUpdated() OVERRIDE; 64 virtual void OnCredentialsUpdated() OVERRIDE;
64 virtual void OnConnectionStatusChange() OVERRIDE; 65 virtual void OnConnectionStatusChange() OVERRIDE;
65 66
66 // SyncSession::Delegate implementation. 67 // SyncSession::Delegate implementation.
(...skipping 13 matching lines...) Expand all
80 private: 81 private:
81 enum JobProcessDecision { 82 enum JobProcessDecision {
82 // Indicates we should continue with the current job. 83 // Indicates we should continue with the current job.
83 CONTINUE, 84 CONTINUE,
84 // Indicates that we should save it to be processed later. 85 // Indicates that we should save it to be processed later.
85 SAVE, 86 SAVE,
86 // Indicates we should drop this job. 87 // Indicates we should drop this job.
87 DROP, 88 DROP,
88 }; 89 };
89 90
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 };
124 friend class SyncSchedulerTest; 91 friend class SyncSchedulerTest;
125 friend class SyncSchedulerWhiteboxTest; 92 friend class SyncSchedulerWhiteboxTest;
126 friend class SyncerTest; 93 friend class SyncerTest;
127 94
128 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, 95 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
129 DropNudgeWhileExponentialBackOff); 96 DropNudgeWhileExponentialBackOff);
130 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, SaveNudge); 97 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, SaveNudge);
131 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, 98 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest,
132 SaveNudgeWhileTypeThrottled); 99 SaveNudgeWhileTypeThrottled);
133 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueNudge); 100 FRIEND_TEST_ALL_PREFIXES(SyncSchedulerWhiteboxTest, ContinueNudge);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 132
166 Mode mode; 133 Mode mode;
167 134
168 // This bool is set to true if we have observed a nudge during this 135 // This bool is set to true if we have observed a nudge during this
169 // interval and mode == EXPONENTIAL_BACKOFF. 136 // interval and mode == EXPONENTIAL_BACKOFF.
170 bool had_nudge; 137 bool had_nudge;
171 base::TimeDelta length; 138 base::TimeDelta length;
172 base::OneShotTimer<SyncSchedulerImpl> timer; 139 base::OneShotTimer<SyncSchedulerImpl> timer;
173 140
174 // Configure jobs are saved only when backing off or throttling. So we 141 // Configure jobs are saved only when backing off or throttling. So we
175 // expose the pointer here. 142 // expose the pointer here (does not own, similar to pending_nudge).
176 scoped_ptr<SyncSessionJob> pending_configure_job; 143 SyncSessionJob* pending_configure_job;
akalin 2012/10/26 06:52:29 i don't like these raw pointers, but i guess there
177 }; 144 };
178 145
179 static const char* GetModeString(Mode mode); 146 static const char* GetModeString(Mode mode);
180 147
181 static const char* GetDecisionString(JobProcessDecision decision); 148 static const char* GetDecisionString(JobProcessDecision decision);
182 149
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
189 // Helpers that log before posting to |sync_loop_|. These will only post 150 // Helpers that log before posting to |sync_loop_|. These will only post
190 // the task in between calls to Start/Stop. 151 // the task in between calls to Start/Stop.
191 void PostTask(const tracked_objects::Location& from_here, 152 void PostTask(const tracked_objects::Location& from_here,
192 const char* name, 153 const char* name,
193 const base::Closure& task); 154 const base::Closure& task);
194 void PostDelayedTask(const tracked_objects::Location& from_here, 155 void PostDelayedTask(const tracked_objects::Location& from_here,
195 const char* name, 156 const char* name,
196 const base::Closure& task, 157 const base::Closure& task,
197 base::TimeDelta delay); 158 base::TimeDelta delay);
198 159
199 // Helper to assemble a job and post a delayed task to sync. 160 // Helper to assemble a job and post a delayed task to sync.
200 void ScheduleSyncSessionJob(const SyncSessionJob& job); 161 void ScheduleSyncSessionJob(scoped_ptr<SyncSessionJob> job);
201 162
202 // Invoke the Syncer to perform a sync. 163 // Invoke the Syncer to perform a sync.
203 void DoSyncSessionJob(const SyncSessionJob& job); 164 bool DoSyncSessionJob(scoped_ptr<SyncSessionJob> job);
204 165
205 // Called after the Syncer has performed the sync represented by |job|, to 166 // Called after the Syncer has performed the sync represented by |job|, to
206 // reset our state. 167 // reset our state. |premature_exit| is true if the Syncer did not manage
akalin 2012/10/26 06:52:29 update comment (premature_exit -> exited_premature
207 void FinishSyncSessionJob(const SyncSessionJob& job); 168 // to 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(scoped_ptr<SyncSessionJob> job,
171 bool exited_prematurely);
208 172
209 // Helper to FinishSyncSessionJob to schedule the next sync operation. 173 // Helper to FinishSyncSessionJob to schedule the next sync operation.
210 void ScheduleNextSync(const SyncSessionJob& old_job); 174 // |succeeded| carries the return value of |old_job|->Finish.
175 void ScheduleNextSync(scoped_ptr<SyncSessionJob> finished_job,
176 bool succeeded);
211 177
212 // Helper to configure polling intervals. Used by Start and ScheduleNextSync. 178 // Helper to configure polling intervals. Used by Start and ScheduleNextSync.
213 void AdjustPolling(const SyncSessionJob* old_job); 179 void AdjustPolling(const SyncSessionJob* old_job);
214 180
215 // Helper to restart waiting with |wait_interval_|'s timer. 181 // Helper to restart waiting with |wait_interval_|'s timer.
216 void RestartWaiting(); 182 void RestartWaiting(scoped_ptr<SyncSessionJob> job);
217 183
218 // Helper to ScheduleNextSync in case of consecutive sync errors. 184 // Helper to ScheduleNextSync in case of consecutive sync errors.
219 void HandleContinuationError(const SyncSessionJob& old_job); 185 void HandleContinuationError(const SyncSessionJob* old_job);
akalin 2012/10/26 06:52:29 const ref, please! actually, looking at this agai
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);
225 186
226 // Decide whether we should CONTINUE, SAVE or DROP the job. 187 // Decide whether we should CONTINUE, SAVE or DROP the job.
227 JobProcessDecision DecideOnJob(const SyncSessionJob& job); 188 JobProcessDecision DecideOnJob(const SyncSessionJob& job);
228 189
190 // If DecideOnJob decides that |job| should be SAVEd, this function will
akalin 2012/10/26 06:52:29 indentation
191 // carry out the task of actually "saving" (or coalescing) the job.
192 void HandleSaveJobDecision(scoped_ptr<SyncSessionJob> job);
193
229 // Decide on whether to CONTINUE, SAVE or DROP the job when we are in 194 // Decide on whether to CONTINUE, SAVE or DROP the job when we are in
230 // backoff mode. 195 // backoff mode.
231 JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job); 196 JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job);
232 197
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
239 // 'Impl' here refers to real implementation of public functions, running on 198 // 'Impl' here refers to real implementation of public functions, running on
240 // |thread_|. 199 // |thread_|.
241 void StopImpl(const base::Closure& callback); 200 void StopImpl(const base::Closure& callback);
242 void ScheduleNudgeImpl( 201 void ScheduleNudgeImpl(
243 const base::TimeDelta& delay, 202 const base::TimeDelta& delay,
244 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source, 203 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
245 const ModelTypeInvalidationMap& invalidation_map, 204 const ModelTypeInvalidationMap& invalidation_map,
246 bool is_canary_job, const tracked_objects::Location& nudge_location); 205 const tracked_objects::Location& nudge_location);
247 206
248 // Returns true if the client is currently in exponential backoff. 207 // Returns true if the client is currently in exponential backoff.
249 bool IsBackingOff() const; 208 bool IsBackingOff() const;
250 209
251 // Helper to signal all listeners registered with |session_context_|. 210 // Helper to signal all listeners registered with |session_context_|.
252 void Notify(SyncEngineEvent::EventCause cause); 211 void Notify(SyncEngineEvent::EventCause cause);
253 212
254 // Callback to change backoff state. 213 // Callback to change backoff state. |to_be_canary| in both cases is the job
255 void DoCanaryJob(); 214 // that should be granted canary privileges. Note: it is possible that the
256 void Unthrottle(); 215 // job that gets scheduled when this callback is scheduled is different from
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);
257 220
258 // Executes the pending job. Called whenever an event occurs that may 221 // Returns a pending job that has potential to run given the state of the
259 // change conditions permitting a job to run. Like when network connection is 222 // scheduler, if it exists. Useful whenever an event occurs that may
260 // re-established, mode changes etc. 223 // change conditions that permit a job to run, such as re-establishing
261 void DoPendingJobIfPossible(bool is_canary_job); 224 // network connection, auth refresh, mode changes etc. Note that the returned
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();
262 229
263 // Called when the root cause of the current connection error is fixed. 230 // Called when the root cause of the current connection error is fixed.
264 void OnServerConnectionErrorFixed(); 231 void OnServerConnectionErrorFixed();
265 232
266 // The pointer is owned by the caller. 233 scoped_ptr<sessions::SyncSession> CreateSyncSession(
267 sessions::SyncSession* CreateSyncSession(
268 const sessions::SyncSourceInfo& info); 234 const sessions::SyncSourceInfo& info);
269 235
270 // Creates a session for a poll and performs the sync. 236 // Creates a session for a poll and performs the sync.
271 void PollTimerCallback(); 237 void PollTimerCallback();
272 238
273 // Used to update |connection_code_|, see below. 239 // Used to update |connection_code_|, see below.
274 void UpdateServerConnectionManagerStatus( 240 void UpdateServerConnectionManagerStatus(
275 HttpResponse::ServerConnectionCode code); 241 HttpResponse::ServerConnectionCode code);
276 242
277 // Called once the first time thread_ is started to broadcast an initial 243 // Called once the first time thread_ is started to broadcast an initial
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 282
317 // Periodic timer for polling. See AdjustPolling. 283 // Periodic timer for polling. See AdjustPolling.
318 base::RepeatingTimer<SyncSchedulerImpl> poll_timer_; 284 base::RepeatingTimer<SyncSchedulerImpl> poll_timer_;
319 285
320 // The mode of operation. 286 // The mode of operation.
321 Mode mode_; 287 Mode mode_;
322 288
323 // The latest connection code we got while trying to connect. 289 // The latest connection code we got while trying to connect.
324 HttpResponse::ServerConnectionCode connection_code_; 290 HttpResponse::ServerConnectionCode connection_code_;
325 291
326 // Tracks in-flight nudges so we can coalesce. 292 // Tracks (does not own) in-flight nudges (scheduled or unscheduled),
327 scoped_ptr<SyncSessionJob> pending_nudge_; 293 // so we can coalesce. NULL if there is no 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_;
328 304
329 // Current wait state. Null if we're not in backoff and not throttled. 305 // Current wait state. Null if we're not in backoff and not throttled.
330 scoped_ptr<WaitInterval> wait_interval_; 306 scoped_ptr<WaitInterval> wait_interval_;
331 307
332 scoped_ptr<BackoffDelayProvider> delay_provider_; 308 scoped_ptr<BackoffDelayProvider> delay_provider_;
333 309
334 // Invoked to run through the sync cycle. 310 // Invoked to run through the sync cycle.
335 scoped_ptr<Syncer> syncer_; 311 scoped_ptr<Syncer> syncer_;
336 312
337 sessions::SyncSessionContext* session_context_; 313 sessions::SyncSessionContext* session_context_;
(...skipping 10 matching lines...) Expand all
348 // take place during a sync cycle. We call this out because such violations 324 // take place during a sync cycle. We call this out because such violations
349 // could result in tight sync loops hitting sync servers. 325 // could result in tight sync loops hitting sync servers.
350 bool no_scheduling_allowed_; 326 bool no_scheduling_allowed_;
351 327
352 DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl); 328 DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl);
353 }; 329 };
354 330
355 } // namespace syncer 331 } // namespace syncer
356 332
357 #endif // SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ 333 #endif // SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698