summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2017-06-22 16:55:04 -0400
committerMathias Stearn <mathias@10gen.com>2017-07-13 16:53:12 -0400
commita6cc94d141f13feff33178a769c81282c7bc0170 (patch)
tree1a043a3718c54e8522f8b9bf0932c8d7f96ae79f
parent8204c7dacf17851057dda165e6d1638cbff70cbf (diff)
downloadmongo-a6cc94d141f13feff33178a769c81282c7bc0170.tar.gz
SERVER-29731 Unify logic around directly invoking a command
-rw-r--r--src/mongo/db/commands.cpp21
-rw-r--r--src/mongo/db/commands.h7
-rw-r--r--src/mongo/db/commands/count_cmd.cpp11
-rw-r--r--src/mongo/db/commands/distinct.cpp11
-rw-r--r--src/mongo/db/commands/find_cmd.cpp25
-rw-r--r--src/mongo/db/dbdirectclient.cpp21
-rw-r--r--src/mongo/db/ftdc/ftdc_server.cpp17
-rw-r--r--src/mongo/db/ftdc/ftdc_server.h6
-rw-r--r--src/mongo/db/ops/write_ops_exec.cpp11
-rw-r--r--src/mongo/s/commands/cluster_count_cmd.cpp7
-rw-r--r--src/mongo/s/commands/commands_public.cpp7
11 files changed, 71 insertions, 73 deletions
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp
index b431751dc9f..2e4b0116afd 100644
--- a/src/mongo/db/commands.cpp
+++ b/src/mongo/db/commands.cpp
@@ -50,6 +50,7 @@
#include "mongo/db/namespace_string.h"
#include "mongo/db/server_parameters.h"
#include "mongo/rpc/write_concern_error_detail.h"
+#include "mongo/s/stale_exception.h"
#include "mongo/util/log.h"
namespace mongo {
@@ -182,6 +183,26 @@ Status Command::explain(OperationContext* opCtx,
return {ErrorCodes::IllegalOperation, str::stream() << "Cannot explain cmd: " << getName()};
}
+BSONObj Command::runCommandDirectly(OperationContext* opCtx, const OpMsgRequest& request) {
+ auto command = Command::findCommand(request.getCommandName());
+ invariant(command);
+
+ BSONObjBuilder out;
+ try {
+ std::string errmsg;
+ bool ok = command->enhancedRun(opCtx, request, errmsg, out);
+ appendCommandStatus(out, ok, errmsg);
+ } catch (const StaleConfigException& ex) {
+ // These exceptions are intended to be handled at a higher level and cannot losslessly
+ // round-trip through Status.
+ throw;
+ } catch (const DBException& ex) {
+ out.resetToEmpty();
+ appendCommandStatus(out, ex.toStatus());
+ }
+ return out.obj();
+}
+
Command* Command::findCommand(StringData name) {
CommandMap::const_iterator i = _commands->find(name);
if (i == _commands->end())
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index 1efd437d3ef..96cf930d4c0 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -401,6 +401,13 @@ public:
// Counter for unknown commands
static Counter64 unknownCommands;
+ /**
+ * Runs a command directly and returns the result. Does not do any other work normally handled
+ * by command dispatch, such as checking auth, dealing with CurOp or waiting for write concern.
+ * It is illegal to call this if the command does not exist.
+ */
+ static BSONObj runCommandDirectly(OperationContext* txn, const OpMsgRequest& request);
+
static Command* findCommand(StringData name);
// Helper for setting errmsg and ok field in command result object.
diff --git a/src/mongo/db/commands/count_cmd.cpp b/src/mongo/db/commands/count_cmd.cpp
index b34eb049b0b..2a3db9a0341 100644
--- a/src/mongo/db/commands/count_cmd.cpp
+++ b/src/mongo/db/commands/count_cmd.cpp
@@ -177,16 +177,15 @@ public:
return appendCommandStatus(result, viewAggregation.getStatus());
}
- BSONObjBuilder aggResult;
- (void)Command::findCommand("aggregate")
- ->run(opCtx, dbname, viewAggregation.getValue(), errmsg, aggResult);
+ BSONObj aggResult = Command::runCommandDirectly(
+ opCtx, OpMsgRequest::fromDBAndBody(dbname, std::move(viewAggregation.getValue())));
- if (ResolvedView::isResolvedViewErrorResponse(aggResult.asTempObj())) {
- result.appendElements(aggResult.obj());
+ if (ResolvedView::isResolvedViewErrorResponse(aggResult)) {
+ result.appendElements(aggResult);
return false;
}
- ViewResponseFormatter formatter(aggResult.obj());
+ ViewResponseFormatter formatter(aggResult);
Status formatStatus = formatter.appendAsCountResponse(&result);
if (!formatStatus.isOK()) {
return appendCommandStatus(result, formatStatus);
diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp
index 521862f0ccf..ba72b5cd7a6 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -178,17 +178,16 @@ public:
if (!viewAggregation.isOK()) {
return appendCommandStatus(result, viewAggregation.getStatus());
}
- BSONObjBuilder aggResult;
- (void)Command::findCommand("aggregate")
- ->run(opCtx, dbname, viewAggregation.getValue(), errmsg, aggResult);
+ BSONObj aggResult = Command::runCommandDirectly(
+ opCtx, OpMsgRequest::fromDBAndBody(dbname, std::move(viewAggregation.getValue())));
- if (ResolvedView::isResolvedViewErrorResponse(aggResult.asTempObj())) {
- result.appendElements(aggResult.obj());
+ if (ResolvedView::isResolvedViewErrorResponse(aggResult)) {
+ result.appendElements(aggResult);
return false;
}
- ViewResponseFormatter formatter(aggResult.obj());
+ ViewResponseFormatter formatter(aggResult);
Status formatStatus = formatter.appendAsDistinctResponse(&result);
if (!formatStatus.isOK()) {
return appendCommandStatus(result, formatStatus);
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index e7d40b08c70..c597fbcc0e9 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -53,6 +53,7 @@
#include "mongo/db/server_parameters.h"
#include "mongo/db/service_context.h"
#include "mongo/db/stats/counters.h"
+#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/util/log.h"
namespace mongo {
@@ -284,19 +285,19 @@ public:
if (!viewAggregationCommand.isOK())
return appendCommandStatus(result, viewAggregationCommand.getStatus());
- Command* agg = Command::findCommand("aggregate");
- try {
- agg->run(opCtx, dbname, viewAggregationCommand.getValue(), errmsg, result);
- } catch (DBException& error) {
- if (error.getCode() == ErrorCodes::InvalidPipelineOperator) {
- return appendCommandStatus(
- result,
- {ErrorCodes::InvalidPipelineOperator,
- str::stream() << "Unsupported in view pipeline: " << error.what()});
- }
- return appendCommandStatus(result, error.toStatus());
+ BSONObj aggResult = Command::runCommandDirectly(
+ opCtx,
+ OpMsgRequest::fromDBAndBody(dbname, std::move(viewAggregationCommand.getValue())));
+ auto status = getStatusFromCommandResult(aggResult);
+ if (status.code() == ErrorCodes::InvalidPipelineOperator) {
+ return appendCommandStatus(
+ result,
+ {ErrorCodes::InvalidPipelineOperator,
+ str::stream() << "Unsupported in view pipeline: " << status.reason()});
}
- return true;
+ result.resetToEmpty();
+ result.appendElements(aggResult);
+ return status.isOK();
}
// Get the execution plan for the query.
diff --git a/src/mongo/db/dbdirectclient.cpp b/src/mongo/db/dbdirectclient.cpp
index b85be86dd0d..6609d69a642 100644
--- a/src/mongo/db/dbdirectclient.cpp
+++ b/src/mongo/db/dbdirectclient.cpp
@@ -164,23 +164,12 @@ unsigned long long DBDirectClient::count(
BSONObj cmdObj = _countCmd(ns, query, options, limit, skip);
NamespaceString nsString(ns);
- std::string dbname = nsString.db().toString();
-
- Command* countCmd = Command::findCommand("count");
- invariant(countCmd);
-
- std::string errmsg;
- BSONObjBuilder result;
- bool runRetval = countCmd->run(_opCtx, dbname, cmdObj, errmsg, result);
- if (!runRetval) {
- Command::appendCommandStatus(result, runRetval, errmsg);
- Status commandStatus = getStatusFromCommandResult(result.obj());
- invariant(!commandStatus.isOK());
- uassertStatusOK(commandStatus);
- }
- BSONObj resultObj = result.obj();
- return static_cast<unsigned long long>(resultObj["n"].numberLong());
+ auto result = Command::runCommandDirectly(
+ _opCtx, OpMsgRequest::fromDBAndBody(nsString.db(), std::move(cmdObj)));
+
+ uassertStatusOK(getStatusFromCommandResult(result));
+ return static_cast<unsigned long long>(result["n"].numberLong());
}
} // namespace mongo
diff --git a/src/mongo/db/ftdc/ftdc_server.cpp b/src/mongo/db/ftdc/ftdc_server.cpp
index 534cbf37650..a4bb5572c7c 100644
--- a/src/mongo/db/ftdc/ftdc_server.cpp
+++ b/src/mongo/db/ftdc/ftdc_server.cpp
@@ -247,21 +247,14 @@ FTDCSimpleInternalCommandCollector::FTDCSimpleInternalCommandCollector(StringDat
StringData name,
StringData ns,
BSONObj cmdObj)
- : _name(name.toString()), _ns(ns.toString()), _cmdObj(std::move(cmdObj)) {
- _command = Command::findCommand(command);
- invariant(_command);
+ : _name(name.toString()), _request(OpMsgRequest::fromDBAndBody(ns, std::move(cmdObj))) {
+ invariant(command == _request.getCommandName());
+ invariant(Command::findCommand(command)); // Fail early if it doesn't exist.
}
void FTDCSimpleInternalCommandCollector::collect(OperationContext* opCtx, BSONObjBuilder& builder) {
- std::string errmsg;
-
- bool ret = _command->run(opCtx, _ns, _cmdObj, errmsg, builder);
-
- // Some commands return errmsgs when they return false (collstats)
- // Some commands return bson objs when they return false (replGetStatus)
- // We append the status as needed to ensure readers of the collected data can check the
- // status of any individual command.
- _command->appendCommandStatus(builder, ret, errmsg);
+ auto result = Command::runCommandDirectly(opCtx, _request);
+ builder.appendElements(result);
}
std::string FTDCSimpleInternalCommandCollector::name() const {
diff --git a/src/mongo/db/ftdc/ftdc_server.h b/src/mongo/db/ftdc/ftdc_server.h
index 4b4583ae153..02357c24e6f 100644
--- a/src/mongo/db/ftdc/ftdc_server.h
+++ b/src/mongo/db/ftdc/ftdc_server.h
@@ -93,11 +93,7 @@ public:
private:
std::string _name;
- std::string _ns;
- BSONObj _cmdObj;
-
- // Not owned
- Command* _command;
+ const OpMsgRequest _request;
};
} // namespace mongo
diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp
index 76e1d9a0acc..17ffdead6b5 100644
--- a/src/mongo/db/ops/write_ops_exec.cpp
+++ b/src/mongo/db/ops/write_ops_exec.cpp
@@ -252,14 +252,9 @@ SingleWriteResult createIndex(OperationContext* opCtx,
BSONObjBuilder cmdBuilder;
cmdBuilder << "createIndexes" << ns.coll();
cmdBuilder << "indexes" << BSON_ARRAY(spec);
- auto cmd = cmdBuilder.obj();
-
- BSONObjBuilder cmdReplyBuilder;
- std::string errMsg;
- bool ok = Command::findCommand("createIndexes")
- ->run(opCtx, systemIndexes.db().toString(), cmd, errMsg, cmdReplyBuilder);
- Command::appendCommandStatus(cmdReplyBuilder, ok, errMsg);
- auto cmdResult = cmdReplyBuilder.obj();
+
+ auto cmdResult = Command::runCommandDirectly(
+ opCtx, OpMsgRequest::fromDBAndBody(systemIndexes.db(), cmdBuilder.obj()));
uassertStatusOK(getStatusFromCommandResult(cmdResult));
// Unlike normal inserts, it is not an error to "insert" a duplicate index.
diff --git a/src/mongo/s/commands/cluster_count_cmd.cpp b/src/mongo/s/commands/cluster_count_cmd.cpp
index e21dc7bad41..6736d6c4174 100644
--- a/src/mongo/s/commands/cluster_count_cmd.cpp
+++ b/src/mongo/s/commands/cluster_count_cmd.cpp
@@ -184,12 +184,11 @@ public:
resolvedView.asExpandedViewAggregation(aggRequestOnView.getValue());
auto resolvedAggCmd = resolvedAggRequest.serializeToCommandObj().toBson();
- BSONObjBuilder aggResult;
- Command::findCommand("aggregate")
- ->run(opCtx, dbname, resolvedAggCmd, errmsg, aggResult);
+ BSONObj aggResult = Command::runCommandDirectly(
+ opCtx, OpMsgRequest::fromDBAndBody(dbname, std::move(resolvedAggCmd)));
result.resetToEmpty();
- ViewResponseFormatter formatter(aggResult.obj());
+ ViewResponseFormatter formatter(aggResult);
auto formatStatus = formatter.appendAsCountResponse(&result);
if (!formatStatus.isOK()) {
return appendCommandStatus(result, formatStatus);
diff --git a/src/mongo/s/commands/commands_public.cpp b/src/mongo/s/commands/commands_public.cpp
index bdc73bd5adc..9ba05a7298b 100644
--- a/src/mongo/s/commands/commands_public.cpp
+++ b/src/mongo/s/commands/commands_public.cpp
@@ -1041,11 +1041,10 @@ public:
resolvedView.asExpandedViewAggregation(aggRequestOnView.getValue());
auto resolvedAggCmd = resolvedAggRequest.serializeToCommandObj().toBson();
- BSONObjBuilder aggResult;
- Command::findCommand("aggregate")
- ->run(opCtx, dbName, resolvedAggCmd, errmsg, aggResult);
+ BSONObj aggResult = Command::runCommandDirectly(
+ opCtx, OpMsgRequest::fromDBAndBody(dbName, std::move(resolvedAggCmd)));
- ViewResponseFormatter formatter(aggResult.obj());
+ ViewResponseFormatter formatter(aggResult);
auto formatStatus = formatter.appendAsDistinctResponse(&result);
if (!formatStatus.isOK()) {
return appendCommandStatus(result, formatStatus);