diff options
author | Mathias Stearn <mathias@10gen.com> | 2017-06-22 16:55:04 -0400 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2017-07-13 16:53:12 -0400 |
commit | a6cc94d141f13feff33178a769c81282c7bc0170 (patch) | |
tree | 1a043a3718c54e8522f8b9bf0932c8d7f96ae79f | |
parent | 8204c7dacf17851057dda165e6d1638cbff70cbf (diff) | |
download | mongo-a6cc94d141f13feff33178a769c81282c7bc0170.tar.gz |
SERVER-29731 Unify logic around directly invoking a command
-rw-r--r-- | src/mongo/db/commands.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/commands.h | 7 | ||||
-rw-r--r-- | src/mongo/db/commands/count_cmd.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/commands/distinct.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/commands/find_cmd.cpp | 25 | ||||
-rw-r--r-- | src/mongo/db/dbdirectclient.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_server.cpp | 17 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_server.h | 6 | ||||
-rw-r--r-- | src/mongo/db/ops/write_ops_exec.cpp | 11 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_count_cmd.cpp | 7 | ||||
-rw-r--r-- | src/mongo/s/commands/commands_public.cpp | 7 |
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); |