summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2018-03-16 11:50:13 -0400
committerBilly Donahue <billy.donahue@mongodb.com>2018-03-16 14:02:48 -0400
commitf092c84d7fbba8220c8fecca51d0a582e90ee4a7 (patch)
tree97a5f3e85d80e62c46186f1ebe62b7d106e44fa3 /src/mongo
parent2b4643d98e5a49af2b57f37a37ce42904bb01af1 (diff)
downloadmongo-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.cpp30
-rw-r--r--src/mongo/db/commands.h138
-rw-r--r--src/mongo/db/commands/explain_cmd.cpp6
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp91
-rw-r--r--src/mongo/s/commands/cluster_explain_cmd.cpp6
-rw-r--r--src/mongo/s/commands/cluster_write_cmd.cpp49
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 {