From f5337c32ab8470454af46a3e391575840a5b39ce Mon Sep 17 00:00:00 2001 From: Dianna Hohensee Date: Thu, 22 Oct 2020 16:54:59 -0400 Subject: SERVER-51396 Add a LockFreeReadsBlock that sets a flag on the OperationContext in order to safely bypass RSTL lock invariants for lock-free reads. --- src/mongo/db/operation_context.h | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'src/mongo/db/operation_context.h') diff --git a/src/mongo/db/operation_context.h b/src/mongo/db/operation_context.h index 7997674747d..dbb21caf7d3 100644 --- a/src/mongo/db/operation_context.h +++ b/src/mongo/db/operation_context.h @@ -282,6 +282,13 @@ public: return _writesAreReplicated; } + /** + * Returns true if the operation is running lock-free. + */ + bool isLockFreeReadsOp() const { + return _isLockFreeReadsOp; + } + /** * Returns true if operations' durations should be added to serverStatus latency metrics. */ @@ -572,8 +579,16 @@ private: _writesAreReplicated = writesAreReplicated; } + /** + * Set whether or not the operation is running lock-free. + */ + void setIsLockFreeReadsOp(bool isLockFreeReadsOp) { + _isLockFreeReadsOp = isLockFreeReadsOp; + } + friend class WriteUnitOfWork; friend class repl::UnreplicatedWritesBlock; + friend class LockFreeReadsBlock; Client* const _client; @@ -626,6 +641,7 @@ private: Timer _elapsedTime; bool _writesAreReplicated = true; + bool _isLockFreeReadsOp = false; bool _shouldIncrementLatencyStats = true; bool _shouldParticipateInFlowControl = true; bool _inMultiDocumentTransaction = false; @@ -673,4 +689,29 @@ private: const bool _shouldReplicateWrites; }; } // namespace repl + +/** + * RAII-style class to indicate the operation is lock-free and code should behave accordingly. + */ +class LockFreeReadsBlock { + LockFreeReadsBlock(const LockFreeReadsBlock&) = delete; + LockFreeReadsBlock& operator=(const LockFreeReadsBlock&) = delete; + +public: + LockFreeReadsBlock(OperationContext* opCtx) + : _opCtx(opCtx), _previousLockFreeReadsSetting(opCtx->isLockFreeReadsOp()) { + opCtx->setIsLockFreeReadsOp(true); + } + + ~LockFreeReadsBlock() { + _opCtx->setIsLockFreeReadsOp(_previousLockFreeReadsSetting); + } + +private: + OperationContext* _opCtx; + + // Used to re-set the value on the operation context upon destruction that was originally set. + const bool _previousLockFreeReadsSetting; +}; + } // namespace mongo -- cgit v1.2.1