summaryrefslogtreecommitdiff
path: root/src/mongo/db/operation_context_test.cpp
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2016-05-02 10:55:01 -0400
committerAndy Schwerin <schwerin@mongodb.com>2016-05-23 10:28:31 -0400
commit2e627487ef0475c46143b5f57d3e7c3d3027d5dc (patch)
tree7ad552be9a3cae113bc3cfd9df0faea78aa50e24 /src/mongo/db/operation_context_test.cpp
parentc9aac9d6eaba6ef2eb8903f07e997b594e88addc (diff)
downloadmongo-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.cpp61
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