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 | |
parent | 9173f799dd56a4e4813e163e927965787db951b9 (diff) | |
download | mongo-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.cpp | 4 | ||||
-rw-r--r-- | src/mongo/client/dbclient_connection.h | 2 | ||||
-rw-r--r-- | src/mongo/dbtests/basictests.cpp | 27 | ||||
-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 |
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 |