diff options
author | Andy Schwerin <schwerin@mongodb.com> | 2016-05-02 10:55:01 -0400 |
---|---|---|
committer | Andy Schwerin <schwerin@mongodb.com> | 2016-05-23 10:28:31 -0400 |
commit | 2e627487ef0475c46143b5f57d3e7c3d3027d5dc (patch) | |
tree | 7ad552be9a3cae113bc3cfd9df0faea78aa50e24 /src/mongo/db/operation_context_test.cpp | |
parent | c9aac9d6eaba6ef2eb8903f07e997b594e88addc (diff) | |
download | mongo-2e627487ef0475c46143b5f57d3e7c3d3027d5dc.tar.gz |
SERVER-18277 Track elapsed time on cursors using microsecond resolution on OperationContext.
This completes the mechanics of moving max-time tracking to OperationContext and
switching the checkForInterrupt checks to use the service context's fast clock
source, while tracking the amount of execution time remaining on a cursor with
microsecond granularity to ensure that remaining execution time always declines,
even for very brief operations on cursors.
This patch does not complete the transition from wait_for waiting to wait_until
waiting in all places that do waiting based on operation deadlines.
Diffstat (limited to 'src/mongo/db/operation_context_test.cpp')
-rw-r--r-- | src/mongo/db/operation_context_test.cpp | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/src/mongo/db/operation_context_test.cpp b/src/mongo/db/operation_context_test.cpp index b1210afc358..cae366b845f 100644 --- a/src/mongo/db/operation_context_test.cpp +++ b/src/mongo/db/operation_context_test.cpp @@ -29,11 +29,13 @@ #include "mongo/platform/basic.h" #include "mongo/db/client.h" +#include "mongo/db/operation_context.h" #include "mongo/db/service_context.h" #include "mongo/db/service_context_noop.h" #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" #include "mongo/util/clock_source_mock.h" +#include "mongo/util/tick_source_mock.h" #include "mongo/util/time_support.h" namespace mongo { @@ -47,26 +49,81 @@ public: mockClock = uniqueMockClock.get(); service = stdx::make_unique<ServiceContextNoop>(); service->setFastClockSource(std::move(uniqueMockClock)); + service->setTickSource(stdx::make_unique<TickSourceMock>()); + client = service->makeClient("OperationDeadlineTest"); } ClockSourceMock* mockClock; std::unique_ptr<ServiceContext> service; + ServiceContext::UniqueClient client; }; TEST_F(OperationDeadlineTests, OperationDeadlineExpiration) { - auto client = service->makeClient("CurOpTest"); auto txn = client->makeOperationContext(); - txn->setMaxTimeMicros(durationCount<Microseconds>(Seconds{1})); + txn->setDeadlineAfterNowBy(Seconds{1}); mockClock->advance(Milliseconds{500}); ASSERT_OK(txn->checkForInterruptNoAssert()); + + // 1ms before relative deadline reports no interrupt mockClock->advance(Milliseconds{499}); ASSERT_OK(txn->checkForInterruptNoAssert()); + + // Exactly at deadline reports no interrupt, because setDeadlineAfterNowBy adds one clock + // precision unit to the deadline, to ensure that the deadline does not expire in less than the + // requested amount of time. + mockClock->advance(Milliseconds{1}); + ASSERT_OK(txn->checkForInterruptNoAssert()); + + // Since the mock clock's precision is 1ms, at test start + 1001 ms, we expect + // checkForInterruptNoAssert to return ExceededTimeLimit. mockClock->advance(Milliseconds{1}); ASSERT_EQ(ErrorCodes::ExceededTimeLimit, txn->checkForInterruptNoAssert()); + + // Also at times greater than start + 1001ms, we expect checkForInterruptNoAssert to keep + // returning ExceededTimeLimit. mockClock->advance(Milliseconds{1}); ASSERT_EQ(ErrorCodes::ExceededTimeLimit, txn->checkForInterruptNoAssert()); } +template <typename D> +void assertLargeRelativeDeadlineLikeInfinity(Client& client, D maxTime) { + auto txn = client.makeOperationContext(); + txn->setDeadlineAfterNowBy(maxTime); + ASSERT_FALSE(txn->hasDeadline()) << "Tried to set maxTime to " << maxTime; +} + +TEST_F(OperationDeadlineTests, VeryLargeRelativeDeadlinesHours) { + ASSERT_FALSE(client->makeOperationContext()->hasDeadline()); + assertLargeRelativeDeadlineLikeInfinity(*client, Hours::max()); +} + +TEST_F(OperationDeadlineTests, VeryLargeRelativeDeadlinesMinutes) { + assertLargeRelativeDeadlineLikeInfinity(*client, Minutes::max()); +} + +TEST_F(OperationDeadlineTests, VeryLargeRelativeDeadlinesSeconds) { + assertLargeRelativeDeadlineLikeInfinity(*client, Seconds::max()); +} + +TEST_F(OperationDeadlineTests, VeryLargeRelativeDeadlinesMilliseconds) { + assertLargeRelativeDeadlineLikeInfinity(*client, Milliseconds::max()); +} + +TEST_F(OperationDeadlineTests, VeryLargeRelativeDeadlinesMicroseconds) { + assertLargeRelativeDeadlineLikeInfinity(*client, Microseconds::max()); +} + +TEST_F(OperationDeadlineTests, VeryLargeRelativeDeadlinesNanoseconds) { + // Nanoseconds::max() is less than Microseconds::max(), so it is possible to set + // a deadline of that duration. + auto txn = client->makeOperationContext(); + txn->setDeadlineAfterNowBy(Nanoseconds::max()); + ASSERT_TRUE(txn->hasDeadline()); + ASSERT_EQ(mockClock->now() + mockClock->getPrecision() + + duration_cast<Milliseconds>(Nanoseconds::max()), + txn->getDeadline()); +} + } // namespace } // namespace mongo |