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

Side by Side Diff: chrome/browser/sync/engine/syncer_thread2.h

Issue 6874018: make new syncer thread the default. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Upload before submit. Created 9 years, 8 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
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // A class to run the syncer on a thread.
6 #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD2_H_
7 #define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD2_H_
8 #pragma once
9
10 #include "base/callback.h"
11 #include "base/memory/linked_ptr.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/observer_list.h"
14 #include "base/task.h"
15 #include "base/threading/thread.h"
16 #include "base/time.h"
17 #include "base/timer.h"
18 #include "chrome/browser/sync/engine/nudge_source.h"
19 #include "chrome/browser/sync/engine/polling_constants.h"
20 #include "chrome/browser/sync/engine/syncer.h"
21 #include "chrome/browser/sync/syncable/model_type_payload_map.h"
22 #include "chrome/browser/sync/engine/net/server_connection_manager.h"
23 #include "chrome/browser/sync/sessions/sync_session.h"
24 #include "chrome/browser/sync/sessions/sync_session_context.h"
25
26 namespace browser_sync {
27
28 struct ServerConnectionEvent;
29
30 namespace s3 {
31
32 class SyncerThread : public sessions::SyncSession::Delegate,
33 public ServerConnectionEventListener {
34 public:
35 enum Mode {
36 // In this mode, the thread only performs configuration tasks. This is
37 // designed to make the case where we want to download updates for a
38 // specific type only, and not continue syncing until we are moved into
39 // normal mode.
40 CONFIGURATION_MODE,
41 // Resumes polling and allows nudges, drops configuration tasks. Runs
42 // through entire sync cycle.
43 NORMAL_MODE,
44 };
45
46 // Takes ownership of both |context| and |syncer|.
47 SyncerThread(sessions::SyncSessionContext* context, Syncer* syncer);
48 virtual ~SyncerThread();
49
50 typedef Callback0::Type ModeChangeCallback;
51
52 // Change the mode of operation.
53 // We don't use a lock when changing modes, so we won't cause currently
54 // scheduled jobs to adhere to the new mode. We could protect it, but it
55 // doesn't buy very much as a) a session could already be in progress and it
56 // will continue no matter what, b) the scheduled sessions already contain
57 // all their required state and won't be affected by potential change at
58 // higher levels (i.e. the registrar), and c) we service tasks FIFO, so once
59 // the mode changes all future jobs will be run against the updated mode.
60 // If supplied, |callback| will be invoked when the mode has been
61 // changed to |mode| *from the SyncerThread*, and not from the caller
62 // thread.
63 void Start(Mode mode, ModeChangeCallback* callback);
64
65 // Joins on the thread as soon as possible (currently running session
66 // completes).
67 void Stop();
68
69 // The meat and potatoes.
70 void ScheduleNudge(const base::TimeDelta& delay, NudgeSource source,
71 const syncable::ModelTypeBitSet& types,
72 const tracked_objects::Location& nudge_location);
73 void ScheduleNudgeWithPayloads(
74 const base::TimeDelta& delay, NudgeSource source,
75 const syncable::ModelTypePayloadMap& types_with_payloads,
76 const tracked_objects::Location& nudge_location);
77 void ScheduleConfig(const syncable::ModelTypeBitSet& types);
78 void ScheduleClearUserData();
79
80 // Change status of notifications in the SyncSessionContext.
81 void set_notifications_enabled(bool notifications_enabled);
82
83 // DDOS avoidance function. Calculates how long we should wait before trying
84 // again after a failed sync attempt, where the last delay was |base_delay|.
85 // TODO(tim): Look at URLRequestThrottlerEntryInterface.
86 static base::TimeDelta GetRecommendedDelay(const base::TimeDelta& base_delay);
87
88 // SyncSession::Delegate implementation.
89 virtual void OnSilencedUntil(const base::TimeTicks& silenced_until);
90 virtual bool IsSyncingCurrentlySilenced();
91 virtual void OnReceivedShortPollIntervalUpdate(
92 const base::TimeDelta& new_interval);
93 virtual void OnReceivedLongPollIntervalUpdate(
94 const base::TimeDelta& new_interval);
95 virtual void OnShouldStopSyncingPermanently();
96
97 // ServerConnectionEventListener implementation.
98 // TODO(tim): schedule a nudge when valid connection detected? in 1 minute?
99 virtual void OnServerConnectionEvent(const ServerConnectionEvent2& event);
100
101 private:
102 enum JobProcessDecision {
103 // Indicates we should continue with the current job.
104 CONTINUE,
105 // Indicates that we should save it to be processed later.
106 SAVE,
107 // Indicates we should drop this job.
108 DROP,
109 };
110
111 struct SyncSessionJob {
112 // An enum used to describe jobs for scheduling purposes.
113 enum SyncSessionJobPurpose {
114 // Our poll timer schedules POLL jobs periodically based on a server
115 // assigned poll interval.
116 POLL,
117 // A nudge task can come from a variety of components needing to force
118 // a sync. The source is inferable from |session.source()|.
119 NUDGE,
120 // The user invoked a function in the UI to clear their entire account
121 // and stop syncing (globally).
122 CLEAR_USER_DATA,
123 // Typically used for fetching updates for a subset of the enabled types
124 // during initial sync or reconfiguration. We don't run all steps of
125 // the sync cycle for these (e.g. CleanupDisabledTypes is skipped).
126 CONFIGURATION,
127 };
128 SyncSessionJob();
129 SyncSessionJob(SyncSessionJobPurpose purpose, base::TimeTicks start,
130 linked_ptr<sessions::SyncSession> session, bool is_canary_job,
131 const tracked_objects::Location& nudge_location);
132 ~SyncSessionJob();
133 SyncSessionJobPurpose purpose;
134 base::TimeTicks scheduled_start;
135 linked_ptr<sessions::SyncSession> session;
136 bool is_canary_job;
137
138 // This is the location the nudge came from. used for debugging purpose.
139 // In case of multiple nudges getting coalesced this stores the first nudge
140 // that came in.
141 tracked_objects::Location nudge_location;
142 };
143 friend class SyncerThread2Test;
144 friend class SyncerThread2WhiteboxTest;
145
146 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
147 DropNudgeWhileExponentialBackOff);
148 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, SaveNudge);
149 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueNudge);
150 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, DropPoll);
151 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinuePoll);
152 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueConfiguration);
153 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
154 SaveConfigurationWhileThrottled);
155 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
156 SaveNudgeWhileThrottled);
157 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
158 ContinueClearUserDataUnderAllCircumstances);
159 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
160 ContinueCanaryJobConfig);
161 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
162 ContinueNudgeWhileExponentialBackOff);
163
164 // A component used to get time delays associated with exponential backoff.
165 // Encapsulated into a class to facilitate testing.
166 class DelayProvider {
167 public:
168 DelayProvider();
169 virtual base::TimeDelta GetDelay(const base::TimeDelta& last_delay);
170 virtual ~DelayProvider();
171 private:
172 DISALLOW_COPY_AND_ASSIGN(DelayProvider);
173 };
174
175 struct WaitInterval {
176 enum Mode {
177 // A wait interval whose duration has been affected by exponential
178 // backoff.
179 // EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval.
180 EXPONENTIAL_BACKOFF,
181 // A server-initiated throttled interval. We do not allow any syncing
182 // during such an interval.
183 THROTTLED,
184 };
185 WaitInterval();
186 ~WaitInterval();
187
188 Mode mode;
189
190 // This bool is set to true if we have observed a nudge during this
191 // interval and mode == EXPONENTIAL_BACKOFF.
192 bool had_nudge;
193 base::TimeDelta length;
194 base::OneShotTimer<SyncerThread> timer;
195
196 // Configure jobs are saved only when backing off or throttling. So we
197 // expose the pointer here.
198 scoped_ptr<SyncSessionJob> pending_configure_job;
199 WaitInterval(Mode mode, base::TimeDelta length);
200 };
201
202 // Helper to assemble a job and post a delayed task to sync.
203 void ScheduleSyncSessionJob(
204 const base::TimeDelta& delay,
205 SyncSessionJob::SyncSessionJobPurpose purpose,
206 sessions::SyncSession* session,
207 const tracked_objects::Location& nudge_location);
208
209 // Invoke the Syncer to perform a sync.
210 void DoSyncSessionJob(const SyncSessionJob& job);
211
212 // Called after the Syncer has performed the sync represented by |job|, to
213 // reset our state.
214 void FinishSyncSessionJob(const SyncSessionJob& job);
215
216 // Record important state that might be needed in future syncs, such as which
217 // data types may require cleanup.
218 void UpdateCarryoverSessionState(const SyncSessionJob& old_job);
219
220 // Helper to FinishSyncSessionJob to schedule the next sync operation.
221 void ScheduleNextSync(const SyncSessionJob& old_job);
222
223 // Helper to configure polling intervals. Used by Start and ScheduleNextSync.
224 void AdjustPolling(const SyncSessionJob* old_job);
225
226 // Helper to ScheduleNextSync in case of consecutive sync errors.
227 void HandleConsecutiveContinuationError(const SyncSessionJob& old_job);
228
229 // Determines if it is legal to run |job| by checking current
230 // operational mode, backoff or throttling, freshness
231 // (so we don't make redundant syncs), and connection.
232 bool ShouldRunJob(const SyncSessionJob& job);
233
234 // Decide whether we should CONTINUE, SAVE or DROP the job.
235 JobProcessDecision DecideOnJob(const SyncSessionJob& job);
236
237 // Decide on whether to CONTINUE, SAVE or DROP the job when we are in
238 // backoff mode.
239 JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job);
240
241 // Saves the job for future execution. Note: It drops all the poll jobs.
242 void SaveJob(const SyncSessionJob& job);
243
244 // Coalesces the current job with the pending nudge.
245 void InitOrCoalescePendingJob(const SyncSessionJob& job);
246
247 // 'Impl' here refers to real implementation of public functions, running on
248 // |thread_|.
249 void StartImpl(Mode mode, linked_ptr<ModeChangeCallback> callback);
250 void ScheduleNudgeImpl(
251 const base::TimeDelta& delay,
252 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
253 const syncable::ModelTypePayloadMap& types_with_payloads,
254 bool is_canary_job, const tracked_objects::Location& nudge_location);
255 void ScheduleConfigImpl(const ModelSafeRoutingInfo& routing_info,
256 const std::vector<ModelSafeWorker*>& workers,
257 const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
258 void ScheduleClearUserDataImpl();
259
260 // Returns true if the client is currently in exponential backoff.
261 bool IsBackingOff() const;
262
263 // Helper to signal all listeners registered with |session_context_|.
264 void Notify(SyncEngineEvent::EventCause cause);
265
266 // Callback to change backoff state.
267 void DoCanaryJob();
268 void Unthrottle();
269
270 // Executes the pending job. Called whenever an event occurs that may
271 // change conditions permitting a job to run. Like when network connection is
272 // re-established, mode changes etc.
273 void DoPendingJobIfPossible(bool is_canary_job);
274
275 // The pointer is owned by the caller.
276 browser_sync::sessions::SyncSession* CreateSyncSession(
277 const browser_sync::sessions::SyncSourceInfo& info);
278
279 // Creates a session for a poll and performs the sync.
280 void PollTimerCallback();
281
282 // Assign |start| and |end| to appropriate SyncerStep values for the
283 // specified |purpose|.
284 void SetSyncerStepsForPurpose(SyncSessionJob::SyncSessionJobPurpose purpose,
285 SyncerStep* start,
286 SyncerStep* end);
287
288 // Initializes the hookup between the ServerConnectionManager and us.
289 void WatchConnectionManager();
290
291 // Used to update |server_connection_ok_|, see below.
292 void CheckServerConnectionManagerStatus(
293 HttpResponse::ServerConnectionCode code);
294
295 // Called once the first time thread_ is started to broadcast an initial
296 // session snapshot containing data like initial_sync_ended. Important when
297 // the client starts up and does not need to perform an initial sync.
298 void SendInitialSnapshot();
299
300 base::Thread thread_;
301
302 // Modifiable versions of kDefaultLongPollIntervalSeconds which can be
303 // updated by the server.
304 base::TimeDelta syncer_short_poll_interval_seconds_;
305 base::TimeDelta syncer_long_poll_interval_seconds_;
306
307 // Periodic timer for polling. See AdjustPolling.
308 base::RepeatingTimer<SyncerThread> poll_timer_;
309
310 // The mode of operation. We don't use a lock, see Start(...) comment.
311 Mode mode_;
312
313 // TODO(tim): Bug 26339. This needs to track more than just time I think,
314 // since the nudges could be for different types. Current impl doesn't care.
315 base::TimeTicks last_sync_session_end_time_;
316
317 // Have we observed a valid server connection?
318 bool server_connection_ok_;
319
320 // Tracks in-flight nudges so we can coalesce.
321 scoped_ptr<SyncSessionJob> pending_nudge_;
322
323 // Current wait state. Null if we're not in backoff and not throttled.
324 scoped_ptr<WaitInterval> wait_interval_;
325
326 scoped_ptr<DelayProvider> delay_provider_;
327
328 // Invoked to run through the sync cycle.
329 scoped_ptr<Syncer> syncer_;
330
331 scoped_ptr<sessions::SyncSessionContext> session_context_;
332
333 DISALLOW_COPY_AND_ASSIGN(SyncerThread);
334 };
335
336 } // namespace s3
337
338 } // namespace browser_sync
339
340 // The SyncerThread manages its own internal thread and thus outlives it. We
341 // don't need refcounting for posting tasks to this internal thread.
342 DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::s3::SyncerThread);
343
344 #endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD2_H_
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/syncer_thread.cc ('k') | chrome/browser/sync/engine/syncer_thread2.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698