diff options
Diffstat (limited to 'src/mongo/db/query/plan_yield_policy.cpp')
-rw-r--r-- | src/mongo/db/query/plan_yield_policy.cpp | 126 |
1 files changed, 62 insertions, 64 deletions
diff --git a/src/mongo/db/query/plan_yield_policy.cpp b/src/mongo/db/query/plan_yield_policy.cpp index 67eb574ef5c..45d996893a9 100644 --- a/src/mongo/db/query/plan_yield_policy.cpp +++ b/src/mongo/db/query/plan_yield_policy.cpp @@ -38,75 +38,73 @@ namespace mongo { - PlanYieldPolicy::PlanYieldPolicy(PlanExecutor* exec, PlanExecutor::YieldPolicy policy) - : _policy(policy), - _forceYield(false), - _elapsedTracker(internalQueryExecYieldIterations, internalQueryExecYieldPeriodMS), - _planYielding(exec) { } - - bool PlanYieldPolicy::shouldYield() { - if (!allowedToYield()) return false; - invariant(!_planYielding->getOpCtx()->lockState()->inAWriteUnitOfWork()); - if (_forceYield) return true; - return _elapsedTracker.intervalHasElapsed(); - } - - void PlanYieldPolicy::resetTimer() { - _elapsedTracker.resetLastTime(); - } - - bool PlanYieldPolicy::yield(RecordFetcher* fetcher) { - invariant(_planYielding); - invariant(allowedToYield()); - - _forceYield = false; +PlanYieldPolicy::PlanYieldPolicy(PlanExecutor* exec, PlanExecutor::YieldPolicy policy) + : _policy(policy), + _forceYield(false), + _elapsedTracker(internalQueryExecYieldIterations, internalQueryExecYieldPeriodMS), + _planYielding(exec) {} + +bool PlanYieldPolicy::shouldYield() { + if (!allowedToYield()) + return false; + invariant(!_planYielding->getOpCtx()->lockState()->inAWriteUnitOfWork()); + if (_forceYield) + return true; + return _elapsedTracker.intervalHasElapsed(); +} + +void PlanYieldPolicy::resetTimer() { + _elapsedTracker.resetLastTime(); +} + +bool PlanYieldPolicy::yield(RecordFetcher* fetcher) { + invariant(_planYielding); + invariant(allowedToYield()); + + _forceYield = false; + + OperationContext* opCtx = _planYielding->getOpCtx(); + invariant(opCtx); + invariant(!opCtx->lockState()->inAWriteUnitOfWork()); + + // Can't use MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN/END since we need to call saveState + // before reseting the transaction. + for (int attempt = 1; true; attempt++) { + try { + // All YIELD_AUTO plans will get here eventually when the elapsed tracker triggers + // that it's time to yield. Whether or not we will actually yield, we need to check + // if this operation has been interrupted. Throws if the interrupt flag is set. + if (_policy == PlanExecutor::YIELD_AUTO) { + opCtx->checkForInterrupt(); + } - OperationContext* opCtx = _planYielding->getOpCtx(); - invariant(opCtx); - invariant(!opCtx->lockState()->inAWriteUnitOfWork()); + // No need to yield if the collection is NULL. + if (NULL == _planYielding->collection()) { + return true; + } - // Can't use MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN/END since we need to call saveState - // before reseting the transaction. - for (int attempt = 1; true; attempt++) { try { - // All YIELD_AUTO plans will get here eventually when the elapsed tracker triggers - // that it's time to yield. Whether or not we will actually yield, we need to check - // if this operation has been interrupted. Throws if the interrupt flag is set. - if (_policy == PlanExecutor::YIELD_AUTO) { - opCtx->checkForInterrupt(); - } - - // No need to yield if the collection is NULL. - if (NULL == _planYielding->collection()) { - return true; - } - - try { - _planYielding->saveState(); - } - catch (const WriteConflictException& wce) { - invariant(!"WriteConflictException not allowed in saveState"); - } - - if (_policy == PlanExecutor::WRITE_CONFLICT_RETRY_ONLY) { - // Just reset the snapshot. Leave all LockManager locks alone. - opCtx->recoveryUnit()->abandonSnapshot(); - } - else { - // Release and reacquire locks. - QueryYield::yieldAllLocks(opCtx, fetcher); - } - - return _planYielding->restoreStateWithoutRetrying(opCtx); + _planYielding->saveState(); + } catch (const WriteConflictException& wce) { + invariant(!"WriteConflictException not allowed in saveState"); } - catch (const WriteConflictException& wce) { - CurOp::get(opCtx)->debug().writeConflicts++; - WriteConflictException::logAndBackoff(attempt, - "plan execution restoreState", - _planYielding->collection()->ns().ns()); - // retry + + if (_policy == PlanExecutor::WRITE_CONFLICT_RETRY_ONLY) { + // Just reset the snapshot. Leave all LockManager locks alone. + opCtx->recoveryUnit()->abandonSnapshot(); + } else { + // Release and reacquire locks. + QueryYield::yieldAllLocks(opCtx, fetcher); } + + return _planYielding->restoreStateWithoutRetrying(opCtx); + } catch (const WriteConflictException& wce) { + CurOp::get(opCtx)->debug().writeConflicts++; + WriteConflictException::logAndBackoff( + attempt, "plan execution restoreState", _planYielding->collection()->ns().ns()); + // retry } } +} -} // namespace mongo +} // namespace mongo |