summaryrefslogtreecommitdiff
path: root/src/mongo/db/db_raii.cpp
diff options
context:
space:
mode:
authorDianna Hohensee <dianna.hohensee@mongodb.com>2020-12-18 19:01:33 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-01-08 14:15:17 +0000
commit6221e2ee0ff5527f13d25a28a5de6a245bd0e641 (patch)
tree6aa5c7793c48bdad89659c761b52b8ecfd326224 /src/mongo/db/db_raii.cpp
parenta2bd60fb04358ce7250c87477365a26b660b907a (diff)
downloadmongo-6221e2ee0ff5527f13d25a28a5de6a245bd0e641.tar.gz
SERVER-52835 Nested LFR lock helpers should read from copied CollectionCatalog
Diffstat (limited to 'src/mongo/db/db_raii.cpp')
-rw-r--r--src/mongo/db/db_raii.cpp53
1 files changed, 37 insertions, 16 deletions
diff --git a/src/mongo/db/db_raii.cpp b/src/mongo/db/db_raii.cpp
index ec09f87cfe8..49f39041f78 100644
--- a/src/mongo/db/db_raii.cpp
+++ b/src/mongo/db/db_raii.cpp
@@ -53,13 +53,14 @@ const auto allowSecondaryReadsDuringBatchApplication_DONT_USE =
/**
* Performs some checks to determine whether the operation is compatible with a lock-free read.
- * The DBDirectClient and multi-doc transactions are not supported.
+ * Multi-doc transactions are not supported, nor are operations holding an exclusive lock.
*/
bool supportsLockFreeRead(OperationContext* opCtx) {
- // Lock-free reads are only supported for external queries, not internal via DBDirectClient.
// Lock-free reads are not supported in multi-document transactions.
- return !storageGlobalParams.disableLockFreeReads && !opCtx->getClient()->isInDirectClient() &&
- !opCtx->inMultiDocumentTransaction();
+ // Lock-free reads are not supported under an exclusive lock (nested reads under exclusive lock
+ // holding operations).
+ return !storageGlobalParams.disableLockFreeReads && !opCtx->inMultiDocumentTransaction() &&
+ !opCtx->lockState()->isWriteLocked();
}
/**
@@ -78,8 +79,9 @@ bool supportsLockFreeRead(OperationContext* opCtx) {
template <typename GetCollectionAndEstablishReadSourceFunc,
typename GetCollectionAfterSnapshotFunc,
typename ResetFunc>
-auto aquireCollectionAndConsistentSnapshot(
+auto acquireCollectionAndConsistentSnapshot(
OperationContext* opCtx,
+ bool isLockFreeReadSubOperation,
CollectionCatalogStasher& catalogStasher,
GetCollectionAndEstablishReadSourceFunc getCollectionAndEstablishReadSource,
GetCollectionAfterSnapshotFunc getCollectionAfterSnapshot,
@@ -103,6 +105,12 @@ auto aquireCollectionAndConsistentSnapshot(
if (!collection)
break;
+ // If this is a nested lock acquisition, then we already have a consistent stashed catalog
+ // and snapshot from which to read and we can skip the below logic.
+ if (isLockFreeReadSubOperation) {
+ return collection;
+ }
+
// We must open a storage snapshot consistent with the fetched in-memory Collection instance
// and chosen read source. The Collection instance and replication state after opening a
// snapshot will be compared with the previously acquired state. If either does not match,
@@ -363,12 +371,14 @@ AutoGetCollectionForReadLockFree::EmplaceHelper::EmplaceHelper(
CollectionCatalogStasher& catalogStasher,
const NamespaceStringOrUUID& nsOrUUID,
AutoGetCollectionViewMode viewMode,
- Date_t deadline)
+ Date_t deadline,
+ bool isLockFreeReadSubOperation)
: _opCtx(opCtx),
_catalogStasher(catalogStasher),
_nsOrUUID(nsOrUUID),
_viewMode(viewMode),
- _deadline(deadline) {}
+ _deadline(deadline),
+ _isLockFreeReadSubOperation(isLockFreeReadSubOperation) {}
void AutoGetCollectionForReadLockFree::EmplaceHelper::emplace(
boost::optional<AutoGetCollectionLockFree>& autoColl) const {
@@ -376,14 +386,18 @@ void AutoGetCollectionForReadLockFree::EmplaceHelper::emplace(
_opCtx,
_nsOrUUID,
/* restoreFromYield */
- [& catalogStasher = _catalogStasher](std::shared_ptr<const Collection>& collection,
- OperationContext* opCtx,
- CollectionUUID uuid) {
- collection = aquireCollectionAndConsistentSnapshot(
+ [& catalogStasher = _catalogStasher, isSubOperation = _isLockFreeReadSubOperation](
+ std::shared_ptr<const Collection>& collection,
+ OperationContext* opCtx,
+ CollectionUUID uuid) {
+ collection = acquireCollectionAndConsistentSnapshot(
opCtx,
+ /* isLockFreeReadSubOperation */
+ isSubOperation,
+ /* CollectionCatalogStasher */
catalogStasher,
/* GetCollectionAndEstablishReadSourceFunc */
- [uuid](OperationContext* opCtx, const CollectionCatalog& catalog) {
+ [uuid, isSubOperation](OperationContext* opCtx, const CollectionCatalog& catalog) {
auto coll = catalog.lookupCollectionByUUIDForRead(opCtx, uuid);
// After yielding and reacquiring locks, the preconditions that were used to
@@ -418,15 +432,21 @@ AutoGetCollectionForReadLockFree::AutoGetCollectionForReadLockFree(
AutoGetCollectionViewMode viewMode,
Date_t deadline)
: _catalogStash(opCtx) {
+ bool isLockFreeReadSubOperation = opCtx->isLockFreeReadsOp();
+
// Supported lock-free reads should only ever have an open storage snapshot prior to calling
// this helper if it is a nested lock-free operation. The storage snapshot and in-memory state
// used across lock=free reads must be consistent.
invariant(supportsLockFreeRead(opCtx) &&
- (!opCtx->recoveryUnit()->isActive() || opCtx->isLockFreeReadsOp()));
+ (!opCtx->recoveryUnit()->isActive() || isLockFreeReadSubOperation));
- EmplaceHelper emplaceFunc(opCtx, _catalogStash, nsOrUUID, viewMode, deadline);
- aquireCollectionAndConsistentSnapshot(
+ EmplaceHelper emplaceFunc(
+ opCtx, _catalogStash, nsOrUUID, viewMode, deadline, isLockFreeReadSubOperation);
+ acquireCollectionAndConsistentSnapshot(
opCtx,
+ /* isLockFreeReadSubOperation */
+ isLockFreeReadSubOperation,
+ /* CollectionCatalogStasher */
_catalogStash,
/* GetCollectionAndEstablishReadSourceFunc */
[this, &emplaceFunc](OperationContext* opCtx, const CollectionCatalog&) {
@@ -495,7 +515,8 @@ AutoGetCollectionForReadCommandBase<AutoGetCollectionForReadType>::
deadline) {
if (!_autoCollForRead.getView()) {
- auto* const css = CollectionShardingState::get(opCtx, _autoCollForRead.getNss());
+ auto css =
+ CollectionShardingState::getSharedForLockFreeReads(opCtx, _autoCollForRead.getNss());
css->checkShardVersionOrThrow(opCtx);
}
}