diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2019-01-02 12:04:53 -0500 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2019-01-14 11:40:48 -0500 |
commit | 0cb50f1023c394ba3e51e70a5daa2aea417cea5d (patch) | |
tree | 8fe720bce5abe4bebaf2d9f48b35ad0059260a84 /src/mongo/util | |
parent | 9173f799dd56a4e4813e163e927965787db951b9 (diff) | |
download | mongo-0cb50f1023c394ba3e51e70a5daa2aea417cea5d.tar.gz |
SERVER-37880 Make time_support's Backoff class non-blocking
Diffstat (limited to 'src/mongo/util')
-rw-r--r-- | src/mongo/util/time_support.cpp | 22 | ||||
-rw-r--r-- | src/mongo/util/time_support.h | 17 | ||||
-rw-r--r-- | src/mongo/util/time_support_test.cpp | 29 |
3 files changed, 46 insertions, 22 deletions
diff --git a/src/mongo/util/time_support.cpp b/src/mongo/util/time_support.cpp index b396d0d53c3..91830f4db05 100644 --- a/src/mongo/util/time_support.cpp +++ b/src/mongo/util/time_support.cpp @@ -756,14 +756,15 @@ void sleepmicros(long long s) { stdx::this_thread::sleep_for(Microseconds(s).toSystemDuration()); } -void Backoff::nextSleepMillis() { +Milliseconds Backoff::nextSleep() { // Get the current time unsigned long long currTimeMillis = curTimeMillis64(); int lastSleepMillis = _lastSleepMillis; - if (_lastErrorTimeMillis == 0 || _lastErrorTimeMillis > currTimeMillis /* VM bugs exist */) + if (!_lastErrorTimeMillis || _lastErrorTimeMillis > currTimeMillis /* VM bugs exist */) _lastErrorTimeMillis = currTimeMillis; + unsigned long long lastErrorTimeMillis = _lastErrorTimeMillis; _lastErrorTimeMillis = currTimeMillis; @@ -771,28 +772,21 @@ void Backoff::nextSleepMillis() { // Store the last slept time _lastSleepMillis = lastSleepMillis; - sleepmillis(lastSleepMillis); + return Milliseconds(lastSleepMillis); } -int Backoff::getNextSleepMillis(int lastSleepMillis, +int Backoff::getNextSleepMillis(long long lastSleepMillis, unsigned long long currTimeMillis, unsigned long long lastErrorTimeMillis) const { // Backoff logic // Get the time since the last error - unsigned long long timeSinceLastErrorMillis = currTimeMillis - lastErrorTimeMillis; - - // Makes the cast below safe - verify(_resetAfterMillis >= 0); + const long long timeSinceLastErrorMillis = currTimeMillis - lastErrorTimeMillis; - // If we haven't seen another error recently (3x the max wait time), reset our - // wait counter. - if (timeSinceLastErrorMillis > (unsigned)(_resetAfterMillis)) + // If we haven't seen another error recently (3x the max wait time), reset our wait counter + if (timeSinceLastErrorMillis > _resetAfterMillis) lastSleepMillis = 0; - // Makes the test below sane - verify(_maxSleepMillis > 0); - // Wait a power of two millis if (lastSleepMillis == 0) lastSleepMillis = 1; diff --git a/src/mongo/util/time_support.h b/src/mongo/util/time_support.h index 4a452ec841c..484797cdedd 100644 --- a/src/mongo/util/time_support.h +++ b/src/mongo/util/time_support.h @@ -312,28 +312,29 @@ void sleepFor(DurationType time) { class Backoff { public: - Backoff(int maxSleepMillis, int resetAfter) - : _maxSleepMillis(maxSleepMillis), - _resetAfterMillis(maxSleepMillis + resetAfter), // Don't reset < the max sleep + Backoff(Milliseconds maxSleep, Milliseconds resetAfter) + : _maxSleepMillis(durationCount<Milliseconds>(maxSleep)), + _resetAfterMillis( + durationCount<Milliseconds>(resetAfter)), // Don't reset < the max sleep _lastSleepMillis(0), _lastErrorTimeMillis(0) {} - void nextSleepMillis(); + Milliseconds nextSleep(); /** * testing-only function. used in dbtests/basictests.cpp */ - int getNextSleepMillis(int lastSleepMillis, + int getNextSleepMillis(long long lastSleepMillis, unsigned long long currTimeMillis, unsigned long long lastErrorTimeMillis) const; private: // Parameters - int _maxSleepMillis; - int _resetAfterMillis; + long long _maxSleepMillis; + long long _resetAfterMillis; // Last sleep information - int _lastSleepMillis; + long long _lastSleepMillis; unsigned long long _lastErrorTimeMillis; }; diff --git a/src/mongo/util/time_support_test.cpp b/src/mongo/util/time_support_test.cpp index 544ce822bab..6f2de1faf9d 100644 --- a/src/mongo/util/time_support_test.cpp +++ b/src/mongo/util/time_support_test.cpp @@ -888,5 +888,34 @@ TEST(DateTArithmetic, SubtractionOverflowThrows) { ErrorCodes::DurationOverflow); ASSERT_THROWS_CODE(Date_t::max() - Milliseconds(-1), DBException, ErrorCodes::DurationOverflow); } + +TEST(Backoff, NextSleep) { + Backoff backoff(Milliseconds(8), Milliseconds::max()); + ASSERT_EQ(Milliseconds(1), backoff.nextSleep()); + ASSERT_EQ(Milliseconds(2), backoff.nextSleep()); + ASSERT_EQ(Milliseconds(4), backoff.nextSleep()); + ASSERT_EQ(Milliseconds(8), backoff.nextSleep()); + ASSERT_EQ(Milliseconds(8), backoff.nextSleep()); +} + +TEST(Backoff, SleepBackoffTest) { + const int maxSleepTimeMillis = 1000; + Backoff backoff(Milliseconds(maxSleepTimeMillis), Milliseconds(maxSleepTimeMillis * 2)); + + // Double previous sleep duration + ASSERT_EQUALS(backoff.getNextSleepMillis(0, 0, 0), 1); + ASSERT_EQUALS(backoff.getNextSleepMillis(2, 0, 0), 4); + ASSERT_EQUALS(backoff.getNextSleepMillis(256, 0, 0), 512); + + // Make sure our backoff increases to the maximum value + ASSERT_EQUALS(backoff.getNextSleepMillis(maxSleepTimeMillis - 200, 0, 0), maxSleepTimeMillis); + ASSERT_EQUALS(backoff.getNextSleepMillis(maxSleepTimeMillis * 2, 0, 0), maxSleepTimeMillis); + + // Make sure that our backoff gets reset if we wait much longer than the maximum wait + const unsigned long long resetAfterMillis = maxSleepTimeMillis * 2; + ASSERT_EQUALS(backoff.getNextSleepMillis(20, resetAfterMillis, 0), 40); // no reset here + ASSERT_EQUALS(backoff.getNextSleepMillis(20, resetAfterMillis + 1, 0), 1); // reset expected +} + } // namespace } // namespace mongo |