summaryrefslogtreecommitdiff
path: root/src/mongo/db/concurrency
diff options
context:
space:
mode:
authorJamie Heppenstall <jamie.heppenstall@mongodb.com>2020-05-08 16:52:12 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-05-12 20:26:53 +0000
commit02ceb3f342d4295aef49b3b1d5479930496186f0 (patch)
treebaca4a4374e455af7499aa6237c0a50c3910fca5 /src/mongo/db/concurrency
parentc4c5768798b72027a7b40eb0bbf4455f7e9564b9 (diff)
downloadmongo-02ceb3f342d4295aef49b3b1d5479930496186f0.tar.gz
SERVER-46698 Invariant that operations holding open an oplog hole cannot call blocking functions
Diffstat (limited to 'src/mongo/db/concurrency')
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp10
-rw-r--r--src/mongo/db/concurrency/locker.h2
2 files changed, 11 insertions, 1 deletions
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp
index 5a2871a563b..e668bcd1cc2 100644
--- a/src/mongo/db/concurrency/lock_state.cpp
+++ b/src/mongo/db/concurrency/lock_state.cpp
@@ -353,6 +353,12 @@ bool LockerImpl::_acquireTicket(OperationContext* opCtx, LockMode mode, Date_t d
// If the ticket wait is interrupted, restore the state of the client.
auto restoreStateOnErrorGuard = makeGuard([&] { _clientState.store(kInactive); });
+ // Acquiring a ticket is a potentially blocking operation. This must not be called after a
+ // transaction timestamp has been set, indicating this transaction has created an oplog
+ // hole.
+ if (opCtx)
+ invariant(!opCtx->recoveryUnit()->isTimestamped());
+
OperationContext* interruptible = _uninterruptibleLocksRequested ? nullptr : opCtx;
if (deadline == Date_t::max()) {
holder->waitForTicket(interruptible);
@@ -1002,6 +1008,10 @@ void LockerImpl::getFlowControlTicket(OperationContext* opCtx, LockMode lockMode
// tracking whether other resources need to be released.
_clientState.store(kQueuedWriter);
auto restoreState = makeGuard([&] { _clientState.store(kInactive); });
+ // Acquiring a ticket is a potentially blocking operation. This must not be called after a
+ // transaction timestamp has been set, indicating this transaction has created an oplog
+ // hole.
+ invariant(!opCtx->recoveryUnit()->isTimestamped());
ticketholder->getTicket(opCtx, &_flowControlStats);
}
}
diff --git a/src/mongo/db/concurrency/locker.h b/src/mongo/db/concurrency/locker.h
index 48674103bd5..34ac15d8586 100644
--- a/src/mongo/db/concurrency/locker.h
+++ b/src/mongo/db/concurrency/locker.h
@@ -71,7 +71,7 @@ public:
* Require global lock attempts to obtain tickets from 'reading' (for MODE_S and MODE_IS),
* and from 'writing' (for MODE_IX), which must have static lifetimes. There is no throttling
* for MODE_X, as there can only ever be a single locker using this mode. The throttling is
- * intended to defend against arge drops in throughput under high load due to too much
+ * intended to defend against large drops in throughput under high load due to too much
* concurrency.
*/
static void setGlobalThrottling(class TicketHolder* reading, class TicketHolder* writing);