OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 run the syncer on a thread. | 5 // A class to run the syncer on a thread. |
6 // This is the default implementation of SyncerThread whose Stop implementation | |
7 // does not support a timeout, but is greatly simplified. | |
8 #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_ | 6 #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_ |
9 #define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_ | 7 #define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_ |
10 #pragma once | 8 #pragma once |
11 | 9 |
12 #include <list> | 10 #include "base/callback.h" |
13 #include <string> | 11 #include "base/memory/linked_ptr.h" |
tim (not reviewing)
2011/04/18 16:11:47
I'm assuming there were no changes to syncer_threa
lipalani1
2011/04/18 20:36:41
Yes it was a straight port.
On 2011/04/18 16:11:47
| |
14 #include <vector> | |
15 | |
16 #include "base/basictypes.h" | |
17 #include "base/gtest_prod_util.h" | |
18 #include "base/memory/ref_counted.h" | |
19 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
20 #include "base/synchronization/condition_variable.h" | 13 #include "base/observer_list.h" |
14 #include "base/task.h" | |
21 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
22 #include "base/time.h" | 16 #include "base/time.h" |
23 #include "base/synchronization/waitable_event.h" | 17 #include "base/timer.h" |
24 #include "chrome/browser/sync/engine/syncer_types.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" | |
25 #include "chrome/browser/sync/sessions/sync_session.h" | 23 #include "chrome/browser/sync/sessions/sync_session.h" |
26 #include "chrome/browser/sync/syncable/model_type.h" | 24 #include "chrome/browser/sync/sessions/sync_session_context.h" |
27 #include "chrome/browser/sync/syncable/model_type_payload_map.h" | |
28 #include "chrome/common/deprecated/event_sys-inl.h" | |
29 | |
30 #if defined(OS_LINUX) | |
31 #include "chrome/browser/sync/engine/idle_query_linux.h" | |
32 #endif | |
33 | |
34 class EventListenerHookup; | |
35 | 25 |
36 namespace browser_sync { | 26 namespace browser_sync { |
37 | 27 |
38 class ModelSafeWorker; | |
39 class ServerConnectionManager; | |
40 class Syncer; | |
41 class URLFactory; | |
42 struct ServerConnectionEvent; | 28 struct ServerConnectionEvent; |
43 | 29 |
44 class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>, | 30 class SyncerThread : public sessions::SyncSession::Delegate, |
45 public sessions::SyncSession::Delegate { | 31 public ServerConnectionEventListener { |
46 FRIEND_TEST_ALL_PREFIXES(SyncerThreadTest, CalculateSyncWaitTime); | |
47 FRIEND_TEST_ALL_PREFIXES(SyncerThreadTest, CalculatePollingWaitTime); | |
48 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Polling); | |
49 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Nudge); | |
50 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, NudgeWithDataTypes); | |
51 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, | |
52 NudgeWithDataTypesCoalesced); | |
53 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, NudgeWithPayloads); | |
54 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, | |
55 NudgeWithPayloadsCoalesced); | |
56 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Throttling); | |
57 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, AuthInvalid); | |
58 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Pause); | |
59 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, StartWhenNotConnected); | |
60 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, PauseWhenNotConnected); | |
61 FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, StopSyncPermanently); | |
62 friend class SyncerThreadWithSyncerTest; | |
63 friend class SyncerThreadFactory; | |
64 public: | 32 public: |
65 // Encapsulates the parameters that make up an interval on which the | 33 enum Mode { |
66 // syncer thread is sleeping. | 34 // In this mode, the thread only performs configuration tasks. This is |
35 // designed to make the case where we want to download updates for a | |
36 // specific type only, and not continue syncing until we are moved into | |
37 // normal mode. | |
38 CONFIGURATION_MODE, | |
39 // Resumes polling and allows nudges, drops configuration tasks. Runs | |
40 // through entire sync cycle. | |
41 NORMAL_MODE, | |
42 }; | |
43 | |
44 // Takes ownership of both |context| and |syncer|. | |
45 SyncerThread(sessions::SyncSessionContext* context, Syncer* syncer); | |
46 virtual ~SyncerThread(); | |
47 | |
48 typedef Callback0::Type ModeChangeCallback; | |
49 | |
50 // Change the mode of operation. | |
51 // We don't use a lock when changing modes, so we won't cause currently | |
52 // scheduled jobs to adhere to the new mode. We could protect it, but it | |
53 // doesn't buy very much as a) a session could already be in progress and it | |
54 // will continue no matter what, b) the scheduled sessions already contain | |
55 // all their required state and won't be affected by potential change at | |
56 // higher levels (i.e. the registrar), and c) we service tasks FIFO, so once | |
57 // the mode changes all future jobs will be run against the updated mode. | |
58 // If supplied, |callback| will be invoked when the mode has been | |
59 // changed to |mode| *from the SyncerThread*, and not from the caller | |
60 // thread. | |
61 void Start(Mode mode, ModeChangeCallback* callback); | |
62 | |
63 // Joins on the thread as soon as possible (currently running session | |
64 // completes). | |
65 void Stop(); | |
66 | |
67 // The meat and potatoes. | |
68 void ScheduleNudge(const base::TimeDelta& delay, NudgeSource source, | |
69 const syncable::ModelTypeBitSet& types, | |
70 const tracked_objects::Location& nudge_location); | |
71 void ScheduleNudgeWithPayloads( | |
72 const base::TimeDelta& delay, NudgeSource source, | |
73 const syncable::ModelTypePayloadMap& types_with_payloads, | |
74 const tracked_objects::Location& nudge_location); | |
75 void ScheduleConfig(const syncable::ModelTypeBitSet& types); | |
76 void ScheduleClearUserData(); | |
77 | |
78 // Change status of notifications in the SyncSessionContext. | |
79 void set_notifications_enabled(bool notifications_enabled); | |
80 | |
81 // DDOS avoidance function. Calculates how long we should wait before trying | |
82 // again after a failed sync attempt, where the last delay was |base_delay|. | |
83 // TODO(tim): Look at URLRequestThrottlerEntryInterface. | |
84 static base::TimeDelta GetRecommendedDelay(const base::TimeDelta& base_delay); | |
85 | |
86 // SyncSession::Delegate implementation. | |
87 virtual void OnSilencedUntil(const base::TimeTicks& silenced_until); | |
88 virtual bool IsSyncingCurrentlySilenced(); | |
89 virtual void OnReceivedShortPollIntervalUpdate( | |
90 const base::TimeDelta& new_interval); | |
91 virtual void OnReceivedLongPollIntervalUpdate( | |
92 const base::TimeDelta& new_interval); | |
93 virtual void OnShouldStopSyncingPermanently(); | |
94 | |
95 // ServerConnectionEventListener implementation. | |
96 // TODO(tim): schedule a nudge when valid connection detected? in 1 minute? | |
97 virtual void OnServerConnectionEvent(const ServerConnectionEvent2& event); | |
98 | |
99 private: | |
100 enum JobProcessDecision { | |
101 // Indicates we should continue with the current job. | |
102 CONTINUE, | |
103 // Indicates that we should save it to be processed later. | |
104 SAVE, | |
105 // Indicates we should drop this job. | |
106 DROP, | |
107 }; | |
108 | |
109 struct SyncSessionJob { | |
110 // An enum used to describe jobs for scheduling purposes. | |
111 enum SyncSessionJobPurpose { | |
112 // Our poll timer schedules POLL jobs periodically based on a server | |
113 // assigned poll interval. | |
114 POLL, | |
115 // A nudge task can come from a variety of components needing to force | |
116 // a sync. The source is inferable from |session.source()|. | |
117 NUDGE, | |
118 // The user invoked a function in the UI to clear their entire account | |
119 // and stop syncing (globally). | |
120 CLEAR_USER_DATA, | |
121 // Typically used for fetching updates for a subset of the enabled types | |
122 // during initial sync or reconfiguration. We don't run all steps of | |
123 // the sync cycle for these (e.g. CleanupDisabledTypes is skipped). | |
124 CONFIGURATION, | |
125 }; | |
126 SyncSessionJob(); | |
127 SyncSessionJob(SyncSessionJobPurpose purpose, base::TimeTicks start, | |
128 linked_ptr<sessions::SyncSession> session, bool is_canary_job, | |
129 const tracked_objects::Location& nudge_location); | |
130 ~SyncSessionJob(); | |
131 SyncSessionJobPurpose purpose; | |
132 base::TimeTicks scheduled_start; | |
133 linked_ptr<sessions::SyncSession> session; | |
134 bool is_canary_job; | |
135 | |
136 // This is the location the nudge came from. used for debugging purpose. | |
137 // In case of multiple nudges getting coalesced this stores the first nudge | |
138 // that came in. | |
139 tracked_objects::Location nudge_location; | |
140 }; | |
141 friend class SyncerThread2Test; | |
142 friend class SyncerThread2WhiteboxTest; | |
143 | |
144 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, | |
145 DropNudgeWhileExponentialBackOff); | |
146 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, SaveNudge); | |
147 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueNudge); | |
148 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, DropPoll); | |
149 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinuePoll); | |
150 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueConfiguration); | |
151 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, | |
152 SaveConfigurationWhileThrottled); | |
153 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, | |
154 SaveNudgeWhileThrottled); | |
155 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, | |
156 ContinueClearUserDataUnderAllCircumstances); | |
157 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, | |
158 ContinueCanaryJobConfig); | |
159 FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, | |
160 ContinueNudgeWhileExponentialBackOff); | |
161 | |
162 // A component used to get time delays associated with exponential backoff. | |
163 // Encapsulated into a class to facilitate testing. | |
164 class DelayProvider { | |
165 public: | |
166 DelayProvider(); | |
167 virtual base::TimeDelta GetDelay(const base::TimeDelta& last_delay); | |
168 virtual ~DelayProvider(); | |
169 private: | |
170 DISALLOW_COPY_AND_ASSIGN(DelayProvider); | |
171 }; | |
172 | |
67 struct WaitInterval { | 173 struct WaitInterval { |
68 enum Mode { | 174 enum Mode { |
69 // A wait interval whose duration has not been affected by exponential | |
70 // backoff. The base case for exponential backoff falls in to this case | |
71 // (e.g when the exponent is 1). So far, we don't need a separate case. | |
72 // NORMAL intervals are not nudge-rate limited. | |
73 NORMAL, | |
74 // A wait interval whose duration has been affected by exponential | 175 // A wait interval whose duration has been affected by exponential |
75 // backoff. | 176 // backoff. |
76 // EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval. | 177 // EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval. |
77 EXPONENTIAL_BACKOFF, | 178 EXPONENTIAL_BACKOFF, |
78 // A server-initiated throttled interval. We do not allow any syncing | 179 // A server-initiated throttled interval. We do not allow any syncing |
79 // during such an interval. | 180 // during such an interval. |
80 THROTTLED, | 181 THROTTLED, |
81 }; | 182 }; |
183 WaitInterval(); | |
184 ~WaitInterval(); | |
82 | 185 |
83 Mode mode; | 186 Mode mode; |
84 // This bool is set to true if we have observed a nudge during during this | 187 |
188 // This bool is set to true if we have observed a nudge during this | |
85 // interval and mode == EXPONENTIAL_BACKOFF. | 189 // interval and mode == EXPONENTIAL_BACKOFF. |
86 bool had_nudge_during_backoff; | 190 bool had_nudge; |
87 base::TimeDelta poll_delta; // The wait duration until the next poll. | 191 base::TimeDelta length; |
192 base::OneShotTimer<SyncerThread> timer; | |
88 | 193 |
89 WaitInterval() : mode(NORMAL), had_nudge_during_backoff(false) { } | 194 // Configure jobs are saved only when backing off or throttling. So we |
195 // expose the pointer here. | |
196 scoped_ptr<SyncSessionJob> pending_configure_job; | |
197 WaitInterval(Mode mode, base::TimeDelta length); | |
90 }; | 198 }; |
91 | 199 |
92 enum NudgeSource { | 200 // Helper to assemble a job and post a delayed task to sync. |
93 kUnknown = 0, | 201 void ScheduleSyncSessionJob( |
94 kNotification, | 202 const base::TimeDelta& delay, |
95 kLocal, | 203 SyncSessionJob::SyncSessionJobPurpose purpose, |
96 kContinuation, | 204 sessions::SyncSession* session, |
97 kClearPrivateData | 205 const tracked_objects::Location& nudge_location); |
98 }; | |
99 // Server can overwrite these values via client commands. | |
100 // Standard short poll. This is used when XMPP is off. | |
101 static const int kDefaultShortPollIntervalSeconds; | |
102 // Long poll is used when XMPP is on. | |
103 static const int kDefaultLongPollIntervalSeconds; | |
104 // 30 minutes by default. If exponential backoff kicks in, this is the | |
105 // longest possible poll interval. | |
106 static const int kDefaultMaxPollIntervalMs; | |
107 // Maximum interval for exponential backoff. | |
108 static const int kMaxBackoffSeconds; | |
109 | 206 |
110 explicit SyncerThread(sessions::SyncSessionContext* context); | 207 // Invoke the Syncer to perform a sync. |
111 virtual ~SyncerThread(); | 208 void DoSyncSessionJob(const SyncSessionJob& job); |
112 | 209 |
113 virtual void WatchConnectionManager(ServerConnectionManager* conn_mgr); | 210 // Called after the Syncer has performed the sync represented by |job|, to |
211 // reset our state. | |
212 void FinishSyncSessionJob(const SyncSessionJob& job); | |
114 | 213 |
115 // Starts a syncer thread. | 214 // Record important state that might be needed in future syncs, such as which |
116 // Returns true if it creates a thread or if there's currently a thread | 215 // data types may require cleanup. |
117 // running and false otherwise. | 216 void UpdateCarryoverSessionState(const SyncSessionJob& old_job); |
118 virtual bool Start(); | |
119 | 217 |
120 // Stop processing. |max_wait| doesn't do anything in this version. | 218 // Helper to FinishSyncSessionJob to schedule the next sync operation. |
121 virtual bool Stop(int max_wait); | 219 void ScheduleNextSync(const SyncSessionJob& old_job); |
122 | 220 |
123 // Request that the thread pauses. Returns false if the request can | 221 // Helper to configure polling intervals. Used by Start and ScheduleNextSync. |
124 // not be completed (e.g. the thread is not running). When the | 222 void AdjustPolling(const SyncSessionJob* old_job); |
125 // thread actually pauses, a SyncEngineEvent::PAUSED event notification | |
126 // will be sent to the relay channel. | |
127 virtual bool RequestPause(); | |
128 | 223 |
129 // Request that the thread resumes from pause. Returns false if the | 224 // Helper to ScheduleNextSync in case of consecutive sync errors. |
130 // request can not be completed (e.g. the thread is not running or | 225 void HandleConsecutiveContinuationError(const SyncSessionJob& old_job); |
131 // is not currently paused). When the thread actually resumes, a | |
132 // SyncEngineEvent::RESUMED event notification will be sent to the relay | |
133 // channel. | |
134 virtual bool RequestResume(); | |
135 | 226 |
136 // Nudges the syncer to sync with a delay specified. This API is for access | 227 // Determines if it is legal to run |job| by checking current |
137 // from the SyncerThread's controller and will cause a mutex lock. | 228 // operational mode, backoff or throttling, freshness |
138 virtual void NudgeSyncer(int milliseconds_from_now, NudgeSource source); | 229 // (so we don't make redundant syncs), and connection. |
230 bool ShouldRunJob(const SyncSessionJob& job); | |
139 | 231 |
140 // Same as |NudgeSyncer|, but supports tracking the datatypes that caused | 232 // Decide whether we should CONTINUE, SAVE or DROP the job. |
141 // the nudge to occur. | 233 JobProcessDecision DecideOnJob(const SyncSessionJob& job); |
142 virtual void NudgeSyncerWithDataTypes( | |
143 int milliseconds_from_now, | |
144 NudgeSource source, | |
145 const syncable::ModelTypeBitSet& model_types); | |
146 | 234 |
147 // Same as |NudgeSyncer|, but supports including a payload for passing on to | 235 // Decide on whether to CONTINUE, SAVE or DROP the job when we are in |
148 // the download updates command. Datatypes with payloads are also considered | 236 // backoff mode. |
149 // to have caused a nudged to occur and treated accordingly. | 237 JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job); |
150 virtual void NudgeSyncerWithPayloads( | |
151 int milliseconds_from_now, | |
152 NudgeSource source, | |
153 const syncable::ModelTypePayloadMap& model_types_with_payloads); | |
154 | 238 |
155 void SetNotificationsEnabled(bool notifications_enabled); | 239 // Saves the job for future execution. Note: It drops all the poll jobs. |
240 void SaveJob(const SyncSessionJob& job); | |
156 | 241 |
157 // Call this when a directory is opened | 242 // Coalesces the current job with the pending nudge. |
158 void CreateSyncer(const std::string& dirname); | 243 void InitOrCoalescePendingJob(const SyncSessionJob& job); |
159 | 244 |
160 // DDOS avoidance function. The argument and return value is in seconds | 245 // 'Impl' here refers to real implementation of public functions, running on |
161 static int GetRecommendedDelaySeconds(int base_delay_seconds); | 246 // |thread_|. |
247 void StartImpl(Mode mode, linked_ptr<ModeChangeCallback> callback); | |
248 void ScheduleNudgeImpl( | |
249 const base::TimeDelta& delay, | |
250 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source, | |
251 const syncable::ModelTypePayloadMap& types_with_payloads, | |
252 bool is_canary_job, const tracked_objects::Location& nudge_location); | |
253 void ScheduleConfigImpl(const ModelSafeRoutingInfo& routing_info, | |
254 const std::vector<ModelSafeWorker*>& workers, | |
255 const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source); | |
256 void ScheduleClearUserDataImpl(); | |
162 | 257 |
163 protected: | 258 // Returns true if the client is currently in exponential backoff. |
164 virtual void ThreadMain(); | 259 bool IsBackingOff() const; |
165 void ThreadMainLoop(); | |
166 | 260 |
167 virtual void SetConnected(bool connected); | 261 // Helper to signal all listeners registered with |session_context_|. |
168 | |
169 virtual void SetSyncerPollingInterval(base::TimeDelta interval); | |
170 virtual void SetSyncerShortPollInterval(base::TimeDelta interval); | |
171 | |
172 // Needed to emulate the behavior of pthread_create, which synchronously | |
173 // started the thread and set the value of thread_running_ to true. | |
174 // We can't quite match that because we asynchronously post the task, | |
175 // which opens a window for Stop to get called before the task actually | |
176 // makes it. To prevent this, we block Start() until we're sure it's ok. | |
177 base::WaitableEvent thread_main_started_; | |
178 | |
179 // Handle of the running thread. | |
180 base::Thread thread_; | |
181 | |
182 // Fields that are modified / accessed by multiple threads go in this struct | |
183 // for clarity and explicitness. | |
184 struct ProtectedFields { | |
185 ProtectedFields(); | |
186 ~ProtectedFields(); | |
187 | |
188 // False when we want to stop the thread. | |
189 bool stop_syncer_thread_; | |
190 | |
191 // True when a pause was requested. | |
192 bool pause_requested_; | |
193 | |
194 // True when the thread is paused. | |
195 bool paused_; | |
196 | |
197 Syncer* syncer_; | |
198 | |
199 // State of the server connection. | |
200 bool connected_; | |
201 | |
202 // kUnknown if there is no pending nudge. (Theoretically, there | |
203 // could be a pending nudge of type kUnknown, so it's better to | |
204 // check pending_nudge_time_.) | |
205 NudgeSource pending_nudge_source_; | |
206 | |
207 // Map of all datatypes that are requesting a nudge. Can be union | |
208 // from multiple nudges that are coalesced. In addition, we | |
209 // optionally track a payload associated with each datatype (most recent | |
210 // payload overwrites old ones). These payloads are used by the download | |
211 // updates command and can contain datatype specific information the server | |
212 // might use. | |
213 syncable::ModelTypePayloadMap pending_nudge_types_; | |
214 | |
215 // null iff there is no pending nudge. | |
216 base::TimeTicks pending_nudge_time_; | |
217 | |
218 // The wait interval for to the current iteration of our main loop. This is | |
219 // only written to by the syncer thread, and since the only reader from a | |
220 // different thread (NudgeSync) is called at totally random times, we don't | |
221 // really need to access mutually exclusively as the data races that exist | |
222 // are intrinsic, but do so anyway and avoid using 'volatile'. | |
223 WaitInterval current_wait_interval_; | |
224 } vault_; | |
225 | |
226 // Gets signaled whenever a thread outside of the syncer thread changes a | |
227 // protected field in the vault_. | |
228 base::ConditionVariable vault_field_changed_; | |
229 | |
230 // Used to lock everything in |vault_|. | |
231 base::Lock lock_; | |
232 | |
233 private: | |
234 // Threshold multipler for how long before user should be considered idle. | |
235 static const int kPollBackoffThresholdMultiplier = 10; | |
236 | |
237 // SyncSession::Delegate implementation. | |
238 virtual void OnSilencedUntil(const base::TimeTicks& silenced_until); | |
239 virtual bool IsSyncingCurrentlySilenced(); | |
240 virtual void OnReceivedShortPollIntervalUpdate( | |
241 const base::TimeDelta& new_interval); | |
242 virtual void OnReceivedLongPollIntervalUpdate( | |
243 const base::TimeDelta& new_interval); | |
244 virtual void OnShouldStopSyncingPermanently(); | |
245 | |
246 void HandleServerConnectionEvent(const ServerConnectionEvent& event); | |
247 | |
248 // Collect all local state required for a sync and build a SyncSession out of | |
249 // it, reset state for the next time, and performs the sync cycle. | |
250 // See |GetAndResetNudgeSource| for details on what 'reset' means. | |
251 // |was_nudged| is set to true if the session returned is fulfilling a nudge. | |
252 // Returns once the session is finished (HasMoreToSync returns false). The | |
253 // caller owns the returned SyncSession. | |
254 sessions::SyncSession* SyncMain(Syncer* syncer, | |
255 bool was_throttled, | |
256 bool continue_sync_cycle, | |
257 bool* initial_sync_for_thread, | |
258 bool* was_nudged); | |
259 | |
260 // Calculates the next sync wait time and exponential backoff state. | |
261 // last_poll_wait is the time duration of the previous polling timeout which | |
262 // was used. user_idle_milliseconds is updated by this method, and is a report | |
263 // of the full amount of time since the last period of activity for the user. | |
264 // The continue_sync_cycle parameter is used to determine whether or not we | |
265 // are calculating a polling wait time that is a continuation of an sync cycle | |
266 // which terminated while the syncer still had work to do. was_nudged is used | |
267 // in case of exponential backoff so we only allow one nudge per backoff | |
268 // interval. | |
269 WaitInterval CalculatePollingWaitTime( | |
270 int last_poll_wait, // in s | |
271 int* user_idle_milliseconds, | |
272 bool* continue_sync_cycle, | |
273 bool was_nudged); | |
274 | |
275 // Helper to above function, considers effect of user idle time. | |
276 virtual int CalculateSyncWaitTime(int last_wait, int user_idle_ms); | |
277 | |
278 // Resets the source tracking state to a clean slate and returns the current | |
279 // state in a SyncSourceInfo. | |
280 // The initial sync boolean is updated if read as a sentinel. The following | |
281 // two methods work in concert to achieve this goal. | |
282 // If |was_throttled| was true, this still discards elapsed nudges, but we | |
283 // treat the request as a periodic poll rather than a nudge from a source. | |
284 // Builds a SyncSourceInfo and returns whether a nudge occurred in the | |
285 // |was_nudged| parameter. | |
286 sessions::SyncSourceInfo GetAndResetNudgeSource(bool was_throttled, | |
287 bool continue_sync_cycle, | |
288 bool* initial_sync, | |
289 bool* was_nudged); | |
290 | |
291 sessions::SyncSourceInfo MakeSyncSourceInfo( | |
292 bool nudged, | |
293 NudgeSource nudge_source, | |
294 const syncable::ModelTypePayloadMap& model_types_with_payloads, | |
295 bool* initial_sync); | |
296 | |
297 int UserIdleTime(); | |
298 | |
299 void WaitUntilConnectedOrQuit(); | |
300 | |
301 // The thread will remain in this method until a resume is requested | |
302 // or shutdown is started. | |
303 void PauseUntilResumedOrQuit(); | |
304 | |
305 void EnterPausedState(); | |
306 | |
307 void ExitPausedState(); | |
308 | |
309 // For unit tests only. | |
310 virtual void DisableIdleDetection(); | |
311 | |
312 // This sets all conditions for syncer thread termination but does not | |
313 // actually join threads. It is expected that Stop will be called at some | |
314 // time after to fully stop and clean up. | |
315 void RequestSyncerExitAndSetThreadStopConditions(); | |
316 | |
317 void Notify(SyncEngineEvent::EventCause cause); | 262 void Notify(SyncEngineEvent::EventCause cause); |
318 | 263 |
319 scoped_ptr<EventListenerHookup> conn_mgr_hookup_; | 264 // Callback to change backoff state. |
265 void DoCanaryJob(); | |
266 void Unthrottle(); | |
267 | |
268 // Executes the pending job. Called whenever an event occurs that may | |
269 // change conditions permitting a job to run. Like when network connection is | |
270 // re-established, mode changes etc. | |
271 void DoPendingJobIfPossible(bool is_canary_job); | |
272 | |
273 // The pointer is owned by the caller. | |
274 browser_sync::sessions::SyncSession* CreateSyncSession( | |
275 const browser_sync::sessions::SyncSourceInfo& info); | |
276 | |
277 // Creates a session for a poll and performs the sync. | |
278 void PollTimerCallback(); | |
279 | |
280 // Assign |start| and |end| to appropriate SyncerStep values for the | |
281 // specified |purpose|. | |
282 void SetSyncerStepsForPurpose(SyncSessionJob::SyncSessionJobPurpose purpose, | |
283 SyncerStep* start, | |
284 SyncerStep* end); | |
285 | |
286 // Initializes the hookup between the ServerConnectionManager and us. | |
287 void WatchConnectionManager(); | |
288 | |
289 // Used to update |server_connection_ok_|, see below. | |
290 void CheckServerConnectionManagerStatus( | |
291 HttpResponse::ServerConnectionCode code); | |
292 | |
293 // Called once the first time thread_ is started to broadcast an initial | |
294 // session snapshot containing data like initial_sync_ended. Important when | |
295 // the client starts up and does not need to perform an initial sync. | |
296 void SendInitialSnapshot(); | |
297 | |
298 base::Thread thread_; | |
320 | 299 |
321 // Modifiable versions of kDefaultLongPollIntervalSeconds which can be | 300 // Modifiable versions of kDefaultLongPollIntervalSeconds which can be |
322 // updated by the server. | 301 // updated by the server. |
323 int syncer_short_poll_interval_seconds_; | 302 base::TimeDelta syncer_short_poll_interval_seconds_; |
324 int syncer_long_poll_interval_seconds_; | 303 base::TimeDelta syncer_long_poll_interval_seconds_; |
325 | 304 |
326 // The time we wait between polls in seconds. This is used as lower bound on | 305 // Periodic timer for polling. See AdjustPolling. |
327 // our wait time. Updated once per loop from the command line flag. | 306 base::RepeatingTimer<SyncerThread> poll_timer_; |
328 int syncer_polling_interval_; | |
329 | 307 |
330 // The upper bound on the nominal wait between polls in seconds. Note that | 308 // The mode of operation. We don't use a lock, see Start(...) comment. |
331 // this bounds the "nominal" poll interval, while the the actual interval | 309 Mode mode_; |
332 // also takes previous failures into account. | |
333 int syncer_max_interval_; | |
334 | 310 |
335 // This causes syncer to start syncing ASAP. If the rate of requests is too | 311 // TODO(tim): Bug 26339. This needs to track more than just time I think, |
336 // high the request will be silently dropped. mutex_ should be held when | 312 // since the nudges could be for different types. Current impl doesn't care. |
337 // this is called. | 313 base::TimeTicks last_sync_session_end_time_; |
338 void NudgeSyncImpl( | |
339 int milliseconds_from_now, | |
340 NudgeSource source, | |
341 const syncable::ModelTypePayloadMap& model_types_with_payloads); | |
342 | 314 |
343 #if defined(OS_LINUX) | 315 // Have we observed a valid server connection? |
344 // On Linux, we need this information in order to query idle time. | 316 bool server_connection_ok_; |
345 scoped_ptr<IdleQueryLinux> idle_query_; | 317 |
346 #endif | 318 // Tracks in-flight nudges so we can coalesce. |
319 scoped_ptr<SyncSessionJob> pending_nudge_; | |
320 | |
321 // Current wait state. Null if we're not in backoff and not throttled. | |
322 scoped_ptr<WaitInterval> wait_interval_; | |
323 | |
324 scoped_ptr<DelayProvider> delay_provider_; | |
325 | |
326 // Invoked to run through the sync cycle. | |
327 scoped_ptr<Syncer> syncer_; | |
347 | 328 |
348 scoped_ptr<sessions::SyncSessionContext> session_context_; | 329 scoped_ptr<sessions::SyncSessionContext> session_context_; |
349 | 330 |
350 // Set whenever the server instructs us to stop sending it requests until | |
351 // a specified time, and reset for each call to SyncShare. (Note that the | |
352 // WaitInterval::THROTTLED contract is such that we don't call SyncShare at | |
353 // all until the "silenced until" embargo expires.) | |
354 base::TimeTicks silenced_until_; | |
355 | |
356 // Useful for unit tests | |
357 bool disable_idle_detection_; | |
358 | |
359 DISALLOW_COPY_AND_ASSIGN(SyncerThread); | 331 DISALLOW_COPY_AND_ASSIGN(SyncerThread); |
360 }; | 332 }; |
361 | 333 |
334 | |
362 } // namespace browser_sync | 335 } // namespace browser_sync |
363 | 336 |
337 // The SyncerThread manages its own internal thread and thus outlives it. We | |
338 // don't need refcounting for posting tasks to this internal thread. | |
339 DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::SyncerThread); | |
340 | |
364 #endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_ | 341 #endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_ |
OLD | NEW |