summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Caimano <ben.caimano@10gen.com>2020-07-23 21:59:46 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-07-28 20:57:56 +0000
commit214379825c248f5a5e5f0a01ad9863b900faaf30 (patch)
tree077a4844ec0daaf1a738933920525cde7d440131 /src
parent6dd301449ec7a48e35a7114e93b888df9958217f (diff)
downloadmongo-214379825c248f5a5e5f0a01ad9863b900faaf30.tar.gz
SERVER-48650 Gave the ClockSourceMock a global impl
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/repl/initial_syncer_test.cpp7
-rw-r--r--src/mongo/db/repl/replication_coordinator_test_fixture.cpp5
-rw-r--r--src/mongo/db/service_context_test_fixture.cpp7
-rw-r--r--src/mongo/executor/SConscript1
-rw-r--r--src/mongo/executor/network_interface_mock.cpp22
-rw-r--r--src/mongo/executor/network_interface_mock.h29
-rw-r--r--src/mongo/s/mongos_topology_coordinator_test.cpp35
-rw-r--r--src/mongo/util/clock_source_mock.cpp96
-rw-r--r--src/mongo/util/clock_source_mock.h16
10 files changed, 115 insertions, 104 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 0fbabb87582..2f5aad83e4c 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -1697,6 +1697,7 @@ env.Library(
],
LIBDEPS_PRIVATE=[
'op_observer',
+ '$BUILD_DIR/mongo/util/clock_source_mock',
],
)
diff --git a/src/mongo/db/repl/initial_syncer_test.cpp b/src/mongo/db/repl/initial_syncer_test.cpp
index 4180a2a5b74..455dfd10d6a 100644
--- a/src/mongo/db/repl/initial_syncer_test.cpp
+++ b/src/mongo/db/repl/initial_syncer_test.cpp
@@ -67,6 +67,7 @@
#include "mongo/executor/network_interface_mock.h"
#include "mongo/executor/thread_pool_task_executor_test_fixture.h"
#include "mongo/platform/mutex.h"
+#include "mongo/util/clock_source_mock.h"
#include "mongo/util/concurrency/thread_name.h"
#include "mongo/util/concurrency/thread_pool.h"
#include "mongo/util/fail_point.h"
@@ -340,10 +341,8 @@ protected:
};
auto* service = getGlobalServiceContext();
- service->setFastClockSource(
- std::make_unique<executor::NetworkInterfaceMockClockSource>(getNet()));
- service->setPreciseClockSource(
- std::make_unique<executor::NetworkInterfaceMockClockSource>(getNet()));
+ service->setFastClockSource(std::make_unique<ClockSourceMock>());
+ service->setPreciseClockSource(std::make_unique<ClockSourceMock>());
ThreadPool::Options dbThreadPoolOptions;
dbThreadPoolOptions.poolName = "dbthread";
dbThreadPoolOptions.minThreads = 1U;
diff --git a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp
index f2147923ed9..e54eda1b6f1 100644
--- a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp
+++ b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp
@@ -153,9 +153,8 @@ void ReplCoordTest::init() {
replicationProcess,
_storageInterface,
seed);
- service->setFastClockSource(std::make_unique<executor::NetworkInterfaceMockClockSource>(_net));
- service->setPreciseClockSource(
- std::make_unique<executor::NetworkInterfaceMockClockSource>(_net));
+ service->setFastClockSource(std::make_unique<ClockSourceMock>());
+ service->setPreciseClockSource(std::make_unique<ClockSourceMock>());
}
void ReplCoordTest::init(const ReplSettings& settings) {
diff --git a/src/mongo/db/service_context_test_fixture.cpp b/src/mongo/db/service_context_test_fixture.cpp
index 3a1a8b4edb5..3ba046db3de 100644
--- a/src/mongo/db/service_context_test_fixture.cpp
+++ b/src/mongo/db/service_context_test_fixture.cpp
@@ -37,11 +37,18 @@
#include "mongo/db/client.h"
#include "mongo/db/op_observer_registry.h"
#include "mongo/util/assert_util.h"
+#include "mongo/util/clock_source_mock.h"
#include "mongo/util/diagnostic_info.h"
namespace mongo {
ScopedGlobalServiceContextForTest::ScopedGlobalServiceContextForTest() {
+ {
+ // Reset the global clock source
+ ClockSourceMock clkSource;
+ clkSource.reset();
+ }
+
auto serviceContext = [] {
auto serviceContext = ServiceContext::make();
auto serviceContextPtr = serviceContext.get();
diff --git a/src/mongo/executor/SConscript b/src/mongo/executor/SConscript
index 80ee3174a12..da4acd722ab 100644
--- a/src/mongo/executor/SConscript
+++ b/src/mongo/executor/SConscript
@@ -74,6 +74,7 @@ env.Library('network_interface_mock',
LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/rpc/metadata',
+ '$BUILD_DIR/mongo/util/clock_source_mock',
'$BUILD_DIR/mongo/util/net/network',
'network_interface',
'task_executor_interface',
diff --git a/src/mongo/executor/network_interface_mock.cpp b/src/mongo/executor/network_interface_mock.cpp
index ab1fcceb126..ed9e7fe1d4d 100644
--- a/src/mongo/executor/network_interface_mock.cpp
+++ b/src/mongo/executor/network_interface_mock.cpp
@@ -50,9 +50,9 @@ using CallbackHandle = TaskExecutor::CallbackHandle;
using ResponseStatus = TaskExecutor::ResponseStatus;
NetworkInterfaceMock::NetworkInterfaceMock()
- : _waitingToRunMask(0),
+ : _clkSource(std::make_unique<ClockSourceMock>()),
+ _waitingToRunMask(0),
_currentlyRunning(kNoThread),
- _now(fassert(18653, dateFromISOString("2014-08-01T00:00:00Z"))),
_hasStarted(false),
_inShutdown(false),
_executorNextWakeupDate(Date_t::max()) {}
@@ -416,8 +416,11 @@ Date_t NetworkInterfaceMock::runUntil(Date_t until) {
if (until < newNow) {
newNow = until;
}
- invariant(_now_inlock() <= newNow);
- _now = newNow;
+
+ auto duration = newNow - _now_inlock();
+ invariant(duration >= Milliseconds{0});
+ _clkSource->advance(duration);
+
_waitingToRunMask |= kExecutorThread;
}
_runReadyNetworkOperations_inlock(&lk);
@@ -427,8 +430,10 @@ Date_t NetworkInterfaceMock::runUntil(Date_t until) {
void NetworkInterfaceMock::advanceTime(Date_t newTime) {
stdx::unique_lock<stdx::mutex> lk(_mutex);
invariant(_currentlyRunning == kNetworkThread);
- invariant(newTime > _now_inlock());
- _now = newTime;
+
+ auto duration = newTime - _now_inlock();
+ invariant(duration > Milliseconds{0});
+ _clkSource->advance(duration);
_waitingToRunMask |= kExecutorThread;
_runReadyNetworkOperations_inlock(&lk);
@@ -720,10 +725,5 @@ NetworkInterfaceMock* NetworkInterfaceMock::InNetworkGuard::operator->() const {
return _net;
}
-NetworkInterfaceMockClockSource::NetworkInterfaceMockClockSource(NetworkInterfaceMock* net)
- : _net(net) {
- _tracksSystemClock = false;
-}
-
} // namespace executor
} // namespace mongo
diff --git a/src/mongo/executor/network_interface_mock.h b/src/mongo/executor/network_interface_mock.h
index 8781101329d..911917523fc 100644
--- a/src/mongo/executor/network_interface_mock.h
+++ b/src/mongo/executor/network_interface_mock.h
@@ -42,6 +42,7 @@
#include "mongo/stdx/unordered_map.h"
#include "mongo/stdx/unordered_set.h"
#include "mongo/util/clock_source.h"
+#include "mongo/util/clock_source_mock.h"
#include "mongo/util/time_support.h"
namespace mongo {
@@ -319,7 +320,7 @@ private:
* Returns the current virtualized time.
*/
Date_t _now_inlock() const {
- return _now;
+ return _clkSource->now();
}
/**
@@ -364,6 +365,9 @@ private:
// in multi-threaded execution, and so unsynchronized, are labeled (R).
stdx::mutex _mutex; // NOLINT
+ // A mocked clock source.
+ std::unique_ptr<ClockSourceMock> _clkSource; // (M)
+
// Condition signaled to indicate that the network processing thread should wake up.
stdx::condition_variable _shouldWakeNetworkCondition; // (M)
@@ -376,9 +380,6 @@ private:
// Indicator of which thread, if any, is currently running.
ThreadType _currentlyRunning; // (M)
- // The current time reported by this instance of NetworkInterfaceMock.
- Date_t _now; // (M)
-
// Set to true by "startUp()"
bool _hasStarted; // (M)
@@ -556,25 +557,5 @@ private:
bool _callExitNetwork = true;
};
-class NetworkInterfaceMockClockSource : public ClockSource {
-public:
- explicit NetworkInterfaceMockClockSource(NetworkInterfaceMock* net);
-
- Milliseconds getPrecision() override {
- return Milliseconds{1};
- }
- Date_t now() override {
- return _net->now();
- }
- Status setAlarm(Date_t when, unique_function<void()> action) override {
- return _net->setAlarm(TaskExecutor::CallbackHandle(),
- when,
- [action = std::move(action)](Status) { action(); });
- }
-
-private:
- NetworkInterfaceMock* _net;
-};
-
} // namespace executor
} // namespace mongo
diff --git a/src/mongo/s/mongos_topology_coordinator_test.cpp b/src/mongo/s/mongos_topology_coordinator_test.cpp
index 012dd4d9b41..5959e939754 100644
--- a/src/mongo/s/mongos_topology_coordinator_test.cpp
+++ b/src/mongo/s/mongos_topology_coordinator_test.cpp
@@ -49,18 +49,15 @@ public:
virtual void setUp() {
_topo = std::make_unique<MongosTopologyCoordinator>();
- getServiceContext()->setFastClockSource(std::make_unique<ClockSourceMock>());
- _fastClock = dynamic_cast<ClockSourceMock*>(getServiceContext()->getFastClockSource());
-
- getServiceContext()->setPreciseClockSource(std::make_unique<ClockSourceMock>());
- _preciseClock =
- dynamic_cast<ClockSourceMock*>(getServiceContext()->getPreciseClockSource());
+ // The fast clock is used by OperationContext::hasDeadlineExpired.
+ getServiceContext()->setFastClockSource(
+ std::make_unique<SharedClockSourceAdapter>(_clkSource));
+ // The precise clock is used by waitForConditionOrInterruptNoAssertUntil.
+ getServiceContext()->setPreciseClockSource(
+ std::make_unique<SharedClockSourceAdapter>(_clkSource));
}
- virtual void tearDown() {
- _fastClock = nullptr;
- _preciseClock = nullptr;
- }
+ virtual void tearDown() {}
protected:
/**
@@ -74,24 +71,19 @@ protected:
* Advance the time by millis on both clock source mocks.
*/
void advanceTime(Milliseconds millis) {
- _fastClock->advance(millis);
- _preciseClock->advance(millis);
+ _clkSource->advance(millis);
}
/**
* Assumes that the times on both clock source mocks is the same.
*/
Date_t now() {
- invariant(_fastClock->now() == _preciseClock->now());
- return _fastClock->now();
+ return _clkSource->now();
}
private:
- unique_ptr<MongosTopologyCoordinator> _topo;
- // The fast clock is used by OperationContext::hasDeadlineExpired.
- ClockSourceMock* _fastClock;
- // The precise clock is used by waitForConditionOrInterruptNoAssertUntil.
- ClockSourceMock* _preciseClock;
+ std::unique_ptr<MongosTopologyCoordinator> _topo;
+ std::shared_ptr<ClockSourceMock> _clkSource = std::make_shared<ClockSourceMock>();
};
TEST_F(MongosTopoCoordTest, MongosTopologyVersionCounterInitializedAtStartup) {
@@ -120,7 +112,6 @@ TEST_F(MongosTopoCoordTest, AwaitIsMasterResponseReturnsCurrentMongosTopologyVer
auto opCtx = makeOperationContext();
auto maxAwaitTime = Milliseconds(5000);
auto halfwayToMaxAwaitTime = maxAwaitTime / 2;
- auto halfwayToDeadline = now() + halfwayToMaxAwaitTime;
auto deadline = now() + maxAwaitTime;
// isMaster request with the current TopologyVersion should attempt to wait for maxAwaitTimeMS.
@@ -141,12 +132,10 @@ TEST_F(MongosTopoCoordTest, AwaitIsMasterResponseReturnsCurrentMongosTopologyVer
// Advance the clocks halfway and make sure awaitIsMasterResponse did not return yet.
advanceTime(halfwayToMaxAwaitTime);
- ASSERT_EQUALS(halfwayToDeadline, now());
ASSERT_FALSE(isMasterReturned);
// Advance the clocks the rest of the way so that awaitIsMasterResponse times out.
advanceTime(halfwayToMaxAwaitTime);
- ASSERT_EQUALS(deadline, now());
getIsMasterThread.join();
ASSERT_TRUE(isMasterReturned);
}
@@ -300,4 +289,4 @@ TEST_F(MongosTopoCoordTest, IsMasterReturnsErrorOnEnteringQuiesceMode) {
}
} // namespace
-} // namespace mongo \ No newline at end of file
+} // namespace mongo
diff --git a/src/mongo/util/clock_source_mock.cpp b/src/mongo/util/clock_source_mock.cpp
index 0319e67b481..c50aca29a82 100644
--- a/src/mongo/util/clock_source_mock.cpp
+++ b/src/mongo/util/clock_source_mock.cpp
@@ -31,55 +31,91 @@
#include "mongo/platform/mutex.h"
#include "mongo/util/clock_source_mock.h"
+#include "mongo/util/static_immortal.h"
#include <algorithm>
namespace mongo {
+namespace {
+/**
+ * This is a synchronized global mocked ClockSource.
+ *
+ * For ease of use, this is the underlying source behind *every* clock source.
+ **/
+class ClockSourceMockImpl {
+public:
+ using Alarm = std::pair<Date_t, unique_function<void()>>;
+
+ static ClockSourceMockImpl* get() noexcept {
+ static auto clkSource = StaticImmortal<ClockSourceMockImpl>();
+ return &clkSource.value();
+ }
+
+ Date_t now() {
+ stdx::lock_guard<stdx::mutex> lk(_mutex);
+ return _now;
+ }
+
+ void advance(Milliseconds ms) {
+ stdx::unique_lock<stdx::mutex> lk(_mutex);
+ _now += ms;
+ _processAlarms(std::move(lk));
+ }
+ void reset(Date_t newNow) {
+ stdx::unique_lock<stdx::mutex> lk(_mutex);
+ _now = newNow;
+ _processAlarms(std::move(lk));
+ }
+
+ Status setAlarm(Date_t when, unique_function<void()> action) {
+ stdx::unique_lock<stdx::mutex> lk(_mutex);
+ if (when <= _now) {
+ lk.unlock();
+ action();
+ return Status::OK();
+ }
+ _alarms.emplace_back(when, std::move(action));
+ return Status::OK();
+ }
+
+private:
+ void _processAlarms(stdx::unique_lock<stdx::mutex> lk) {
+ invariant(lk.owns_lock());
+ std::vector<Alarm> readyAlarms;
+ auto alarmIsNotExpired = [&](const Alarm& alarm) { return alarm.first > _now; };
+ auto expiredAlarmsBegin = std::partition(_alarms.begin(), _alarms.end(), alarmIsNotExpired);
+ std::move(expiredAlarmsBegin, _alarms.end(), std::back_inserter(readyAlarms));
+ _alarms.erase(expiredAlarmsBegin, _alarms.end());
+ lk.unlock();
+ for (const auto& alarm : readyAlarms) {
+ alarm.second();
+ }
+ }
+
+ stdx::mutex _mutex; // NOLINT
+ Date_t _now = ClockSourceMock::kInitialNow;
+ std::vector<Alarm> _alarms;
+};
+} // namespace
Milliseconds ClockSourceMock::getPrecision() {
return Milliseconds(1);
}
Date_t ClockSourceMock::now() {
- stdx::lock_guard<stdx::mutex> lk(_mutex);
- return _now;
+ return ClockSourceMockImpl::get()->now();
}
void ClockSourceMock::advance(Milliseconds ms) {
- stdx::unique_lock<stdx::mutex> lk(_mutex);
- _now += ms;
- _processAlarms(std::move(lk));
+ ClockSourceMockImpl::get()->advance(ms);
}
void ClockSourceMock::reset(Date_t newNow) {
- stdx::unique_lock<stdx::mutex> lk(_mutex);
- _now = newNow;
- _processAlarms(std::move(lk));
+ ClockSourceMockImpl::get()->reset(newNow);
}
Status ClockSourceMock::setAlarm(Date_t when, unique_function<void()> action) {
- stdx::unique_lock<stdx::mutex> lk(_mutex);
- if (when <= _now) {
- lk.unlock();
- action();
- return Status::OK();
- }
- _alarms.emplace_back(std::make_pair(when, std::move(action)));
- return Status::OK();
-}
-
-void ClockSourceMock::_processAlarms(stdx::unique_lock<stdx::mutex> lk) {
- using std::swap;
- invariant(lk.owns_lock());
- std::vector<Alarm> readyAlarms;
- auto alarmIsNotExpired = [&](const Alarm& alarm) { return alarm.first > _now; };
- auto expiredAlarmsBegin = std::partition(_alarms.begin(), _alarms.end(), alarmIsNotExpired);
- std::move(expiredAlarmsBegin, _alarms.end(), std::back_inserter(readyAlarms));
- _alarms.erase(expiredAlarmsBegin, _alarms.end());
- lk.unlock();
- for (const auto& alarm : readyAlarms) {
- alarm.second();
- }
+ return ClockSourceMockImpl::get()->setAlarm(when, std::move(action));
}
} // namespace mongo
diff --git a/src/mongo/util/clock_source_mock.h b/src/mongo/util/clock_source_mock.h
index 689a03832f7..44f3eb13283 100644
--- a/src/mongo/util/clock_source_mock.h
+++ b/src/mongo/util/clock_source_mock.h
@@ -41,9 +41,13 @@ namespace mongo {
/**
* Mock clock source that returns a fixed time until explicitly advanced.
+ *
+ * Each ClockSourceMock that is constructed tracks the same shared global understanding of time.
*/
class ClockSourceMock : public ClockSource {
public:
+ static constexpr auto kInitialNow = Date_t::fromMillisSinceEpoch(1);
+
/**
* Constructs a ClockSourceMock with the current time set to the Unix epoch.
*/
@@ -51,6 +55,8 @@ public:
_tracksSystemClock = false;
}
+ static ClockSourceMock* get() noexcept;
+
Milliseconds getPrecision() override;
Date_t now() override;
Status setAlarm(Date_t when, unique_function<void()> action) override;
@@ -63,15 +69,7 @@ public:
/**
* Resets the current time to the given value.
*/
- void reset(Date_t newNow);
-
-private:
- using Alarm = std::pair<Date_t, unique_function<void()>>;
- void _processAlarms(stdx::unique_lock<stdx::mutex> lk);
-
- stdx::mutex _mutex; // NOLINT
- Date_t _now{Date_t::fromMillisSinceEpoch(1)};
- std::vector<Alarm> _alarms;
+ void reset(Date_t newNow = kInitialNow);
};
/**