summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@mongodb.com>2021-06-04 16:41:11 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-06-15 20:40:09 +0000
commit71cfc41653768c29c719689a949a75a0ebbaa941 (patch)
tree12e2162f584662640055ca53456d4c771bf06c3e
parent214defdb236b3620806d7ce3b2d9eb485d68cd89 (diff)
downloadmongo-71cfc41653768c29c719689a949a75a0ebbaa941.tar.gz
SERVER-57096 Make SBE rely purely on the kExternal lock policy
After this patch, the AutoGet db_raii object is no longer held by the SBE scan/ixscan stages. SBE now assumes that any lock/snapshot acquisition is done at a higher level.
-rw-r--r--src/mongo/db/commands/index_filter_commands_test.cpp2
-rw-r--r--src/mongo/db/dbhelpers.cpp1
-rw-r--r--src/mongo/db/exec/sbe/parser/parser.cpp12
-rw-r--r--src/mongo/db/exec/sbe/parser/sbe_parser_test.cpp27
-rw-r--r--src/mongo/db/exec/sbe/stages/collection_helpers.cpp66
-rw-r--r--src/mongo/db/exec/sbe/stages/collection_helpers.h38
-rw-r--r--src/mongo/db/exec/sbe/stages/ix_scan.cpp19
-rw-r--r--src/mongo/db/exec/sbe/stages/ix_scan.h6
-rw-r--r--src/mongo/db/exec/sbe/stages/scan.cpp49
-rw-r--r--src/mongo/db/exec/sbe/stages/scan.h13
-rw-r--r--src/mongo/db/query/classic_stage_builder_test.cpp2
-rw-r--r--src/mongo/db/query/get_executor.cpp4
-rw-r--r--src/mongo/db/query/plan_cache_test.cpp7
-rw-r--r--src/mongo/db/query/planner_analysis.cpp2
-rw-r--r--src/mongo/db/query/query_planner.cpp3
-rw-r--r--src/mongo/db/query/query_planner_params.h9
-rw-r--r--src/mongo/db/query/query_solution.h14
-rw-r--r--src/mongo/db/query/query_solution_test.cpp2
-rw-r--r--src/mongo/db/query/sbe_stage_builder.cpp31
-rw-r--r--src/mongo/db/query/sbe_stage_builder.h4
-rw-r--r--src/mongo/db/query/sbe_stage_builder_coll_scan.cpp45
-rw-r--r--src/mongo/db/query/sbe_stage_builder_coll_scan.h3
-rw-r--r--src/mongo/db/query/sbe_stage_builder_index_scan.cpp63
-rw-r--r--src/mongo/db/query/sbe_stage_builder_index_scan.h4
-rw-r--r--src/mongo/db/query/sbe_stage_builder_test_fixture.cpp2
-rw-r--r--src/mongo/db/query/sbe_sub_planner.cpp11
-rw-r--r--src/mongo/db/transaction_history_iterator.cpp8
-rw-r--r--src/mongo/dbtests/query_stage_multiplan.cpp10
28 files changed, 156 insertions, 301 deletions
diff --git a/src/mongo/db/commands/index_filter_commands_test.cpp b/src/mongo/db/commands/index_filter_commands_test.cpp
index 1293a0d0db3..785530ca6f4 100644
--- a/src/mongo/db/commands/index_filter_commands_test.cpp
+++ b/src/mongo/db/commands/index_filter_commands_test.cpp
@@ -139,7 +139,7 @@ void addQueryShapeToPlanCache(OperationContext* opCtx,
ASSERT_OK(statusWithCQ.getStatus());
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- QuerySolution qs{QueryPlannerParams::Options::DEFAULT};
+ QuerySolution qs{};
qs.cacheData.reset(new SolutionCacheData());
qs.cacheData->tree.reset(new PlanCacheIndexTree());
std::vector<QuerySolution*> solns;
diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp
index ccb5a9e7c43..0a1a5e44fd2 100644
--- a/src/mongo/db/dbhelpers.cpp
+++ b/src/mongo/db/dbhelpers.cpp
@@ -108,7 +108,6 @@ RecordId Helpers::findOne(OperationContext* opCtx,
unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
size_t options = requireIndex ? QueryPlannerParams::NO_TABLE_SCAN : QueryPlannerParams::DEFAULT;
- options = options | QueryPlannerParams::OMIT_REPL_STATE_PERMITS_READS_CHECK;
auto exec = uassertStatusOK(getExecutor(
opCtx, &collection, std::move(cq), PlanYieldPolicy::YieldPolicy::NO_YIELD, options));
diff --git a/src/mongo/db/exec/sbe/parser/parser.cpp b/src/mongo/db/exec/sbe/parser/parser.cpp
index adf65024aca..eae7fccded7 100644
--- a/src/mongo/db/exec/sbe/parser/parser.cpp
+++ b/src/mongo/db/exec/sbe/parser/parser.cpp
@@ -682,7 +682,7 @@ void Parser::walkScan(AstQuery& ast) {
forward,
_yieldPolicy,
getCurrentPlanNodeId(),
- ScanCallbacks({}));
+ ScanCallbacks{});
}
void Parser::walkParallelScan(AstQuery& ast) {
@@ -733,7 +733,7 @@ void Parser::walkParallelScan(AstQuery& ast) {
lookupSlots(ast.nodes[projectsPos]->renames),
_yieldPolicy,
getCurrentPlanNodeId(),
- ScanCallbacks({}));
+ ScanCallbacks{});
}
void Parser::walkSeek(AstQuery& ast) {
@@ -796,7 +796,7 @@ void Parser::walkSeek(AstQuery& ast) {
forward,
_yieldPolicy,
getCurrentPlanNodeId(),
- ScanCallbacks({}));
+ ScanCallbacks{});
}
void Parser::walkIndexScan(AstQuery& ast) {
@@ -856,8 +856,7 @@ void Parser::walkIndexScan(AstQuery& ast) {
boost::none,
boost::none,
_yieldPolicy,
- getCurrentPlanNodeId(),
- LockAcquisitionCallback{});
+ getCurrentPlanNodeId());
}
void Parser::walkIndexSeek(AstQuery& ast) {
@@ -917,8 +916,7 @@ void Parser::walkIndexSeek(AstQuery& ast) {
lookupSlot(ast.nodes[0]->identifier),
lookupSlot(ast.nodes[1]->identifier),
_yieldPolicy,
- getCurrentPlanNodeId(),
- LockAcquisitionCallback{});
+ getCurrentPlanNodeId());
}
void Parser::walkProject(AstQuery& ast) {
diff --git a/src/mongo/db/exec/sbe/parser/sbe_parser_test.cpp b/src/mongo/db/exec/sbe/parser/sbe_parser_test.cpp
index 80ed5112dc9..29532022114 100644
--- a/src/mongo/db/exec/sbe/parser/sbe_parser_test.cpp
+++ b/src/mongo/db/exec/sbe/parser/sbe_parser_test.cpp
@@ -123,8 +123,7 @@ protected:
boost::none,
boost::none,
nullptr,
- planNodeId,
- nullptr),
+ planNodeId),
// IXSCAN with 'seekKeySlotLow' / 'seekKeySlotHigh' present.
sbe::makeS<sbe::IndexScanStage>(fakeUuid,
"_id",
@@ -137,8 +136,7 @@ protected:
sbe::value::SlotId{1},
sbe::value::SlotId{2},
nullptr,
- planNodeId,
- nullptr),
+ planNodeId),
// IXSCAN with 'recordIdSlot' missing and 'seekKeySlotLow' present.
sbe::makeS<sbe::IndexScanStage>(fakeUuid,
"_id",
@@ -151,8 +149,7 @@ protected:
sbe::value::SlotId{2},
boost::none,
nullptr,
- planNodeId,
- nullptr),
+ planNodeId),
// IXSCAN with all slots except seek keys present.
sbe::makeS<sbe::IndexScanStage>(fakeUuid,
"_id",
@@ -165,8 +162,7 @@ protected:
boost::none,
boost::none,
nullptr,
- planNodeId,
- nullptr),
+ planNodeId),
// IXSCAN with all slots present.
sbe::makeS<sbe::IndexScanStage>(fakeUuid,
"_id",
@@ -179,8 +175,7 @@ protected:
sbe::value::SlotId{4},
sbe::value::SlotId{5},
nullptr,
- planNodeId,
- nullptr),
+ planNodeId),
// SCAN with 'recordSlot' and 'recordIdSlot' slots only.
sbe::makeS<sbe::ScanStage>(fakeUuid,
sbe::value::SlotId{1},
@@ -196,7 +191,7 @@ protected:
true /* forward */,
nullptr,
planNodeId,
- sbe::ScanCallbacks({})),
+ sbe::ScanCallbacks{}),
// SCAN with 'recordSlot', 'recordIdSlot' and 'seekKeySlot' slots.
sbe::makeS<sbe::ScanStage>(fakeUuid,
sbe::value::SlotId{1},
@@ -212,7 +207,7 @@ protected:
true /* forward */,
nullptr,
planNodeId,
- sbe::ScanCallbacks({})),
+ sbe::ScanCallbacks{}),
// SCAN with all slots present.
sbe::makeS<sbe::ScanStage>(
fakeUuid,
@@ -229,7 +224,7 @@ protected:
true /* forward */,
nullptr,
planNodeId,
- sbe::ScanCallbacks({})),
+ sbe::ScanCallbacks{}),
// PSCAN with both 'recordSlot' and 'recordIdSlot' slots present.
sbe::makeS<sbe::ParallelScanStage>(fakeUuid,
sbe::value::SlotId{1},
@@ -242,7 +237,7 @@ protected:
sbe::makeSV(1, 2),
nullptr,
planNodeId,
- sbe::ScanCallbacks({})),
+ sbe::ScanCallbacks{}),
// PSCAN with 'recordSlot' missing.
sbe::makeS<sbe::ParallelScanStage>(fakeUuid,
sbe::value::SlotId{1},
@@ -255,7 +250,7 @@ protected:
sbe::makeSV(1, 2),
nullptr,
planNodeId,
- sbe::ScanCallbacks({})),
+ sbe::ScanCallbacks{}),
// PSCAN with all slots.
sbe::makeS<sbe::ParallelScanStage>(fakeUuid,
sbe::value::SlotId{1},
@@ -268,7 +263,7 @@ protected:
sbe::makeSV(1, 2),
nullptr,
planNodeId,
- sbe::ScanCallbacks({})),
+ sbe::ScanCallbacks{}),
// COSCAN
sbe::makeS<sbe::CoScanStage>(planNodeId),
// PROJECT
diff --git a/src/mongo/db/exec/sbe/stages/collection_helpers.cpp b/src/mongo/db/exec/sbe/stages/collection_helpers.cpp
index 41b6d8b4075..01139f3c5c5 100644
--- a/src/mongo/db/exec/sbe/stages/collection_helpers.cpp
+++ b/src/mongo/db/exec/sbe/stages/collection_helpers.cpp
@@ -35,59 +35,41 @@
namespace mongo::sbe {
-std::pair<NamespaceString, uint64_t> acquireCollection(
- OperationContext* opCtx,
- CollectionUUID collUuid,
- const LockAcquisitionCallback& lockAcquisitionCallback,
- boost::optional<AutoGetCollectionForReadMaybeLockFree>& coll) {
- tassert(5071012, "cannot restore 'coll' if already held", !coll.has_value());
- // The caller is expected to hold the appropriate db_raii object to give us a consistent view of
- // the catalog, so the UUID must still exist.
- auto collName = CollectionCatalog::get(opCtx)->lookupNSSByUUID(opCtx, collUuid);
- tassert(5071000,
- str::stream() << "Collection uuid " << collUuid << " does not exist",
- collName.has_value());
+std::tuple<CollectionPtr, NamespaceString, uint64_t> acquireCollection(OperationContext* opCtx,
+ CollectionUUID collUuid) {
+ // The collection is either locked at a higher level or a snapshot of the catalog (consistent
+ // with the storage engine snapshot from which we are reading) has been stashed on the
+ // 'OperationContext'. Either way, this means that the UUID must still exist in our view of the
+ // collection catalog.
+ CollectionPtr collPtr = CollectionCatalog::get(opCtx)->lookupCollectionByUUID(opCtx, collUuid);
+ tassert(5071000, str::stream() << "Collection uuid " << collUuid << " does not exist", collPtr);
- coll.emplace(opCtx, NamespaceStringOrUUID{collName->db().toString(), collUuid});
- if (lockAcquisitionCallback) {
- lockAcquisitionCallback(opCtx, *coll);
- }
-
- tassert(4938501,
- str::stream() << "expected CollectionPtr for: " << *collName,
- static_cast<bool>(coll->getCollection()));
-
- return {*collName, CollectionCatalog::get(opCtx)->getEpoch()};
+ return std::make_tuple(
+ std::move(collPtr), collPtr->ns(), CollectionCatalog::get(opCtx)->getEpoch());
}
-void restoreCollection(OperationContext* opCtx,
- const NamespaceString& collName,
- CollectionUUID collUuid,
- uint64_t catalogEpoch,
- const LockAcquisitionCallback& lockAcquisitionCallback,
- boost::optional<AutoGetCollectionForReadMaybeLockFree>& coll) {
- tassert(5071011, "cannot restore 'coll' if already held", !coll.has_value());
- // Reaquire the AutoGet object, looking up in the catalog by UUID. If the collection has been
- // dropped, then this UUID lookup will fail, throwing an exception and terminating the query.
- NamespaceStringOrUUID nssOrUuid{collName.db().toString(), collUuid};
- try {
- coll.emplace(opCtx, nssOrUuid);
- } catch (ExceptionFor<ErrorCodes::NamespaceNotFound>& ex) {
- ex.addContext(str::stream() << "collection dropped: '" << collName << "'");
- throw;
+CollectionPtr restoreCollection(OperationContext* opCtx,
+ const NamespaceString& collName,
+ CollectionUUID collUuid,
+ uint64_t catalogEpoch) {
+ // Re-lookup the collection pointer, by UUID. If the collection has been dropped, then this UUID
+ // lookup will result in a null pointer. If the collection has been renamed, then the resulting
+ // collection object should have a different name from the original 'collName'. In either
+ // scenario, we throw a 'QueryPlanKilled' error and terminate the query.
+ CollectionPtr collPtr = CollectionCatalog::get(opCtx)->lookupCollectionByUUID(opCtx, collUuid);
+ if (!collPtr) {
+ PlanYieldPolicy::throwCollectionDroppedError(collUuid);
}
- if (collName != coll->getNss()) {
- PlanYieldPolicy::throwCollectionRenamedError(collName, coll->getNss(), collUuid);
+ if (collName != collPtr->ns()) {
+ PlanYieldPolicy::throwCollectionRenamedError(collName, collPtr->ns(), collUuid);
}
uassert(ErrorCodes::QueryPlanKilled,
"the catalog was closed and reopened",
CollectionCatalog::get(opCtx)->getEpoch() == catalogEpoch);
- if (lockAcquisitionCallback) {
- lockAcquisitionCallback(opCtx, *coll);
- }
+ return collPtr;
}
} // namespace mongo::sbe
diff --git a/src/mongo/db/exec/sbe/stages/collection_helpers.h b/src/mongo/db/exec/sbe/stages/collection_helpers.h
index 65ea730c9b5..ed446c8aaee 100644
--- a/src/mongo/db/exec/sbe/stages/collection_helpers.h
+++ b/src/mongo/db/exec/sbe/stages/collection_helpers.h
@@ -37,14 +37,6 @@
namespace mongo::sbe {
/**
- * A callback which gets called whenever a stage which accesses the storage engine (e.g. "scan",
- * "seek", or "ixscan") obtains or re-obtains its AutoGet*.
- */
-using LockAcquisitionCallback =
- std::function<void(OperationContext*, const AutoGetCollectionForReadMaybeLockFree&)>;
-
-
-/**
* A callback which gets called whenever a SCAN stage asks an underlying index scan for a result.
*/
using IndexKeyConsistencyCheckCallback = std::function<bool(OperationContext* opCtx,
@@ -63,29 +55,25 @@ using IndexKeyCorruptionCheckCallback =
const NamespaceString& nss)>;
/**
- * Given a collection UUID, acquires 'coll', invokes the provided 'lockAcquisiionCallback', and
- * returns the collection's name as well as the current catalog epoch.
+ * Given a collection UUID, looks up the UUID in the catalog and returns a pointer to the
+ * collection, the collection's name, and the current catalog epoch.
*
* This is intended for use during the preparation of an SBE plan. The caller must hold the
* appropriate db_raii object in order to ensure that SBE plan preparation sees a consistent view of
* the catalog.
*/
-std::pair<NamespaceString, uint64_t> acquireCollection(
- OperationContext* opCtx,
- CollectionUUID collUuid,
- const LockAcquisitionCallback& lockAcquisitionCallback,
- boost::optional<AutoGetCollectionForReadMaybeLockFree>& coll);
+std::tuple<CollectionPtr, NamespaceString, uint64_t> acquireCollection(OperationContext* opCtx,
+ CollectionUUID collUuid);
/**
- * Re-acquires 'coll', intended for use during SBE yield recovery or when a closed SBE plan is
- * re-opened. In addition to acquiring 'coll', throws a UserException if the collection has been
- * dropped or renamed, or if the catalog has been closed and re-opened. SBE query execution
- * currently cannot survive such events if they occur during a yield or between getMores.
+ * Re-acquires a pointer to the collection, intended for use during SBE yield recovery or when a
+ * closed SBE plan is re-opened. In addition to acquiring the collection pointer, throws a
+ * UserException if the collection has been dropped or renamed, or if the catalog has been closed
+ * and re-opened. SBE query execution currently cannot survive such events if they occur during a
+ * yield or between getMores.
*/
-void restoreCollection(OperationContext* opCtx,
- const NamespaceString& collName,
- CollectionUUID collUuid,
- uint64_t catalogEpoch,
- const LockAcquisitionCallback& lockAcquisitionCallback,
- boost::optional<AutoGetCollectionForReadMaybeLockFree>& coll);
+CollectionPtr restoreCollection(OperationContext* opCtx,
+ const NamespaceString& collName,
+ CollectionUUID collUuid,
+ uint64_t catalogEpoch);
} // namespace mongo::sbe
diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.cpp b/src/mongo/db/exec/sbe/stages/ix_scan.cpp
index a5e679b65ce..63cea42e018 100644
--- a/src/mongo/db/exec/sbe/stages/ix_scan.cpp
+++ b/src/mongo/db/exec/sbe/stages/ix_scan.cpp
@@ -49,8 +49,7 @@ IndexScanStage::IndexScanStage(CollectionUUID collUuid,
boost::optional<value::SlotId> seekKeySlotLow,
boost::optional<value::SlotId> seekKeySlotHigh,
PlanYieldPolicy* yieldPolicy,
- PlanNodeId nodeId,
- LockAcquisitionCallback lockAcquisitionCallback)
+ PlanNodeId nodeId)
: PlanStage(seekKeySlotLow ? "ixseek"_sd : "ixscan"_sd, yieldPolicy, nodeId),
_collUuid(collUuid),
_indexName(indexName),
@@ -61,8 +60,7 @@ IndexScanStage::IndexScanStage(CollectionUUID collUuid,
_indexKeysToInclude(indexKeysToInclude),
_vars(std::move(vars)),
_seekKeySlotLow(seekKeySlotLow),
- _seekKeySlotHigh(seekKeySlotHigh),
- _lockAcquisitionCallback(std::move(lockAcquisitionCallback)) {
+ _seekKeySlotHigh(seekKeySlotHigh) {
// The valid state is when both boundaries, or none is set, or only low key is set.
invariant((_seekKeySlotLow && _seekKeySlotHigh) || (!_seekKeySlotLow && !_seekKeySlotHigh) ||
(_seekKeySlotLow && !_seekKeySlotHigh));
@@ -82,8 +80,7 @@ std::unique_ptr<PlanStage> IndexScanStage::clone() const {
_seekKeySlotLow,
_seekKeySlotHigh,
_yieldPolicy,
- _commonStats.nodeId,
- _lockAcquisitionCallback);
+ _commonStats.nodeId);
}
void IndexScanStage::prepare(CompileCtx& ctx) {
@@ -114,10 +111,10 @@ void IndexScanStage::prepare(CompileCtx& ctx) {
}
_seekKeyLowHolder = std::make_unique<value::OwnedValueAccessor>();
- std::tie(_collName, _catalogEpoch) =
- acquireCollection(_opCtx, _collUuid, _lockAcquisitionCallback, _coll);
+ tassert(5709602, "'_coll' should not be initialized prior to 'acquireCollection()'", !_coll);
+ std::tie(_coll, _collName, _catalogEpoch) = acquireCollection(_opCtx, _collUuid);
- auto indexCatalog = _coll->getCollection()->getIndexCatalog();
+ auto indexCatalog = _coll->getIndexCatalog();
auto indexDesc = indexCatalog->findIndexByName(_opCtx, _indexName);
tassert(4938500,
str::stream() << "could not find index named '" << _indexName << "' in collection '"
@@ -189,7 +186,7 @@ void IndexScanStage::doSaveState() {
}
void IndexScanStage::restoreCollectionAndIndex() {
- restoreCollection(_opCtx, _collName, _collUuid, _catalogEpoch, _lockAcquisitionCallback, _coll);
+ _coll = restoreCollection(_opCtx, _collName, _collUuid, _catalogEpoch);
auto indexCatalogEntry = _weakIndexCatalogEntry.lock();
uassert(ErrorCodes::QueryPlanKilled,
str::stream() << "query plan killed :: index '" << _indexName << "' dropped",
@@ -248,7 +245,7 @@ void IndexScanStage::open(bool reOpen) {
if (_open) {
tassert(5071006, "reopened IndexScanStage but reOpen=false", reOpen);
- tassert(5071007, "IndexScanStage is open but _coll is not held", _coll);
+ tassert(5071007, "IndexScanStage is open but _coll is null", _coll);
tassert(5071008, "IndexScanStage is open but don't have _cursor", _cursor);
} else {
tassert(5071009, "first open to IndexScanStage but reOpen=true", !reOpen);
diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.h b/src/mongo/db/exec/sbe/stages/ix_scan.h
index 00e3dd16bfb..4d52c7d7881 100644
--- a/src/mongo/db/exec/sbe/stages/ix_scan.h
+++ b/src/mongo/db/exec/sbe/stages/ix_scan.h
@@ -71,8 +71,7 @@ public:
boost::optional<value::SlotId> seekKeySlotLow,
boost::optional<value::SlotId> seekKeySlotHigh,
PlanYieldPolicy* yieldPolicy,
- PlanNodeId nodeId,
- LockAcquisitionCallback lockAcquisitionCallback);
+ PlanNodeId nodeId);
std::unique_ptr<PlanStage> clone() const final;
@@ -119,7 +118,7 @@ private:
NamespaceString _collName;
uint64_t _catalogEpoch;
- LockAcquisitionCallback _lockAcquisitionCallback;
+ CollectionPtr _coll;
std::unique_ptr<value::OwnedValueAccessor> _recordAccessor;
std::unique_ptr<value::OwnedValueAccessor> _recordIdAccessor;
@@ -139,7 +138,6 @@ private:
std::unique_ptr<SortedDataInterface::Cursor> _cursor;
std::weak_ptr<const IndexCatalogEntry> _weakIndexCatalogEntry;
boost::optional<Ordering> _ordering{boost::none};
- boost::optional<AutoGetCollectionForReadMaybeLockFree> _coll;
boost::optional<KeyStringEntry> _nextRecord;
// This buffer stores values that are projected out of the index entry. Values in the
diff --git a/src/mongo/db/exec/sbe/stages/scan.cpp b/src/mongo/db/exec/sbe/stages/scan.cpp
index 61f6010a458..f5e282e7b5e 100644
--- a/src/mongo/db/exec/sbe/stages/scan.cpp
+++ b/src/mongo/db/exec/sbe/stages/scan.cpp
@@ -136,8 +136,8 @@ void ScanStage::prepare(CompileCtx& ctx) {
_oplogTsAccessor = ctx.getRuntimeEnvAccessor(*_oplogTsSlot);
}
- std::tie(_collName, _catalogEpoch) =
- acquireCollection(_opCtx, _collUuid, _scanCallbacks.lockAcquisitionCallback, _coll);
+ tassert(5709600, "'_coll' should not be initialized prior to 'acquireCollection()'", !_coll);
+ std::tie(_coll, _collName, _catalogEpoch) = acquireCollection(_opCtx, _collUuid);
}
value::SlotAccessor* ScanStage::getAccessor(CompileCtx& ctx, value::SlotId slot) {
@@ -189,8 +189,7 @@ void ScanStage::doRestoreState() {
return;
}
- restoreCollection(
- _opCtx, _collName, _collUuid, _catalogEpoch, _scanCallbacks.lockAcquisitionCallback, _coll);
+ _coll = restoreCollection(_opCtx, _collName, _collUuid, _catalogEpoch);
if (_cursor) {
const bool couldRestore = _cursor->restore();
@@ -229,7 +228,7 @@ void ScanStage::open(bool reOpen) {
if (_open) {
tassert(5071001, "reopened ScanStage but reOpen=false", reOpen);
- tassert(5071002, "ScanStage is open but _coll is not held", _coll);
+ tassert(5071002, "ScanStage is open but _coll is not null", _coll);
tassert(5071003, "ScanStage is open but don't have _cursor", _cursor);
} else {
tassert(5071004, "first open to ScanStage but reOpen=true", !reOpen);
@@ -237,20 +236,15 @@ void ScanStage::open(bool reOpen) {
// We're being opened after 'close()'. We need to re-acquire '_coll' in this case and
// make some validity checks (the collection has not been dropped, renamed, etc.).
tassert(5071005, "ScanStage is not open but have _cursor", !_cursor);
- restoreCollection(_opCtx,
- _collName,
- _collUuid,
- _catalogEpoch,
- _scanCallbacks.lockAcquisitionCallback,
- _coll);
+ _coll = restoreCollection(_opCtx, _collName, _collUuid, _catalogEpoch);
}
}
if (_scanCallbacks.scanOpenCallback) {
- _scanCallbacks.scanOpenCallback(_opCtx, _coll->getCollection(), reOpen);
+ _scanCallbacks.scanOpenCallback(_opCtx, _coll, reOpen);
}
- if (const auto& collection = _coll->getCollection()) {
+ if (_coll) {
if (_seekKeyAccessor) {
auto [tag, val] = _seekKeyAccessor->getViewOfValue();
const auto msgTag = tag;
@@ -262,7 +256,7 @@ void ScanStage::open(bool reOpen) {
}
if (!_cursor || !_seekKeyAccessor) {
- _cursor = collection->getCursor(_opCtx, _forward);
+ _cursor = _coll->getCursor(_opCtx, _forward);
}
} else {
_cursor.reset();
@@ -309,12 +303,8 @@ PlanState ScanStage::getNext() {
// Return EOF if the index key is found to be inconsistent.
if (_scanCallbacks.indexKeyConsistencyCheckCallBack &&
- !_scanCallbacks.indexKeyConsistencyCheckCallBack(_opCtx,
- _snapshotIdAccessor,
- _indexIdAccessor,
- _indexKeyAccessor,
- _coll->getCollection(),
- *nextRecord)) {
+ !_scanCallbacks.indexKeyConsistencyCheckCallBack(
+ _opCtx, _snapshotIdAccessor, _indexIdAccessor, _indexKeyAccessor, _coll, *nextRecord)) {
return trackPlanState(PlanState::IS_EOF);
}
@@ -594,7 +584,8 @@ void ParallelScanStage::prepare(CompileCtx& ctx) {
_indexKeyPatternAccessor = ctx.getAccessor(*_indexKeyPatternSlot);
}
- std::tie(_collName, _catalogEpoch) = acquireCollection(_opCtx, _collUuid, nullptr, _coll);
+ tassert(5709601, "'_coll' should not be initialized prior to 'acquireCollection()'", !_coll);
+ std::tie(_coll, _collName, _catalogEpoch) = acquireCollection(_opCtx, _collUuid);
}
value::SlotAccessor* ParallelScanStage::getAccessor(CompileCtx& ctx, value::SlotId slot) {
@@ -642,7 +633,7 @@ void ParallelScanStage::doRestoreState() {
return;
}
- restoreCollection(_opCtx, _collName, _collUuid, _catalogEpoch, nullptr, _coll);
+ _coll = restoreCollection(_opCtx, _collName, _collUuid, _catalogEpoch);
if (_cursor) {
const bool couldRestore = _cursor->restore();
@@ -675,23 +666,21 @@ void ParallelScanStage::open(bool reOpen) {
// we're being opened after 'close()'. we need to re-acquire '_coll' in this case and
// make some validity checks (the collection has not been dropped, renamed, etc.).
tassert(5071013, "ParallelScanStage is not open but have _cursor", !_cursor);
- restoreCollection(_opCtx, _collName, _collUuid, _catalogEpoch, nullptr, _coll);
+ _coll = restoreCollection(_opCtx, _collName, _collUuid, _catalogEpoch);
}
- const auto& collection = _coll->getCollection();
-
- if (collection) {
+ if (_coll) {
{
stdx::unique_lock lock(_state->mutex);
if (_state->ranges.empty()) {
- auto ranges = collection->getRecordStore()->numRecords(_opCtx) / 10240;
+ auto ranges = _coll->getRecordStore()->numRecords(_opCtx) / 10240;
if (ranges < 2) {
_state->ranges.emplace_back(Range{RecordId{}, RecordId{}});
} else {
if (ranges > 1024) {
ranges = 1024;
}
- auto randomCursor = collection->getRecordStore()->getRandomCursor(_opCtx);
+ auto randomCursor = _coll->getRecordStore()->getRandomCursor(_opCtx);
invariant(randomCursor);
std::set<RecordId> rids;
while (ranges--) {
@@ -710,7 +699,7 @@ void ParallelScanStage::open(bool reOpen) {
}
}
- _cursor = collection->getCursor(_opCtx);
+ _cursor = _coll->getCursor(_opCtx);
}
_open = true;
@@ -775,7 +764,7 @@ PlanState ParallelScanStage::getNext() {
_snapshotIdAccessor,
_indexIdAccessor,
_indexKeyAccessor,
- _coll->getCollection(),
+ _coll,
*nextRecord)) {
return trackPlanState(PlanState::IS_EOF);
}
diff --git a/src/mongo/db/exec/sbe/stages/scan.h b/src/mongo/db/exec/sbe/stages/scan.h
index dca4da1c496..3180c337af8 100644
--- a/src/mongo/db/exec/sbe/stages/scan.h
+++ b/src/mongo/db/exec/sbe/stages/scan.h
@@ -40,16 +40,13 @@ namespace sbe {
using ScanOpenCallback = std::function<void(OperationContext*, const CollectionPtr&, bool)>;
struct ScanCallbacks {
- ScanCallbacks(LockAcquisitionCallback lockAcquisition,
- IndexKeyCorruptionCheckCallback indexKeyCorruptionCheck = {},
+ ScanCallbacks(IndexKeyCorruptionCheckCallback indexKeyCorruptionCheck = {},
IndexKeyConsistencyCheckCallback indexKeyConsistencyCheck = {},
ScanOpenCallback scanOpen = {})
- : lockAcquisitionCallback(std::move(lockAcquisition)),
- indexKeyCorruptionCheckCallback(std::move(indexKeyCorruptionCheck)),
+ : indexKeyCorruptionCheckCallback(std::move(indexKeyCorruptionCheck)),
indexKeyConsistencyCheckCallBack(std::move(indexKeyConsistencyCheck)),
scanOpenCallback(std::move(scanOpen)) {}
- LockAcquisitionCallback lockAcquisitionCallback;
IndexKeyCorruptionCheckCallback indexKeyCorruptionCheckCallback;
IndexKeyConsistencyCheckCallback indexKeyConsistencyCheckCallBack;
ScanOpenCallback scanOpenCallback;
@@ -112,6 +109,8 @@ private:
NamespaceString _collName;
uint64_t _catalogEpoch;
+ CollectionPtr _coll;
+
// If provided, used during a trial run to accumulate certain execution stats. Once the trial
// run is complete, this pointer is reset to nullptr.
TrialRunTracker* _tracker{nullptr};
@@ -133,7 +132,6 @@ private:
bool _open{false};
std::unique_ptr<SeekableRecordCursor> _cursor;
- boost::optional<AutoGetCollectionForReadMaybeLockFree> _coll;
RecordId _key;
bool _firstGetNext{false};
@@ -219,6 +217,8 @@ private:
NamespaceString _collName;
uint64_t _catalogEpoch;
+ CollectionPtr _coll;
+
std::shared_ptr<ParallelState> _state;
const ScanCallbacks _scanCallbacks;
@@ -239,7 +239,6 @@ private:
bool _open{false};
std::unique_ptr<SeekableRecordCursor> _cursor;
- boost::optional<AutoGetCollectionForReadMaybeLockFree> _coll;
};
} // namespace sbe
} // namespace mongo
diff --git a/src/mongo/db/query/classic_stage_builder_test.cpp b/src/mongo/db/query/classic_stage_builder_test.cpp
index 4e8f87140b7..407cd67e426 100644
--- a/src/mongo/db/query/classic_stage_builder_test.cpp
+++ b/src/mongo/db/query/classic_stage_builder_test.cpp
@@ -59,7 +59,7 @@ public:
* Converts a 'QuerySolutionNode' to a 'QuerySolution'.
*/
std::unique_ptr<QuerySolution> makeQuerySolution(std::unique_ptr<QuerySolutionNode> root) {
- auto querySoln = std::make_unique<QuerySolution>(QueryPlannerParams::Options::DEFAULT);
+ auto querySoln = std::make_unique<QuerySolution>();
querySoln->setRoot(std::move(root));
return querySoln;
}
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index 0e22091419b..383a872e180 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -568,7 +568,7 @@ public:
"namespace"_attr = _cq->ns(),
"canonicalQuery"_attr = redact(_cq->toStringShort()));
- auto solution = std::make_unique<QuerySolution>(_plannerOptions);
+ auto solution = std::make_unique<QuerySolution>();
solution->setRoot(std::make_unique<EofNode>());
auto root = buildExecutableTree(*solution);
@@ -975,7 +975,7 @@ protected:
}
}
- auto soln = std::make_unique<QuerySolution>(plannerParams->options);
+ auto soln = std::make_unique<QuerySolution>();
soln->setRoot(std::move(root));
auto execTree = buildExecutableTree(*soln);
diff --git a/src/mongo/db/query/plan_cache_test.cpp b/src/mongo/db/query/plan_cache_test.cpp
index 230e8e162aa..07f98a84967 100644
--- a/src/mongo/db/query/plan_cache_test.cpp
+++ b/src/mongo/db/query/plan_cache_test.cpp
@@ -316,7 +316,7 @@ std::pair<CoreIndexInfo, std::unique_ptr<WildcardProjection>> makeWildcardUpdate
*/
struct GenerateQuerySolution {
QuerySolution* operator()() const {
- unique_ptr<QuerySolution> qs(new QuerySolution(QueryPlannerParams::Options::DEFAULT));
+ auto qs = std::make_unique<QuerySolution>();
qs->cacheData.reset(new SolutionCacheData());
qs->cacheData->solnType = SolutionCacheData::COLLSCAN_SOLN;
qs->cacheData->tree.reset(new PlanCacheIndexTree());
@@ -379,8 +379,7 @@ void assertShouldNotCacheQuery(const char* queryStr) {
}
std::unique_ptr<QuerySolution> getQuerySolutionForCaching() {
- std::unique_ptr<QuerySolution> qs =
- std::make_unique<QuerySolution>(QueryPlannerParams::Options::DEFAULT);
+ std::unique_ptr<QuerySolution> qs = std::make_unique<QuerySolution>();
qs->cacheData = std::make_unique<SolutionCacheData>();
qs->cacheData->tree = std::make_unique<PlanCacheIndexTree>();
return qs;
@@ -1176,7 +1175,7 @@ protected:
// Create a CachedSolution the long way..
// QuerySolution -> PlanCacheEntry -> CachedSolution
- QuerySolution qs{QueryPlannerParams::Options::DEFAULT};
+ QuerySolution qs{};
qs.cacheData = soln.cacheData->clone();
std::vector<QuerySolution*> solutions;
solutions.push_back(&qs);
diff --git a/src/mongo/db/query/planner_analysis.cpp b/src/mongo/db/query/planner_analysis.cpp
index 71892e12b51..dc943fd771c 100644
--- a/src/mongo/db/query/planner_analysis.cpp
+++ b/src/mongo/db/query/planner_analysis.cpp
@@ -913,7 +913,7 @@ std::unique_ptr<QuerySolution> QueryPlannerAnalysis::analyzeDataAccess(
const CanonicalQuery& query,
const QueryPlannerParams& params,
std::unique_ptr<QuerySolutionNode> solnRoot) {
- auto soln = std::make_unique<QuerySolution>(params.options);
+ auto soln = std::make_unique<QuerySolution>();
soln->indexFilterApplied = params.indexFiltersApplied;
solnRoot->computeProperties();
diff --git a/src/mongo/db/query/query_planner.cpp b/src/mongo/db/query/query_planner.cpp
index ab803e03254..0d13c318193 100644
--- a/src/mongo/db/query/query_planner.cpp
+++ b/src/mongo/db/query/query_planner.cpp
@@ -179,9 +179,6 @@ string optionString(size_t options) {
case QueryPlannerParams::ENUMERATE_OR_CHILDREN_LOCKSTEP:
ss << "ENUMERATE_OR_CHILDREN_LOCKSTEP ";
break;
- case QueryPlannerParams::OMIT_REPL_STATE_PERMITS_READS_CHECK:
- ss << "OMIT_REPL_STATE_PERMITS_READS_CHECK";
- break;
case QueryPlannerParams::RETURN_OWNED_DATA:
ss << "RETURN_OWNED_DATA ";
break;
diff --git a/src/mongo/db/query/query_planner_params.h b/src/mongo/db/query/query_planner_params.h
index 5278c94f8e9..deb452eacf6 100644
--- a/src/mongo/db/query/query_planner_params.h
+++ b/src/mongo/db/query/query_planner_params.h
@@ -120,16 +120,9 @@ struct QueryPlannerParams {
// $or use the same fields and have the same indexes available, as in this example.
ENUMERATE_OR_CHILDREN_LOCKSTEP = 1 << 12,
- // Instructs the planner to produce a plan which will *not* check at runtime that the node's
- // replica set member state allows reads. Typically, replica set members will only serve
- // reads to clients if thet are in parimary or secondary state. Client reads are disallowed
- // in other states, e.g. during initial sync. Internal operations, on the other hand, can
- // use this flag to exempt themselves from this repl set note state requirement.
- OMIT_REPL_STATE_PERMITS_READS_CHECK = 1 << 13,
-
// Ensure that any plan generated returns data that is "owned." That is, all BSONObjs are
// in an "owned" state and are not pointing to data that belongs to the storage engine.
- RETURN_OWNED_DATA = 1 << 14,
+ RETURN_OWNED_DATA = 1 << 13,
};
// See Options enum above.
diff --git a/src/mongo/db/query/query_solution.h b/src/mongo/db/query/query_solution.h
index e950d34db67..9d0c8f5f9bf 100644
--- a/src/mongo/db/query/query_solution.h
+++ b/src/mongo/db/query/query_solution.h
@@ -326,7 +326,7 @@ struct QuerySolutionNodeWithSortSet : public QuerySolutionNode {
*/
class QuerySolution {
public:
- explicit QuerySolution(size_t plannerOptions) : plannerOptions(plannerOptions) {}
+ QuerySolution() = default;
/**
* Return true if this solution tree contains a node of the given 'type'.
@@ -362,18 +362,6 @@ public:
*/
void setRoot(std::unique_ptr<QuerySolutionNode> root);
- /**
- * Returns true if the execution plan which is constructed from this QuerySolution should check
- * that the node is eligible to serve reads prior to actually performing any reads.
- */
- bool shouldCheckCanServeReads() const {
- return !(plannerOptions & QueryPlannerParams::OMIT_REPL_STATE_PERMITS_READS_CHECK);
- }
-
- // A bit vector of flags which clients to the QueryPlanner pass to control which plans are
- // generated and their properties.
- const size_t plannerOptions;
-
// There are two known scenarios in which a query solution might potentially block:
//
// Sort stage:
diff --git a/src/mongo/db/query/query_solution_test.cpp b/src/mongo/db/query/query_solution_test.cpp
index 71470e22c50..8763b208fcd 100644
--- a/src/mongo/db/query/query_solution_test.cpp
+++ b/src/mongo/db/query/query_solution_test.cpp
@@ -1061,7 +1061,7 @@ TEST(QuerySolutionTest, NodeIdsAssignedInPostOrderFashionStartingFromOne) {
ASSERT_EQ(orNode->children[0]->nodeId(), 0u);
ASSERT_EQ(orNode->children[1]->nodeId(), 0u);
- auto querySolution = std::make_unique<QuerySolution>(QueryPlannerParams::Options::DEFAULT);
+ auto querySolution = std::make_unique<QuerySolution>();
querySolution->setRoot(std::move(orNode));
auto root = querySolution->root();
diff --git a/src/mongo/db/query/sbe_stage_builder.cpp b/src/mongo/db/query/sbe_stage_builder.cpp
index b97d1c3a340..f2f53662346 100644
--- a/src/mongo/db/query/sbe_stage_builder.cpp
+++ b/src/mongo/db/query/sbe_stage_builder.cpp
@@ -457,17 +457,6 @@ const QuerySolutionNode* getLoneNodeByType(const QuerySolutionNode* root, StageT
return result;
}
-sbe::LockAcquisitionCallback makeLockAcquisitionCallback(bool checkNodeCanServeReads) {
- if (!checkNodeCanServeReads) {
- return {};
- }
-
- return [](OperationContext* opCtx, const AutoGetCollectionForReadMaybeLockFree& coll) {
- uassertStatusOK(repl::ReplicationCoordinator::get(opCtx)->checkCanServeReadsFor(
- opCtx, coll.getNss(), true));
- };
-}
-
/**
* Callback function that logs a message and uasserts if it detects a corrupt index key. An index
* key is considered corrupt if it has no corresponding Record.
@@ -649,7 +638,6 @@ SlotBasedStageBuilder::SlotBasedStageBuilder(OperationContext* opCtx,
_yieldPolicy(yieldPolicy),
_data(makeRuntimeEnvironment(_cq, _opCtx, &_slotIdGenerator)),
_shardFiltererFactory(shardFiltererFactory),
- _lockAcquisitionCallback(makeLockAcquisitionCallback(solution.shouldCheckCanServeReads())),
_state(_opCtx,
_data.env,
_cq.getExpCtxRaw()->variables,
@@ -708,12 +696,8 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> SlotBasedStageBuilder
auto csn = static_cast<const CollectionScanNode*>(root);
- auto [stage, outputs] = generateCollScan(_state,
- _collection,
- csn,
- _yieldPolicy,
- reqs.getIsTailableCollScanResumeBranch(),
- _lockAcquisitionCallback);
+ auto [stage, outputs] = generateCollScan(
+ _state, _collection, csn, _yieldPolicy, reqs.getIsTailableCollScanResumeBranch());
if (reqs.has(kReturnKey)) {
// Assign the 'returnKeySlot' to be the empty object.
@@ -825,14 +809,8 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> SlotBasedStageBuilder
iamMap = nullptr;
}
- auto [stage, outputs] = generateIndexScan(_state,
- _collection,
- ixn,
- indexKeyBitset,
- _yieldPolicy,
- _lockAcquisitionCallback,
- iamMap,
- reqs.has(kIndexKeyPattern));
+ auto [stage, outputs] = generateIndexScan(
+ _state, _collection, ixn, indexKeyBitset, _yieldPolicy, iamMap, reqs.has(kIndexKeyPattern));
if (reqs.has(PlanStageSlots::kReturnKey)) {
std::vector<std::unique_ptr<sbe::EExpression>> mkObjArgs;
@@ -888,7 +866,6 @@ SlotBasedStageBuilder::makeLoopJoinForFetch(std::unique_ptr<sbe::PlanStage> inpu
using namespace std::placeholders;
sbe::ScanCallbacks callbacks(
- _lockAcquisitionCallback,
indexKeyCorruptionCheckCallback,
std::bind(indexKeyConsistencyCheckCallback, _1, std::move(iamMap), _2, _3, _4, _5, _6));
// Scan the collection in the range [seekKeySlot, Inf).
diff --git a/src/mongo/db/query/sbe_stage_builder.h b/src/mongo/db/query/sbe_stage_builder.h
index 49534b02f9f..81335f937e0 100644
--- a/src/mongo/db/query/sbe_stage_builder.h
+++ b/src/mongo/db/query/sbe_stage_builder.h
@@ -381,10 +381,6 @@ private:
// A factory to construct shard filters.
ShardFiltererFactoryInterface* _shardFiltererFactory;
- // A callback that should be installed on "scan" and "ixscan" nodes. It will get invoked when
- // these data access stages acquire their AutoGet*.
- const sbe::LockAcquisitionCallback _lockAcquisitionCallback;
-
// Common parameters to SBE stage builder functions.
StageBuilderState _state;
};
diff --git a/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp b/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp
index bd045c33801..740f5e71c36 100644
--- a/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp
@@ -141,8 +141,7 @@ std::unique_ptr<sbe::PlanStage> buildResumeFromRecordIdSubtree(
std::unique_ptr<sbe::EExpression> seekRecordIdExpression,
PlanYieldPolicy* yieldPolicy,
bool isTailableResumeBranch,
- bool resumeAfterRecordId,
- sbe::LockAcquisitionCallback lockAcquisitionCallback) {
+ bool resumeAfterRecordId) {
invariant(seekRecordIdExpression);
const auto forward = csn->direction == CollectionScanParams::FORWARD;
@@ -174,7 +173,7 @@ std::unique_ptr<sbe::PlanStage> buildResumeFromRecordIdSubtree(
forward,
yieldPolicy,
csn->nodeId(),
- lockAcquisitionCallback),
+ sbe::ScanCallbacks{}),
sbe::makeSV(seekSlot),
sbe::makeSV(seekSlot),
nullptr,
@@ -247,8 +246,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateOptimizedOplo
const CollectionPtr& collection,
const CollectionScanNode* csn,
PlanYieldPolicy* yieldPolicy,
- bool isTailableResumeBranch,
- sbe::LockAcquisitionCallback lockAcquisitionCallback) {
+ bool isTailableResumeBranch) {
invariant(collection->ns().isOplog());
// We can apply oplog scan optimizations only when at least one of the following was specified.
invariant(csn->resumeAfterRecordId || csn->minRecord || csn->maxRecord);
@@ -293,8 +291,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateOptimizedOplo
auto&& [fields, slots, tsSlot] = makeOplogTimestampSlotsIfNeeded(
state.env, state.slotIdGenerator, shouldTrackLatestOplogTimestamp);
- sbe::ScanCallbacks callbacks(
- lockAcquisitionCallback, {}, {}, makeOpenCallbackIfNeeded(collection, csn));
+ sbe::ScanCallbacks callbacks({}, {}, makeOpenCallbackIfNeeded(collection, csn));
auto stage = sbe::makeS<sbe::ScanStage>(collection->uuid(),
resultSlot,
recordIdSlot,
@@ -321,8 +318,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateOptimizedOplo
std::move(seekRecordIdExpression),
yieldPolicy,
isTailableResumeBranch,
- csn->resumeAfterRecordId.has_value(),
- lockAcquisitionCallback);
+ csn->resumeAfterRecordId.has_value());
}
// Create a filter which checks the first document to ensure either that its 'ts' is less than
@@ -367,7 +363,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateOptimizedOplo
// the expression does match, then it returns 'false', which causes the filter (and as a
// result, the branch) to EOF immediately. Note that the resultSlot and recordIdSlot
// arguments to the ScanStage are boost::none, as we do not need them.
- sbe::ScanCallbacks branchCallbacks(lockAcquisitionCallback);
+ sbe::ScanCallbacks branchCallbacks{};
auto minTsBranch = sbe::makeS<sbe::FilterStage<false, true>>(
sbe::makeS<sbe::ScanStage>(collection->uuid(),
boost::none /* resultSlot */,
@@ -511,7 +507,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateOptimizedOplo
true /* forward */,
yieldPolicy,
csn->nodeId(),
- std::move(lockAcquisitionCallback)),
+ sbe::ScanCallbacks{}),
sbe::makeSV(),
sbe::makeSV(*seekRecordIdSlot),
nullptr,
@@ -542,8 +538,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateGenericCollSc
const CollectionPtr& collection,
const CollectionScanNode* csn,
PlanYieldPolicy* yieldPolicy,
- bool isTailableResumeBranch,
- sbe::LockAcquisitionCallback lockAcquisitionCallback) {
+ bool isTailableResumeBranch) {
const auto forward = csn->direction == CollectionScanParams::FORWARD;
invariant(!csn->shouldTrackLatestOplogTimestamp || collection->ns().isOplog());
@@ -569,8 +564,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateGenericCollSc
auto&& [fields, slots, tsSlot] = makeOplogTimestampSlotsIfNeeded(
state.env, state.slotIdGenerator, csn->shouldTrackLatestOplogTimestamp);
- sbe::ScanCallbacks callbacks(
- lockAcquisitionCallback, {}, {}, makeOpenCallbackIfNeeded(collection, csn));
+ sbe::ScanCallbacks callbacks({}, {}, makeOpenCallbackIfNeeded(collection, csn));
auto stage = sbe::makeS<sbe::ScanStage>(collection->uuid(),
resultSlot,
recordIdSlot,
@@ -596,8 +590,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateGenericCollSc
std::move(seekRecordIdExpression),
yieldPolicy,
isTailableResumeBranch,
- true, /* resumeAfterRecordId */
- lockAcquisitionCallback);
+ true /* resumeAfterRecordId */);
}
if (csn->filter) {
@@ -629,22 +622,12 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateCollScan(
const CollectionPtr& collection,
const CollectionScanNode* csn,
PlanYieldPolicy* yieldPolicy,
- bool isTailableResumeBranch,
- sbe::LockAcquisitionCallback lockAcquisitionCallback) {
+ bool isTailableResumeBranch) {
if (csn->minRecord || csn->maxRecord || csn->stopApplyingFilterAfterFirstMatch) {
- return generateOptimizedOplogScan(state,
- collection,
- csn,
- yieldPolicy,
- isTailableResumeBranch,
- std::move(lockAcquisitionCallback));
+ return generateOptimizedOplogScan(
+ state, collection, csn, yieldPolicy, isTailableResumeBranch);
} else {
- return generateGenericCollScan(state,
- collection,
- csn,
- yieldPolicy,
- isTailableResumeBranch,
- std::move(lockAcquisitionCallback));
+ return generateGenericCollScan(state, collection, csn, yieldPolicy, isTailableResumeBranch);
}
}
} // namespace mongo::stage_builder
diff --git a/src/mongo/db/query/sbe_stage_builder_coll_scan.h b/src/mongo/db/query/sbe_stage_builder_coll_scan.h
index 58b28a0e1f1..b204c5487a8 100644
--- a/src/mongo/db/query/sbe_stage_builder_coll_scan.h
+++ b/src/mongo/db/query/sbe_stage_builder_coll_scan.h
@@ -57,7 +57,6 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateCollScan(
const CollectionPtr& collection,
const CollectionScanNode* csn,
PlanYieldPolicy* yieldPolicy,
- bool isTailableResumeBranch,
- sbe::LockAcquisitionCallback lockAcquisitionCallback);
+ bool isTailableResumeBranch);
} // namespace mongo::stage_builder
diff --git a/src/mongo/db/query/sbe_stage_builder_index_scan.cpp b/src/mongo/db/query/sbe_stage_builder_index_scan.cpp
index b1af7fb38e5..9eeeeab6b30 100644
--- a/src/mongo/db/query/sbe_stage_builder_index_scan.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_index_scan.cpp
@@ -292,8 +292,7 @@ generateOptimizedMultiIntervalIndexScan(
boost::optional<sbe::value::SlotId> indexKeyPatternSlot,
sbe::value::SlotIdGenerator* slotIdGenerator,
PlanYieldPolicy* yieldPolicy,
- PlanNodeId planNodeId,
- sbe::LockAcquisitionCallback lockAcquisitionCallback) {
+ PlanNodeId planNodeId) {
using namespace std::literals;
auto recordIdSlot = slotIdGenerator->generate();
@@ -376,8 +375,7 @@ generateOptimizedMultiIntervalIndexScan(
lowKeySlot,
highKeySlot,
yieldPolicy,
- planNodeId,
- std::move(lockAcquisitionCallback));
+ planNodeId);
// Add a project on top of the index scan to remember the snapshotId of the most recent index
// key returned by the IndexScan above. Otherwise, the index key's snapshot id would be
@@ -451,8 +449,7 @@ makeRecursiveBranchForGenericIndexScan(const CollectionPtr& collection,
boost::optional<sbe::value::SlotId> indexKeyPatternSlot,
sbe::value::SlotIdGenerator* slotIdGenerator,
PlanYieldPolicy* yieldPolicy,
- PlanNodeId planNodeId,
- sbe::LockAcquisitionCallback lockAcquisitionCallback) {
+ PlanNodeId planNodeId) {
// The IndexScanStage in this branch will always produce a KeyString. As such, we use
// 'indexKeySlot' if is defined and generate a new slot otherwise.
sbe::value::SlotId resultSlot;
@@ -499,8 +496,7 @@ makeRecursiveBranchForGenericIndexScan(const CollectionPtr& collection,
lowKeySlot,
boost::none,
yieldPolicy,
- planNodeId,
- std::move(lockAcquisitionCallback));
+ planNodeId);
// Get the low key from the outer side and feed it to the inner side (ixscan).
sbe::value::SlotVector outerSv = sbe::makeSV();
@@ -631,8 +627,7 @@ generateGenericMultiIntervalIndexScan(const CollectionPtr& collection,
boost::optional<sbe::value::SlotId> indexKeyPatternSlot,
sbe::value::SlotIdGenerator* slotIdGenerator,
sbe::value::SpoolIdGenerator* spoolIdGenerator,
- PlanYieldPolicy* yieldPolicy,
- sbe::LockAcquisitionCallback lockAcquisitionCallback) {
+ PlanYieldPolicy* yieldPolicy) {
using namespace std::literals;
auto resultSlot = slotIdGenerator->generate();
@@ -752,8 +747,7 @@ generateGenericMultiIntervalIndexScan(const CollectionPtr& collection,
savedKeyPattern,
slotIdGenerator,
yieldPolicy,
- ixn->nodeId(),
- std::move(lockAcquisitionCallback));
+ ixn->nodeId());
// Construct a union stage from the two branches.
auto makeSlotVector = [](sbe::value::SlotId headSlot, const sbe::value::SlotVector& varSlots) {
@@ -805,8 +799,7 @@ std::pair<sbe::value::SlotId, std::unique_ptr<sbe::PlanStage>> generateSingleInt
boost::optional<sbe::value::SlotId> indexKeyPatternSlot,
sbe::value::SlotIdGenerator* slotIdGenerator,
PlanYieldPolicy* yieldPolicy,
- PlanNodeId planNodeId,
- sbe::LockAcquisitionCallback lockAcquisitionCallback) {
+ PlanNodeId planNodeId) {
auto recordIdSlot = slotIdGenerator->generate();
auto lowKeySlot = slotIdGenerator->generate();
auto highKeySlot = slotIdGenerator->generate();
@@ -860,8 +853,7 @@ std::pair<sbe::value::SlotId, std::unique_ptr<sbe::PlanStage>> generateSingleInt
lowKeySlot,
highKeySlot,
yieldPolicy,
- planNodeId,
- std::move(lockAcquisitionCallback));
+ planNodeId);
// Add a project on top of the index scan to remember the snapshotId of the most recent index
// key returned by the IndexScan above. Otherwise, the index key's snapshot id would be
@@ -896,7 +888,6 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateIndexScan(
const IndexScanNode* ixn,
const sbe::IndexKeysInclusionSet& originalIndexKeyBitset,
PlanYieldPolicy* yieldPolicy,
- sbe::LockAcquisitionCallback lockAcquisitionCallback,
StringMap<const IndexAccessMethod*>* iamMap,
bool needsCorruptionCheck) {
@@ -970,23 +961,21 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateIndexScan(
auto&& [lowKey, highKey] = intervals[0];
sbe::value::SlotId recordIdSlot;
- std::tie(recordIdSlot, stage) =
- generateSingleIntervalIndexScan(collection,
- indexName,
- keyPattern,
- ixn->direction == 1,
- std::move(lowKey),
- std::move(highKey),
- indexKeyBitset,
- indexKeySlots,
- snapshotIdSlot,
- indexIdSlot,
- indexKeySlot,
- indexKeyPatternSlot,
- state.slotIdGenerator,
- yieldPolicy,
- ixn->nodeId(),
- std::move(lockAcquisitionCallback));
+ std::tie(recordIdSlot, stage) = generateSingleIntervalIndexScan(collection,
+ indexName,
+ keyPattern,
+ ixn->direction == 1,
+ std::move(lowKey),
+ std::move(highKey),
+ indexKeyBitset,
+ indexKeySlots,
+ snapshotIdSlot,
+ indexIdSlot,
+ indexKeySlot,
+ indexKeyPatternSlot,
+ state.slotIdGenerator,
+ yieldPolicy,
+ ixn->nodeId());
outputs.set(PlanStageSlots::kRecordId, recordIdSlot);
} else if (intervals.size() > 1) {
@@ -1007,8 +996,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateIndexScan(
indexKeyPatternSlot,
state.slotIdGenerator,
yieldPolicy,
- ixn->nodeId(),
- std::move(lockAcquisitionCallback));
+ ixn->nodeId());
outputs.set(PlanStageSlots::kRecordId, recordIdSlot);
} else {
@@ -1027,8 +1015,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateIndexScan(
indexKeyPatternSlot,
state.slotIdGenerator,
state.spoolIdGenerator,
- yieldPolicy,
- std::move(lockAcquisitionCallback));
+ yieldPolicy);
outputs.set(PlanStageSlots::kRecordId, recordIdSlot);
}
diff --git a/src/mongo/db/query/sbe_stage_builder_index_scan.h b/src/mongo/db/query/sbe_stage_builder_index_scan.h
index 71a7e0eafe6..846fa7fbbfb 100644
--- a/src/mongo/db/query/sbe_stage_builder_index_scan.h
+++ b/src/mongo/db/query/sbe_stage_builder_index_scan.h
@@ -57,7 +57,6 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateIndexScan(
const IndexScanNode* ixn,
const sbe::IndexKeysInclusionSet& indexKeyBitset,
PlanYieldPolicy* yieldPolicy,
- sbe::LockAcquisitionCallback lockAcquisitionCallback,
StringMap<const IndexAccessMethod*>* iamMap,
bool needsCorruptionCheck);
@@ -95,7 +94,6 @@ std::pair<sbe::value::SlotId, std::unique_ptr<sbe::PlanStage>> generateSingleInt
boost::optional<sbe::value::SlotId> keyPatternSlot,
sbe::value::SlotIdGenerator* slotIdGenerator,
PlanYieldPolicy* yieldPolicy,
- PlanNodeId nodeId,
- sbe::LockAcquisitionCallback lockAcquisitionCallback);
+ PlanNodeId nodeId);
} // namespace mongo::stage_builder
diff --git a/src/mongo/db/query/sbe_stage_builder_test_fixture.cpp b/src/mongo/db/query/sbe_stage_builder_test_fixture.cpp
index 36fb19ed215..84a471c1841 100644
--- a/src/mongo/db/query/sbe_stage_builder_test_fixture.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_test_fixture.cpp
@@ -39,7 +39,7 @@
namespace mongo {
std::unique_ptr<QuerySolution> SbeStageBuilderTestFixture::makeQuerySolution(
std::unique_ptr<QuerySolutionNode> root) {
- auto querySoln = std::make_unique<QuerySolution>(QueryPlannerParams::Options::DEFAULT);
+ auto querySoln = std::make_unique<QuerySolution>();
querySoln->setRoot(std::move(root));
return querySoln;
}
diff --git a/src/mongo/db/query/sbe_sub_planner.cpp b/src/mongo/db/query/sbe_sub_planner.cpp
index e0d08f10a04..77b40a2121d 100644
--- a/src/mongo/db/query/sbe_sub_planner.cpp
+++ b/src/mongo/db/query/sbe_sub_planner.cpp
@@ -58,15 +58,15 @@ CandidatePlans SubPlanner::plan(
// branch of the OR query. In this case, fail with a 'QueryPlanKilled' error.
_indexExistenceChecker.check();
+ // Ensure that no previous plans are registered to yield while we multi plan each branch.
+ _yieldPolicy->clearRegisteredPlans();
+
std::vector<std::pair<std::unique_ptr<PlanStage>, stage_builder::PlanStageData>> roots;
for (auto&& solution : solutions) {
roots.push_back(stage_builder::buildSlotBasedExecutableTree(
_opCtx, _collection, *cq, *solution, _yieldPolicy));
}
- // Ensure that no previous plans are registered to yield while we multi plan each branch.
- _yieldPolicy->clearRegisteredPlans();
-
// Clear any plans registered to yield once multiplanning is done for this branch. We don't
// want to leave dangling pointers to the execution plans used in multi planning hanging
// around in the YieldPolicy.
@@ -82,12 +82,13 @@ CandidatePlans SubPlanner::plan(
return std::move(candidates[winnerIdx].solution);
};
+ auto subplanSelectStat = QueryPlanner::choosePlanForSubqueries(
+ _cq, _queryParams, std::move(subplanningStatus.getValue()), multiplanCallback);
+
// One of the indexes in '_queryParams' might have been dropped while planning the final branch
// of the OR query. In this case, fail with a 'QueryPlanKilled' error.
_indexExistenceChecker.check();
- auto subplanSelectStat = QueryPlanner::choosePlanForSubqueries(
- _cq, _queryParams, std::move(subplanningStatus.getValue()), multiplanCallback);
if (!subplanSelectStat.isOK()) {
// Query planning can continue if we failed to find a solution for one of the children.
// Otherwise, it cannot, as it may no longer be safe to access the collection (an index
diff --git a/src/mongo/db/transaction_history_iterator.cpp b/src/mongo/db/transaction_history_iterator.cpp
index bb9e33662c6..ae21a26038e 100644
--- a/src/mongo/db/transaction_history_iterator.cpp
+++ b/src/mongo/db/transaction_history_iterator.cpp
@@ -86,12 +86,8 @@ BSONObj findOneOplogEntry(OperationContext* opCtx,
CollectionCatalog::get(opCtx)->getDatabaseProfileLevel(NamespaceString::kLocalDb),
Date_t::max());
- auto exec =
- uassertStatusOK(getExecutorFind(opCtx,
- &oplogRead.getCollection(),
- std::move(cq),
- permitYield,
- QueryPlannerParams::OMIT_REPL_STATE_PERMITS_READS_CHECK));
+ auto exec = uassertStatusOK(
+ getExecutorFind(opCtx, &oplogRead.getCollection(), std::move(cq), permitYield));
PlanExecutor::ExecState getNextResult;
try {
diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp
index 17b40df8cee..0a89202af53 100644
--- a/src/mongo/dbtests/query_stage_multiplan.cpp
+++ b/src/mongo/dbtests/query_stage_multiplan.cpp
@@ -76,7 +76,7 @@ using std::vector;
static const NamespaceString nss("unittests.QueryStageMultiPlan");
std::unique_ptr<QuerySolution> createQuerySolution() {
- auto soln = std::make_unique<QuerySolution>(QueryPlannerParams::Options::DEFAULT);
+ auto soln = std::make_unique<QuerySolution>();
soln->cacheData = std::make_unique<SolutionCacheData>();
soln->cacheData->solnType = SolutionCacheData::COLLSCAN_SOLN;
soln->cacheData->tree = std::make_unique<PlanCacheIndexTree>();
@@ -499,12 +499,8 @@ TEST_F(QueryStageMultiPlanTest, MPSExplainAllPlans) {
std::make_unique<MultiPlanStage>(_expCtx.get(), ctx.getCollection(), cq.get());
// Put each plan into the MultiPlanStage. Takes ownership of 'firstPlan' and 'secondPlan'.
- mps->addPlan(std::make_unique<QuerySolution>(QueryPlannerParams::Options::DEFAULT),
- std::move(firstPlan),
- ws.get());
- mps->addPlan(std::make_unique<QuerySolution>(QueryPlannerParams::Options::DEFAULT),
- std::move(secondPlan),
- ws.get());
+ mps->addPlan(std::make_unique<QuerySolution>(), std::move(firstPlan), ws.get());
+ mps->addPlan(std::make_unique<QuerySolution>(), std::move(secondPlan), ws.get());
// Making a PlanExecutor chooses the best plan.
auto exec = uassertStatusOK(plan_executor_factory::make(_expCtx,