summaryrefslogtreecommitdiff
path: root/src/mongo/db/operation_context.h
diff options
context:
space:
mode:
authorDianna Hohensee <dianna.hohensee@mongodb.com>2020-10-22 16:54:59 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-11-02 19:55:18 +0000
commitf5337c32ab8470454af46a3e391575840a5b39ce (patch)
treea21b194c45c4fbaa48c0afcbda533d27edbd19ea /src/mongo/db/operation_context.h
parent0008250ba85ce47e054241eedec8cddcda1c96d6 (diff)
downloadmongo-f5337c32ab8470454af46a3e391575840a5b39ce.tar.gz
SERVER-51396 Add a LockFreeReadsBlock that sets a flag on the OperationContext in order to safely bypass RSTL lock invariants for lock-free reads.
Diffstat (limited to 'src/mongo/db/operation_context.h')
-rw-r--r--src/mongo/db/operation_context.h41
1 files changed, 41 insertions, 0 deletions
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
@@ -283,6 +283,13 @@ public:
}
/**
+ * 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.
*/
bool shouldIncrementLatencyStats() const {
@@ -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