summaryrefslogtreecommitdiff
path: root/src/mongo/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util')
-rw-r--r--src/mongo/util/concurrency/ticketholder.cpp4
-rw-r--r--src/mongo/util/net/ssl_manager_apple.cpp11
-rw-r--r--src/mongo/util/net/ssl_manager_openssl.cpp14
-rw-r--r--src/mongo/util/net/ssl_manager_windows.cpp10
-rw-r--r--src/mongo/util/pair_map.h204
-rw-r--r--src/mongo/util/system_tick_source.cpp136
-rw-r--r--src/mongo/util/system_tick_source.h23
-rw-r--r--src/mongo/util/tick_source.h13
-rw-r--r--src/mongo/util/tick_source_test.cpp72
-rw-r--r--src/mongo/util/timer.cpp2
10 files changed, 298 insertions, 191 deletions
diff --git a/src/mongo/util/concurrency/ticketholder.cpp b/src/mongo/util/concurrency/ticketholder.cpp
index a9c44467536..2e9e90eeec1 100644
--- a/src/mongo/util/concurrency/ticketholder.cpp
+++ b/src/mongo/util/concurrency/ticketholder.cpp
@@ -51,7 +51,7 @@ void updateQueueStatsOnRelease(ServiceContext* serviceContext,
queueStats.totalFinishedProcessing.fetchAndAddRelaxed(1);
auto startTime = admCtx->getStartProcessingTime();
auto tickSource = serviceContext->getTickSource();
- auto delta = tickSource->spanTo<Microseconds>(startTime, tickSource->getTicks());
+ auto delta = tickSource->ticksTo<Microseconds>(tickSource->getTicks() - startTime);
queueStats.totalTimeProcessingMicros.fetchAndAddRelaxed(delta.count());
}
@@ -163,7 +163,7 @@ boost::optional<Ticket> TicketHolderWithQueueingStats::waitForTicketUntil(Operat
auto currentWaitTime = tickSource->getTicks();
auto updateQueuedTime = [&]() {
auto oldWaitTime = std::exchange(currentWaitTime, tickSource->getTicks());
- auto waitDelta = tickSource->spanTo<Microseconds>(oldWaitTime, currentWaitTime).count();
+ auto waitDelta = tickSource->ticksTo<Microseconds>(currentWaitTime - oldWaitTime).count();
queueStats.totalTimeQueuedMicros.fetchAndAddRelaxed(waitDelta);
};
queueStats.totalAddedQueue.fetchAndAddRelaxed(1);
diff --git a/src/mongo/util/net/ssl_manager_apple.cpp b/src/mongo/util/net/ssl_manager_apple.cpp
index 832e0b54262..98024421e5a 100644
--- a/src/mongo/util/net/ssl_manager_apple.cpp
+++ b/src/mongo/util/net/ssl_manager_apple.cpp
@@ -1675,11 +1675,12 @@ Future<SSLPeerInfo> SSLManagerApple::parseAndValidatePeerCertificate(
// The cipher will be presented as a number.
::SSLCipherSuite cipher;
uassertOSStatusOK(::SSLGetNegotiatedCipher(ssl, &cipher));
-
- LOGV2_INFO(6723803,
- "Accepted TLS connection from peer",
- "peerSubjectName"_attr = peerSubjectName,
- "cipher"_attr = cipher);
+ if (!serverGlobalParams.quiet.load()) {
+ LOGV2_INFO(6723803,
+ "Accepted TLS connection from peer",
+ "peerSubjectName"_attr = peerSubjectName,
+ "cipher"_attr = cipher);
+ }
// Server side.
if (remoteHost.empty()) {
diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp
index a8418eed3fa..606dd1e8868 100644
--- a/src/mongo/util/net/ssl_manager_openssl.cpp
+++ b/src/mongo/util/net/ssl_manager_openssl.cpp
@@ -771,6 +771,10 @@ Future<UniqueOCSPResponse> retrieveOCSPResponse(const std::string& host,
return getSSLFailure("Could not convert type OCSP Response to DER encoded object.");
}
+ if (!OCSPManager::get(getGlobalServiceContext())) {
+ return getSSLFailure("OCSP fetch could not complete, server is in shutdown mode.");
+ }
+
// Query the OCSP responder
return OCSPManager::get(getGlobalServiceContext())
->requestStatus(buffer, host, purpose)
@@ -3309,10 +3313,12 @@ Future<SSLPeerInfo> SSLManagerOpenSSL::parseAndValidatePeerCertificate(
// TODO: check optional cipher restriction, using cert.
auto peerSubject = getCertificateSubjectX509Name(peerCert.get());
const auto cipher = SSL_get_current_cipher(conn);
- LOGV2_INFO(6723801,
- "Accepted TLS connection from peer",
- "peerSubject"_attr = peerSubject,
- "cipher"_attr = SSL_CIPHER_get_name(cipher));
+ if (!serverGlobalParams.quiet.load()) {
+ LOGV2_INFO(6723801,
+ "Accepted TLS connection from peer",
+ "peerSubject"_attr = peerSubject,
+ "cipher"_attr = SSL_CIPHER_get_name(cipher));
+ }
StatusWith<stdx::unordered_set<RoleName>> swPeerCertificateRoles =
_parsePeerRoles(peerCert.get());
diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp
index 782ff15d417..760b81b4e07 100644
--- a/src/mongo/util/net/ssl_manager_windows.cpp
+++ b/src/mongo/util/net/ssl_manager_windows.cpp
@@ -2067,10 +2067,12 @@ Future<SSLPeerInfo> SSLManagerWindows::parseAndValidatePeerCertificate(
}
const auto cipher = std::wstring(cipherInfo.szCipherSuite);
- LOGV2_INFO(6723802,
- "Accepted TLS connection from peer",
- "peerSubjectName"_attr = peerSubjectName,
- "cipher"_attr = toUtf8String(cipher));
+ if (!serverGlobalParams.quiet.load()) {
+ LOGV2_INFO(6723802,
+ "Accepted TLS connection from peer",
+ "peerSubjectName"_attr = peerSubjectName,
+ "cipher"_attr = toUtf8String(cipher));
+ }
// If this is a server and client and server certificate are the same, log a warning.
if (remoteHost.empty() && _sslConfiguration.serverSubjectName() == peerSubjectName) {
diff --git a/src/mongo/util/pair_map.h b/src/mongo/util/pair_map.h
new file mode 100644
index 00000000000..6271fb9ae6d
--- /dev/null
+++ b/src/mongo/util/pair_map.h
@@ -0,0 +1,204 @@
+/**
+ * Copyright (C) 2022-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include <absl/container/flat_hash_map.h>
+#include <absl/container/flat_hash_set.h>
+
+#include "mongo/base/string_data.h"
+#include "mongo/util/assert_util.h"
+
+namespace mongo {
+
+template <typename T>
+class PairMapTraits {
+public:
+ using OwnedType = T;
+ using ViewType = T;
+ using HashableType = T;
+
+ static const T& toOwned(const T& t) {
+ return t;
+ }
+ static const T& toView(const T& t) {
+ return t;
+ }
+ static const T& toHashable(const T& t) {
+ return t;
+ }
+};
+
+template <>
+class PairMapTraits<StringData> {
+public:
+ using OwnedType = std::string;
+ using ViewType = StringData;
+ using HashableType = absl::string_view;
+
+ static std::string toOwned(const StringData& t) {
+ return t.toString();
+ }
+ static const StringData& toView(const StringData& t) {
+ return t;
+ }
+ static absl::string_view toHashable(const StringData& t) {
+ // Use the default absl string hasher.
+ return absl::string_view(t.rawData(), t.size());
+ }
+};
+
+template <>
+class PairMapTraits<std::string> {
+public:
+ using OwnedType = std::string;
+ using ViewType = StringData;
+ using HashableType = absl::string_view;
+
+ static const std::string& toOwned(const std::string& t) {
+ return t;
+ }
+ static StringData toView(const std::string& t) {
+ return StringData(t);
+ }
+ static absl::string_view toHashable(const std::string& t) {
+ // Use the default absl string hasher.
+ return absl::string_view(t.data(), t.size());
+ }
+};
+
+/**
+ * Type that bundles a hashed key with the actual pair value so that hashing can be performed
+ * outside of insert() call. This is needed to facilitate heterogeneous lookup.
+ */
+template <typename T1, typename T2>
+class PairMapHashedKey {
+public:
+ using OwnedType1 = typename PairMapTraits<T1>::OwnedType;
+ using OwnedType2 = typename PairMapTraits<T2>::OwnedType;
+ using OwnedPairType = std::pair<OwnedType1, OwnedType2>;
+ using ViewType1 = typename PairMapTraits<T1>::ViewType;
+ using ViewType2 = typename PairMapTraits<T2>::ViewType;
+ using ViewPairType = std::pair<ViewType1, ViewType2>;
+
+ explicit PairMapHashedKey(ViewPairType key, std::size_t hash)
+ : _key(std::move(key)), _hash(hash) {}
+
+ explicit operator OwnedPairType() const {
+ return {PairMapTraits<ViewType1>::toOwned(_key.first),
+ PairMapTraits<ViewType2>::toOwned(_key.second)};
+ }
+
+ const ViewPairType& key() const {
+ return _key;
+ }
+
+ std::size_t hash() const {
+ return _hash;
+ }
+
+private:
+ ViewPairType _key;
+ std::size_t _hash;
+};
+
+/**
+ * Hasher to support heterogeneous lookup.
+ */
+template <typename T1, typename T2>
+class PairMapHasher {
+public:
+ using OwnedType1 = typename PairMapTraits<T1>::OwnedType;
+ using OwnedType2 = typename PairMapTraits<T2>::OwnedType;
+ using OwnedPairType = std::pair<OwnedType1, OwnedType2>;
+ using ViewType1 = typename PairMapTraits<T1>::ViewType;
+ using ViewType2 = typename PairMapTraits<T2>::ViewType;
+ using ViewPairType = std::pair<ViewType1, ViewType2>;
+ using HashableType1 = typename PairMapTraits<T1>::HashableType;
+ using HashableType2 = typename PairMapTraits<T2>::HashableType;
+ using HashablePairType = std::pair<HashableType1, HashableType2>;
+
+ // This using directive activates heterogeneous lookup in the hash table.
+ using is_transparent = void;
+
+ std::size_t operator()(const ViewPairType& sd) const {
+ return absl::Hash<HashablePairType>{}(
+ std::make_pair(PairMapTraits<ViewType1>::toHashable(sd.first),
+ PairMapTraits<ViewType2>::toHashable(sd.second)));
+ }
+
+ std::size_t operator()(const OwnedPairType& s) const {
+ return operator()(std::make_pair(PairMapTraits<OwnedType1>::toView(s.first),
+ PairMapTraits<OwnedType2>::toView(s.second)));
+ }
+
+ std::size_t operator()(const PairMapHashedKey<T1, T2>& key) const {
+ return key.hash();
+ }
+
+ PairMapHashedKey<T1, T2> hashed_key(const ViewPairType& sd) const {
+ return PairMapHashedKey<T1, T2>(sd, operator()(sd));
+ }
+};
+
+template <typename T1, typename T2>
+class PairMapEq {
+public:
+ using ViewType1 = typename PairMapTraits<T1>::ViewType;
+ using ViewType2 = typename PairMapTraits<T2>::ViewType;
+ using ViewPairType = std::pair<ViewType1, ViewType2>;
+
+ // This using directive activates heterogeneous lookup in the hash table.
+ using is_transparent = void;
+
+ bool operator()(const ViewPairType& lhs, const ViewPairType& rhs) const {
+ return lhs == rhs;
+ }
+
+ bool operator()(const PairMapHashedKey<T1, T2>& lhs, const ViewPairType& rhs) const {
+ return lhs.key() == rhs;
+ }
+
+ bool operator()(const ViewPairType& lhs, const PairMapHashedKey<T1, T2>& rhs) const {
+ return lhs == rhs.key();
+ }
+
+ bool operator()(const PairMapHashedKey<T1, T2>& lhs,
+ const PairMapHashedKey<T1, T2>& rhs) const {
+ return lhs.key() == rhs.key();
+ }
+};
+
+template <typename K1, typename K2, typename V>
+using PairMap = absl::flat_hash_map<std::pair<K1, K2>, V, PairMapHasher<K1, K2>, PairMapEq<K1, K2>>;
+
+template <typename K1, typename K2>
+using PairSet = absl::flat_hash_set<std::pair<K1, K2>, PairMapHasher<K1, K2>, PairMapEq<K1, K2>>;
+
+} // namespace mongo
diff --git a/src/mongo/util/system_tick_source.cpp b/src/mongo/util/system_tick_source.cpp
index ee5f24d4e83..293b072f079 100644
--- a/src/mongo/util/system_tick_source.cpp
+++ b/src/mongo/util/system_tick_source.cpp
@@ -27,132 +27,32 @@
* it in the license file.
*/
-#include "mongo/platform/basic.h"
-
#include "mongo/util/system_tick_source.h"
-#include "mongo/config.h"
-
-#include <ctime>
-#include <limits>
-#if defined(MONGO_CONFIG_HAVE_HEADER_UNISTD_H)
-#include <unistd.h>
-#endif
+#include <chrono> // NOLINT
#include <memory>
-#include "mongo/base/init.h"
-#include "mongo/util/assert_util.h"
#include "mongo/util/tick_source.h"
-#include "mongo/util/time_support.h"
namespace mongo {
-namespace {
-
-const int64_t kMillisPerSecond = 1000;
-const int64_t kMicrosPerSecond = 1000 * kMillisPerSecond;
-const int64_t kNanosPerSecond = 1000 * kMicrosPerSecond;
-
-/**
- * Internally, the timer counts platform-dependent ticks of some sort, and
- * must then convert those ticks to microseconds and their ilk. This field
- * stores the frequency of the platform-dependent counter.
- *
- * Define ticksPerSecond before init to ensure correct relative sequencing
- * regardless of how it is initialized (static or dynamic).
- */
-TickSource::Tick ticksPerSecond = kMicrosPerSecond;
-
-// "Generic" implementation for _timerNow.
-TickSource::Tick _timerNowGeneric() {
- return curTimeMicros64();
-}
-
-// Function pointer to timer implementation.
-// Overridden in initTickSource() with better implementation where available.
-TickSource::Tick (*_timerNow)() = &_timerNowGeneric;
-
-#if defined(_WIN32)
-
-/**
- * Windows-specific implementation of the
- * Timer class. Windows selects the best available timer, in its estimation, for
- * measuring time at high resolution. This may be the HPET of the TSC on x86 systems,
- * but is promised to be synchronized across processors, barring BIOS errors.
- */
-TickSource::Tick timerNowWindows() {
- LARGE_INTEGER i;
- fassert(16161, QueryPerformanceCounter(&i));
- return i.QuadPart;
-}
-
-void initTickSource() {
- LARGE_INTEGER x;
- bool ok = QueryPerformanceFrequency(&x);
- verify(ok);
- ticksPerSecond = x.QuadPart;
- _timerNow = &timerNowWindows;
-}
-
-#elif defined(MONGO_CONFIG_HAVE_POSIX_MONOTONIC_CLOCK)
-
-/**
- * Implementation for timer on systems that support the
- * POSIX clock API and CLOCK_MONOTONIC clock.
- */
-TickSource::Tick timerNowPosixMonotonicClock() {
- timespec the_time;
- long long result;
-
- fassert(16160, !clock_gettime(CLOCK_MONOTONIC, &the_time));
-
- // Safe for 292 years after the clock epoch, even if we switch to a signed time value.
- // On Linux, the monotonic clock's epoch is the UNIX epoch.
- result = static_cast<long long>(the_time.tv_sec);
- result *= kNanosPerSecond;
- result += static_cast<long long>(the_time.tv_nsec);
- return result;
-}
-
-void initTickSource() {
- // If the monotonic clock is not available at runtime (sysconf() returns 0 or -1),
- // do not override the generic implementation or modify ticksPerSecond.
- if (sysconf(_SC_MONOTONIC_CLOCK) <= 0) {
- return;
- }
-
- ticksPerSecond = kNanosPerSecond;
- _timerNow = &timerNowPosixMonotonicClock;
-
- // Make sure that the current time relative to the (unspecified) epoch isn't already too
- // big to represent as a 64-bit count of nanoseconds.
- long long maxSecs = std::numeric_limits<long long>::max() / kNanosPerSecond;
- timespec the_time;
- fassert(16162, !clock_gettime(CLOCK_MONOTONIC, &the_time));
- fassert(16163, static_cast<long long>(the_time.tv_sec) < maxSecs);
-}
-#else
-void initTickSource() {}
-#endif
-
-} // unnamed namespace
-
-MONGO_INITIALIZER(SystemTickSourceInit)(InitializerContext* context) {
- initTickSource();
- SystemTickSource::get();
-}
-
-TickSource::Tick SystemTickSource::getTicks() {
- return _timerNow();
-}
-
-TickSource::Tick SystemTickSource::getTicksPerSecond() {
- return ticksPerSecond;
-}
-
-SystemTickSource* SystemTickSource::get() {
- static const auto globalSystemTickSource = std::make_unique<SystemTickSource>();
- return globalSystemTickSource.get();
+std::unique_ptr<TickSource> makeSystemTickSource() {
+ class Steady : public TickSource {
+ using C = std::chrono::steady_clock; // NOLINT
+ Tick getTicksPerSecond() override {
+ static_assert(C::period::num == 1, "Fractional frequency disallowed");
+ return C::period::den;
+ }
+ Tick getTicks() override {
+ return C::now().time_since_epoch().count();
+ }
+ };
+ return std::make_unique<Steady>();
+}
+
+TickSource* globalSystemTickSource() {
+ static const auto p = makeSystemTickSource().release();
+ return p;
}
} // namespace mongo
diff --git a/src/mongo/util/system_tick_source.h b/src/mongo/util/system_tick_source.h
index df59541fcee..360b38616f0 100644
--- a/src/mongo/util/system_tick_source.h
+++ b/src/mongo/util/system_tick_source.h
@@ -31,25 +31,14 @@
#include "mongo/util/tick_source.h"
+#include <memory>
+
namespace mongo {
-/**
- * Tick source based on platform specific clock ticks. Should be of reasonably high
- * performance. The maximum span measurable by the counter and convertible to microseconds
- * is about 10 trillion ticks. As long as there are fewer than 100 ticks per nanosecond,
- * timer durations of 2.5 years will be supported. Since a typical tick duration will be
- * under 10 per nanosecond, if not below 1 per nanosecond, this should not be an issue.
- */
-class SystemTickSource final : public TickSource {
-public:
- TickSource::Tick getTicks() override;
+/** Tick source based on `std:::chrono::steady_clock`. Monotonic, cheap, and high-precision. */
+std::unique_ptr<TickSource> makeSystemTickSource();
- TickSource::Tick getTicksPerSecond() override;
+/** Accesses a singleton instance made by `makeSystemTickSource`. Safe to call at any time. */
+TickSource* globalSystemTickSource();
- /**
- * Gets the singleton instance of SystemTickSource. Should not be called before
- * the global initializers are done.
- */
- static SystemTickSource* get();
-};
} // namespace mongo
diff --git a/src/mongo/util/tick_source.h b/src/mongo/util/tick_source.h
index 5b0abc88aca..759a6354ed1 100644
--- a/src/mongo/util/tick_source.h
+++ b/src/mongo/util/tick_source.h
@@ -65,18 +65,5 @@ public:
static_cast<double>(getTicksPerSecond()) * D::period::num / D::period::den;
return D(static_cast<int64_t>(ticks / ticksPerD));
}
-
- /**
- * Measures the length of the span from the start tick to the end tick and returns the result
- * using duration type D.
- * If the start tick is after (greater than) the end tick, returns a duration equivalent to 0
- * ticks.
- *
- * e.g. tickSource->spanTo<Milliseconds>(start, end);
- */
- template <typename D>
- D spanTo(Tick start, Tick end) {
- return ticksTo<D>(std::max((end - start), Tick{0}));
- }
};
} // namespace mongo
diff --git a/src/mongo/util/tick_source_test.cpp b/src/mongo/util/tick_source_test.cpp
index 9cfd907677a..b0fd6e43cb3 100644
--- a/src/mongo/util/tick_source_test.cpp
+++ b/src/mongo/util/tick_source_test.cpp
@@ -27,10 +27,10 @@
* it in the license file.
*/
-#include "mongo/platform/basic.h"
-
+#include "mongo/unittest/assert_that.h"
#include "mongo/unittest/unittest.h"
-#include "mongo/util/clock_source_mock.h"
+#include "mongo/util/duration.h"
+#include "mongo/util/system_tick_source.h"
#include "mongo/util/tick_source.h"
#include "mongo/util/tick_source_mock.h"
#include "mongo/util/time_support.h"
@@ -38,35 +38,53 @@
namespace mongo {
namespace {
+namespace m = unittest::match;
+
+template <typename SourceDuration, typename OutDuration>
+auto tickToDuration(int ticks) {
+ TickSourceMock<SourceDuration> ts;
+ ts.reset(ticks);
+ return ts.template ticksTo<OutDuration>(ts.getTicks()).count();
+}
+
TEST(TickSourceTest, TicksToDurationConversion) {
- TickSourceMock<Seconds> tsSecs;
- tsSecs.reset(1);
- ASSERT_EQ(tsSecs.ticksTo<Seconds>(tsSecs.getTicks()).count(), 1);
- ASSERT_EQ(tsSecs.ticksTo<Milliseconds>(tsSecs.getTicks()).count(), 1000);
- ASSERT_EQ(tsSecs.ticksTo<Microseconds>(tsSecs.getTicks()).count(), 1000 * 1000);
+ ASSERT_EQ((tickToDuration<Seconds, Seconds>(1)), 1);
+ ASSERT_EQ((tickToDuration<Seconds, Milliseconds>(1)), 1'000);
+ ASSERT_EQ((tickToDuration<Seconds, Microseconds>(1)), 1'000'000);
+ ASSERT_EQ((tickToDuration<Milliseconds, Milliseconds>(1)), 1);
+ ASSERT_EQ((tickToDuration<Milliseconds, Microseconds>(1)), 1'000);
+ ASSERT_EQ((tickToDuration<Microseconds, Microseconds>(1)), 1);
+}
- TickSourceMock<Milliseconds> tsMillis;
- tsMillis.reset(1);
- ASSERT_EQ(tsMillis.ticksTo<Milliseconds>(tsMillis.getTicks()).count(), 1);
- ASSERT_EQ(tsMillis.ticksTo<Microseconds>(tsMillis.getTicks()).count(), 1000);
+TEST(SystemTickSourceTest, TicksPerSecond) {
+ ASSERT_EQ(makeSystemTickSource()->getTicksPerSecond(), 1'000'000'000);
+}
- TickSourceMock<Microseconds> tsMicros;
- tsMicros.reset(1);
- ASSERT_EQ(tsMicros.ticksTo<Microseconds>(tsMicros.getTicks()).count(), 1);
+TEST(SystemTickSourceTest, GetTicks) {
+ auto ts = makeSystemTickSource();
+ auto t0 = ts->getTicks();
+ for (int reps = 20; reps--;) {
+ static constexpr Milliseconds delay{200};
+ static constexpr Milliseconds err{20};
+ sleepFor(delay);
+ auto t1 = ts->getTicks();
+ ASSERT_THAT(ts->ticksTo<Milliseconds>(t1 - t0),
+ m::AllOf(m::Ge(delay - err), m::Le(delay + err)));
+ t0 = t1;
+ }
}
-TEST(TickSourceTest, SpansToDurationConversion) {
- TickSourceMock<Seconds> tsSecs;
- tsSecs.reset(0);
- TickSource::Tick zero = tsSecs.getTicks();
- tsSecs.reset(10);
- TickSource::Tick ten = tsSecs.getTicks();
- ASSERT_EQ(tsSecs.spanTo<Seconds>(zero, ten).count(), 10);
- ASSERT_EQ(tsSecs.spanTo<Seconds>(ten, zero).count(), 0);
- ASSERT_EQ(tsSecs.spanTo<Milliseconds>(zero, ten).count(), 10 * 1000);
- ASSERT_EQ(tsSecs.spanTo<Milliseconds>(ten, zero).count(), 0);
- ASSERT_EQ(tsSecs.spanTo<Microseconds>(zero, ten).count(), 10 * 1000 * 1000);
- ASSERT_EQ(tsSecs.spanTo<Microseconds>(ten, zero).count(), 0);
+TEST(SystemTickSourceTest, Monotonic) {
+ auto ts = makeSystemTickSource();
+ auto t0 = ts->getTicks();
+ std::vector<TickSource::Tick> samples;
+ samples.reserve(1'000'000);
+ do {
+ samples.clear();
+ for (size_t i = 0; i < 1'000'000; ++i)
+ samples.push_back(ts->getTicks());
+ ASSERT_TRUE(std::is_sorted(samples.begin(), samples.end()));
+ } while (ts->ticksTo<Milliseconds>(ts->getTicks() - t0) < Seconds{5});
}
} // namespace
} // namespace mongo
diff --git a/src/mongo/util/timer.cpp b/src/mongo/util/timer.cpp
index f69bfc4cbb8..7992cd0788c 100644
--- a/src/mongo/util/timer.cpp
+++ b/src/mongo/util/timer.cpp
@@ -42,7 +42,7 @@ const int64_t kMicrosPerSecond = 1000 * 1000;
} // unnamed namespace
-Timer::Timer() : Timer(SystemTickSource::get()) {}
+Timer::Timer() : Timer(globalSystemTickSource()) {}
Timer::Timer(TickSource* tickSource)
: _tickSource(tickSource),