diff options
Diffstat (limited to 'chrome/browser/sync')
-rw-r--r-- | chrome/browser/sync/engine/syncer_thread.cc | 72 | ||||
-rw-r--r-- | chrome/browser/sync/engine/syncer_thread.h | 66 | ||||
-rw-r--r-- | chrome/browser/sync/engine/syncer_thread_unittest.cc | 360 |
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); } } |