Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / sync / engine / sync_scheduler_impl.h
1 // Copyright 2012 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 #ifndef SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_
6 #define SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_
7
8 #include <map>
9 #include <string>
10
11 #include "base/callback.h"
12 #include "base/cancelable_callback.h"
13 #include "base/compiler_specific.h"
14 #include "base/gtest_prod_util.h"
15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/threading/non_thread_safe.h"
19 #include "base/time/time.h"
20 #include "base/timer/timer.h"
21 #include "sync/base/sync_export.h"
22 #include "sync/engine/net/server_connection_manager.h"
23 #include "sync/engine/nudge_source.h"
24 #include "sync/engine/sync_scheduler.h"
25 #include "sync/engine/syncer.h"
26 #include "sync/internal_api/public/engine/polling_constants.h"
27 #include "sync/internal_api/public/util/weak_handle.h"
28 #include "sync/sessions/nudge_tracker.h"
29 #include "sync/sessions/sync_session.h"
30 #include "sync/sessions/sync_session_context.h"
31
32 namespace syncer {
33
34 class BackoffDelayProvider;
35
36 namespace sessions {
37 struct ModelNeutralState;
38 }
39
40 class SYNC_EXPORT_PRIVATE SyncSchedulerImpl
41     : public SyncScheduler,
42       public base::NonThreadSafe {
43  public:
44   // |name| is a display string to identify the syncer thread.  Takes
45   // |ownership of |syncer| and |delay_provider|.
46   SyncSchedulerImpl(const std::string& name,
47                     BackoffDelayProvider* delay_provider,
48                     sessions::SyncSessionContext* context,
49                     Syncer* syncer);
50
51   // Calls Stop().
52   ~SyncSchedulerImpl() override;
53
54   void Start(Mode mode) override;
55   void ScheduleConfiguration(const ConfigurationParams& params) override;
56   void Stop() override;
57   void ScheduleLocalNudge(
58       ModelTypeSet types,
59       const tracked_objects::Location& nudge_location) override;
60   void ScheduleLocalRefreshRequest(
61       ModelTypeSet types,
62       const tracked_objects::Location& nudge_location) override;
63   void ScheduleInvalidationNudge(
64       syncer::ModelType type,
65       scoped_ptr<InvalidationInterface> invalidation,
66       const tracked_objects::Location& nudge_location) override;
67   void ScheduleInitialSyncNudge(syncer::ModelType model_type) override;
68   void SetNotificationsEnabled(bool notifications_enabled) override;
69
70   void OnCredentialsUpdated() override;
71   void OnConnectionStatusChange() override;
72
73   // SyncSession::Delegate implementation.
74   void OnThrottled(const base::TimeDelta& throttle_duration) override;
75   void OnTypesThrottled(ModelTypeSet types,
76                         const base::TimeDelta& throttle_duration) override;
77   bool IsCurrentlyThrottled() override;
78   void OnReceivedShortPollIntervalUpdate(
79       const base::TimeDelta& new_interval) override;
80   void OnReceivedLongPollIntervalUpdate(
81       const base::TimeDelta& new_interval) override;
82   void OnReceivedCustomNudgeDelays(
83       const std::map<ModelType, base::TimeDelta>& nudge_delays) override;
84   void OnReceivedClientInvalidationHintBufferSize(int size) override;
85   void OnSyncProtocolError(
86       const SyncProtocolError& sync_protocol_error) override;
87   void OnReceivedGuRetryDelay(const base::TimeDelta& delay) override;
88   void OnReceivedMigrationRequest(syncer::ModelTypeSet types) override;
89
90   // Returns true if the client is currently in exponential backoff.
91   bool IsBackingOff() const;
92
93  private:
94   enum JobPriority {
95     // Non-canary jobs respect exponential backoff.
96     NORMAL_PRIORITY,
97     // Canary jobs bypass exponential backoff, so use with extreme caution.
98     CANARY_PRIORITY
99   };
100
101   enum PollAdjustType {
102     // Restart the poll interval.
103     FORCE_RESET,
104     // Restart the poll interval only if its length has changed.
105     UPDATE_INTERVAL,
106   };
107
108   friend class SyncSchedulerTest;
109   friend class SyncSchedulerWhiteboxTest;
110   friend class SyncerTest;
111
112   FRIEND_TEST_ALL_PREFIXES(SyncSchedulerTest, TransientPollFailure);
113   FRIEND_TEST_ALL_PREFIXES(SyncSchedulerTest,
114                            ServerConnectionChangeDuringBackoff);
115   FRIEND_TEST_ALL_PREFIXES(SyncSchedulerTest,
116                            ConnectionChangeCanaryPreemptedByNudge);
117   FRIEND_TEST_ALL_PREFIXES(BackoffTriggersSyncSchedulerTest,
118                            FailGetEncryptionKey);
119   FRIEND_TEST_ALL_PREFIXES(SyncSchedulerTest, SuccessfulRetry);
120   FRIEND_TEST_ALL_PREFIXES(SyncSchedulerTest, FailedRetry);
121   FRIEND_TEST_ALL_PREFIXES(SyncSchedulerTest, ReceiveNewRetryDelay);
122
123   struct SYNC_EXPORT_PRIVATE WaitInterval {
124     enum Mode {
125       // Uninitialized state, should not be set in practice.
126       UNKNOWN = -1,
127       // We enter a series of increasingly longer WaitIntervals if we experience
128       // repeated transient failures.  We retry at the end of each interval.
129       EXPONENTIAL_BACKOFF,
130       // A server-initiated throttled interval.  We do not allow any syncing
131       // during such an interval.
132       THROTTLED,
133     };
134     WaitInterval();
135     ~WaitInterval();
136     WaitInterval(Mode mode, base::TimeDelta length);
137
138     static const char* GetModeString(Mode mode);
139
140     Mode mode;
141     base::TimeDelta length;
142   };
143
144   static const char* GetModeString(Mode mode);
145
146   void SetDefaultNudgeDelay(base::TimeDelta delay_ms);
147
148   // Invoke the syncer to perform a nudge job.
149   void DoNudgeSyncSessionJob(JobPriority priority);
150
151   // Invoke the syncer to perform a configuration job.
152   void DoConfigurationSyncSessionJob(JobPriority priority);
153
154   // Helper function for Do{Nudge,Configuration}SyncSessionJob.
155   void HandleFailure(
156       const sessions::ModelNeutralState& model_neutral_state);
157
158   // Invoke the Syncer to perform a poll job.
159   void DoPollSyncSessionJob();
160
161   // Helper function to calculate poll interval.
162   base::TimeDelta GetPollInterval();
163
164   // Adjusts the poll timer to account for new poll interval, and possibly
165   // resets the poll interval, depedning on the flag's value.
166   void AdjustPolling(PollAdjustType type);
167
168   // Helper to restart waiting with |wait_interval_|'s timer.
169   void RestartWaiting();
170
171   // Determines if we're allowed to contact the server right now.
172   bool CanRunJobNow(JobPriority priority);
173
174   // Determines if we're allowed to contact the server right now.
175   bool CanRunNudgeJobNow(JobPriority priority);
176
177   // If the scheduler's current state supports it, this will create a job based
178   // on the passed in parameters and coalesce it with any other pending jobs,
179   // then post a delayed task to run it.  It may also choose to drop the job or
180   // save it for later, depending on the scheduler's current state.
181   void ScheduleNudgeImpl(
182       const base::TimeDelta& delay,
183       const tracked_objects::Location& nudge_location);
184
185   // Helper to signal listeners about changed retry time.
186   void NotifyRetryTime(base::Time retry_time);
187
188   // Helper to signal listeners about changed throttled types.
189   void NotifyThrottledTypesChanged(ModelTypeSet types);
190
191   // Looks for pending work and, if it finds any, run this work at "canary"
192   // priority.
193   void TryCanaryJob();
194
195   // At the moment TrySyncSessionJob just posts call to TrySyncSessionJobImpl on
196   // current thread. In the future it will request access token here.
197   void TrySyncSessionJob();
198   void TrySyncSessionJobImpl();
199
200   // Transitions out of the THROTTLED WaitInterval then calls TryCanaryJob().
201   void Unthrottle();
202
203   // Called when a per-type throttling interval expires.
204   void TypeUnthrottle(base::TimeTicks unthrottle_time);
205
206   // Runs a normal nudge job when the scheduled timer expires.
207   void PerformDelayedNudge();
208
209   // Attempts to exit EXPONENTIAL_BACKOFF by calling TryCanaryJob().
210   void ExponentialBackoffRetry();
211
212   // Called when the root cause of the current connection error is fixed.
213   void OnServerConnectionErrorFixed();
214
215   // Creates a session for a poll and performs the sync.
216   void PollTimerCallback();
217
218   // Creates a session for a retry and performs the sync.
219   void RetryTimerCallback();
220
221   // Returns the set of types that are enabled and not currently throttled.
222   ModelTypeSet GetEnabledAndUnthrottledTypes();
223
224   // Called as we are started to broadcast an initial session snapshot
225   // containing data like initial_sync_ended.  Important when the client starts
226   // up and does not need to perform an initial sync.
227   void SendInitialSnapshot();
228
229   // This is used for histogramming and analysis of ScheduleNudge* APIs.
230   // SyncScheduler is the ultimate choke-point for all such invocations (with
231   // and without InvalidationState variants, all NudgeSources, etc) and as such
232   // is the most flexible place to do this bookkeeping.
233   void UpdateNudgeTimeRecords(ModelTypeSet types);
234
235   // For certain methods that need to worry about X-thread posting.
236   WeakHandle<SyncSchedulerImpl> weak_handle_this_;
237
238   // Used for logging.
239   const std::string name_;
240
241   // Set in Start(), unset in Stop().
242   bool started_;
243
244   // Modifiable versions of kDefaultLongPollIntervalSeconds which can be
245   // updated by the server.
246   base::TimeDelta syncer_short_poll_interval_seconds_;
247   base::TimeDelta syncer_long_poll_interval_seconds_;
248
249   // Periodic timer for polling.  See AdjustPolling.
250   base::RepeatingTimer<SyncSchedulerImpl> poll_timer_;
251
252   // The mode of operation.
253   Mode mode_;
254
255   // Current wait state.  Null if we're not in backoff and not throttled.
256   scoped_ptr<WaitInterval> wait_interval_;
257
258   scoped_ptr<BackoffDelayProvider> delay_provider_;
259
260   // The event that will wake us up.
261   base::OneShotTimer<SyncSchedulerImpl> pending_wakeup_timer_;
262
263   // An event that fires when data type throttling expires.
264   base::OneShotTimer<SyncSchedulerImpl> type_unthrottle_timer_;
265
266   // Storage for variables related to an in-progress configure request.  Note
267   // that (mode_ != CONFIGURATION_MODE) \implies !pending_configure_params_.
268   scoped_ptr<ConfigurationParams> pending_configure_params_;
269
270   // If we have a nudge pending to run soon, it will be listed here.
271   base::TimeTicks scheduled_nudge_time_;
272
273   // Keeps track of work that the syncer needs to handle.
274   sessions::NudgeTracker nudge_tracker_;
275
276   // Invoked to run through the sync cycle.
277   scoped_ptr<Syncer> syncer_;
278
279   sessions::SyncSessionContext* session_context_;
280
281   // A map tracking LOCAL NudgeSource invocations of ScheduleNudge* APIs,
282   // organized by datatype. Each datatype that was part of the types requested
283   // in the call will have its TimeTicks value updated.
284   typedef std::map<ModelType, base::TimeTicks> ModelTypeTimeMap;
285   ModelTypeTimeMap last_local_nudges_by_model_type_;
286
287   // Used as an "anti-reentrancy defensive assertion".
288   // While true, it is illegal for any new scheduling activity to take place.
289   // Ensures that higher layers don't break this law in response to events that
290   // take place during a sync cycle. We call this out because such violations
291   // could result in tight sync loops hitting sync servers.
292   bool no_scheduling_allowed_;
293
294   // crbug/251307. This is a workaround for M29. crbug/259913 tracks proper fix
295   // for M30.
296   // The issue is that poll job runs after few hours of inactivity and therefore
297   // will always fail with auth error because of expired access token. Once
298   // fresh access token is requested poll job is not retried.
299   // The change is to remember that poll timer just fired and retry poll job
300   // after credentials are updated.
301   bool do_poll_after_credentials_updated_;
302
303   // TryJob might get called for multiple reasons. It should only call
304   // DoPollSyncSessionJob after some time since the last attempt.
305   // last_poll_reset_ keeps track of when was last attempt.
306   base::TimeTicks last_poll_reset_;
307
308   // next_sync_session_job_priority_ defines which priority will be used next
309   // time TrySyncSessionJobImpl is called. CANARY_PRIORITY allows syncer to run
310   // even if scheduler is in exponential backoff. This is needed for events that
311   // have chance of resolving previous error (e.g. network connection change
312   // after NETWORK_UNAVAILABLE error).
313   // It is reset back to NORMAL_PRIORITY on every call to TrySyncSessionJobImpl.
314   JobPriority next_sync_session_job_priority_;
315
316   // One-shot timer for scheduling GU retry according to delay set by server.
317   base::OneShotTimer<SyncSchedulerImpl> retry_timer_;
318
319   base::WeakPtrFactory<SyncSchedulerImpl> weak_ptr_factory_;
320
321   // A second factory specially for weak_handle_this_, to allow the handle
322   // to be const and alleviate threading concerns.
323   base::WeakPtrFactory<SyncSchedulerImpl> weak_ptr_factory_for_weak_handle_;
324
325   DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl);
326 };
327
328 }  // namespace syncer
329
330 #endif  // SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_