summaryrefslogtreecommitdiff
path: root/src/mongo/db/ops/delete_executor.cpp
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-09-18 14:06:54 -0400
committerDavid Storch <david.storch@10gen.com>2014-09-19 10:46:17 -0400
commit6572c75e85cd7ec0a3269a13a5290c9a46416a3e (patch)
tree62ef5685e1323df63f1c00b99f624d3273b4b5e2 /src/mongo/db/ops/delete_executor.cpp
parent759b6e8cabfb745b712b5ffd0748561129c3b421 (diff)
downloadmongo-6572c75e85cd7ec0a3269a13a5290c9a46416a3e.tar.gz
SERVER-14100 explain for delete
Diffstat (limited to 'src/mongo/db/ops/delete_executor.cpp')
-rw-r--r--src/mongo/db/ops/delete_executor.cpp69
1 files changed, 48 insertions, 21 deletions
diff --git a/src/mongo/db/ops/delete_executor.cpp b/src/mongo/db/ops/delete_executor.cpp
index ddb0c29b025..25f603ce7f6 100644
--- a/src/mongo/db/ops/delete_executor.cpp
+++ b/src/mongo/db/ops/delete_executor.cpp
@@ -78,8 +78,16 @@ namespace mongo {
return status;
}
- long long DeleteExecutor::execute(Database* db) {
- uassertStatusOK(prepare());
+ PlanExecutor* DeleteExecutor::getPlanExecutor() {
+ return _exec.get();
+ }
+
+ Status DeleteExecutor::prepareInLock(Database* db) {
+ // If we have a non-NULL PlanExecutor, then we've already done the in-lock preparation.
+ if (_exec.get()) {
+ return Status::OK();
+ }
+
uassert(17417,
mongoutils::str::stream() <<
"DeleteExecutor::prepare() failed to parse query " << _request->getQuery(),
@@ -98,52 +106,71 @@ namespace mongo {
}
}
+ // Note that 'collection' may by NULL in the case that the collection we are trying to
+ // delete from does not exist. NULL 'collection' is handled by getExecutorDelete(); we
+ // expect to get back a plan executor whose plan is a DeleteStage on top of an EOFStage.
Collection* collection = db->getCollection(_request->getOpCtx(), ns.ns());
- if (NULL == collection) {
- return 0;
- }
- uassert(10101,
- str::stream() << "cannot remove from a capped collection: " << ns.ns(),
- !collection->isCapped());
+ if (collection && collection->isCapped()) {
+ return Status(ErrorCodes::IllegalOperation,
+ str::stream() << "cannot remove from a capped collection: " << ns.ns());
+ }
- uassert(ErrorCodes::NotMaster,
- str::stream() << "Not primary while removing from " << ns.ns(),
- !_request->shouldCallLogOp() ||
- repl::getGlobalReplicationCoordinator()->canAcceptWritesForDatabase(ns.db()));
+ if (_request->shouldCallLogOp() &&
+ !repl::getGlobalReplicationCoordinator()->canAcceptWritesForDatabase(ns.db())) {
+ return Status(ErrorCodes::NotMaster,
+ str::stream() << "Not primary while removing from " << ns.ns());
+ }
PlanExecutor* rawExec;
+ Status getExecStatus = Status::OK();
if (_canonicalQuery.get()) {
// This is the non-idhack branch.
- uassertStatusOK(getExecutorDelete(_request->getOpCtx(),
+ getExecStatus = getExecutorDelete(_request->getOpCtx(),
collection,
_canonicalQuery.release(),
_request->isMulti(),
_request->shouldCallLogOp(),
_request->isFromMigrate(),
- &rawExec));
+ _request->isExplain(),
+ &rawExec);
}
else {
// This is the idhack branch.
- uassertStatusOK(getExecutorDelete(_request->getOpCtx(),
+ getExecStatus = getExecutorDelete(_request->getOpCtx(),
collection,
ns.ns(),
_request->getQuery(),
_request->isMulti(),
_request->shouldCallLogOp(),
_request->isFromMigrate(),
- &rawExec));
+ _request->isExplain(),
+ &rawExec);
+ }
+
+ if (getExecStatus.isOK()) {
+ invariant(rawExec);
+ _exec.reset(rawExec);
}
- scoped_ptr<PlanExecutor> exec(rawExec);
+
+ return getExecStatus;
+ }
+
+ long long DeleteExecutor::execute(Database* db) {
+ uassertStatusOK(prepare());
+
+ // If we've already done the in-lock preparation, this is a no-op.
+ uassertStatusOK(prepareInLock(db));
+ invariant(_exec.get());
// Concurrently mutating state (by us) so we need to register 'exec'.
- const ScopedExecutorRegistration safety(exec.get());
+ const ScopedExecutorRegistration safety(_exec.get());
- uassertStatusOK(exec->executePlan());
+ uassertStatusOK(_exec->executePlan());
// Extract the number of documents deleted from the DeleteStage stats.
- invariant(exec->getRootStage()->stageType() == STAGE_DELETE);
- DeleteStage* deleteStage = static_cast<DeleteStage*>(exec->getRootStage());
+ invariant(_exec->getRootStage()->stageType() == STAGE_DELETE);
+ DeleteStage* deleteStage = static_cast<DeleteStage*>(_exec->getRootStage());
const DeleteStats* deleteStats =
static_cast<const DeleteStats*>(deleteStage->getSpecificStats());
return deleteStats->docsDeleted;