summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSally McNichols <sally.mcnichols@mongodb.com>2016-06-09 11:51:27 -0400
committerSally McNichols <sally.mcnichols@mongodb.com>2016-06-09 11:51:27 -0400
commit197fab23f1e6d928bc800f5a2a560c48c0543e82 (patch)
tree6f98775ff9142270ceb639dcaa1514583bbd00e6 /src
parente8ac632f9ce47e7febfd4737ee743bfcba219688 (diff)
downloadmongo-197fab23f1e6d928bc800f5a2a560c48c0543e82.tar.gz
SERVER-23238 remove the public method PlanExecutor::collection()
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/capped_utils.cpp2
-rw-r--r--src/mongo/db/catalog/cursor_manager.cpp3
-rw-r--r--src/mongo/db/catalog/index_create.cpp4
-rw-r--r--src/mongo/db/clientcursor.cpp3
-rw-r--r--src/mongo/db/commands/count_cmd.cpp2
-rw-r--r--src/mongo/db/commands/distinct.cpp2
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp4
-rw-r--r--src/mongo/db/commands/find_cmd.cpp2
-rw-r--r--src/mongo/db/commands/group_cmd.cpp2
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp11
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp4
-rw-r--r--src/mongo/db/dbcommands.cpp2
-rw-r--r--src/mongo/db/dbhelpers.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_cursor.cpp4
-rw-r--r--src/mongo/db/query/explain.cpp8
-rw-r--r--src/mongo/db/query/explain.h3
-rw-r--r--src/mongo/db/query/find.cpp2
-rw-r--r--src/mongo/db/query/plan_executor.cpp65
-rw-r--r--src/mongo/db/query/plan_executor.h31
-rw-r--r--src/mongo/db/query/plan_yield_policy.cpp7
-rw-r--r--src/mongo/db/s/check_sharding_index_command.cpp2
-rw-r--r--src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp4
-rw-r--r--src/mongo/db/s/split_vector_command.cpp4
-rw-r--r--src/mongo/dbtests/documentsourcetests.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_multiplan.cpp3
25 files changed, 86 insertions, 92 deletions
diff --git a/src/mongo/db/catalog/capped_utils.cpp b/src/mongo/db/catalog/capped_utils.cpp
index c18a7b0975f..bfaf21c823a 100644
--- a/src/mongo/db/catalog/capped_utils.cpp
+++ b/src/mongo/db/catalog/capped_utils.cpp
@@ -137,7 +137,7 @@ Status cloneCollectionAsCapped(OperationContext* txn,
std::unique_ptr<PlanExecutor> exec(InternalPlanner::collectionScan(
txn, fromNs, fromCollection, PlanExecutor::YIELD_MANUAL, InternalPlanner::FORWARD));
- exec->setYieldPolicy(PlanExecutor::WRITE_CONFLICT_RETRY_ONLY);
+ exec->setYieldPolicy(PlanExecutor::WRITE_CONFLICT_RETRY_ONLY, fromCollection);
Snapshotted<BSONObj> objToClone;
RecordId loc;
diff --git a/src/mongo/db/catalog/cursor_manager.cpp b/src/mongo/db/catalog/cursor_manager.cpp
index 14a7042a13c..da521a6ab6a 100644
--- a/src/mongo/db/catalog/cursor_manager.cpp
+++ b/src/mongo/db/catalog/cursor_manager.cpp
@@ -332,7 +332,6 @@ void CursorManager::invalidateAll(bool collectionGoingAway, const std::string& r
// we kill the executor, but it deletes itself
PlanExecutor* exec = *it;
exec->kill(reason);
- invariant(exec->collection() == NULL);
}
_nonCachedExecutors.clear();
@@ -343,8 +342,6 @@ void CursorManager::invalidateAll(bool collectionGoingAway, const std::string& r
cc->kill();
- invariant(cc->getExecutor() == NULL || cc->getExecutor()->collection() == NULL);
-
// If the CC is pinned, somebody is actively using it and we do not delete it.
// Instead we notify the holder that we killed it. The holder will then delete the
// CC.
diff --git a/src/mongo/db/catalog/index_create.cpp b/src/mongo/db/catalog/index_create.cpp
index 4007879a247..2abcaf2c00e 100644
--- a/src/mongo/db/catalog/index_create.cpp
+++ b/src/mongo/db/catalog/index_create.cpp
@@ -247,9 +247,9 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsO
_txn, _collection->ns().ns(), _collection, PlanExecutor::YIELD_MANUAL));
if (_buildInBackground) {
invariant(_allowInterruption);
- exec->setYieldPolicy(PlanExecutor::YIELD_AUTO);
+ exec->setYieldPolicy(PlanExecutor::YIELD_AUTO, _collection);
} else {
- exec->setYieldPolicy(PlanExecutor::WRITE_CONFLICT_RETRY_ONLY);
+ exec->setYieldPolicy(PlanExecutor::WRITE_CONFLICT_RETRY_ONLY, _collection);
}
Snapshotted<BSONObj> objToIndex;
diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp
index db22953e211..a4f80e44319 100644
--- a/src/mongo/db/clientcursor.cpp
+++ b/src/mongo/db/clientcursor.cpp
@@ -91,9 +91,6 @@ ClientCursor::ClientCursor(CursorManager* cursorManager,
_exec.reset(exec);
_query = query;
_queryOptions = qopts;
- if (exec->collection()) {
- invariant(cursorManager == exec->collection()->getCursorManager());
- }
init();
}
diff --git a/src/mongo/db/commands/count_cmd.cpp b/src/mongo/db/commands/count_cmd.cpp
index 4fe1d251a4f..d74af1b9a95 100644
--- a/src/mongo/db/commands/count_cmd.cpp
+++ b/src/mongo/db/commands/count_cmd.cpp
@@ -116,7 +116,7 @@ public:
unique_ptr<PlanExecutor> exec = std::move(statusWithPlanExecutor.getValue());
- Explain::explainStages(exec.get(), verbosity, out);
+ Explain::explainStages(exec.get(), collection, verbosity, out);
return Status::OK();
}
diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp
index 3171c816ec2..eccc9724db1 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -185,7 +185,7 @@ public:
return executor.getStatus();
}
- Explain::explainStages(executor.getValue().get(), verbosity, out);
+ Explain::explainStages(executor.getValue().get(), collection, verbosity, out);
return Status::OK();
}
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 6efdb157ad8..e6db597545e 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -279,7 +279,7 @@ public:
return statusWithPlanExecutor.getStatus();
}
const std::unique_ptr<PlanExecutor> exec = std::move(statusWithPlanExecutor.getValue());
- Explain::explainStages(exec.get(), verbosity, out);
+ Explain::explainStages(exec.get(), collection, verbosity, out);
} else {
UpdateRequest request(nsString);
UpdateLifecycleImpl updateLifecycle(nsString);
@@ -310,7 +310,7 @@ public:
return statusWithPlanExecutor.getStatus();
}
const std::unique_ptr<PlanExecutor> exec = std::move(statusWithPlanExecutor.getValue());
- Explain::explainStages(exec.get(), verbosity, out);
+ Explain::explainStages(exec.get(), collection, verbosity, out);
}
return Status::OK();
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index dc536e838b6..83844e619a3 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -167,7 +167,7 @@ public:
std::unique_ptr<PlanExecutor> exec = std::move(statusWithPlanExecutor.getValue());
// Got the execution tree. Explain it.
- Explain::explainStages(exec.get(), verbosity, out);
+ Explain::explainStages(exec.get(), collection, verbosity, out);
return Status::OK();
}
diff --git a/src/mongo/db/commands/group_cmd.cpp b/src/mongo/db/commands/group_cmd.cpp
index ba9ff7d2ead..d2c9cefa154 100644
--- a/src/mongo/db/commands/group_cmd.cpp
+++ b/src/mongo/db/commands/group_cmd.cpp
@@ -132,7 +132,7 @@ private:
unique_ptr<PlanExecutor> planExecutor = std::move(statusWithPlanExecutor.getValue());
- Explain::explainStages(planExecutor.get(), verbosity, out);
+ Explain::explainStages(planExecutor.get(), coll, verbosity, out);
return Status::OK();
}
diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp
index 01d7c33624e..375e77a560a 100644
--- a/src/mongo/db/commands/pipeline_command.cpp
+++ b/src/mongo/db/commands/pipeline_command.cpp
@@ -252,7 +252,7 @@ public:
txn, std::move(ws), std::move(proxy), collection, PlanExecutor::YIELD_MANUAL);
invariant(statusWithPlanExecutor.isOK());
exec = std::move(statusWithPlanExecutor.getValue());
-
+
{
auto planSummary = Explain::getPlanSummary(exec.get());
stdx::lock_guard<Client>(*txn->getClient());
@@ -265,13 +265,6 @@ public:
collection->infoCache()->notifyOfQuery(txn, stats.indexesUsed);
}
- if (!collection && input) {
- // If we don't have a collection, we won't be able to register any executors, so
- // make sure that the input PlanExecutor (likely wrapping an EOFStage) doesn't
- // need to be registered.
- invariant(!input->collection());
- }
-
if (collection) {
const bool isAggCursor = true; // enable special locking behavior
ClientCursor* cursor =
@@ -291,7 +284,7 @@ public:
// collection lock later when cleaning up our ClientCursorPin.
// - In the case where we don't have a collection: our PlanExecutor won't be
// registered, so it will be safe to clean it up outside the lock.
- invariant(NULL == exec.get() || NULL == exec->collection());
+ invariant(!exec || !collection);
}
try {
diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp
index ccc86f6b085..653d8552a6b 100644
--- a/src/mongo/db/commands/write_commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands.cpp
@@ -325,7 +325,7 @@ public:
auto exec = uassertStatusOK(getExecutorUpdate(
txn, &CurOp::get(txn)->debug(), collection.getCollection(), &parsedUpdate));
- Explain::explainStages(exec.get(), verbosity, out);
+ Explain::explainStages(exec.get(), collection.getCollection(), verbosity, out);
return Status::OK();
}
} cmdUpdate;
@@ -394,7 +394,7 @@ public:
// Explain the plan tree.
auto exec = uassertStatusOK(getExecutorDelete(
txn, &CurOp::get(txn)->debug(), collection.getCollection(), &parsedDelete));
- Explain::explainStages(exec.get(), verbosity, out);
+ Explain::explainStages(exec.get(), collection.getCollection(), verbosity, out);
return Status::OK();
}
} cmdDelete;
diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp
index 2b00cab6ea3..280c962ff02 100644
--- a/src/mongo/db/dbcommands.cpp
+++ b/src/mongo/db/dbcommands.cpp
@@ -661,7 +661,7 @@ public:
unique_ptr<PlanExecutor> exec = std::move(statusWithPlanExecutor.getValue());
// Process notifications when the lock is released/reacquired in the loop below
- exec->registerExec();
+ exec->registerExec(coll);
BSONObj obj;
PlanExecutor::ExecState state;
diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp
index a3094773e03..04532db988c 100644
--- a/src/mongo/db/dbhelpers.cpp
+++ b/src/mongo/db/dbhelpers.cpp
@@ -374,7 +374,7 @@ long long Helpers::removeRange(OperationContext* txn,
PlanExecutor::YIELD_MANUAL,
InternalPlanner::FORWARD,
InternalPlanner::IXSCAN_FETCH));
- exec->setYieldPolicy(PlanExecutor::YIELD_AUTO);
+ exec->setYieldPolicy(PlanExecutor::YIELD_AUTO, collection);
RecordId rloc;
BSONObj obj;
diff --git a/src/mongo/db/pipeline/document_source_cursor.cpp b/src/mongo/db/pipeline/document_source_cursor.cpp
index 590356baf64..c9a0d0673e3 100644
--- a/src/mongo/db/pipeline/document_source_cursor.cpp
+++ b/src/mongo/db/pipeline/document_source_cursor.cpp
@@ -195,7 +195,9 @@ Value DocumentSourceCursor::serialize(bool explain) const {
massert(17392, "No _exec. Were we disposed before explained?", _exec);
_exec->restoreState();
- Explain::explainStages(_exec.get(), ExplainCommon::QUERY_PLANNER, &explainBuilder);
+ Explain::explainStages(
+ _exec.get(), autoColl.getCollection(), ExplainCommon::QUERY_PLANNER, &explainBuilder);
+
_exec->saveState();
}
diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp
index f257b7d0ff1..a37104b6960 100644
--- a/src/mongo/db/query/explain.cpp
+++ b/src/mongo/db/query/explain.cpp
@@ -563,6 +563,7 @@ void Explain::getWinningPlanStats(const PlanExecutor* exec, BSONObjBuilder* bob)
// static
void Explain::generatePlannerInfo(PlanExecutor* exec,
+ const Collection* collection,
PlanStageStats* winnerStats,
const vector<unique_ptr<PlanStageStats>>& rejectedStats,
BSONObjBuilder* out) {
@@ -577,8 +578,8 @@ void Explain::generatePlannerInfo(PlanExecutor* exec,
// Find whether there is an index filter set for the query shape. The 'indexFilterSet'
// field will always be false in the case of EOF or idhack plans.
bool indexFilterSet = false;
- if (exec->collection() && exec->getCanonicalQuery()) {
- const CollectionInfoCache* infoCache = exec->collection()->infoCache();
+ if (collection && exec->getCanonicalQuery()) {
+ const CollectionInfoCache* infoCache = collection->infoCache();
const QuerySettings* querySettings = infoCache->getQuerySettings();
PlanCacheKey planCacheKey =
infoCache->getPlanCache()->computeKey(*exec->getCanonicalQuery());
@@ -665,6 +666,7 @@ void Explain::generateServerInfo(BSONObjBuilder* out) {
// static
void Explain::explainStages(PlanExecutor* exec,
+ const Collection* collection,
ExplainCommon::Verbosity verbosity,
BSONObjBuilder* out) {
//
@@ -714,7 +716,7 @@ void Explain::explainStages(PlanExecutor* exec,
//
if (verbosity >= ExplainCommon::QUERY_PLANNER) {
- generatePlannerInfo(exec, winningStats.get(), allPlansStats, out);
+ generatePlannerInfo(exec, collection, winningStats.get(), allPlansStats, out);
}
if (verbosity >= ExplainCommon::EXEC_STATS) {
diff --git a/src/mongo/db/query/explain.h b/src/mongo/db/query/explain.h
index 95fc193cbb2..fb9b8d56c2a 100644
--- a/src/mongo/db/query/explain.h
+++ b/src/mongo/db/query/explain.h
@@ -63,6 +63,7 @@ public:
* added to the "executionStats" section of the explain.
*/
static void explainStages(PlanExecutor* exec,
+ const Collection* collection,
ExplainCommon::Verbosity verbosity,
BSONObjBuilder* out);
@@ -138,11 +139,13 @@ private:
* This is a helper for generating explain BSON. It is used by explainStages(...).
*
* @param exec -- the stage tree for the operation being explained.
+ * @param collection -- the collection used in the operation.
* @param winnerStats -- the stats tree for the winning plan.
* @param rejectedStats -- an array of stats trees, one per rejected plan
*/
static void generatePlannerInfo(
PlanExecutor* exec,
+ const Collection* collection,
PlanStageStats* winnerStats,
const std::vector<std::unique_ptr<PlanStageStats>>& rejectedStats,
BSONObjBuilder* out);
diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp
index f39f4dd6772..6e501242cee 100644
--- a/src/mongo/db/query/find.cpp
+++ b/src/mongo/db/query/find.cpp
@@ -535,7 +535,7 @@ std::string runQuery(OperationContext* txn,
bb.skip(sizeof(QueryResult::Value));
BSONObjBuilder explainBob;
- Explain::explainStages(exec.get(), ExplainCommon::EXEC_ALL_PLANS, &explainBob);
+ Explain::explainStages(exec.get(), collection, ExplainCommon::EXEC_ALL_PLANS, &explainBob);
// Add the resulting object to the return buffer.
BSONObj explainObj = explainBob.obj();
diff --git a/src/mongo/db/query/plan_executor.cpp b/src/mongo/db/query/plan_executor.cpp
index 6a74f988ad7..395e84ce1a7 100644
--- a/src/mongo/db/query/plan_executor.cpp
+++ b/src/mongo/db/query/plan_executor.cpp
@@ -144,7 +144,7 @@ StatusWith<unique_ptr<PlanExecutor>> PlanExecutor::make(OperationContext* txn,
txn, std::move(ws), std::move(rt), std::move(qs), std::move(cq), collection, ns));
// Perform plan selection, if necessary.
- Status status = exec->pickBestPlan(yieldPolicy);
+ Status status = exec->pickBestPlan(yieldPolicy, collection);
if (!status.isOK()) {
return status;
}
@@ -160,32 +160,31 @@ PlanExecutor::PlanExecutor(OperationContext* opCtx,
const Collection* collection,
const string& ns)
: _opCtx(opCtx),
- _collection(collection),
_cq(std::move(cq)),
_workingSet(std::move(ws)),
_qs(std::move(qs)),
_root(std::move(rt)),
_ns(ns),
_yieldPolicy(new PlanYieldPolicy(this, YIELD_MANUAL)) {
- // We may still need to initialize _ns from either _collection or _cq.
+ // We may still need to initialize _ns from either collection or _cq.
if (!_ns.empty()) {
// We already have an _ns set, so there's nothing more to do.
return;
}
- if (NULL != _collection) {
- _ns = _collection->ns().ns();
+ if (collection) {
+ _ns = collection->ns().ns();
} else {
- invariant(NULL != _cq.get());
+ invariant(_cq);
_ns = _cq->getQueryRequest().ns();
}
}
-Status PlanExecutor::pickBestPlan(YieldPolicy policy) {
+Status PlanExecutor::pickBestPlan(YieldPolicy policy, const Collection* collection) {
invariant(_currentState == kUsable);
// For YIELD_AUTO, this will both set an auto yield policy on the PlanExecutor and
// register it to receive notifications.
- this->setYieldPolicy(policy);
+ this->setYieldPolicy(policy, collection);
// First check if we need to do subplanning.
PlanStage* foundStage = getStageByType(_root.get(), STAGE_SUBPLAN);
@@ -247,10 +246,6 @@ unique_ptr<PlanStageStats> PlanExecutor::getStats() const {
return _root->getStats();
}
-const Collection* PlanExecutor::collection() const {
- return _collection;
-}
-
BSONObjSet PlanExecutor::getOutputSorts() const {
if (_qs && _qs->root) {
_qs->root->computeProperties();
@@ -302,7 +297,7 @@ bool PlanExecutor::restoreState() {
throw;
// Handles retries by calling restoreStateWithoutRetrying() in a loop.
- return _yieldPolicy->yield(NULL);
+ return _yieldPolicy->yield();
}
}
@@ -472,8 +467,7 @@ PlanExecutor::ExecState PlanExecutor::getNextImpl(Snapshotted<BSONObj>* objOut,
throw WriteConflictException();
CurOp::get(_opCtx)->debug().writeConflicts++;
writeConflictsInARow++;
- WriteConflictException::logAndBackoff(
- writeConflictsInARow, "plan execution", _collection->ns().ns());
+ WriteConflictException::logAndBackoff(writeConflictsInARow, "plan execution", _ns);
} else {
WorkingSetMember* member = _workingSet->get(id);
@@ -509,8 +503,12 @@ bool PlanExecutor::isEOF() {
return killed() || (_stash.empty() && _root->isEOF());
}
-void PlanExecutor::registerExec() {
- _safety.reset(new ScopedExecutorRegistration(this));
+void PlanExecutor::registerExec(const Collection* collection) {
+ // There's no need to register a PlanExecutor for which the underlying collection
+ // doesn't exist.
+ if (collection) {
+ _safety.reset(new ScopedExecutorRegistration(this, collection));
+ }
}
void PlanExecutor::deregisterExec() {
@@ -519,7 +517,6 @@ void PlanExecutor::deregisterExec() {
void PlanExecutor::kill(string reason) {
_killReason = std::move(reason);
- _collection = NULL;
// XXX: PlanExecutor is designed to wrap a single execution tree. In the case of
// aggregation queries, PlanExecutor wraps a proxy stage responsible for pulling results
@@ -568,7 +565,15 @@ const string& PlanExecutor::ns() {
return _ns;
}
-void PlanExecutor::setYieldPolicy(YieldPolicy policy, bool registerExecutor) {
+void PlanExecutor::setYieldPolicy(YieldPolicy policy,
+ const Collection* collection,
+ bool registerExecutor) {
+ if (!collection) {
+ // If the collection doesn't exist, then there's no need to yield at all.
+ invariant(!_yieldPolicy->allowedToYield());
+ return;
+ }
+
_yieldPolicy->setPolicy(policy);
if (PlanExecutor::YIELD_AUTO == policy) {
// Runners that yield automatically generally need to be registered so that
@@ -577,7 +582,7 @@ void PlanExecutor::setYieldPolicy(YieldPolicy policy, bool registerExecutor) {
// by ClientCursor instead of being registered here. This is unneeded if we only do
// partial "yields" for WriteConflict retrying.
if (registerExecutor) {
- this->registerExec();
+ this->registerExec(collection);
}
}
}
@@ -590,19 +595,21 @@ void PlanExecutor::enqueue(const BSONObj& obj) {
// ScopedExecutorRegistration
//
-PlanExecutor::ScopedExecutorRegistration::ScopedExecutorRegistration(PlanExecutor* exec)
- : _exec(exec) {
- // Collection can be null for an EOFStage plan, or other places where registration
- // is not needed.
- if (_exec->collection()) {
- _exec->collection()->getCursorManager()->registerExecutor(exec);
- }
+// PlanExecutor::ScopedExecutorRegistration
+PlanExecutor::ScopedExecutorRegistration::ScopedExecutorRegistration(PlanExecutor* exec,
+ const Collection* collection)
+ : _exec(exec), _collection(collection) {
+ invariant(_collection);
+ _collection->getCursorManager()->registerExecutor(_exec);
}
PlanExecutor::ScopedExecutorRegistration::~ScopedExecutorRegistration() {
- if (_exec->collection()) {
- _exec->collection()->getCursorManager()->deregisterExecutor(_exec);
+ if (_exec->killed()) {
+ // If the plan executor has been killed, then it's possible that the collection
+ // no longer exists.
+ return;
}
+ _collection->getCursorManager()->deregisterExecutor(_exec);
}
} // namespace mongo
diff --git a/src/mongo/db/query/plan_executor.h b/src/mongo/db/query/plan_executor.h
index 2cd0271bafd..09b8de7dd8e 100644
--- a/src/mongo/db/query/plan_executor.h
+++ b/src/mongo/db/query/plan_executor.h
@@ -201,11 +201,6 @@ public:
CanonicalQuery* getCanonicalQuery() const;
/**
- * The collection in which this executor is working.
- */
- const Collection* collection() const;
-
- /**
* Return the NS that the query is running over.
*/
const std::string& ns();
@@ -287,6 +282,7 @@ public:
* If a YIELD_AUTO policy is set, then this method may yield.
*/
ExecState getNextSnapshotted(Snapshotted<BSONObj>* objOut, RecordId* dlOut);
+
ExecState getNext(BSONObj* objOut, RecordId* dlOut);
/**
@@ -315,7 +311,7 @@ public:
*
* Deregistration happens automatically when this plan executor is destroyed.
*/
- void registerExec();
+ void registerExec(const Collection* collection);
/**
* Unregister this PlanExecutor. Normally you want the PlanExecutor to be registered
@@ -353,7 +349,9 @@ public:
* register (or not) here, rather than require all users to have yet another RAII object.
* Only cursor-creating things like find.cpp set registerExecutor to false.
*/
- void setYieldPolicy(YieldPolicy policy, bool registerExecutor = true);
+ void setYieldPolicy(YieldPolicy policy,
+ const Collection* collection,
+ bool registerExecutor = true);
/**
* Stash the BSONObj so that it gets returned from the PlanExecutor on a later call to
@@ -390,10 +388,11 @@ private:
* by virtue of being cached, so this exception-proofing is not required.
*/
struct ScopedExecutorRegistration {
- ScopedExecutorRegistration(PlanExecutor* exec);
+ ScopedExecutorRegistration(PlanExecutor* exec, const Collection* collection);
~ScopedExecutorRegistration();
PlanExecutor* const _exec;
+ const Collection* const _collection;
};
/**
@@ -430,7 +429,7 @@ private:
*
* If a YIELD_AUTO policy is set then locks are yielded during plan selection.
*/
- Status pickBestPlan(YieldPolicy policy);
+ Status pickBestPlan(YieldPolicy policy, const Collection* collection);
bool killed() {
return static_cast<bool>(_killReason);
@@ -440,25 +439,23 @@ private:
// locks.
OperationContext* _opCtx;
- // Collection over which this plan executor runs. Used to resolve record ids retrieved by
- // the plan stages. The collection must not be destroyed while there are active plans.
- const Collection* _collection;
-
std::unique_ptr<CanonicalQuery> _cq;
std::unique_ptr<WorkingSet> _workingSet;
std::unique_ptr<QuerySolution> _qs;
std::unique_ptr<PlanStage> _root;
+ // If _killReason has a value, then we have been killed and the value represents the reason
+ // for the kill.
+ // The ScopedExecutorRegistration skips dereigstering the plan executor when the plan executor
+ // has been killed, so _killReason must outlive _safety.
+ boost::optional<std::string> _killReason;
+
// Deregisters this executor when it is destroyed.
std::unique_ptr<ScopedExecutorRegistration> _safety;
// What namespace are we operating over?
std::string _ns;
- // If _killReason has a value, then we have been killed and the value represents the reason
- // for the kill.
- boost::optional<std::string> _killReason;
-
// This is used to handle automatic yielding when allowed by the YieldPolicy. Never NULL.
// TODO make this a non-pointer member. This requires some header shuffling so that this
// file includes plan_yield_policy.h rather than the other way around.
diff --git a/src/mongo/db/query/plan_yield_policy.cpp b/src/mongo/db/query/plan_yield_policy.cpp
index 76705aafb93..7a665d29905 100644
--- a/src/mongo/db/query/plan_yield_policy.cpp
+++ b/src/mongo/db/query/plan_yield_policy.cpp
@@ -97,11 +97,6 @@ bool PlanYieldPolicy::yield(RecordFetcher* fetcher) {
opCtx->checkForInterrupt();
}
- // No need to yield if the collection is NULL.
- if (NULL == _planYielding->collection()) {
- return true;
- }
-
try {
_planYielding->saveState();
} catch (const WriteConflictException& wce) {
@@ -120,7 +115,7 @@ bool PlanYieldPolicy::yield(RecordFetcher* fetcher) {
} catch (const WriteConflictException& wce) {
CurOp::get(opCtx)->debug().writeConflicts++;
WriteConflictException::logAndBackoff(
- attempt, "plan execution restoreState", _planYielding->collection()->ns().ns());
+ attempt, "plan execution restoreState", _planYielding->ns());
// retry
}
}
diff --git a/src/mongo/db/s/check_sharding_index_command.cpp b/src/mongo/db/s/check_sharding_index_command.cpp
index afbb278e4f6..379e15db6f6 100644
--- a/src/mongo/db/s/check_sharding_index_command.cpp
+++ b/src/mongo/db/s/check_sharding_index_command.cpp
@@ -142,7 +142,7 @@ public:
false, // endKeyInclusive
PlanExecutor::YIELD_MANUAL,
InternalPlanner::FORWARD));
- exec->setYieldPolicy(PlanExecutor::YIELD_AUTO);
+ exec->setYieldPolicy(PlanExecutor::YIELD_AUTO, collection);
// Find the 'missingField' value used to represent a missing document field in a key of
// this index.
diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp
index a36feb23ebf..e5b15ac679d 100644
--- a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp
+++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp
@@ -534,7 +534,7 @@ Status MigrationChunkClonerSourceLegacy::_storeCurrentLocs(OperationContext* txn
invariant(statusWithPlanExecutor.isOK());
_deleteNotifyExec = std::move(statusWithPlanExecutor.getValue());
- _deleteNotifyExec->registerExec();
+ _deleteNotifyExec->registerExec(collection);
}
// Assume both min and max non-empty, append MinKey's to make them fit chosen index
@@ -553,7 +553,7 @@ Status MigrationChunkClonerSourceLegacy::_storeCurrentLocs(OperationContext* txn
// We can afford to yield here because any change to the base data that we might miss is already
// being queued and will migrate in the 'transferMods' stage.
- exec->setYieldPolicy(PlanExecutor::YIELD_AUTO);
+ exec->setYieldPolicy(PlanExecutor::YIELD_AUTO, collection);
// Use the average object size to estimate how many objects a full chunk would carry do that
// while traversing the chunk's range using the sharding index, below there's a fair amount of
diff --git a/src/mongo/db/s/split_vector_command.cpp b/src/mongo/db/s/split_vector_command.cpp
index b6922737f96..5ee14dc09cf 100644
--- a/src/mongo/db/s/split_vector_command.cpp
+++ b/src/mongo/db/s/split_vector_command.cpp
@@ -275,7 +275,7 @@ public:
splitKeys.push_back(dps::extractElementsBasedOnTemplate(
prettyKey(idx->keyPattern(), currKey.getOwned()), keyPattern));
- exec->setYieldPolicy(PlanExecutor::YIELD_AUTO);
+ exec->setYieldPolicy(PlanExecutor::YIELD_AUTO, collection);
while (1) {
while (PlanExecutor::ADVANCED == state) {
currCount++;
@@ -337,7 +337,7 @@ public:
PlanExecutor::YIELD_MANUAL,
InternalPlanner::FORWARD);
- exec->setYieldPolicy(PlanExecutor::YIELD_AUTO);
+ exec->setYieldPolicy(PlanExecutor::YIELD_AUTO, collection);
state = exec->getNext(&currKey, NULL);
}
diff --git a/src/mongo/dbtests/documentsourcetests.cpp b/src/mongo/dbtests/documentsourcetests.cpp
index 5d18e0c4bb1..5206be6974f 100644
--- a/src/mongo/dbtests/documentsourcetests.cpp
+++ b/src/mongo/dbtests/documentsourcetests.cpp
@@ -107,7 +107,7 @@ protected:
getExecutor(&_opCtx, ctx.getCollection(), std::move(cq), PlanExecutor::YIELD_MANUAL));
_exec->saveState();
- _exec->registerExec();
+ _exec->registerExec(ctx.getCollection());
_source = DocumentSourceCursor::create(nss.ns(), _exec, _ctx);
}
diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp
index a5b4d000a1e..03a7d321205 100644
--- a/src/mongo/dbtests/query_stage_multiplan.cpp
+++ b/src/mongo/dbtests/query_stage_multiplan.cpp
@@ -355,7 +355,8 @@ public:
ASSERT_EQ(root->bestPlanIdx(), 0);
BSONObjBuilder bob;
- Explain::explainStages(exec.get(), ExplainCommon::EXEC_ALL_PLANS, &bob);
+ Explain::explainStages(
+ exec.get(), ctx.getCollection(), ExplainCommon::EXEC_ALL_PLANS, &bob);
BSONObj explained = bob.done();
ASSERT_EQ(explained["executionStats"]["nReturned"].Int(), nDocs);