diff options
author | Billy Donahue <billy.donahue@mongodb.com> | 2018-03-16 11:50:13 -0400 |
---|---|---|
committer | Billy Donahue <billy.donahue@mongodb.com> | 2018-03-16 14:02:48 -0400 |
commit | f092c84d7fbba8220c8fecca51d0a582e90ee4a7 (patch) | |
tree | 97a5f3e85d80e62c46186f1ebe62b7d106e44fa3 /src/mongo | |
parent | 2b4643d98e5a49af2b57f37a37ce42904bb01af1 (diff) | |
download | mongo-f092c84d7fbba8220c8fecca51d0a582e90ee4a7.tar.gz |
SERVER-33881 move members from Command to BasicCommand
BasicCommand::InvocationShim->BasicCommand::Invocation
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/commands.cpp | 30 | ||||
-rw-r--r-- | src/mongo/db/commands.h | 138 | ||||
-rw-r--r-- | src/mongo/db/commands/explain_cmd.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands/write_commands.cpp | 91 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_explain_cmd.cpp | 6 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_write_cmd.cpp | 49 |
6 files changed, 137 insertions, 183 deletions
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index eaa45a68a41..28cb6ec3c62 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -376,9 +376,9 @@ CommandInvocation::~CommandInvocation() = default; ////////////////////////////////////////////////////////////// // Command -class Command::InvocationShim final : public CommandInvocation { +class BasicCommand::Invocation final : public CommandInvocation { public: - InvocationShim(OperationContext*, const OpMsgRequest& request, Command* command) + Invocation(OperationContext*, const OpMsgRequest& request, BasicCommand* command) : CommandInvocation(command), _command(command), _request(&request), @@ -388,7 +388,7 @@ private: void run(OperationContext* opCtx, CommandReplyBuilder* result) override { try { BSONObjBuilder bob = result->getBodyBuilder(); - bool ok = _command->enhancedRun(opCtx, *_request, bob); + bool ok = _command->run(opCtx, _dbName, _request->body, bob); CommandHelpers::appendCommandStatus(bob, ok); } catch (const ExceptionFor<ErrorCodes::Unauthorized>&) { CommandAuditHook hook(_command); @@ -432,16 +432,17 @@ private: return _request->body; } - Command* const _command; + BasicCommand* const _command; const OpMsgRequest* const _request; const std::string _dbName; }; Command::~Command() = default; -std::unique_ptr<CommandInvocation> Command::parse(OperationContext* opCtx, - const OpMsgRequest& request) { - return stdx::make_unique<InvocationShim>(opCtx, request, this); +std::unique_ptr<CommandInvocation> BasicCommand::parse(OperationContext* opCtx, + const OpMsgRequest& request) { + CommandHelpers::uassertNoDocumentSequences(getName(), request); + return stdx::make_unique<Invocation>(opCtx, request, this); } std::string Command::parseNs(const std::string& dbname, const BSONObj& cmdObj) const { @@ -468,10 +469,10 @@ Command::Command(StringData name, StringData oldName) globalCommandRegistry()->registerCommand(this, name, oldName); } -Status Command::explain(OperationContext* opCtx, - const OpMsgRequest& request, - ExplainOptions::Verbosity verbosity, - BSONObjBuilder* out) const { +Status BasicCommand::explain(OperationContext* opCtx, + const OpMsgRequest& request, + ExplainOptions::Verbosity verbosity, + BSONObjBuilder* out) const { return {ErrorCodes::IllegalOperation, str::stream() << "Cannot explain cmd: " << getName()}; } @@ -551,13 +552,6 @@ void Command::generateHelpResponse(OperationContext* opCtx, replyBuilder->setMetadata(rpc::makeEmptyMetadata()); } -bool BasicCommand::enhancedRun(OperationContext* opCtx, - const OpMsgRequest& request, - BSONObjBuilder& result) { - CommandHelpers::uassertNoDocumentSequences(getName(), request); - return run(opCtx, request.getDatabase().toString(), request.body, result); -} - bool ErrmsgCommandDeprecated::run(OperationContext* opCtx, const std::string& db, const BSONObj& cmdObj, diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index 7c3e7c63b0c..0401c232fa2 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -225,7 +225,7 @@ public: virtual ~Command(); virtual std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx, - const OpMsgRequest& request); + const OpMsgRequest& request) = 0; /** * Returns the command's name. This value never changes for the lifetime of the command. @@ -388,76 +388,6 @@ public: const OpMsgRequest& request); private: - class InvocationShim; - - /** - * Commands which can be explained override this method. Any operation which has a query - * part and executes as a tree of execution stages can be explained. A command should - * implement explain by: - * - * 1) Calling its custom parse function in order to parse the command. The output of - * this function should be a CanonicalQuery (representing the query part of the - * operation), and a PlanExecutor which wraps the tree of execution stages. - * - * 2) Calling Explain::explainStages(...) on the PlanExecutor. This is the function - * which knows how to convert an execution stage tree into explain output. - */ - virtual Status explain(OperationContext* opCtx, - const OpMsgRequest& request, - ExplainOptions::Verbosity verbosity, - BSONObjBuilder* out) const; - - /** - * supportsWriteConcern returns true if this command should be parsed for a writeConcern - * field and wait for that write concern to be satisfied after the command runs. - * - * @param cmd is a BSONObj representation of the command that is used to determine if the - * the command supports a write concern. Ex. aggregate only supports write concern - * when $out is provided. - */ - virtual bool supportsWriteConcern(const BSONObj& cmd) const = 0; - - /** - * Returns true if this Command supports the given readConcern level. Takes the command object - * and the name of the database on which it was invoked as arguments, so that readConcern can be - * conditionally rejected based on the command's parameters and/or namespace. - * - * If a readConcern level argument is sent to a command that returns false the command processor - * will reject the command, returning an appropriate error message. - * - * Note that this is never called on mongos. Sharded commands are responsible for forwarding - * the option to the shards as needed. We rely on the shards to fail the commands in the - * cases where it isn't supported. - */ - virtual bool supportsReadConcern(const std::string& dbName, - const BSONObj& cmdObj, - repl::ReadConcernLevel level) const { - return level == repl::ReadConcernLevel::kLocalReadConcern; - } - - /** - * Returns true if command allows afterClusterTime in its readConcern. The command may not allow - * it if it is specifically intended not to take any LockManager locks. Waiting for - * afterClusterTime takes the MODE_IS lock. - */ - virtual bool allowsAfterClusterTime(const BSONObj& cmdObj) const { - return true; - } - - /** - * Runs the command. - * - * The default implementation verifies that request has no document sections then forwards to - * BasicCommand::run(). - * - * For now commands should only implement if they need access to OP_MSG-specific functionality. - */ - virtual bool enhancedRun(OperationContext* opCtx, - const OpMsgRequest& request, - BSONObjBuilder& result) { - MONGO_UNREACHABLE; - } - // Counters for how many times this command has been executed and failed Counter64 _commandsExecuted; Counter64 _commandsFailed; @@ -526,8 +456,6 @@ public: */ virtual bool supportsWriteConcern() const = 0; - virtual Command::AllowedOnSecondary secondaryAllowed(ServiceContext* context) const = 0; - /** * Returns true if this Command supports the given readConcern level. Takes the command object * and the name of the database on which it was invoked as arguments, so that readConcern can be @@ -553,6 +481,8 @@ public: return true; } + virtual Command::AllowedOnSecondary secondaryAllowed(ServiceContext* context) const = 0; + /** * The command definition that this invocation runs. * Note: nonvirtual. @@ -587,6 +517,9 @@ private: * sequences. */ class BasicCommand : public Command { +private: + class Invocation; + public: using Command::Command; @@ -606,6 +539,23 @@ public: BSONObjBuilder& result) = 0; /** + * Commands which can be explained override this method. Any operation which has a query + * part and executes as a tree of execution stages can be explained. A command should + * implement explain by: + * + * 1) Calling its custom parse function in order to parse the command. The output of + * this function should be a CanonicalQuery (representing the query part of the + * operation), and a PlanExecutor which wraps the tree of execution stages. + * + * 2) Calling Explain::explainStages(...) on the PlanExecutor. This is the function + * which knows how to convert an execution stage tree into explain output. + */ + virtual Status explain(OperationContext* opCtx, + const OpMsgRequest& request, + ExplainOptions::Verbosity verbosity, + BSONObjBuilder* out) const; + + /** * Checks if the client associated with the given OperationContext is authorized to run this * command. Default implementation defers to checkAuthForCommand. */ @@ -613,7 +563,42 @@ public: const std::string& dbname, const BSONObj& cmdObj) const; + /** + * supportsWriteConcern returns true if this command should be parsed for a writeConcern + * field and wait for that write concern to be satisfied after the command runs. + * + * @param cmd is a BSONObj representation of the command that is used to determine if the + * the command supports a write concern. Ex. aggregate only supports write concern + * when $out is provided. + */ + virtual bool supportsWriteConcern(const BSONObj& cmdObj) const = 0; + + /** + * Returns true if this Command supports the given readConcern level. Takes the command object + * and the name of the database on which it was invoked as arguments, so that readConcern can be + * conditionally rejected based on the command's parameters and/or namespace. + * + * If a readConcern level argument is sent to a command that returns false the command processor + * will reject the command, returning an appropriate error message. + * + * Note that this is never called on mongos. Sharded commands are responsible for forwarding + * the option to the shards as needed. We rely on the shards to fail the commands in the + * cases where it isn't supported. + */ + virtual bool supportsReadConcern(const std::string& dbName, + const BSONObj& cmdObj, + repl::ReadConcernLevel level) const { + return level == repl::ReadConcernLevel::kLocalReadConcern; + } + + virtual bool allowsAfterClusterTime(const BSONObj& cmdObj) const { + return true; + } + private: + std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx, + const OpMsgRequest& request) final; + // // Deprecated virtual methods. // @@ -645,13 +630,6 @@ private: // /** - * Calls run(). - */ - bool enhancedRun(OperationContext* opCtx, - const OpMsgRequest& request, - BSONObjBuilder& result) final; - - /** * Calls checkAuthForOperation. */ Status checkAuthForRequest(OperationContext* opCtx, const OpMsgRequest& request) const final; diff --git a/src/mongo/db/commands/explain_cmd.cpp b/src/mongo/db/commands/explain_cmd.cpp index 6935678a53b..38bcfc2c7f5 100644 --- a/src/mongo/db/commands/explain_cmd.cpp +++ b/src/mongo/db/commands/explain_cmd.cpp @@ -55,10 +55,6 @@ public: std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx, const OpMsgRequest& request) override; - bool supportsWriteConcern(const BSONObj& cmd) const override { - return false; - } - /** * Running an explain on a secondary requires explicitly setting slaveOk. */ @@ -160,7 +156,7 @@ public: } bool supportsWriteConcern() const override { - return command()->supportsWriteConcern(_outerRequest->body); + return false; } Command::AllowedOnSecondary secondaryAllowed(ServiceContext* context) const override { diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp index 34ae56f0a3e..0f9919e038a 100644 --- a/src/mongo/db/commands/write_commands/write_commands.cpp +++ b/src/mongo/db/commands/write_commands/write_commands.cpp @@ -212,36 +212,13 @@ public: return false; } - bool supportsReadConcern(const std::string& dbName, - const BSONObj& cmdObj, - repl::ReadConcernLevel level) const final { - return level == repl::ReadConcernLevel::kLocalReadConcern || - level == repl::ReadConcernLevel::kSnapshotReadConcern; - } - - bool supportsWriteConcern(const BSONObj& cmd) const { - return true; - } - ReadWriteType getReadWriteType() const { return ReadWriteType::kWrite; } - bool enhancedRun(OperationContext* opCtx, - const OpMsgRequest& request, - BSONObjBuilder& result) final { - try { - runImpl(opCtx, request, result); - return true; - } catch (const DBException& ex) { - LastError::get(opCtx->getClient()).setLastError(ex.code(), ex.reason()); - throw; - } - } - virtual void runImpl(OperationContext* opCtx, const OpMsgRequest& request, - BSONObjBuilder& result) = 0; + BSONObjBuilder& result) const = 0; virtual Status explainImpl(OperationContext* opCtx, const OpMsgRequest& request, @@ -256,53 +233,65 @@ private: class WriteCommand::Invocation : public CommandInvocation { public: - Invocation(OperationContext* opCtx, const OpMsgRequest& request, WriteCommand* writeCommand) - : CommandInvocation(writeCommand), _request{&request}, _writeCommand{writeCommand} {} + Invocation(const WriteCommand* writeCommand, const OpMsgRequest& request, NamespaceString ns) + : CommandInvocation(writeCommand), _request{&request}, _ns{std::move(ns)} {} private: - void run(OperationContext* opCtx, CommandReplyBuilder* result) override { + void run(OperationContext* opCtx, CommandReplyBuilder* result) final { try { - BSONObjBuilder bob = result->getBodyBuilder(); - bool ok = _writeCommand->enhancedRun(opCtx, *_request, bob); - CommandHelpers::appendCommandStatus(bob, ok); + try { + BSONObjBuilder bob = result->getBodyBuilder(); + command()->runImpl(opCtx, *_request, bob); + CommandHelpers::extractOrAppendOk(bob); + } catch (const DBException& ex) { + LastError::get(opCtx->getClient()).setLastError(ex.code(), ex.reason()); + throw; + } } catch (const ExceptionFor<ErrorCodes::Unauthorized>&) { - CommandHelpers::logAuthViolation( - opCtx, _writeCommand, *_request, ErrorCodes::Unauthorized); + CommandHelpers::logAuthViolation(opCtx, command(), *_request, ErrorCodes::Unauthorized); throw; } } void explain(OperationContext* opCtx, ExplainOptions::Verbosity verbosity, - BSONObjBuilder* result) override { - uassertStatusOK(_writeCommand->explainImpl(opCtx, *_request, verbosity, result)); + BSONObjBuilder* result) final { + uassertStatusOK(command()->explainImpl(opCtx, *_request, verbosity, result)); } - NamespaceString ns() const override { - return NamespaceString( - _writeCommand->parseNs(_request->getDatabase().toString(), _request->body)); + + NamespaceString ns() const final { + return _ns; } - bool supportsWriteConcern() const override { - return _writeCommand->supportsWriteConcern(_request->body); + + Command::AllowedOnSecondary secondaryAllowed(ServiceContext* context) const final { + return command()->secondaryAllowed(context); } - Command::AllowedOnSecondary secondaryAllowed(ServiceContext* context) const override { - return _writeCommand->secondaryAllowed(context); + + bool supportsReadConcern(repl::ReadConcernLevel level) const final { + return level == repl::ReadConcernLevel::kLocalReadConcern || + level == repl::ReadConcernLevel::kSnapshotReadConcern; } - bool supportsReadConcern(repl::ReadConcernLevel level) const override { - return _writeCommand->supportsReadConcern( - _request->getDatabase().toString(), _request->body, level); + + bool supportsWriteConcern() const final { + return true; + } + + void doCheckAuthorization(OperationContext* opCtx) const final { + uassertStatusOK(command()->checkAuthForRequest(opCtx, *_request)); } - void doCheckAuthorization(OperationContext* opCtx) const override { - uassertStatusOK(_writeCommand->checkAuthForRequest(opCtx, *_request)); + const WriteCommand* command() const { + return static_cast<const WriteCommand*>(definition()); } const OpMsgRequest* _request; - WriteCommand* _writeCommand; + NamespaceString _ns; }; std::unique_ptr<CommandInvocation> WriteCommand::parse(OperationContext* opCtx, const OpMsgRequest& request) { - return std::unique_ptr<CommandInvocation>(stdx::make_unique<Invocation>(opCtx, request, this)); + return stdx::make_unique<Invocation>( + this, request, NamespaceString(parseNs(request.getDatabase().toString(), request.body))); } class CmdInsert final : public WriteCommand { @@ -324,7 +313,7 @@ public: void runImpl(OperationContext* opCtx, const OpMsgRequest& request, - BSONObjBuilder& result) final { + BSONObjBuilder& result) const final { const auto batch = InsertOp::parse(request); auto reply = performInserts(opCtx, batch); serializeReply(opCtx, @@ -355,7 +344,7 @@ public: void runImpl(OperationContext* opCtx, const OpMsgRequest& request, - BSONObjBuilder& result) final { + BSONObjBuilder& result) const final { const auto batch = UpdateOp::parse(request); auto reply = performUpdates(opCtx, batch); serializeReply(opCtx, @@ -420,7 +409,7 @@ public: void runImpl(OperationContext* opCtx, const OpMsgRequest& request, - BSONObjBuilder& result) final { + BSONObjBuilder& result) const final { const auto batch = DeleteOp::parse(request); auto reply = performDeletes(opCtx, batch); serializeReply(opCtx, diff --git a/src/mongo/s/commands/cluster_explain_cmd.cpp b/src/mongo/s/commands/cluster_explain_cmd.cpp index 43ef3c9acec..4a8dfc091a6 100644 --- a/src/mongo/s/commands/cluster_explain_cmd.cpp +++ b/src/mongo/s/commands/cluster_explain_cmd.cpp @@ -56,10 +56,6 @@ public: std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx, const OpMsgRequest& request) override; - bool supportsWriteConcern(const BSONObj& cmd) const override { - return false; - } - /** * Running an explain on a secondary requires explicitly setting slaveOk. */ @@ -149,7 +145,7 @@ private: } bool supportsWriteConcern() const override { - return command()->supportsWriteConcern(_outerRequest->body); + return false; } Command::AllowedOnSecondary secondaryAllowed(ServiceContext* context) const override { diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp index 34e65a876e1..fd6eac3e887 100644 --- a/src/mongo/s/commands/cluster_write_cmd.cpp +++ b/src/mongo/s/commands/cluster_write_cmd.cpp @@ -139,16 +139,12 @@ public: virtual ~ClusterWriteCmd() {} std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx, - const OpMsgRequest& request) override; + const OpMsgRequest& request) final; AllowedOnSecondary secondaryAllowed(ServiceContext*) const final { return AllowedOnSecondary::kNever; } - bool supportsWriteConcern(const BSONObj& cmd) const final { - return true; - } - LogicalOp getLogicalOp() const { switch (_writeType) { case BatchedCommandRequest::BatchType::BatchType_Insert: @@ -205,7 +201,7 @@ public: bool runImpl(OperationContext* opCtx, const OpMsgRequest& request, BatchedCommandRequest& batchedRequest, - BSONObjBuilder& result) { + BSONObjBuilder& result) const { auto db = batchedRequest.getNS().db(); if (db != NamespaceString::kAdminDb && db != NamespaceString::kConfigDb) { batchedRequest.setAllowImplicitCreate(false); @@ -347,25 +343,25 @@ private: const BatchedCommandRequest::BatchType _writeType; }; -class ClusterWriteCmd::Invocation : public CommandInvocation { +class ClusterWriteCmd::Invocation final : public CommandInvocation { public: - Invocation(OperationContext* opCtx, + Invocation(const ClusterWriteCmd* clusterWriteCmd, const OpMsgRequest& request, - BatchedCommandRequest batchedRequest, - ClusterWriteCmd* command) - : CommandInvocation(command), + NamespaceString ns, + BatchedCommandRequest batchedRequest) + : CommandInvocation(clusterWriteCmd), _request{&request}, - _command{command}, + _ns{std::move(ns)}, _batchedRequest{std::move(batchedRequest)} {} private: void run(OperationContext* opCtx, CommandReplyBuilder* result) override { try { BSONObjBuilder bob = result->getBodyBuilder(); - bool ok = _command->runImpl(opCtx, *_request, _batchedRequest, bob); + bool ok = command()->runImpl(opCtx, *_request, _batchedRequest, bob); CommandHelpers::appendCommandStatus(bob, ok); } catch (const ExceptionFor<ErrorCodes::Unauthorized>&) { - CommandHelpers::logAuthViolation(opCtx, _command, *_request, ErrorCodes::Unauthorized); + CommandHelpers::logAuthViolation(opCtx, command(), *_request, ErrorCodes::Unauthorized); throw; } } @@ -374,36 +370,41 @@ private: ExplainOptions::Verbosity verbosity, BSONObjBuilder* result) override { uassertStatusOK( - _command->explainImpl(opCtx, *_request, verbosity, _batchedRequest, result)); + command()->explainImpl(opCtx, *_request, verbosity, _batchedRequest, result)); } NamespaceString ns() const override { - return NamespaceString( - _command->parseNs(_request->getDatabase().toString(), _request->body)); + return _ns; } bool supportsWriteConcern() const override { - return _command->supportsWriteConcern(_request->body); + return true; } Command::AllowedOnSecondary secondaryAllowed(ServiceContext* context) const override { - return _command->secondaryAllowed(context); + return command()->secondaryAllowed(context); } void doCheckAuthorization(OperationContext* opCtx) const override { - uassertStatusOK(_command->checkAuthForRequest(opCtx, *_request)); + uassertStatusOK(command()->checkAuthForRequest(opCtx, *_request)); + } + + const ClusterWriteCmd* command() const { + return static_cast<const ClusterWriteCmd*>(definition()); } const OpMsgRequest* _request; - ClusterWriteCmd* _command; + NamespaceString _ns; BatchedCommandRequest _batchedRequest; }; std::unique_ptr<CommandInvocation> ClusterWriteCmd::parse(OperationContext* opCtx, const OpMsgRequest& request) { - auto batchedRequest = parseRequest(_writeType, request); - return std::unique_ptr<CommandInvocation>( - stdx::make_unique<Invocation>(opCtx, request, std::move(batchedRequest), this)); + return stdx::make_unique<Invocation>( + this, + request, + NamespaceString(parseNs(request.getDatabase().toString(), request.body)), + parseRequest(_writeType, request)); } class ClusterCmdInsert : public ClusterWriteCmd { |