| Index: chrome/browser/sync/engine/syncer_thread.h
|
| diff --git a/chrome/browser/sync/engine/syncer_thread.h b/chrome/browser/sync/engine/syncer_thread.h
|
| index d270f14000d127431ceff0ce7b804ec8a8acce0a..11fee167958b5f88dd7db4d1ce0c3f900d5aff5e 100644
|
| --- a/chrome/browser/sync/engine/syncer_thread.h
|
| +++ b/chrome/browser/sync/engine/syncer_thread.h
|
| @@ -3,74 +3,175 @@
|
| // found in the LICENSE file.
|
| //
|
| // A class to run the syncer on a thread.
|
| -// This is the default implementation of SyncerThread whose Stop implementation
|
| -// does not support a timeout, but is greatly simplified.
|
| #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
|
| #define CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
|
| #pragma once
|
|
|
| -#include <list>
|
| -#include <string>
|
| -#include <vector>
|
| -
|
| -#include "base/basictypes.h"
|
| -#include "base/gtest_prod_util.h"
|
| -#include "base/memory/ref_counted.h"
|
| +#include "base/callback.h"
|
| +#include "base/memory/linked_ptr.h"
|
| #include "base/memory/scoped_ptr.h"
|
| -#include "base/synchronization/condition_variable.h"
|
| +#include "base/observer_list.h"
|
| +#include "base/task.h"
|
| #include "base/threading/thread.h"
|
| #include "base/time.h"
|
| -#include "base/synchronization/waitable_event.h"
|
| -#include "chrome/browser/sync/engine/syncer_types.h"
|
| -#include "chrome/browser/sync/sessions/sync_session.h"
|
| -#include "chrome/browser/sync/syncable/model_type.h"
|
| +#include "base/timer.h"
|
| +#include "chrome/browser/sync/engine/nudge_source.h"
|
| +#include "chrome/browser/sync/engine/polling_constants.h"
|
| +#include "chrome/browser/sync/engine/syncer.h"
|
| #include "chrome/browser/sync/syncable/model_type_payload_map.h"
|
| -#include "chrome/common/deprecated/event_sys-inl.h"
|
| -
|
| -#if defined(OS_LINUX)
|
| -#include "chrome/browser/sync/engine/idle_query_linux.h"
|
| -#endif
|
| -
|
| -class EventListenerHookup;
|
| +#include "chrome/browser/sync/engine/net/server_connection_manager.h"
|
| +#include "chrome/browser/sync/sessions/sync_session.h"
|
| +#include "chrome/browser/sync/sessions/sync_session_context.h"
|
|
|
| namespace browser_sync {
|
|
|
| -class ModelSafeWorker;
|
| -class ServerConnectionManager;
|
| -class Syncer;
|
| -class URLFactory;
|
| struct ServerConnectionEvent;
|
|
|
| -class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
|
| - public sessions::SyncSession::Delegate {
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadTest, CalculateSyncWaitTime);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadTest, CalculatePollingWaitTime);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Polling);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Nudge);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, NudgeWithDataTypes);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest,
|
| - NudgeWithDataTypesCoalesced);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, NudgeWithPayloads);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest,
|
| - NudgeWithPayloadsCoalesced);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Throttling);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, AuthInvalid);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, Pause);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, StartWhenNotConnected);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, PauseWhenNotConnected);
|
| - FRIEND_TEST_ALL_PREFIXES(SyncerThreadWithSyncerTest, StopSyncPermanently);
|
| - friend class SyncerThreadWithSyncerTest;
|
| - friend class SyncerThreadFactory;
|
| +class SyncerThread : public sessions::SyncSession::Delegate,
|
| + public ServerConnectionEventListener {
|
| public:
|
| - // Encapsulates the parameters that make up an interval on which the
|
| - // syncer thread is sleeping.
|
| + enum Mode {
|
| + // In this mode, the thread only performs configuration tasks. This is
|
| + // designed to make the case where we want to download updates for a
|
| + // specific type only, and not continue syncing until we are moved into
|
| + // normal mode.
|
| + CONFIGURATION_MODE,
|
| + // Resumes polling and allows nudges, drops configuration tasks. Runs
|
| + // through entire sync cycle.
|
| + NORMAL_MODE,
|
| + };
|
| +
|
| + // Takes ownership of both |context| and |syncer|.
|
| + SyncerThread(sessions::SyncSessionContext* context, Syncer* syncer);
|
| + virtual ~SyncerThread();
|
| +
|
| + typedef Callback0::Type ModeChangeCallback;
|
| +
|
| + // Change the mode of operation.
|
| + // We don't use a lock when changing modes, so we won't cause currently
|
| + // scheduled jobs to adhere to the new mode. We could protect it, but it
|
| + // doesn't buy very much as a) a session could already be in progress and it
|
| + // will continue no matter what, b) the scheduled sessions already contain
|
| + // all their required state and won't be affected by potential change at
|
| + // higher levels (i.e. the registrar), and c) we service tasks FIFO, so once
|
| + // the mode changes all future jobs will be run against the updated mode.
|
| + // If supplied, |callback| will be invoked when the mode has been
|
| + // changed to |mode| *from the SyncerThread*, and not from the caller
|
| + // thread.
|
| + void Start(Mode mode, ModeChangeCallback* callback);
|
| +
|
| + // Joins on the thread as soon as possible (currently running session
|
| + // completes).
|
| + void Stop();
|
| +
|
| + // The meat and potatoes.
|
| + void ScheduleNudge(const base::TimeDelta& delay, NudgeSource source,
|
| + const syncable::ModelTypeBitSet& types,
|
| + const tracked_objects::Location& nudge_location);
|
| + void ScheduleNudgeWithPayloads(
|
| + const base::TimeDelta& delay, NudgeSource source,
|
| + const syncable::ModelTypePayloadMap& types_with_payloads,
|
| + const tracked_objects::Location& nudge_location);
|
| + void ScheduleConfig(const syncable::ModelTypeBitSet& types);
|
| + void ScheduleClearUserData();
|
| +
|
| + // Change status of notifications in the SyncSessionContext.
|
| + void set_notifications_enabled(bool notifications_enabled);
|
| +
|
| + // DDOS avoidance function. Calculates how long we should wait before trying
|
| + // again after a failed sync attempt, where the last delay was |base_delay|.
|
| + // TODO(tim): Look at URLRequestThrottlerEntryInterface.
|
| + static base::TimeDelta GetRecommendedDelay(const base::TimeDelta& base_delay);
|
| +
|
| + // SyncSession::Delegate implementation.
|
| + virtual void OnSilencedUntil(const base::TimeTicks& silenced_until);
|
| + virtual bool IsSyncingCurrentlySilenced();
|
| + virtual void OnReceivedShortPollIntervalUpdate(
|
| + const base::TimeDelta& new_interval);
|
| + virtual void OnReceivedLongPollIntervalUpdate(
|
| + const base::TimeDelta& new_interval);
|
| + virtual void OnShouldStopSyncingPermanently();
|
| +
|
| + // ServerConnectionEventListener implementation.
|
| + // TODO(tim): schedule a nudge when valid connection detected? in 1 minute?
|
| + virtual void OnServerConnectionEvent(const ServerConnectionEvent2& event);
|
| +
|
| + private:
|
| + enum JobProcessDecision {
|
| + // Indicates we should continue with the current job.
|
| + CONTINUE,
|
| + // Indicates that we should save it to be processed later.
|
| + SAVE,
|
| + // Indicates we should drop this job.
|
| + DROP,
|
| + };
|
| +
|
| + struct SyncSessionJob {
|
| + // An enum used to describe jobs for scheduling purposes.
|
| + enum SyncSessionJobPurpose {
|
| + // Our poll timer schedules POLL jobs periodically based on a server
|
| + // assigned poll interval.
|
| + POLL,
|
| + // A nudge task can come from a variety of components needing to force
|
| + // a sync. The source is inferable from |session.source()|.
|
| + NUDGE,
|
| + // The user invoked a function in the UI to clear their entire account
|
| + // and stop syncing (globally).
|
| + CLEAR_USER_DATA,
|
| + // Typically used for fetching updates for a subset of the enabled types
|
| + // during initial sync or reconfiguration. We don't run all steps of
|
| + // the sync cycle for these (e.g. CleanupDisabledTypes is skipped).
|
| + CONFIGURATION,
|
| + };
|
| + SyncSessionJob();
|
| + SyncSessionJob(SyncSessionJobPurpose purpose, base::TimeTicks start,
|
| + linked_ptr<sessions::SyncSession> session, bool is_canary_job,
|
| + const tracked_objects::Location& nudge_location);
|
| + ~SyncSessionJob();
|
| + SyncSessionJobPurpose purpose;
|
| + base::TimeTicks scheduled_start;
|
| + linked_ptr<sessions::SyncSession> session;
|
| + bool is_canary_job;
|
| +
|
| + // This is the location the nudge came from. used for debugging purpose.
|
| + // In case of multiple nudges getting coalesced this stores the first nudge
|
| + // that came in.
|
| + tracked_objects::Location nudge_location;
|
| + };
|
| + friend class SyncerThread2Test;
|
| + friend class SyncerThread2WhiteboxTest;
|
| +
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
|
| + DropNudgeWhileExponentialBackOff);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, SaveNudge);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueNudge);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, DropPoll);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinuePoll);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest, ContinueConfiguration);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
|
| + SaveConfigurationWhileThrottled);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
|
| + SaveNudgeWhileThrottled);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
|
| + ContinueClearUserDataUnderAllCircumstances);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
|
| + ContinueCanaryJobConfig);
|
| + FRIEND_TEST_ALL_PREFIXES(SyncerThread2WhiteboxTest,
|
| + ContinueNudgeWhileExponentialBackOff);
|
| +
|
| + // A component used to get time delays associated with exponential backoff.
|
| + // Encapsulated into a class to facilitate testing.
|
| + class DelayProvider {
|
| + public:
|
| + DelayProvider();
|
| + virtual base::TimeDelta GetDelay(const base::TimeDelta& last_delay);
|
| + virtual ~DelayProvider();
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(DelayProvider);
|
| + };
|
| +
|
| struct WaitInterval {
|
| enum Mode {
|
| - // A wait interval whose duration has not been affected by exponential
|
| - // backoff. The base case for exponential backoff falls in to this case
|
| - // (e.g when the exponent is 1). So far, we don't need a separate case.
|
| - // NORMAL intervals are not nudge-rate limited.
|
| - NORMAL,
|
| // A wait interval whose duration has been affected by exponential
|
| // backoff.
|
| // EXPONENTIAL_BACKOFF intervals are nudge-rate limited to 1 per interval.
|
| @@ -79,286 +180,162 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
|
| // during such an interval.
|
| THROTTLED,
|
| };
|
| + WaitInterval();
|
| + ~WaitInterval();
|
|
|
| Mode mode;
|
| - // This bool is set to true if we have observed a nudge during during this
|
| - // interval and mode == EXPONENTIAL_BACKOFF.
|
| - bool had_nudge_during_backoff;
|
| - base::TimeDelta poll_delta; // The wait duration until the next poll.
|
|
|
| - WaitInterval() : mode(NORMAL), had_nudge_during_backoff(false) { }
|
| + // This bool is set to true if we have observed a nudge during this
|
| + // interval and mode == EXPONENTIAL_BACKOFF.
|
| + bool had_nudge;
|
| + base::TimeDelta length;
|
| + base::OneShotTimer<SyncerThread> timer;
|
| +
|
| + // Configure jobs are saved only when backing off or throttling. So we
|
| + // expose the pointer here.
|
| + scoped_ptr<SyncSessionJob> pending_configure_job;
|
| + WaitInterval(Mode mode, base::TimeDelta length);
|
| };
|
|
|
| - enum NudgeSource {
|
| - kUnknown = 0,
|
| - kNotification,
|
| - kLocal,
|
| - kContinuation,
|
| - kClearPrivateData
|
| - };
|
| - // Server can overwrite these values via client commands.
|
| - // Standard short poll. This is used when XMPP is off.
|
| - static const int kDefaultShortPollIntervalSeconds;
|
| - // Long poll is used when XMPP is on.
|
| - static const int kDefaultLongPollIntervalSeconds;
|
| - // 30 minutes by default. If exponential backoff kicks in, this is the
|
| - // longest possible poll interval.
|
| - static const int kDefaultMaxPollIntervalMs;
|
| - // Maximum interval for exponential backoff.
|
| - static const int kMaxBackoffSeconds;
|
| -
|
| - explicit SyncerThread(sessions::SyncSessionContext* context);
|
| - virtual ~SyncerThread();
|
| + // Helper to assemble a job and post a delayed task to sync.
|
| + void ScheduleSyncSessionJob(
|
| + const base::TimeDelta& delay,
|
| + SyncSessionJob::SyncSessionJobPurpose purpose,
|
| + sessions::SyncSession* session,
|
| + const tracked_objects::Location& nudge_location);
|
|
|
| - virtual void WatchConnectionManager(ServerConnectionManager* conn_mgr);
|
| -
|
| - // Starts a syncer thread.
|
| - // Returns true if it creates a thread or if there's currently a thread
|
| - // running and false otherwise.
|
| - virtual bool Start();
|
| -
|
| - // Stop processing. |max_wait| doesn't do anything in this version.
|
| - virtual bool Stop(int max_wait);
|
| -
|
| - // Request that the thread pauses. Returns false if the request can
|
| - // not be completed (e.g. the thread is not running). When the
|
| - // thread actually pauses, a SyncEngineEvent::PAUSED event notification
|
| - // will be sent to the relay channel.
|
| - virtual bool RequestPause();
|
| -
|
| - // Request that the thread resumes from pause. Returns false if the
|
| - // request can not be completed (e.g. the thread is not running or
|
| - // is not currently paused). When the thread actually resumes, a
|
| - // SyncEngineEvent::RESUMED event notification will be sent to the relay
|
| - // channel.
|
| - virtual bool RequestResume();
|
| -
|
| - // Nudges the syncer to sync with a delay specified. This API is for access
|
| - // from the SyncerThread's controller and will cause a mutex lock.
|
| - virtual void NudgeSyncer(int milliseconds_from_now, NudgeSource source);
|
| -
|
| - // Same as |NudgeSyncer|, but supports tracking the datatypes that caused
|
| - // the nudge to occur.
|
| - virtual void NudgeSyncerWithDataTypes(
|
| - int milliseconds_from_now,
|
| - NudgeSource source,
|
| - const syncable::ModelTypeBitSet& model_types);
|
| -
|
| - // Same as |NudgeSyncer|, but supports including a payload for passing on to
|
| - // the download updates command. Datatypes with payloads are also considered
|
| - // to have caused a nudged to occur and treated accordingly.
|
| - virtual void NudgeSyncerWithPayloads(
|
| - int milliseconds_from_now,
|
| - NudgeSource source,
|
| - const syncable::ModelTypePayloadMap& model_types_with_payloads);
|
| -
|
| - void SetNotificationsEnabled(bool notifications_enabled);
|
| -
|
| - // Call this when a directory is opened
|
| - void CreateSyncer(const std::string& dirname);
|
| -
|
| - // DDOS avoidance function. The argument and return value is in seconds
|
| - static int GetRecommendedDelaySeconds(int base_delay_seconds);
|
| -
|
| - protected:
|
| - virtual void ThreadMain();
|
| - void ThreadMainLoop();
|
| -
|
| - virtual void SetConnected(bool connected);
|
| -
|
| - virtual void SetSyncerPollingInterval(base::TimeDelta interval);
|
| - virtual void SetSyncerShortPollInterval(base::TimeDelta interval);
|
| -
|
| - // Needed to emulate the behavior of pthread_create, which synchronously
|
| - // started the thread and set the value of thread_running_ to true.
|
| - // We can't quite match that because we asynchronously post the task,
|
| - // which opens a window for Stop to get called before the task actually
|
| - // makes it. To prevent this, we block Start() until we're sure it's ok.
|
| - base::WaitableEvent thread_main_started_;
|
| -
|
| - // Handle of the running thread.
|
| - base::Thread thread_;
|
| + // Invoke the Syncer to perform a sync.
|
| + void DoSyncSessionJob(const SyncSessionJob& job);
|
|
|
| - // Fields that are modified / accessed by multiple threads go in this struct
|
| - // for clarity and explicitness.
|
| - struct ProtectedFields {
|
| - ProtectedFields();
|
| - ~ProtectedFields();
|
| + // Called after the Syncer has performed the sync represented by |job|, to
|
| + // reset our state.
|
| + void FinishSyncSessionJob(const SyncSessionJob& job);
|
|
|
| - // False when we want to stop the thread.
|
| - bool stop_syncer_thread_;
|
| + // Record important state that might be needed in future syncs, such as which
|
| + // data types may require cleanup.
|
| + void UpdateCarryoverSessionState(const SyncSessionJob& old_job);
|
|
|
| - // True when a pause was requested.
|
| - bool pause_requested_;
|
| + // Helper to FinishSyncSessionJob to schedule the next sync operation.
|
| + void ScheduleNextSync(const SyncSessionJob& old_job);
|
|
|
| - // True when the thread is paused.
|
| - bool paused_;
|
| + // Helper to configure polling intervals. Used by Start and ScheduleNextSync.
|
| + void AdjustPolling(const SyncSessionJob* old_job);
|
|
|
| - Syncer* syncer_;
|
| + // Helper to ScheduleNextSync in case of consecutive sync errors.
|
| + void HandleConsecutiveContinuationError(const SyncSessionJob& old_job);
|
|
|
| - // State of the server connection.
|
| - bool connected_;
|
| + // Determines if it is legal to run |job| by checking current
|
| + // operational mode, backoff or throttling, freshness
|
| + // (so we don't make redundant syncs), and connection.
|
| + bool ShouldRunJob(const SyncSessionJob& job);
|
|
|
| - // kUnknown if there is no pending nudge. (Theoretically, there
|
| - // could be a pending nudge of type kUnknown, so it's better to
|
| - // check pending_nudge_time_.)
|
| - NudgeSource pending_nudge_source_;
|
| + // Decide whether we should CONTINUE, SAVE or DROP the job.
|
| + JobProcessDecision DecideOnJob(const SyncSessionJob& job);
|
|
|
| - // Map of all datatypes that are requesting a nudge. Can be union
|
| - // from multiple nudges that are coalesced. In addition, we
|
| - // optionally track a payload associated with each datatype (most recent
|
| - // payload overwrites old ones). These payloads are used by the download
|
| - // updates command and can contain datatype specific information the server
|
| - // might use.
|
| - syncable::ModelTypePayloadMap pending_nudge_types_;
|
| + // Decide on whether to CONTINUE, SAVE or DROP the job when we are in
|
| + // backoff mode.
|
| + JobProcessDecision DecideWhileInWaitInterval(const SyncSessionJob& job);
|
|
|
| - // null iff there is no pending nudge.
|
| - base::TimeTicks pending_nudge_time_;
|
| + // Saves the job for future execution. Note: It drops all the poll jobs.
|
| + void SaveJob(const SyncSessionJob& job);
|
|
|
| - // The wait interval for to the current iteration of our main loop. This is
|
| - // only written to by the syncer thread, and since the only reader from a
|
| - // different thread (NudgeSync) is called at totally random times, we don't
|
| - // really need to access mutually exclusively as the data races that exist
|
| - // are intrinsic, but do so anyway and avoid using 'volatile'.
|
| - WaitInterval current_wait_interval_;
|
| - } vault_;
|
| + // Coalesces the current job with the pending nudge.
|
| + void InitOrCoalescePendingJob(const SyncSessionJob& job);
|
|
|
| - // Gets signaled whenever a thread outside of the syncer thread changes a
|
| - // protected field in the vault_.
|
| - base::ConditionVariable vault_field_changed_;
|
| + // 'Impl' here refers to real implementation of public functions, running on
|
| + // |thread_|.
|
| + void StartImpl(Mode mode, linked_ptr<ModeChangeCallback> callback);
|
| + void ScheduleNudgeImpl(
|
| + const base::TimeDelta& delay,
|
| + sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
|
| + const syncable::ModelTypePayloadMap& types_with_payloads,
|
| + bool is_canary_job, const tracked_objects::Location& nudge_location);
|
| + void ScheduleConfigImpl(const ModelSafeRoutingInfo& routing_info,
|
| + const std::vector<ModelSafeWorker*>& workers,
|
| + const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
|
| + void ScheduleClearUserDataImpl();
|
|
|
| - // Used to lock everything in |vault_|.
|
| - base::Lock lock_;
|
| + // Returns true if the client is currently in exponential backoff.
|
| + bool IsBackingOff() const;
|
|
|
| - private:
|
| - // Threshold multipler for how long before user should be considered idle.
|
| - static const int kPollBackoffThresholdMultiplier = 10;
|
| + // Helper to signal all listeners registered with |session_context_|.
|
| + void Notify(SyncEngineEvent::EventCause cause);
|
|
|
| - // SyncSession::Delegate implementation.
|
| - virtual void OnSilencedUntil(const base::TimeTicks& silenced_until);
|
| - virtual bool IsSyncingCurrentlySilenced();
|
| - virtual void OnReceivedShortPollIntervalUpdate(
|
| - const base::TimeDelta& new_interval);
|
| - virtual void OnReceivedLongPollIntervalUpdate(
|
| - const base::TimeDelta& new_interval);
|
| - virtual void OnShouldStopSyncingPermanently();
|
| + // Callback to change backoff state.
|
| + void DoCanaryJob();
|
| + void Unthrottle();
|
|
|
| - void HandleServerConnectionEvent(const ServerConnectionEvent& event);
|
| -
|
| - // Collect all local state required for a sync and build a SyncSession out of
|
| - // it, reset state for the next time, and performs the sync cycle.
|
| - // See |GetAndResetNudgeSource| for details on what 'reset' means.
|
| - // |was_nudged| is set to true if the session returned is fulfilling a nudge.
|
| - // Returns once the session is finished (HasMoreToSync returns false). The
|
| - // caller owns the returned SyncSession.
|
| - sessions::SyncSession* SyncMain(Syncer* syncer,
|
| - bool was_throttled,
|
| - bool continue_sync_cycle,
|
| - bool* initial_sync_for_thread,
|
| - bool* was_nudged);
|
| -
|
| - // Calculates the next sync wait time and exponential backoff state.
|
| - // last_poll_wait is the time duration of the previous polling timeout which
|
| - // was used. user_idle_milliseconds is updated by this method, and is a report
|
| - // of the full amount of time since the last period of activity for the user.
|
| - // The continue_sync_cycle parameter is used to determine whether or not we
|
| - // are calculating a polling wait time that is a continuation of an sync cycle
|
| - // which terminated while the syncer still had work to do. was_nudged is used
|
| - // in case of exponential backoff so we only allow one nudge per backoff
|
| - // interval.
|
| - WaitInterval CalculatePollingWaitTime(
|
| - int last_poll_wait, // in s
|
| - int* user_idle_milliseconds,
|
| - bool* continue_sync_cycle,
|
| - bool was_nudged);
|
| -
|
| - // Helper to above function, considers effect of user idle time.
|
| - virtual int CalculateSyncWaitTime(int last_wait, int user_idle_ms);
|
| -
|
| - // Resets the source tracking state to a clean slate and returns the current
|
| - // state in a SyncSourceInfo.
|
| - // The initial sync boolean is updated if read as a sentinel. The following
|
| - // two methods work in concert to achieve this goal.
|
| - // If |was_throttled| was true, this still discards elapsed nudges, but we
|
| - // treat the request as a periodic poll rather than a nudge from a source.
|
| - // Builds a SyncSourceInfo and returns whether a nudge occurred in the
|
| - // |was_nudged| parameter.
|
| - sessions::SyncSourceInfo GetAndResetNudgeSource(bool was_throttled,
|
| - bool continue_sync_cycle,
|
| - bool* initial_sync,
|
| - bool* was_nudged);
|
| -
|
| - sessions::SyncSourceInfo MakeSyncSourceInfo(
|
| - bool nudged,
|
| - NudgeSource nudge_source,
|
| - const syncable::ModelTypePayloadMap& model_types_with_payloads,
|
| - bool* initial_sync);
|
| -
|
| - int UserIdleTime();
|
| -
|
| - void WaitUntilConnectedOrQuit();
|
| -
|
| - // The thread will remain in this method until a resume is requested
|
| - // or shutdown is started.
|
| - void PauseUntilResumedOrQuit();
|
| -
|
| - void EnterPausedState();
|
| -
|
| - void ExitPausedState();
|
| -
|
| - // For unit tests only.
|
| - virtual void DisableIdleDetection();
|
| -
|
| - // This sets all conditions for syncer thread termination but does not
|
| - // actually join threads. It is expected that Stop will be called at some
|
| - // time after to fully stop and clean up.
|
| - void RequestSyncerExitAndSetThreadStopConditions();
|
| + // Executes the pending job. Called whenever an event occurs that may
|
| + // change conditions permitting a job to run. Like when network connection is
|
| + // re-established, mode changes etc.
|
| + void DoPendingJobIfPossible(bool is_canary_job);
|
|
|
| - void Notify(SyncEngineEvent::EventCause cause);
|
| + // The pointer is owned by the caller.
|
| + browser_sync::sessions::SyncSession* CreateSyncSession(
|
| + const browser_sync::sessions::SyncSourceInfo& info);
|
| +
|
| + // Creates a session for a poll and performs the sync.
|
| + void PollTimerCallback();
|
| +
|
| + // Assign |start| and |end| to appropriate SyncerStep values for the
|
| + // specified |purpose|.
|
| + void SetSyncerStepsForPurpose(SyncSessionJob::SyncSessionJobPurpose purpose,
|
| + SyncerStep* start,
|
| + SyncerStep* end);
|
|
|
| - scoped_ptr<EventListenerHookup> conn_mgr_hookup_;
|
| + // Initializes the hookup between the ServerConnectionManager and us.
|
| + void WatchConnectionManager();
|
| +
|
| + // Used to update |server_connection_ok_|, see below.
|
| + void CheckServerConnectionManagerStatus(
|
| + HttpResponse::ServerConnectionCode code);
|
| +
|
| + // Called once the first time thread_ is started to broadcast an initial
|
| + // session snapshot containing data like initial_sync_ended. Important when
|
| + // the client starts up and does not need to perform an initial sync.
|
| + void SendInitialSnapshot();
|
| +
|
| + base::Thread thread_;
|
|
|
| // Modifiable versions of kDefaultLongPollIntervalSeconds which can be
|
| // updated by the server.
|
| - int syncer_short_poll_interval_seconds_;
|
| - int syncer_long_poll_interval_seconds_;
|
| -
|
| - // The time we wait between polls in seconds. This is used as lower bound on
|
| - // our wait time. Updated once per loop from the command line flag.
|
| - int syncer_polling_interval_;
|
| -
|
| - // The upper bound on the nominal wait between polls in seconds. Note that
|
| - // this bounds the "nominal" poll interval, while the the actual interval
|
| - // also takes previous failures into account.
|
| - int syncer_max_interval_;
|
| -
|
| - // This causes syncer to start syncing ASAP. If the rate of requests is too
|
| - // high the request will be silently dropped. mutex_ should be held when
|
| - // this is called.
|
| - void NudgeSyncImpl(
|
| - int milliseconds_from_now,
|
| - NudgeSource source,
|
| - const syncable::ModelTypePayloadMap& model_types_with_payloads);
|
| -
|
| -#if defined(OS_LINUX)
|
| - // On Linux, we need this information in order to query idle time.
|
| - scoped_ptr<IdleQueryLinux> idle_query_;
|
| -#endif
|
| + base::TimeDelta syncer_short_poll_interval_seconds_;
|
| + base::TimeDelta syncer_long_poll_interval_seconds_;
|
|
|
| - scoped_ptr<sessions::SyncSessionContext> session_context_;
|
| + // Periodic timer for polling. See AdjustPolling.
|
| + base::RepeatingTimer<SyncerThread> poll_timer_;
|
| +
|
| + // The mode of operation. We don't use a lock, see Start(...) comment.
|
| + Mode mode_;
|
| +
|
| + // TODO(tim): Bug 26339. This needs to track more than just time I think,
|
| + // since the nudges could be for different types. Current impl doesn't care.
|
| + base::TimeTicks last_sync_session_end_time_;
|
|
|
| - // Set whenever the server instructs us to stop sending it requests until
|
| - // a specified time, and reset for each call to SyncShare. (Note that the
|
| - // WaitInterval::THROTTLED contract is such that we don't call SyncShare at
|
| - // all until the "silenced until" embargo expires.)
|
| - base::TimeTicks silenced_until_;
|
| + // Have we observed a valid server connection?
|
| + bool server_connection_ok_;
|
|
|
| - // Useful for unit tests
|
| - bool disable_idle_detection_;
|
| + // Tracks in-flight nudges so we can coalesce.
|
| + scoped_ptr<SyncSessionJob> pending_nudge_;
|
| +
|
| + // Current wait state. Null if we're not in backoff and not throttled.
|
| + scoped_ptr<WaitInterval> wait_interval_;
|
| +
|
| + scoped_ptr<DelayProvider> delay_provider_;
|
| +
|
| + // Invoked to run through the sync cycle.
|
| + scoped_ptr<Syncer> syncer_;
|
| +
|
| + scoped_ptr<sessions::SyncSessionContext> session_context_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(SyncerThread);
|
| };
|
|
|
| +
|
| } // namespace browser_sync
|
|
|
| +// The SyncerThread manages its own internal thread and thus outlives it. We
|
| +// don't need refcounting for posting tasks to this internal thread.
|
| +DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::SyncerThread);
|
| +
|
| #endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_THREAD_H_
|
|
|