Chromium Code Reviews| 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" |
|
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
|
| #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_ |