summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/plan_yield_policy.cpp
diff options
context:
space:
mode:
authorTess Avitabile <tess.avitabile@mongodb.com>2018-02-05 17:21:06 -0500
committerTess Avitabile <tess.avitabile@mongodb.com>2018-02-08 10:31:50 -0500
commitb730e13c75d21ee86fea0622a55410d790a23224 (patch)
tree5a2aeec9dce06a77fbd0070261b1b6eea17ed248 /src/mongo/db/query/plan_yield_policy.cpp
parentc556e377094792e7253a95cb5fedcd703a99bf2c (diff)
downloadmongo-b730e13c75d21ee86fea0622a55410d790a23224.tar.gz
SERVER-32685 Disable lock and WT transaction yielding under readConcern snapshot for find and getMore
Diffstat (limited to 'src/mongo/db/query/plan_yield_policy.cpp')
-rw-r--r--src/mongo/db/query/plan_yield_policy.cpp35
1 files changed, 31 insertions, 4 deletions
diff --git a/src/mongo/db/query/plan_yield_policy.cpp b/src/mongo/db/query/plan_yield_policy.cpp
index 13bded7f1b4..4c3a96282d4 100644
--- a/src/mongo/db/query/plan_yield_policy.cpp
+++ b/src/mongo/db/query/plan_yield_policy.cpp
@@ -36,11 +36,16 @@
#include "mongo/db/query/query_knobs.h"
#include "mongo/db/query/query_yield.h"
#include "mongo/db/service_context.h"
+#include "mongo/util/fail_point_service.h"
#include "mongo/util/scopeguard.h"
#include "mongo/util/time_support.h"
namespace mongo {
+namespace {
+MONGO_FP_DECLARE(setCheckForInterruptHang);
+} // namespace
+
PlanYieldPolicy::PlanYieldPolicy(PlanExecutor* exec, PlanExecutor::YieldPolicy policy)
: _policy(exec->getOpCtx()->lockState()->isGlobalLockedRecursively() ? PlanExecutor::NO_YIELD
: policy),
@@ -59,6 +64,13 @@ PlanYieldPolicy::PlanYieldPolicy(PlanExecutor::YieldPolicy policy, ClockSource*
Milliseconds(internalQueryExecYieldPeriodMS.load())),
_planYielding(nullptr) {}
+bool PlanYieldPolicy::shouldYieldOrInterrupt() {
+ if (_policy == PlanExecutor::INTERRUPT_ONLY) {
+ return _elapsedTracker.intervalHasElapsed();
+ }
+ return shouldYield();
+}
+
bool PlanYieldPolicy::shouldYield() {
if (!canAutoYield())
return false;
@@ -72,15 +84,28 @@ void PlanYieldPolicy::resetTimer() {
_elapsedTracker.resetLastTime();
}
-Status PlanYieldPolicy::yield(RecordFetcher* recordFetcher) {
+Status PlanYieldPolicy::yieldOrInterrupt(RecordFetcher* recordFetcher) {
invariant(_planYielding);
if (recordFetcher) {
OperationContext* opCtx = _planYielding->getOpCtx();
- return yield([recordFetcher, opCtx] { recordFetcher->setup(opCtx); },
- [recordFetcher] { recordFetcher->fetch(); });
+ return yieldOrInterrupt([recordFetcher, opCtx] { recordFetcher->setup(opCtx); },
+ [recordFetcher] { recordFetcher->fetch(); });
} else {
- return yield(nullptr, nullptr);
+ return yieldOrInterrupt(nullptr, nullptr);
+ }
+}
+
+Status PlanYieldPolicy::yieldOrInterrupt(stdx::function<void()> beforeYieldingFn,
+ stdx::function<void()> whileYieldingFn) {
+ if (_policy == PlanExecutor::INTERRUPT_ONLY) {
+ ON_BLOCK_EXIT([this]() { resetTimer(); });
+ OperationContext* opCtx = _planYielding->getOpCtx();
+ invariant(opCtx);
+ MONGO_FAIL_POINT_PAUSE_WHILE_SET(setCheckForInterruptHang);
+ return opCtx->checkForInterruptNoAssert();
}
+
+ return yield(beforeYieldingFn, whileYieldingFn);
}
Status PlanYieldPolicy::yield(stdx::function<void()> beforeYieldingFn,
@@ -106,6 +131,8 @@ Status PlanYieldPolicy::yield(stdx::function<void()> beforeYieldingFn,
// that it's time to yield. Whether or not we will actually yield, we need to check
// if this operation has been interrupted.
if (_policy == PlanExecutor::YIELD_AUTO) {
+ MONGO_FAIL_POINT_PAUSE_WHILE_SET(setCheckForInterruptHang);
+
auto interruptStatus = opCtx->checkForInterruptNoAssert();
if (!interruptStatus.isOK()) {
return interruptStatus;