summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-14 22:53:50 +0000
committertim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-14 22:53:50 +0000
commitc06061ffe476d5517f976dffd0fb7a924de187b3 (patch)
treedd096f096ae56ad93ab3ba59e3867423c0146157
parent0e133375337e85e1a64822d126128c67a18f2b2f (diff)
downloadchromium_src-c06061ffe476d5517f976dffd0fb7a924de187b3.zip
chromium_src-c06061ffe476d5517f976dffd0fb7a924de187b3.tar.gz
chromium_src-c06061ffe476d5517f976dffd0fb7a924de187b3.tar.bz2
For sync exponential backoff, allow one nudge per exponential backoff interval. If the nudge
still leaves the syncer with more work to do, don't accept any further nudges for this interval, and keep the exponent stage for exponential backoff the same. As a result of the patch, the unittest can now explicitly determine if exponential backoff kicked in or not. We really need to wire this up directly to the error codes to be precise, because the current impl (and it's the same with my patch) appears to trigger exponential backoff in other cases (ShouldSyncAgain). TEST=SyncerThreadTest Review URL: http://codereview.chromium.org/275015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29053 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/sync/engine/syncer_thread.cc72
-rw-r--r--chrome/browser/sync/engine/syncer_thread.h66
-rw-r--r--chrome/browser/sync/engine/syncer_thread_unittest.cc360
3 files changed, 347 insertions, 151 deletions
diff --git a/chrome/browser/sync/engine/syncer_thread.cc b/chrome/browser/sync/engine/syncer_thread.cc
index e509a83..2ab6106 100644
--- a/chrome/browser/sync/engine/syncer_thread.cc
+++ b/chrome/browser/sync/engine/syncer_thread.cc
@@ -130,13 +130,19 @@ SyncerThread* SyncerThreadFactory::Create(
}
}
-bool SyncerThread::NudgeSyncer(int milliseconds_from_now, NudgeSource source) {
+void SyncerThread::NudgeSyncer(int milliseconds_from_now, NudgeSource source) {
AutoLock lock(lock_);
if (vault_.syncer_ == NULL) {
- return false;
+ return;
+ }
+
+ if (vault_.current_wait_interval_.had_nudge_during_backoff) {
+ // Drop nudges on the floor if we've already had one since starting this
+ // stage of exponential backoff.
+ return;
}
+
NudgeSyncImpl(milliseconds_from_now, source);
- return true;
}
SyncerThread::SyncerThread()
@@ -307,7 +313,7 @@ void SyncerThread::ThreadMainLoop() {
LOG(INFO) << "In thread main loop.";
// Use the short poll value by default.
- TimeDelta poll_seconds =
+ vault_.current_wait_interval_.poll_delta =
TimeDelta::FromSeconds(syncer_short_poll_interval_seconds_);
int user_idle_milliseconds = 0;
TimeTicks last_sync_time;
@@ -335,7 +341,8 @@ void SyncerThread::ThreadMainLoop() {
continue;
}
- const TimeTicks next_poll = last_sync_time + poll_seconds;
+ const TimeTicks next_poll = last_sync_time +
+ vault_.current_wait_interval_.poll_delta;
const TimeTicks end_wait =
!vault_.nudge_queue_.empty() &&
vault_.nudge_queue_.top().first < next_poll ?
@@ -365,28 +372,32 @@ void SyncerThread::ThreadMainLoop() {
// Handle a nudge, caused by either a notification or a local bookmark
// event. This will also update the source of the following SyncMain call.
- UpdateNudgeSource(&continue_sync_cycle, &initial_sync_for_thread);
+ bool nudged = UpdateNudgeSource(continue_sync_cycle,
+ &initial_sync_for_thread);
LOG(INFO) << "Calling Sync Main at time " << Time::Now().ToInternalValue();
SyncMain(vault_.syncer_);
last_sync_time = TimeTicks::Now();
LOG(INFO) << "Updating the next polling time after SyncMain";
- poll_seconds = TimeDelta::FromSeconds(CalculatePollingWaitTime(
- allstatus_->status(), static_cast<int>(poll_seconds.InSeconds()),
- &user_idle_milliseconds, &continue_sync_cycle));
+ vault_.current_wait_interval_ = CalculatePollingWaitTime(
+ allstatus_->status(),
+ static_cast<int>(vault_.current_wait_interval_.poll_delta.InSeconds()),
+ &user_idle_milliseconds, &continue_sync_cycle, nudged);
}
-
}
// 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).
-int SyncerThread::CalculatePollingWaitTime(
+SyncerThread::WaitInterval SyncerThread::CalculatePollingWaitTime(
const AllStatus::Status& status,
int last_poll_wait, // Time in seconds.
int* user_idle_milliseconds,
- bool* continue_sync_cycle) {
+ bool* continue_sync_cycle,
+ bool was_nudged) {
+ lock_.AssertAcquired(); // We access 'vault' in here, so we need the lock.
+ WaitInterval return_interval;
bool is_continuing_sync_cyle = *continue_sync_cycle;
*continue_sync_cycle = false;
@@ -402,15 +413,28 @@ int SyncerThread::CalculatePollingWaitTime(
syncer_short_poll_interval_seconds_ :
syncer_long_poll_interval_seconds_;
int default_next_wait = syncer_polling_interval_;
- int actual_next_wait = default_next_wait;
+ return_interval.poll_delta = TimeDelta::FromSeconds(default_next_wait);
if (syncer_has_work_to_do) {
// Provide exponential backoff due to consecutive errors, else attempt to
// complete the work as soon as possible.
- if (!is_continuing_sync_cyle) {
- actual_next_wait = AllStatus::GetRecommendedDelaySeconds(0);
+ if (is_continuing_sync_cyle) {
+ return_interval.mode = WaitInterval::EXPONENTIAL_BACKOFF;
+ if (was_nudged && vault_.current_wait_interval_.mode ==
+ WaitInterval::EXPONENTIAL_BACKOFF) {
+ // We were nudged, it failed, and we were already in backoff.
+ return_interval.had_nudge_during_backoff = true;
+ // Keep exponent for exponential backoff the same in this case.
+ return_interval.poll_delta = vault_.current_wait_interval_.poll_delta;
+ } 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));
+ }
} else {
- actual_next_wait = AllStatus::GetRecommendedDelaySeconds(last_poll_wait);
+ // No consecutive error.
+ return_interval.poll_delta = TimeDelta::FromSeconds(
+ AllStatus::GetRecommendedDelaySeconds(0));
}
*continue_sync_cycle = true;
} else if (!status.notifications_enabled) {
@@ -424,15 +448,17 @@ int SyncerThread::CalculatePollingWaitTime(
if (new_idle_time < *user_idle_milliseconds) {
*user_idle_milliseconds = new_idle_time;
}
- actual_next_wait = CalculateSyncWaitTime(last_poll_wait * 1000,
- *user_idle_milliseconds) / 1000;
- DCHECK_GE(actual_next_wait, default_next_wait);
+ return_interval.poll_delta = TimeDelta::FromMilliseconds(
+ CalculateSyncWaitTime(last_poll_wait * 1000,
+ *user_idle_milliseconds));
+ DCHECK_GE(return_interval.poll_delta.InSeconds(), default_next_wait);
}
LOG(INFO) << "Sync wait: idle " << default_next_wait
- << " non-idle or backoff " << actual_next_wait << ".";
+ << " non-idle or backoff "
+ << return_interval.poll_delta.InSeconds() << ".";
- return actual_next_wait;
+ return return_interval;
}
void SyncerThread::ThreadMain() {
@@ -453,7 +479,7 @@ void SyncerThread::SyncMain(Syncer* syncer) {
LOG(INFO) << "Done looping in sync share";
}
-void SyncerThread::UpdateNudgeSource(bool* continue_sync_cycle,
+bool SyncerThread::UpdateNudgeSource(bool continue_sync_cycle,
bool* initial_sync) {
bool nudged = false;
NudgeSource nudge_source = kUnknown;
@@ -467,12 +493,12 @@ void SyncerThread::UpdateNudgeSource(bool* continue_sync_cycle,
TimeTicks::Now() >= vault_.nudge_queue_.top().first) {
if (!nudged) {
nudge_source = vault_.nudge_queue_.top().second;
- *continue_sync_cycle = false; // Reset the continuation token on nudge.
nudged = true;
}
vault_.nudge_queue_.pop();
}
SetUpdatesSource(nudged, nudge_source, initial_sync);
+ return nudged;
}
void SyncerThread::SetUpdatesSource(bool nudged, NudgeSource nudge_source,
diff --git a/chrome/browser/sync/engine/syncer_thread.h b/chrome/browser/sync/engine/syncer_thread.h
index d6fc63a..e68ac70 100644
--- a/chrome/browser/sync/engine/syncer_thread.h
+++ b/chrome/browser/sync/engine/syncer_thread.h
@@ -74,6 +74,30 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread> {
friend class SyncerThreadWithSyncerTest;
friend class SyncerThreadFactory;
public:
+ // Encapsulates the parameters that make up an interval on which the
+ // syncer thread is sleeping.
+ 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.
+ EXPONENTIAL_BACKOFF,
+ };
+
+ 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) { }
+ };
+
enum NudgeSource {
kUnknown = 0,
kNotification,
@@ -103,7 +127,7 @@ public:
// 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 bool NudgeSyncer(int milliseconds_from_now, NudgeSource source);
+ virtual void NudgeSyncer(int milliseconds_from_now, NudgeSource source);
// Registers this thread to watch talk mediator events.
virtual void WatchTalkMediator(TalkMediator* talk_mediator);
@@ -172,6 +196,13 @@ public:
// NudgeQueue().
NudgeQueue nudge_queue_;
+ // 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_;
+
ProtectedFields()
: stop_syncer_thread_(false), syncer_(NULL), connected_(false) {}
} vault_;
@@ -184,12 +215,6 @@ public:
Lock lock_;
private:
- // A few members to gate the rate at which we nudge the syncer.
- enum {
- kNudgeRateLimitCount = 6,
- kNudgeRateLimitTime = 180,
- };
-
// Threshold multipler for how long before user should be considered idle.
static const int kPollBackoffThresholdMultiplier = 10;
@@ -206,25 +231,30 @@ public:
void SyncMain(Syncer* syncer);
- // Calculates the next sync wait time in seconds. 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.
- virtual int CalculatePollingWaitTime(
+ // 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(
const AllStatus::Status& status,
int last_poll_wait, // in s
int* user_idle_milliseconds,
- bool* continue_sync_cycle);
+ 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);
// Sets the source value of the controlled syncer's updates_source value.
// The initial sync boolean is updated if read as a sentinel. The following
- // two methods work in concert to achieve this goal.
- void UpdateNudgeSource(bool* continue_sync_cycle,
+ // two methods work in concert to achieve this goal. Returns true if it
+ // determines a nudge actually occurred.
+ bool UpdateNudgeSource(bool continue_sync_cycle,
bool* initial_sync);
void SetUpdatesSource(bool nudged, NudgeSource nudge_source,
bool* initial_sync);
diff --git a/chrome/browser/sync/engine/syncer_thread_unittest.cc b/chrome/browser/sync/engine/syncer_thread_unittest.cc
index 846ad36..b80fa30 100644
--- a/chrome/browser/sync/engine/syncer_thread_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_thread_unittest.cc
@@ -22,6 +22,7 @@ using base::TimeDelta;
namespace browser_sync {
typedef testing::Test SyncerThreadTest;
+typedef SyncerThread::WaitInterval WaitInterval;
class SyncerThreadWithSyncerTest : public testing::Test {
public:
@@ -158,6 +159,8 @@ TEST_F(SyncerThreadTest, CalculatePollingWaitTime) {
scoped_refptr<SyncerThread> syncer_thread(
SyncerThreadFactory::Create(NULL, NULL, NULL, NULL, NULL));
syncer_thread->DisableIdleDetection();
+ // Hold the lock to appease asserts in code.
+ AutoLock lock(syncer_thread->lock_);
// Notifications disabled should result in a polling interval of
// kDefaultShortPollInterval.
@@ -167,27 +170,33 @@ TEST_F(SyncerThreadTest, CalculatePollingWaitTime) {
bool continue_sync_cycle_param = false;
// No work and no backoff.
- ASSERT_TRUE(SyncerThread::kDefaultShortPollIntervalSeconds ==
- syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds,
+ interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_FALSE(continue_sync_cycle_param);
// In this case the continue_sync_cycle is turned off.
continue_sync_cycle_param = true;
- ASSERT_TRUE(SyncerThread::kDefaultShortPollIntervalSeconds ==
- syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds,
+ interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_FALSE(continue_sync_cycle_param);
-
- // TODO(brg) : Find a way to test exponential backoff is inoperable.
- // Exponential backoff should be turned on when notifications are disabled
- // but this can not be tested since we can not set the last input info.
}
// Notifications enabled should result in a polling interval of
@@ -198,27 +207,33 @@ TEST_F(SyncerThreadTest, CalculatePollingWaitTime) {
bool continue_sync_cycle_param = false;
// No work and no backoff.
- ASSERT_TRUE(SyncerThread::kDefaultLongPollIntervalSeconds ==
- syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds,
+ interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_FALSE(continue_sync_cycle_param);
// In this case the continue_sync_cycle is turned off.
continue_sync_cycle_param = true;
- ASSERT_TRUE(SyncerThread::kDefaultLongPollIntervalSeconds ==
- syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds,
+ interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_FALSE(continue_sync_cycle_param);
-
- // TODO(brg) : Find a way to test exponential backoff.
- // Exponential backoff should be turned off when notifications are enabled,
- // but this can not be tested since we can not set the last input info.
}
// There are two states which can cause a continuation, either the updates
@@ -230,40 +245,66 @@ TEST_F(SyncerThreadTest, CalculatePollingWaitTime) {
status.updates_received = 0;
bool continue_sync_cycle_param = false;
- ASSERT_TRUE(0 <= syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_LE(0, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
continue_sync_cycle_param = false;
- ASSERT_TRUE(3 >= syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_GE(3, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
- ASSERT_TRUE(0 <= syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
- ASSERT_TRUE(2 >= syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_LE(0, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
+
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_GE(2, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
status.updates_received = 1;
- ASSERT_TRUE(SyncerThread::kDefaultShortPollIntervalSeconds ==
- syncer_thread->CalculatePollingWaitTime(
- status,
- 10,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds,
+ interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_FALSE(continue_sync_cycle_param);
}
@@ -272,28 +313,43 @@ TEST_F(SyncerThreadTest, CalculatePollingWaitTime) {
status.unsynced_count = 1;
bool continue_sync_cycle_param = false;
- ASSERT_TRUE(0 <= syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_LE(0, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
continue_sync_cycle_param = false;
- ASSERT_TRUE(2 >= syncer_thread->CalculatePollingWaitTime(
- status,
- 0,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 0,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_GE(2, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
status.unsynced_count = 0;
- ASSERT_TRUE(SyncerThread::kDefaultShortPollIntervalSeconds ==
- syncer_thread->CalculatePollingWaitTime(
- status,
- 4,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 4,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds,
+ interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_FALSE(continue_sync_cycle_param);
}
@@ -305,60 +361,144 @@ TEST_F(SyncerThreadTest, CalculatePollingWaitTime) {
// Expect move from default polling interval to exponential backoff due to
// unsynced_count != 0.
- ASSERT_TRUE(0 <= syncer_thread->CalculatePollingWaitTime(
- status,
- 3600,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ WaitInterval interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 3600,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_LE(0, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
continue_sync_cycle_param = false;
- ASSERT_TRUE(2 >= syncer_thread->CalculatePollingWaitTime(
- status,
- 3600,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 3600,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_GE(2, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
// Expect exponential backoff.
- ASSERT_TRUE(2 <= syncer_thread->CalculatePollingWaitTime(
- status,
- 2,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
- ASSERT_TRUE(6 >= syncer_thread->CalculatePollingWaitTime(
- status,
- 2,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 2,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_LE(2, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
+ ASSERT_TRUE(continue_sync_cycle_param);
+
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 2,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_GE(6, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
+ ASSERT_TRUE(continue_sync_cycle_param);
+
+ syncer_thread->vault_.current_wait_interval_ = interval;
+
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ static_cast<int>(interval.poll_delta.InSeconds()),
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ true);
+
+ // Don't change poll on a failed nudge during backoff.
+ ASSERT_TRUE(syncer_thread->vault_.current_wait_interval_.poll_delta ==
+ interval.poll_delta);
+ ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
+ ASSERT_TRUE(interval.had_nudge_during_backoff);
+ ASSERT_TRUE(continue_sync_cycle_param);
+
+ // If we got a nudge and we weren't in backoff mode, we see exponential
+ // backoff.
+ syncer_thread->vault_.current_wait_interval_.mode = WaitInterval::NORMAL;
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 2,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ true);
+
+ // 5 and 3 are bounds on the backoff randomization formula given input of 2.
+ ASSERT_GE(5, interval.poll_delta.InSeconds());
+ ASSERT_LE(3, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
+ ASSERT_TRUE(continue_sync_cycle_param);
+
+ // And if another interval expires, we get a bigger backoff.
+ WaitInterval new_interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ static_cast<int>(interval.poll_delta.InSeconds()),
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ false);
+
+ ASSERT_GE(12, new_interval.poll_delta.InSeconds());
+ ASSERT_LE(5, new_interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode);
+ ASSERT_FALSE(new_interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
// A nudge resets the continue_sync_cycle_param value, so our backoff
// should return to the minimum.
continue_sync_cycle_param = false;
- ASSERT_TRUE(0 <= syncer_thread->CalculatePollingWaitTime(
- status,
- 3600,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 3600,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ true);
+
+ ASSERT_LE(0, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
continue_sync_cycle_param = false;
- ASSERT_TRUE(2 >= syncer_thread->CalculatePollingWaitTime(
- status,
- 3600,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 3600,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ true);
+
+ ASSERT_GE(2, interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_TRUE(continue_sync_cycle_param);
// Setting unsynced_count = 0 returns us to the default polling interval.
status.unsynced_count = 0;
- ASSERT_TRUE(SyncerThread::kDefaultShortPollIntervalSeconds ==
- syncer_thread->CalculatePollingWaitTime(
- status,
- 4,
- &user_idle_milliseconds_param,
- &continue_sync_cycle_param));
+ interval = syncer_thread->CalculatePollingWaitTime(
+ status,
+ 4,
+ &user_idle_milliseconds_param,
+ &continue_sync_cycle_param,
+ true);
+
+ ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds,
+ interval.poll_delta.InSeconds());
+ ASSERT_EQ(WaitInterval::NORMAL, interval.mode);
+ ASSERT_FALSE(interval.had_nudge_during_backoff);
ASSERT_FALSE(continue_sync_cycle_param);
}
}