summaryrefslogtreecommitdiff
path: root/src/mongo/util
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2019-01-02 12:04:53 -0500
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2019-01-14 11:40:48 -0500
commit0cb50f1023c394ba3e51e70a5daa2aea417cea5d (patch)
tree8fe720bce5abe4bebaf2d9f48b35ad0059260a84 /src/mongo/util
parent9173f799dd56a4e4813e163e927965787db951b9 (diff)
downloadmongo-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.cpp22
-rw-r--r--src/mongo/util/time_support.h17
-rw-r--r--src/mongo/util/time_support_test.cpp29
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