diff options
author | David Storch <david.storch@mongodb.com> | 2021-06-04 16:41:11 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-06-16 20:24:42 +0000 |
commit | 10bbd8dd5a0879651f446f66bc633ae0a1966acd (patch) | |
tree | fe4f49b66853289889477138f1018581d1b76791 /src/mongo/db/query | |
parent | fc66d558802ecb1cd403d45225d0d77cc47a5d93 (diff) | |
download | mongo-10bbd8dd5a0879651f446f66bc633ae0a1966acd.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.
(cherry picked from commit 71cfc41653768c29c719689a949a75a0ebbaa941)
Diffstat (limited to 'src/mongo/db/query')
-rw-r--r-- | src/mongo/db/query/classic_stage_builder_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/query/get_executor.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/query/plan_cache_test.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/query/planner_analysis.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner_params.h | 9 | ||||
-rw-r--r-- | src/mongo/db/query/query_solution.h | 14 | ||||
-rw-r--r-- | src/mongo/db/query/query_solution_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder.cpp | 31 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder.h | 4 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_coll_scan.cpp | 45 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_coll_scan.h | 3 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_index_scan.cpp | 63 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_index_scan.h | 4 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_test_fixture.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_sub_planner.cpp | 11 |
16 files changed, 62 insertions, 144 deletions
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 5c8980200f8..b894989ea4d 100644 --- a/src/mongo/db/query/get_executor.cpp +++ b/src/mongo/db/query/get_executor.cpp @@ -567,7 +567,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); @@ -974,7 +974,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 d45befd0b54..70783eec7f7 100644 --- a/src/mongo/db/query/plan_cache_test.cpp +++ b/src/mongo/db/query/plan_cache_test.cpp @@ -313,7 +313,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()); @@ -376,8 +376,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; @@ -1167,7 +1166,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 50f8afadc4e..47832fa54ba 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. @@ -646,7 +635,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, @@ -705,12 +693,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. @@ -822,14 +806,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; @@ -885,7 +863,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)); // 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 |