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; |
} |