summaryrefslogtreecommitdiff
path: root/src
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
parent9173f799dd56a4e4813e163e927965787db951b9 (diff)
downloadmongo-0cb50f1023c394ba3e51e70a5daa2aea417cea5d.tar.gz
SERVER-37880 Make time_support's Backoff class non-blocking
Diffstat (limited to 'src')
-rw-r--r--src/mongo/client/dbclient_connection.cpp4
-rw-r--r--src/mongo/client/dbclient_connection.h2
-rw-r--r--src/mongo/dbtests/basictests.cpp27
-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
6 files changed, 49 insertions, 52 deletions
diff --git a/src/mongo/client/dbclient_connection.cpp b/src/mongo/client/dbclient_connection.cpp
index 4f1c8acac54..7ccfdcc0347 100644
--- a/src/mongo/client/dbclient_connection.cpp
+++ b/src/mongo/client/dbclient_connection.cpp
@@ -445,7 +445,7 @@ void DBClientConnection::_checkConnection() {
throwSocketError(SocketErrorKind::FAILED_STATE, toString());
// Don't hammer reconnects, backoff if needed
- autoReconnectBackoff.nextSleepMillis();
+ sleepFor(_autoReconnectBackoff.nextSleep());
LOG(_logLevel) << "trying reconnect to " << toString() << endl;
string errmsg;
@@ -546,7 +546,7 @@ DBClientConnection::DBClientConnection(bool _autoReconnect,
MongoURI uri,
const HandshakeValidationHook& hook)
: autoReconnect(_autoReconnect),
- autoReconnectBackoff(1000, 2000),
+ _autoReconnectBackoff(Seconds(1), Seconds(2)),
_hook(hook),
_uri(std::move(uri)) {
_numConnections.fetchAndAdd(1);
diff --git a/src/mongo/client/dbclient_connection.h b/src/mongo/client/dbclient_connection.h
index d7d58150257..3b55f3d2b22 100644
--- a/src/mongo/client/dbclient_connection.h
+++ b/src/mongo/client/dbclient_connection.h
@@ -304,7 +304,7 @@ protected:
AtomicWord<bool> _stayFailed{false};
AtomicWord<bool> _failed{false};
const bool autoReconnect;
- Backoff autoReconnectBackoff;
+ Backoff _autoReconnectBackoff;
HostAndPort _serverAddress;
std::string _resolvedAddress;
diff --git a/src/mongo/dbtests/basictests.cpp b/src/mongo/dbtests/basictests.cpp
index 3fd33cffde6..22b2cdfe6a4 100644
--- a/src/mongo/dbtests/basictests.cpp
+++ b/src/mongo/dbtests/basictests.cpp
@@ -42,7 +42,6 @@
#include "mongo/util/stringutils.h"
#include "mongo/util/text.h"
#include "mongo/util/thread_safe_string.h"
-#include "mongo/util/time_support.h"
#include "mongo/util/timer.h"
namespace BasicTests {
@@ -219,31 +218,6 @@ public:
};
} // namespace stringbuildertests
-class SleepBackoffTest {
-public:
- void run() {
- int maxSleepTimeMillis = 1000;
-
- Backoff backoff(maxSleepTimeMillis, 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
- unsigned long long resetAfterMillis = maxSleepTimeMillis + maxSleepTimeMillis * 2;
- ASSERT_EQUALS(backoff.getNextSleepMillis(20, resetAfterMillis, 0), 40); // no reset here
- ASSERT_EQUALS(backoff.getNextSleepMillis(20, resetAfterMillis + 1, 0),
- 1); // reset expected
- }
-};
-
class AssertTests {
public:
int x;
@@ -399,7 +373,6 @@ public:
add<stringbuildertests::reset1>();
add<stringbuildertests::reset2>();
- add<SleepBackoffTest>();
add<AssertTests>();
add<StringSplitterTest>();
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