From 73e8c4ec60bc27617c9b5bbda7096603ea70aef4 Mon Sep 17 00:00:00 2001 From: Cheahuychou Mao Date: Mon, 6 Aug 2018 10:42:26 -0400 Subject: SERVER-35708 Make mongos attach errorLabels on command response --- src/mongo/s/commands/SConscript | 1 + src/mongo/s/commands/strategy.cpp | 27 +++++++++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src/mongo/s') diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript index 2c642d077b9..5c75e96236e 100644 --- a/src/mongo/s/commands/SConscript +++ b/src/mongo/s/commands/SConscript @@ -115,6 +115,7 @@ env.Library( '$BUILD_DIR/mongo/db/commands/test_commands_enabled', '$BUILD_DIR/mongo/db/commands/write_commands_common', '$BUILD_DIR/mongo/db/ftdc/ftdc_server', + '$BUILD_DIR/mongo/db/handle_request_response', '$BUILD_DIR/mongo/db/logical_session_cache_impl', '$BUILD_DIR/mongo/db/pipeline/aggregation', '$BUILD_DIR/mongo/db/pipeline/mongos_process_interface', diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp index e10777fcde2..efa76197bb3 100644 --- a/src/mongo/s/commands/strategy.cpp +++ b/src/mongo/s/commands/strategy.cpp @@ -43,6 +43,7 @@ #include "mongo/db/commands.h" #include "mongo/db/commands/test_commands_enabled.h" #include "mongo/db/curop.h" +#include "mongo/db/handle_request_response.h" #include "mongo/db/initialize_operation_session_info.h" #include "mongo/db/lasterror.h" #include "mongo/db/logical_clock.h" @@ -287,10 +288,15 @@ void execCommandClient(OperationContext* opCtx, MONGO_FAIL_POINT_DEFINE(doNotRefreshShardsOnRetargettingError); +/** + * Executes the command for the given request, and appends the result to replyBuilder + * and error labels, if any, to errorBuilder. + */ void runCommand(OperationContext* opCtx, const OpMsgRequest& request, const NetworkOp opType, - rpc::ReplyBuilderInterface* replyBuilder) { + rpc::ReplyBuilderInterface* replyBuilder, + BSONObjBuilder* errorBuilder) { auto const commandName = request.getCommandName(); auto const command = CommandHelpers::findCommand(commandName); if (!command) { @@ -343,10 +349,11 @@ void runCommand(OperationContext* opCtx, } boost::optional scopedSession; - if (auto osi = initializeOperationSessionInfo( - opCtx, request.body, command->requiresAuth(), true, true, true)) { + auto osi = initializeOperationSessionInfo( + opCtx, request.body, command->requiresAuth(), true, true, true); - if (osi->getAutocommit()) { + try { + if (osi && osi->getAutocommit()) { scopedSession.emplace(opCtx); auto txnRouter = TransactionRouter::get(opCtx); @@ -360,9 +367,7 @@ void runCommand(OperationContext* opCtx, txnRouter->beginOrContinueTxn(opCtx, *txnNumber, startTransaction); } - } - try { for (int tries = 0;; ++tries) { // Try kMaxNumStaleVersionRetries times. On the last try, exceptions are rethrown. bool canRetry = tries < kMaxNumStaleVersionRetries - 1; @@ -423,6 +428,8 @@ void runCommand(OperationContext* opCtx, } catch (const DBException& e) { command->incrementCommandsFailed(); LastError::get(opCtx->getClient()).setLastError(e.code(), e.reason()); + auto errorLabels = getErrorLabels(osi, command->getName(), e.code()); + errorBuilder->appendElements(errorLabels); throw; } } @@ -534,6 +541,7 @@ DbResponse Strategy::queryOp(OperationContext* opCtx, const NamespaceString& nss DbResponse Strategy::clientCommand(OperationContext* opCtx, const Message& m) { auto reply = rpc::makeReplyBuilder(rpc::protocolForMessage(m)); + BSONObjBuilder errorBuilder; bool propagateException = false; @@ -556,7 +564,7 @@ DbResponse Strategy::clientCommand(OperationContext* opCtx, const Message& m) { std::string db = request.getDatabase().toString(); try { LOG(3) << "Command begin db: " << db << " msg id: " << m.header().getId(); - runCommand(opCtx, request, m.operation(), reply.get()); + runCommand(opCtx, request, m.operation(), reply.get(), &errorBuilder); LOG(3) << "Command end db: " << db << " msg id: " << m.header().getId(); } catch (const DBException& ex) { LOG(1) << "Exception thrown while processing command on " << db @@ -574,6 +582,7 @@ DbResponse Strategy::clientCommand(OperationContext* opCtx, const Message& m) { auto bob = reply->getBodyBuilder(); CommandHelpers::appendCommandStatusNoThrow(bob, ex.toStatus()); appendRequiredFieldsToResponse(opCtx, &bob); + bob.appendElements(errorBuilder.obj()); } if (OpMsg::isFlagSet(m, OpMsg::kMoreToCome)) { @@ -718,6 +727,7 @@ void Strategy::killCursors(OperationContext* opCtx, DbMessage* dbm) { void Strategy::writeOp(OperationContext* opCtx, DbMessage* dbm) { const auto& msg = dbm->msg(); rpc::OpMsgReplyBuilder reply; + BSONObjBuilder errorBuilder; runCommand(opCtx, [&]() { switch (msg.operation()) { @@ -735,7 +745,8 @@ void Strategy::writeOp(OperationContext* opCtx, DbMessage* dbm) { } }(), msg.operation(), - &reply); // built object is ignored + &reply, + &errorBuilder); // built objects are ignored } void Strategy::explainFind(OperationContext* opCtx, -- cgit v1.2.1