diff options
author | David Storch <david.storch@10gen.com> | 2014-09-18 14:06:54 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2014-09-19 10:46:17 -0400 |
commit | 6572c75e85cd7ec0a3269a13a5290c9a46416a3e (patch) | |
tree | 62ef5685e1323df63f1c00b99f624d3273b4b5e2 /src/mongo/db/ops/delete_executor.cpp | |
parent | 759b6e8cabfb745b712b5ffd0748561129c3b421 (diff) | |
download | mongo-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.cpp | 69 |
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; |