summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2016-09-26 13:47:05 -0400
committerDavid Storch <david.storch@10gen.com>2016-09-26 17:56:56 -0400
commit1d6dce66f73719e8bf710d5e1e19169b27f91344 (patch)
tree4e349ca3714ee4b16cd84616a7a1d4531b03c39d
parent50fd4e6c8e735ab00879547365f61a808b3f0313 (diff)
downloadmongo-1d6dce66f73719e8bf710d5e1e19169b27f91344.tar.gz
SERVER-24755 fix explain to handle collection drop during yield
-rw-r--r--src/mongo/db/query/explain.cpp7
-rw-r--r--src/mongo/db/query/plan_executor.cpp6
-rw-r--r--src/mongo/db/query/plan_executor.h4
3 files changed, 16 insertions, 1 deletions
diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp
index 944c730ebf4..ab63567f770 100644
--- a/src/mongo/db/query/explain.cpp
+++ b/src/mongo/db/query/explain.cpp
@@ -722,13 +722,18 @@ void Explain::explainStages(PlanExecutor* exec,
executePlanStatus = exec->executePlan();
}
+ // If executing the query failed because it was killed, then the collection may no longer be
+ // valid. We indicate this by setting our collection pointer to null.
+ if (executePlanStatus == ErrorCodes::QueryPlanKilled) {
+ collection = nullptr;
+ }
+
// Get stats for the winning plan. If there is only a single candidate plan, it is considered
// the winner.
unique_ptr<PlanStageStats> winningStats(
mps ? std::move(mps->getStats()->children[mps->bestPlanIdx()])
: std::move(exec->getStats()));
-
//
// Use the stats trees to produce explain BSON.
//
diff --git a/src/mongo/db/query/plan_executor.cpp b/src/mongo/db/query/plan_executor.cpp
index ec4d3bf0c1d..d162e998bab 100644
--- a/src/mongo/db/query/plan_executor.cpp
+++ b/src/mongo/db/query/plan_executor.cpp
@@ -530,12 +530,18 @@ Status PlanExecutor::executePlan() {
}
if (PlanExecutor::DEAD == state || PlanExecutor::FAILURE == state) {
+ if (killed()) {
+ return Status(ErrorCodes::QueryPlanKilled,
+ str::stream() << "Operation aborted because: " << *_killReason);
+ }
+
return Status(ErrorCodes::OperationFailed,
str::stream() << "Exec error: " << WorkingSetCommon::toStatusString(obj)
<< ", state: "
<< PlanExecutor::statestr(state));
}
+ invariant(!killed());
invariant(PlanExecutor::IS_EOF == state);
return Status::OK();
}
diff --git a/src/mongo/db/query/plan_executor.h b/src/mongo/db/query/plan_executor.h
index a321ded213d..207fc6765c2 100644
--- a/src/mongo/db/query/plan_executor.h
+++ b/src/mongo/db/query/plan_executor.h
@@ -298,6 +298,10 @@ public:
* underlying tree without getting results back.
*
* If a YIELD_AUTO policy is set on this executor, then this will automatically yield.
+ *
+ * Returns ErrorCodes::QueryPlanKilled if the plan executor was killed during a yield. If this
+ * error occurs, it is illegal to subsequently access the collection, since it may have been
+ * dropped.
*/
Status executePlan();