| Index: chrome/browser/sync/engine/syncer_thread.cc
|
| diff --git a/chrome/browser/sync/engine/syncer_thread.cc b/chrome/browser/sync/engine/syncer_thread.cc
|
| index ffc7bcd1357000b5895217eff0af2b82cf27c6e9..800ddddb36b07f12ecf518b80c00a9d7dd7ab3fd 100644
|
| --- a/chrome/browser/sync/engine/syncer_thread.cc
|
| +++ b/chrome/browser/sync/engine/syncer_thread.cc
|
| @@ -15,11 +15,13 @@
|
| #include <map>
|
| #include <queue>
|
|
|
| +#include "base/rand_util.h"
|
| #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
|
| #include "chrome/browser/sync/engine/auth_watcher.h"
|
| #include "chrome/browser/sync/engine/model_safe_worker.h"
|
| #include "chrome/browser/sync/engine/net/server_connection_manager.h"
|
| #include "chrome/browser/sync/engine/syncer.h"
|
| +#include "chrome/browser/sync/sessions/session_state.h"
|
| #include "chrome/browser/sync/syncable/directory_manager.h"
|
| #include "chrome/common/chrome_switches.h"
|
| #include "jingle/notifier/listener/notification_constants.h"
|
| @@ -30,9 +32,10 @@ using base::Time;
|
| using base::TimeDelta;
|
| using base::TimeTicks;
|
|
|
| -
|
| namespace browser_sync {
|
|
|
| +using sessions::SyncSessionSnapshot;
|
| +
|
| // We use high values here to ensure that failure to receive poll updates from
|
| // the server doesn't result in rapid-fire polling from the client due to low
|
| // local limits.
|
| @@ -47,6 +50,11 @@ const int SyncerThread::kDefaultLongPollIntervalSeconds = 3600 * 12;
|
| // is really something we want and make sure it works, if it is.
|
| const int SyncerThread::kDefaultMaxPollIntervalMs = 30 * 60 * 1000;
|
|
|
| +// Backoff interval randomization factor.
|
| +static const int kBackoffRandomizationFactor = 2;
|
| +
|
| +const int SyncerThread::kMaxBackoffSeconds = 60 * 60 * 4; // 4 hours.
|
| +
|
| void SyncerThread::NudgeSyncer(int milliseconds_from_now, NudgeSource source) {
|
| AutoLock lock(lock_);
|
| if (vault_.syncer_ == NULL) {
|
| @@ -56,15 +64,13 @@ void SyncerThread::NudgeSyncer(int milliseconds_from_now, NudgeSource source) {
|
| NudgeSyncImpl(milliseconds_from_now, source);
|
| }
|
|
|
| -SyncerThread::SyncerThread(sessions::SyncSessionContext* context,
|
| - AllStatus* all_status)
|
| +SyncerThread::SyncerThread(sessions::SyncSessionContext* context)
|
| : thread_main_started_(false, false),
|
| thread_("SyncEngine_SyncerThread"),
|
| vault_field_changed_(&lock_),
|
| p2p_authenticated_(false),
|
| p2p_subscribed_(false),
|
| conn_mgr_hookup_(NULL),
|
| - allstatus_(all_status),
|
| syncer_short_poll_interval_seconds_(kDefaultShortPollIntervalSeconds),
|
| syncer_long_poll_interval_seconds_(kDefaultLongPollIntervalSeconds),
|
| syncer_polling_interval_(kDefaultShortPollIntervalSeconds),
|
| @@ -336,7 +342,6 @@ void SyncerThread::ThreadMainLoop() {
|
|
|
| LOG(INFO) << "Updating the next polling time after SyncMain";
|
| vault_.current_wait_interval_ = CalculatePollingWaitTime(
|
| - allstatus_->status(),
|
| static_cast<int>(vault_.current_wait_interval_.poll_delta.InSeconds()),
|
| &user_idle_milliseconds, &continue_sync_cycle, nudged);
|
| }
|
| @@ -415,9 +420,7 @@ void SyncerThread::ExitPausedState() {
|
|
|
| // We check how long the user's been idle and sync less often if the machine is
|
| // not in use. The aim is to reduce server load.
|
| -// TODO(timsteele): Should use Time(Delta).
|
| SyncerThread::WaitInterval SyncerThread::CalculatePollingWaitTime(
|
| - const AllStatus::Status& status,
|
| int last_poll_wait, // Time in seconds.
|
| int* user_idle_milliseconds,
|
| bool* continue_sync_cycle,
|
| @@ -436,15 +439,16 @@ SyncerThread::WaitInterval SyncerThread::CalculatePollingWaitTime(
|
| bool is_continuing_sync_cyle = *continue_sync_cycle;
|
| *continue_sync_cycle = false;
|
|
|
| - // Determine if the syncer has unfinished work to do from allstatus_.
|
| - const bool syncer_has_work_to_do =
|
| - status.updates_available > status.updates_received
|
| - || status.unsynced_count > 0;
|
| + // Determine if the syncer has unfinished work to do.
|
| + SyncSessionSnapshot* snapshot = session_context_->previous_session_snapshot();
|
| + const bool syncer_has_work_to_do = snapshot &&
|
| + (snapshot->num_server_changes_remaining > snapshot->max_local_timestamp
|
| + || snapshot->unsynced_count > 0);
|
| LOG(INFO) << "syncer_has_work_to_do is " << syncer_has_work_to_do;
|
|
|
| // First calculate the expected wait time, figuring in any backoff because of
|
| // user idle time. next_wait is in seconds
|
| - syncer_polling_interval_ = (!status.notifications_enabled) ?
|
| + syncer_polling_interval_ = (!session_context_->notifications_enabled()) ?
|
| syncer_short_poll_interval_seconds_ :
|
| syncer_long_poll_interval_seconds_;
|
| int default_next_wait = syncer_polling_interval_;
|
| @@ -464,15 +468,15 @@ SyncerThread::WaitInterval SyncerThread::CalculatePollingWaitTime(
|
| } else {
|
| // We weren't nudged, or we were in a NORMAL wait interval until now.
|
| return_interval.poll_delta = TimeDelta::FromSeconds(
|
| - AllStatus::GetRecommendedDelaySeconds(last_poll_wait));
|
| + GetRecommendedDelaySeconds(last_poll_wait));
|
| }
|
| } else {
|
| // No consecutive error.
|
| return_interval.poll_delta = TimeDelta::FromSeconds(
|
| - AllStatus::GetRecommendedDelaySeconds(0));
|
| + GetRecommendedDelaySeconds(0));
|
| }
|
| *continue_sync_cycle = true;
|
| - } else if (!status.notifications_enabled) {
|
| + } else if (!session_context_->notifications_enabled()) {
|
| // Ensure that we start exponential backoff from our base polling
|
| // interval when we are not continuing a sync cycle.
|
| last_poll_wait = std::max(last_poll_wait, syncer_polling_interval_);
|
| @@ -650,6 +654,27 @@ SyncerEventChannel* SyncerThread::relay_channel() {
|
| return syncer_event_relay_channel_.get();
|
| }
|
|
|
| +int SyncerThread::GetRecommendedDelaySeconds(int base_delay_seconds) {
|
| + if (base_delay_seconds >= kMaxBackoffSeconds)
|
| + return kMaxBackoffSeconds;
|
| +
|
| + // This calculates approx. base_delay_seconds * 2 +/- base_delay_seconds / 2
|
| + int backoff_s =
|
| + std::max(1, base_delay_seconds * kBackoffRandomizationFactor);
|
| +
|
| + // Flip a coin to randomize backoff interval by +/- 50%.
|
| + int rand_sign = base::RandInt(0, 1) * 2 - 1;
|
| +
|
| + // Truncation is adequate for rounding here.
|
| + backoff_s = backoff_s +
|
| + (rand_sign * (base_delay_seconds / kBackoffRandomizationFactor));
|
| +
|
| + // Cap the backoff interval.
|
| + backoff_s = std::max(1, std::min(backoff_s, kMaxBackoffSeconds));
|
| +
|
| + return backoff_s;
|
| +}
|
| +
|
| // Inputs and return value in milliseconds.
|
| int SyncerThread::CalculateSyncWaitTime(int last_interval, int user_idle_ms) {
|
| // syncer_polling_interval_ is in seconds
|
| @@ -664,7 +689,7 @@ int SyncerThread::CalculateSyncWaitTime(int last_interval, int user_idle_ms) {
|
| // If the user has been idle for a while, we'll start decreasing the poll
|
| // rate.
|
| if (idle >= kPollBackoffThresholdMultiplier * syncer_polling_interval_ms) {
|
| - next_wait = std::min(AllStatus::GetRecommendedDelaySeconds(
|
| + next_wait = std::min(GetRecommendedDelaySeconds(
|
| last_interval / 1000), syncer_max_interval_ / 1000) * 1000;
|
| }
|
|
|
|
|