diff options
author | Mathias Stearn <mathias@10gen.com> | 2018-07-25 15:04:48 -0400 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2018-07-30 13:57:10 -0400 |
commit | 480192de1789e8387b64976ad015c11fac990617 (patch) | |
tree | 1bd8c4bf54334ca55254bbf534ad3d7127843355 | |
parent | d68d672dd4cc27c92be897e7523fad85664fc39e (diff) | |
download | mongo-480192de1789e8387b64976ad015c11fac990617.tar.gz |
SERVER-33135 Delete code for OP_COMMAND
37 files changed, 84 insertions, 1330 deletions
diff --git a/jstests/libs/profiler.js b/jstests/libs/profiler.js index 6fe2c841cee..63af457299b 100644 --- a/jstests/libs/profiler.js +++ b/jstests/libs/profiler.js @@ -57,8 +57,6 @@ function getProfilerProtocolStringForCommand(conn) { const protocols = conn.getClientRPCProtocols(); if ("all" === protocols || /Msg/.test(protocols)) return "op_msg"; - if (/Command/.test(protocols)) - return "op_command"; if (/Query/.test(protocols)) return "op_query"; doassert(`Unknown prototocol string ${protocols}`); diff --git a/jstests/noPassthroughWithMongod/rpc_protocols.js b/jstests/noPassthroughWithMongod/rpc_protocols.js index 4a5e436454b..ef847e2a359 100644 --- a/jstests/noPassthroughWithMongod/rpc_protocols.js +++ b/jstests/noPassthroughWithMongod/rpc_protocols.js @@ -1,11 +1,11 @@ // Regression test for SERVER-21673. -// A user can configure the shell to send commands via OP_QUERY or OP_COMMAND. This can be done at +// A user can configure the shell to send commands via OP_QUERY or OP_MSG. This can be done at // startup using the "--rpcProtocols" command line option, or at runtime using the // "setClientRPCProtocols" method on the Mongo object. // @tags: [requires_profiling] -var RPC_PROTOCOLS = {OP_QUERY: "opQueryOnly", OP_COMMAND: "opCommandOnly"}; +var RPC_PROTOCOLS = {OP_QUERY: "opQueryOnly", OP_MSG: "opMsgOnly"}; (function() { "use strict"; @@ -34,19 +34,19 @@ var RPC_PROTOCOLS = {OP_QUERY: "opQueryOnly", OP_COMMAND: "opCommandOnly"}; assert(profileDoc !== null); assert.eq(profileDoc.protocol, "op_query"); - // Test that --rpcProtocols=opCommandOnly forces OP_COMMAND commands. - runInShell(RPC_PROTOCOLS.OP_COMMAND, function() { - assert(db.getMongo().getClientRPCProtocols() === "opCommandOnly"); - db.getSiblingDB("test").rpcProtocols.find().comment("opCommandCommandLine").itcount(); + // Test that --rpcProtocols=opMsgOnly forces OP_MSG commands. + runInShell(RPC_PROTOCOLS.OP_MSG, function() { + assert(db.getMongo().getClientRPCProtocols() === "opMsgOnly"); + db.getSiblingDB("test").rpcProtocols.find().comment("opMsgCommandLine").itcount(); }); - profileDoc = db.system.profile.findOne({"command.comment": "opCommandCommandLine"}); + profileDoc = db.system.profile.findOne({"command.comment": "opMsgCommandLine"}); assert(profileDoc !== null); - assert.eq(profileDoc.protocol, "op_command"); + assert.eq(profileDoc.protocol, "op_msg"); // Test that .setClientRPCProtocols("opQueryOnly") forces OP_QUERY commands. We start the shell - // in OP_COMMAND only mode, then switch it to OP_QUERY mode at runtime. - runInShell(RPC_PROTOCOLS.OP_COMMAND, function() { - assert(db.getMongo().getClientRPCProtocols() === "opCommandOnly"); + // in OP_MSG only mode, then switch it to OP_QUERY mode at runtime. + runInShell(RPC_PROTOCOLS.OP_MSG, function() { + assert(db.getMongo().getClientRPCProtocols() === "opMsgOnly"); db.getMongo().setClientRPCProtocols("opQueryOnly"); assert(db.getMongo().getClientRPCProtocols() === "opQueryOnly"); db.getSiblingDB("test").rpcProtocols.find().comment("opQueryRuntime").itcount(); @@ -55,17 +55,17 @@ var RPC_PROTOCOLS = {OP_QUERY: "opQueryOnly", OP_COMMAND: "opCommandOnly"}; assert(profileDoc !== null); assert.eq(profileDoc.protocol, "op_query"); - // Test that .setClientRPCProtocols("opCommandOnly") forces OP_COMMAND commands. We start the - // shell in OP_QUERY only mode, then switch it to OP_COMMAND mode at runtime. + // Test that .setClientRPCProtocols("opMsgOnly") forces OP_MSG commands. We start the + // shell in OP_QUERY only mode, then switch it to OP_MSG mode at runtime. runInShell(RPC_PROTOCOLS.OP_QUERY, function() { assert(db.getMongo().getClientRPCProtocols() === "opQueryOnly"); - db.getMongo().setClientRPCProtocols("opCommandOnly"); - assert(db.getMongo().getClientRPCProtocols() === "opCommandOnly"); - db.getSiblingDB("test").rpcProtocols.find().comment("opCommandRuntime").itcount(); + db.getMongo().setClientRPCProtocols("opMsgOnly"); + assert(db.getMongo().getClientRPCProtocols() === "opMsgOnly"); + db.getSiblingDB("test").rpcProtocols.find().comment("opMsgRuntime").itcount(); }); - profileDoc = db.system.profile.findOne({"command.comment": "opCommandRuntime"}); + profileDoc = db.system.profile.findOne({"command.comment": "opMsgRuntime"}); assert(profileDoc !== null); - assert.eq(profileDoc.protocol, "op_command"); + assert.eq(profileDoc.protocol, "op_msg"); // Reset profiling level. assert.commandWorked(db.setProfilingLevel(oldProfilingLevel)); diff --git a/src/mongo/client/dbclient_base.h b/src/mongo/client/dbclient_base.h index 141f41f880d..7ce43ba657b 100644 --- a/src/mongo/client/dbclient_base.h +++ b/src/mongo/client/dbclient_base.h @@ -702,7 +702,7 @@ private: /** * The rpc protocol the remote server(s) support. We support 'opQueryOnly' by default unless - * we detect support for OP_COMMAND at connection time. + * we detect support for OP_MSG at connection time. */ rpc::ProtocolSet _serverRPCProtocols{rpc::supports::kOpQueryOnly}; diff --git a/src/mongo/client/dbclient_connection.cpp b/src/mongo/client/dbclient_connection.cpp index dbabb5ebc82..d0940a873e4 100644 --- a/src/mongo/client/dbclient_connection.cpp +++ b/src/mongo/client/dbclient_connection.cpp @@ -109,7 +109,7 @@ executor::RemoteCommandResponse initWireVersion(DBClientConnection* conn, StringData applicationName) { try { // We need to force the usage of OP_QUERY on this command, even if we have previously - // detected support for OP_COMMAND on a connection. This is necessary to handle the case + // detected support for OP_MSG on a connection. This is necessary to handle the case // where we reconnect to an older version of MongoDB running at the same host/port. ScopedForceOpQuery forceOpQuery{conn}; diff --git a/src/mongo/client/dbclient_cursor.cpp b/src/mongo/client/dbclient_cursor.cpp index bafdfea1990..321d19d0eef 100644 --- a/src/mongo/client/dbclient_cursor.cpp +++ b/src/mongo/client/dbclient_cursor.cpp @@ -247,7 +247,7 @@ void DBClientCursor::exhaustReceiveMore() { BSONObj DBClientCursor::commandDataReceived(const Message& reply) { int op = reply.operation(); - invariant(op == opReply || op == dbCommandReply || op == dbMsg); + invariant(op == opReply || op == dbMsg); auto commandReply = _client->parseCommandReplyMessage(_client->getServerAddress(), reply); auto commandStatus = getStatusFromCommandResult(commandReply->getCommandReply()); diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index b792d074862..a33f95db62f 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -442,8 +442,7 @@ env.Library( LIBDEPS=[ "$BUILD_DIR/mongo/client/clientdriver_network", "$BUILD_DIR/mongo/db/auth/auth", - "$BUILD_DIR/mongo/rpc/command_reply", - "$BUILD_DIR/mongo/rpc/command_request", + "$BUILD_DIR/mongo/rpc/rpc", "$BUILD_DIR/mongo/rpc/metadata", "$BUILD_DIR/mongo/util/processinfo", "$BUILD_DIR/mongo/util/signal_handlers", diff --git a/src/mongo/db/curop.cpp b/src/mongo/db/curop.cpp index e6bc3462528..edd98dc2b99 100644 --- a/src/mongo/db/curop.cpp +++ b/src/mongo/db/curop.cpp @@ -285,7 +285,7 @@ void CurOp::setGenericOpRequestDetails(OperationContext* opCtx, // Set the _isCommand flags based on network op only. For legacy writes on mongoS, we resolve // them to OpMsgRequests and then pass them into the Commands path, so having a valid Command* // here does not guarantee that the op was issued from the client using a command protocol. - const bool isCommand = (op == dbMsg || op == dbCommand || (op == dbQuery && nss.isCommand())); + const bool isCommand = (op == dbMsg || (op == dbQuery && nss.isCommand())); auto logicalOp = (command ? command->getLogicalOp() : networkOpToLogicalOp(op)); stdx::lock_guard<Client> clientLock(*opCtx->getClient()); @@ -478,8 +478,6 @@ StringData getProtoString(int op) { return "op_msg"; } else if (op == dbQuery) { return "op_query"; - } else if (op == dbCommand) { - return "op_command"; } MONGO_UNREACHABLE; } diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h index 52b03ac7db2..4782935f8bf 100644 --- a/src/mongo/db/curop.h +++ b/src/mongo/db/curop.h @@ -150,10 +150,10 @@ public: // ------------------- // basic options - // _networkOp represents the network-level op code: OP_QUERY, OP_GET_MORE, OP_COMMAND, etc. + // _networkOp represents the network-level op code: OP_QUERY, OP_GET_MORE, OP_MSG, etc. NetworkOp networkOp{opInvalid}; // only set this through setNetworkOp_inlock() to keep synced // _logicalOp is the logical operation type, ie 'dbQuery' regardless of whether this is an - // OP_QUERY find, a find command using OP_QUERY, or a find command using OP_COMMAND. + // OP_QUERY find, a find command using OP_QUERY, or a find command using OP_MSG. // Similarly, the return value will be dbGetMore for both OP_GET_MORE and getMore command. LogicalOp logicalOp{LogicalOp::opInvalid}; // only set this through setNetworkOp_inlock() bool iscommand{false}; @@ -578,10 +578,10 @@ private: // The cumulative duration for which the timer has been paused. Microseconds _totalPausedDuration{0}; - // _networkOp represents the network-level op code: OP_QUERY, OP_GET_MORE, OP_COMMAND, etc. + // _networkOp represents the network-level op code: OP_QUERY, OP_GET_MORE, OP_MSG, etc. NetworkOp _networkOp{opInvalid}; // only set this through setNetworkOp_inlock() to keep synced // _logicalOp is the logical operation type, ie 'dbQuery' regardless of whether this is an - // OP_QUERY find, a find command using OP_QUERY, or a find command using OP_COMMAND. + // OP_QUERY find, a find command using OP_QUERY, or a find command using OP_MSG. // Similarly, the return value will be dbGetMore for both OP_GET_MORE and getMore command. LogicalOp _logicalOp{LogicalOp::opInvalid}; // only set this through setNetworkOp_inlock() diff --git a/src/mongo/db/dbmessage.h b/src/mongo/db/dbmessage.h index e545130e7ed..f3e711bfae8 100644 --- a/src/mongo/db/dbmessage.h +++ b/src/mongo/db/dbmessage.h @@ -450,7 +450,7 @@ struct DbResponse { /** * Prepares query replies to legacy finds (opReply to dbQuery) in place. This is also used for - * command responses that don't use the new dbCommand protocol. + * command responses that don't use the new dbMsg protocol. */ class OpQueryReplyBuilder { MONGO_DISALLOW_COPYING(OpQueryReplyBuilder); diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp index ac6d691418b..16a4671961f 100644 --- a/src/mongo/db/service_entry_point_common.cpp +++ b/src/mongo/db/service_entry_point_common.cpp @@ -1297,7 +1297,7 @@ DbResponse ServiceEntryPointCommon::handleRequest(OperationContext* opCtx, if (nsString.isCommand()) { isCommand = true; } - } else if (op == dbCommand || op == dbMsg) { + } else if (op == dbMsg) { isCommand = true; } @@ -1316,7 +1316,7 @@ DbResponse ServiceEntryPointCommon::handleRequest(OperationContext* opCtx, bool forceLog = false; DbResponse dbresponse; - if (op == dbMsg || op == dbCommand || (op == dbQuery && isCommand)) { + if (op == dbMsg || (op == dbQuery && isCommand)) { dbresponse = receivedCommands(opCtx, m, behaviors); } else if (op == dbQuery) { invariant(!isCommand); diff --git a/src/mongo/dbtests/mock/mock_remote_db_server.cpp b/src/mongo/dbtests/mock/mock_remote_db_server.cpp index 0d09a1036c6..0c18b18bfb1 100644 --- a/src/mongo/dbtests/mock/mock_remote_db_server.cpp +++ b/src/mongo/dbtests/mock/mock_remote_db_server.cpp @@ -32,9 +32,8 @@ #include <tuple> #include "mongo/dbtests/mock/mock_dbclient_connection.h" -#include "mongo/rpc/command_reply.h" -#include "mongo/rpc/command_reply_builder.h" #include "mongo/rpc/metadata.h" +#include "mongo/rpc/op_msg_rpc_impls.h" #include "mongo/stdx/memory.h" #include "mongo/util/assert_util.h" #include "mongo/util/mongoutils/str.h" @@ -163,12 +162,12 @@ rpc::UniqueReply MockRemoteDBServer::runCommand(InstanceID id, const OpMsgReques } // We need to construct a reply message - it will always be read through a view so it - // doesn't matter whether we use CommandReplBuilder or LegacyReplyBuilder - auto message = rpc::CommandReplyBuilder{} + // doesn't matter whether we use OpMsgReplyBuilder or LegacyReplyBuilder + auto message = rpc::OpMsgReplyBuilder{} .setCommandReply(reply) .setMetadata(rpc::makeEmptyMetadata()) .done(); - auto replyView = stdx::make_unique<rpc::CommandReply>(&message); + auto replyView = stdx::make_unique<rpc::OpMsgReply>(&message); return rpc::UniqueReply(std::move(message), std::move(replyView)); } diff --git a/src/mongo/executor/network_interface.h b/src/mongo/executor/network_interface.h index dc3a089626e..f76adbfe35b 100644 --- a/src/mongo/executor/network_interface.h +++ b/src/mongo/executor/network_interface.h @@ -135,7 +135,7 @@ public: /** * Starts asynchronous execution of the command described by "request". * - * The request mutated to append request metadata to be sent in OP_Command messages. + * The request mutated to append request metadata to be merged into the request messages. * * Returns ErrorCodes::ShutdownInProgress if NetworkInterface::shutdown has already started * and Status::OK() otherwise. If it returns Status::OK(), then the onFinish argument will be diff --git a/src/mongo/rpc/SConscript b/src/mongo/rpc/SConscript index fff0a749384..95769004eb1 100644 --- a/src/mongo/rpc/SConscript +++ b/src/mongo/rpc/SConscript @@ -47,8 +47,6 @@ env.Library( 'factory.cpp', ], LIBDEPS=[ - 'command_reply', - 'command_request', 'legacy_reply', 'legacy_request', 'metadata', @@ -73,21 +71,6 @@ env.Library( env.Library( target=[ - 'command_request', - ], - source=[ - 'command_request.cpp', - 'command_request_builder.cpp', - ], - LIBDEPS=[ - '$BUILD_DIR/mongo/client/read_preference', - '$BUILD_DIR/mongo/db/server_options_core', - '$BUILD_DIR/mongo/util/net/network', - ], -) - -env.Library( - target=[ 'legacy_request', ], source=[ @@ -103,31 +86,17 @@ env.Library( env.Library( target=[ - 'command_reply', - ], - source=[ - 'command_reply.cpp', - 'command_reply_builder.cpp', - 'reply_builder_interface.cpp', - ], - LIBDEPS=[ - '$BUILD_DIR/mongo/db/server_options_core', - '$BUILD_DIR/mongo/util/net/network', - ], -) - -env.Library( - target=[ 'legacy_reply', ], source=[ 'legacy_reply.cpp', - 'legacy_reply_builder.cpp' + 'legacy_reply_builder.cpp', + 'reply_builder_interface.cpp', ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/server_options_core', '$BUILD_DIR/mongo/s/common_s', '$BUILD_DIR/mongo/util/net/network', - 'command_reply', 'metadata', 'object_check', ], @@ -197,9 +166,6 @@ env.CppUnitTest( 'rpc_test', ], source=[ - 'command_reply_test.cpp', - 'command_request_builder_test.cpp', - 'command_request_test.cpp', 'get_status_from_command_result_test.cpp', 'legacy_request_test.cpp', 'object_check_test.cpp', diff --git a/src/mongo/rpc/command_reply.cpp b/src/mongo/rpc/command_reply.cpp deleted file mode 100644 index 79de0cc5506..00000000000 --- a/src/mongo/rpc/command_reply.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/rpc/command_reply.h" - -#include <tuple> -#include <utility> - -#include "mongo/base/data_range_cursor.h" -#include "mongo/base/data_type_validated.h" -#include "mongo/bson/simple_bsonobj_comparator.h" -#include "mongo/rpc/message.h" -#include "mongo/rpc/object_check.h" - -namespace mongo { -namespace rpc { - -CommandReply::CommandReply(const Message* message) : _message(message) { - const char* begin = _message->singleData().data(); - std::size_t length = _message->singleData().dataLen(); - - // This check failing would normally be operation fatal, but we expect it to have been - // done earlier in the network layer, so we make it an invariant. - invariant(length <= MaxMessageSizeBytes); - - const char* messageEnd = begin + length; - ConstDataRangeCursor cur(begin, messageEnd); - - _commandReply = uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val; - _commandReply.shareOwnershipWith(message->sharedBuffer()); - - // OP_COMMAND is only used when communicating with 3.4 nodes and they serialize their metadata - // fields differently. We do all up- and down-conversion here so that the rest of the code only - // has to deal with the current format. - auto rawMetadata = uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val; - BSONObjBuilder metadataBuilder; - for (auto elem : rawMetadata) { - if (elem.fieldNameStringData() == "configsvr") { - metadataBuilder.appendAs(elem, "$configServerState"); - } else { - metadataBuilder.append(elem); - } - } - _metadata = metadataBuilder.obj(); - - uassert(40420, "OP_COMMAND reply contains trailing bytes following metadata", cur.empty()); -} - -const BSONObj& CommandReply::getMetadata() const { - return _metadata; -} - -const BSONObj& CommandReply::getCommandReply() const { - return _commandReply; -} - -Protocol CommandReply::getProtocol() const { - return rpc::Protocol::kOpCommandV1; -} - -bool operator==(const CommandReply& lhs, const CommandReply& rhs) { - SimpleBSONObjComparator bsonComparator; - return bsonComparator.evaluate(lhs._metadata == rhs._metadata) && - bsonComparator.evaluate(lhs._commandReply == rhs._commandReply); -} - -bool operator!=(const CommandReply& lhs, const CommandReply& rhs) { - return !(lhs == rhs); -} - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/command_reply.h b/src/mongo/rpc/command_reply.h deleted file mode 100644 index e1fb849f063..00000000000 --- a/src/mongo/rpc/command_reply.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include "mongo/db/jsobj.h" -#include "mongo/rpc/reply_interface.h" - -namespace mongo { -class Message; - -namespace rpc { - -/** - * An immutable view of an OP_COMMANDREPLY message. The underlying bytes are owned - * by a mongo::Message, which must outlive any Reply instances created from it. - * - * TODO: _metadata and _commandReply are owned by the underlying message. When - * we implement a BSONObjView or similar, we should use that here to make these semantics - * explicit. - * See SERVER-16730 for additional details. - */ -class CommandReply : public ReplyInterface { -public: - /** - * Construct a Reply from a Message. - * The underlying message MUST outlive the Reply. - * Required fields are parsed eagerly, outputDocs are parsed lazily. - * - * The underlying Message also handles the wire-protocol header. - */ - explicit CommandReply(const Message* message); - - /** - * Accessor for the metadata object. Metadata is generally used for information - * that is independent of any specific command, e.g. auditing information. - */ - const BSONObj& getMetadata() const final; - - /** - * The result of executing the command. - */ - const BSONObj& getCommandReply() const final; - - Protocol getProtocol() const final; - - friend bool operator==(const CommandReply& lhs, const CommandReply& rhs); - friend bool operator!=(const CommandReply& lhs, const CommandReply& rhs); - -private: - const Message* _message; - - BSONObj _metadata; - BSONObj _commandReply; -}; - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/command_reply_builder.cpp b/src/mongo/rpc/command_reply_builder.cpp deleted file mode 100644 index ba62df3e72e..00000000000 --- a/src/mongo/rpc/command_reply_builder.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/rpc/command_reply_builder.h" - -#include <utility> - -#include "mongo/rpc/message.h" -#include "mongo/stdx/memory.h" -#include "mongo/util/assert_util.h" -#include "mongo/util/mongoutils/str.h" - -namespace mongo { -namespace rpc { - -CommandReplyBuilder::CommandReplyBuilder() : CommandReplyBuilder(Message{}) {} - -CommandReplyBuilder::CommandReplyBuilder(Message&& message) : _message{std::move(message)} { - _builder.skip(mongo::MsgData::MsgDataHeaderSize); -} - -CommandReplyBuilder& CommandReplyBuilder::setRawCommandReply(const BSONObj& commandReply) { - invariant(_state == State::kCommandReply); - commandReply.appendSelfToBufBuilder(_builder); - _state = State::kMetadata; - return *this; -} - -BSONObjBuilder CommandReplyBuilder::getBodyBuilder() { - if (_state == State::kMetadata) { - invariant(_bodyOffset); - return BSONObjBuilder(BSONObjBuilder::ResumeBuildingTag{}, _builder, _bodyOffset); - } - invariant(_state == State::kCommandReply); - _state = State::kMetadata; - auto bob = BSONObjBuilder(_builder); - _bodyOffset = bob.offset(); - return bob; -} - -CommandReplyBuilder& CommandReplyBuilder::setMetadata(const BSONObj& metadata) { - invariant(_state == State::kMetadata); - // OP_COMMAND is only used when communicating with 3.4 nodes and they serialize their metadata - // fields differently. We do all up- and down-conversion here so that the rest of the code only - // has to deal with the current format. - BSONObjBuilder bob(_builder); - for (auto elem : metadata) { - if (elem.fieldNameStringData() == "$configServerState") { - bob.appendAs(elem, "configsvr"); - } else { - bob.append(elem); - } - } - _state = State::kOutputDocs; - return *this; -} - -Protocol CommandReplyBuilder::getProtocol() const { - return rpc::Protocol::kOpCommandV1; -} - -void CommandReplyBuilder::reset() { - // If we are in State::kCommandReply, we are already in the 'start' state, so by - // immediately returning, we save a heap allocation. - if (_state == State::kCommandReply) { - return; - } - _builder.reset(); - _builder.skip(mongo::MsgData::MsgDataHeaderSize); - _message.reset(); - _state = State::kCommandReply; - _bodyOffset = 0; -} - -Message CommandReplyBuilder::done() { - invariant(_state == State::kOutputDocs); - MsgData::View msg = _builder.buf(); - msg.setLen(_builder.len()); - msg.setOperation(dbCommandReply); - _message.setData(_builder.release()); - _state = State::kDone; - return std::move(_message); -} - -} // rpc -} // mongo diff --git a/src/mongo/rpc/command_reply_builder.h b/src/mongo/rpc/command_reply_builder.h deleted file mode 100644 index d3d741d678f..00000000000 --- a/src/mongo/rpc/command_reply_builder.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include <memory> - -#include "mongo/base/status.h" -#include "mongo/db/jsobj.h" -#include "mongo/rpc/message.h" -#include "mongo/rpc/protocol.h" -#include "mongo/rpc/reply_builder_interface.h" - -namespace mongo { -namespace rpc { - -/** - * Constructs an OP_COMMANDREPLY message. - */ -class CommandReplyBuilder : public ReplyBuilderInterface { -public: - /** - * Constructs an OP_COMMANDREPLY in a new buffer. - */ - CommandReplyBuilder(); - - /* - * Constructs an OP_COMMANDREPLY in an existing buffer. Ownership of the buffer - * will be transfered to the CommandReplyBuilder. - */ - CommandReplyBuilder(Message&& message); - - - CommandReplyBuilder& setRawCommandReply(const BSONObj& commandReply) final; - BSONObjBuilder getBodyBuilder() final; - - CommandReplyBuilder& setMetadata(const BSONObj& metadata) final; - - Protocol getProtocol() const final; - - void reset() final; - - /** - * Writes data then transfers ownership of the message to the caller. - * The behavior of calling any methods on the object is subsequently - * undefined. - */ - Message done() final; - - void reserveBytes(const std::size_t bytes) final { - _builder.reserveBytes(bytes); - _builder.claimReservedBytes(bytes); - } - -private: - enum class State { kMetadata, kCommandReply, kOutputDocs, kDone }; - - // Default values are all empty. - std::size_t _bodyOffset = 0; - BufBuilder _builder{}; - Message _message; - State _state{State::kCommandReply}; -}; - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/command_reply_test.cpp b/src/mongo/rpc/command_reply_test.cpp deleted file mode 100644 index e207c497b2b..00000000000 --- a/src/mongo/rpc/command_reply_test.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects - * for all of the code used other than as permitted herein. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you do not - * wish to do so, delete this exception statement from your version. If you - * delete this exception statement from all source files in the program, - * then also delete it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include <cstdint> -#include <iterator> -#include <string> -#include <vector> - -#include "mongo/base/data_type_endian.h" -#include "mongo/base/data_view.h" -#include "mongo/db/jsobj.h" -#include "mongo/rpc/command_reply.h" -#include "mongo/rpc/message.h" -#include "mongo/stdx/memory.h" -#include "mongo/unittest/unittest.h" - -namespace { - -using namespace mongo; - -using std::begin; -using std::end; - -class ReplyTest : public mongo::unittest::Test { -protected: - std::vector<char> _cmdData{}; - Message _message{}; - - virtual void setUp() override { - _message.reset(); - } - - virtual void tearDown() override { - _cmdData.clear(); - } - - void writeObj(const BSONObj& obj) { - _cmdData.insert(end(_cmdData), obj.objdata(), obj.objdata() + obj.objsize()); - } - - void writeObj(const BSONObj& obj, std::size_t length) { - _cmdData.insert(end(_cmdData), obj.objdata(), obj.objdata() + length); - } - - const Message* buildMessage() { - _cmdData.shrink_to_fit(); - _message.setData(dbCommandReply, _cmdData.data(), _cmdData.size()); - return &_message; - } -}; - -TEST_F(ReplyTest, ParseAllFields) { - BSONObjBuilder commandReplyBob{}; - commandReplyBob.append("baz", "garply"); - auto commandReply = commandReplyBob.done(); - writeObj(commandReply); - - BSONObjBuilder metadataBob{}; - metadataBob.append("foo", "bar"); - auto metadata = metadataBob.done(); - writeObj(metadata); - - rpc::CommandReply opCmdReply{buildMessage()}; - - ASSERT_BSONOBJ_EQ(opCmdReply.getMetadata(), metadata); - ASSERT_BSONOBJ_EQ(opCmdReply.getCommandReply(), commandReply); -} - -TEST_F(ReplyTest, EmptyMessageThrows) { - ASSERT_THROWS(rpc::CommandReply{buildMessage()}, AssertionException); -} - -TEST_F(ReplyTest, MetadataOnlyThrows) { - BSONObjBuilder metadataBob{}; - metadataBob.append("foo", "bar"); - auto metadata = metadataBob.done(); - writeObj(metadata); - - ASSERT_THROWS(rpc::CommandReply{buildMessage()}, AssertionException); -} - -TEST_F(ReplyTest, MetadataInvalidLengthThrows) { - BSONObjBuilder metadataBob{}; - metadataBob.append("foo", "bar"); - auto metadata = metadataBob.done(); - auto trueSize = metadata.objsize(); - // write a super long length field - DataView(const_cast<char*>(metadata.objdata())).write<LittleEndian<int32_t>>(100000); - writeObj(metadata, trueSize); - // write a valid commandReply - BSONObjBuilder commandReplyBob{}; - commandReplyBob.append("baz", "garply"); - auto commandReply = commandReplyBob.done(); - writeObj(commandReply); - - ASSERT_THROWS(rpc::CommandReply{buildMessage()}, AssertionException); -} - -TEST_F(ReplyTest, InvalidLengthThrows) { - BSONObjBuilder metadataBob{}; - metadataBob.append("foo", "bar"); - auto metadata = metadataBob.done(); - // write a valid metadata object - writeObj(metadata); - - BSONObjBuilder commandReplyBob{}; - commandReplyBob.append("baz", "garply"); - auto commandReply = commandReplyBob.done(); - auto trueSize = commandReply.objsize(); - // write a super long length field - DataView(const_cast<char*>(commandReply.objdata())).write<LittleEndian<int32_t>>(100000); - writeObj(commandReply, trueSize); - - ASSERT_THROWS(rpc::CommandReply{buildMessage()}, AssertionException); -} -} diff --git a/src/mongo/rpc/command_request.cpp b/src/mongo/rpc/command_request.cpp deleted file mode 100644 index bce2323bfe5..00000000000 --- a/src/mongo/rpc/command_request.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/rpc/command_request.h" - -#include <string> -#include <utility> - -#include "mongo/base/data_range_cursor.h" -#include "mongo/base/data_type.h" -#include "mongo/base/data_type_terminated.h" -#include "mongo/base/data_type_validated.h" -#include "mongo/bson/simple_bsonobj_comparator.h" -#include "mongo/client/read_preference.h" -#include "mongo/db/jsobj.h" -#include "mongo/rpc/message.h" -#include "mongo/rpc/object_check.h" -#include "mongo/util/assert_util.h" -#include "mongo/util/mongoutils/str.h" - -namespace mongo { -namespace rpc { - -namespace { -// None of these include null byte -const std::size_t kMinCommandNameLength = 1; -const std::size_t kMaxCommandNameLength = 128; - -} // namespace - -ParsedOpCommand ParsedOpCommand::parse(const Message& message) { - ParsedOpCommand out; - - char* begin = message.singleData().data(); - std::size_t length = message.singleData().dataLen(); - - // checked in message_port.cpp - invariant(length <= MaxMessageSizeBytes); - - const char* messageEnd = begin + length; - - ConstDataRangeCursor cur(begin, messageEnd); - - Terminated<'\0', StringData> str; - uassertStatusOK(cur.readAndAdvance<>(&str)); - out.database = str.value.toString(); - - uassertStatusOK(cur.readAndAdvance<>(&str)); - const auto commandName = std::move(str.value); - - uassert(28637, - str::stream() << "Command name parsed in OP_COMMAND message must be between " - << kMinCommandNameLength - << " and " - << kMaxCommandNameLength - << " bytes. Got: " - << out.database, - (commandName.size() >= kMinCommandNameLength) && - (commandName.size() <= kMaxCommandNameLength)); - - Validated<BSONObj> obj; - uassertStatusOK(cur.readAndAdvance<>(&obj)); - out.body = std::move(obj.val); - uassert(39950, - str::stream() << "Command name parsed in OP_COMMAND message '" << commandName - << "' doesn't match command name from object '" - << out.body.firstElementFieldName() - << '\'', - out.body.firstElementFieldName() == commandName); - - uassertStatusOK(cur.readAndAdvance<>(&obj)); - out.metadata = std::move(obj.val); - - uassert(40419, "OP_COMMAND request contains trailing bytes following metadata", cur.empty()); - - return out; -} - -OpMsgRequest opMsgRequestFromCommandRequest(const Message& message) { - auto parsed = ParsedOpCommand::parse(message); - - BSONObjBuilder bodyBuilder(std::move(parsed.body)); - - // OP_COMMAND is only used when communicating with 3.4 nodes and they serialize their metadata - // fields differently. We do all up-conversion here so that the rest of the code only has to - // deal with the current format. - for (auto elem : parsed.metadata) { - if (elem.fieldNameStringData() == "configsvr") { - bodyBuilder.appendAs(elem, "$configServerState"); - } else if (elem.fieldNameStringData() == "$ssm") { - auto ssmObj = elem.Obj(); - if (auto readPrefElem = ssmObj["$readPreference"]) { - // Promote the read preference to the top level. - bodyBuilder.append(readPrefElem); - } else if (ssmObj["$secondaryOk"].trueValue()) { - // Convert secondaryOk to equivalent read preference if none was explicitly - // provided. - ReadPreferenceSetting(ReadPreference::SecondaryPreferred) - .toContainingBSON(&bodyBuilder); - } - } else { - bodyBuilder.append(elem); - } - } - - bodyBuilder.append("$db", parsed.database); - - OpMsgRequest request; - request.body = bodyBuilder.obj(); - return request; -} - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/command_request.h b/src/mongo/rpc/command_request.h deleted file mode 100644 index d2163185422..00000000000 --- a/src/mongo/rpc/command_request.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include "mongo/db/jsobj.h" -#include "mongo/rpc/message.h" -#include "mongo/rpc/op_msg.h" - -namespace mongo { -namespace rpc { - -/** - * This captures a full OP_COMMAND message before the body and metadata are merged. It should only - * be used for testing and implementation of opMsgRequestFromCommandRequest(). All other code should - * just use the general OpMsgRequest. - */ -struct ParsedOpCommand { - static ParsedOpCommand parse(const Message& message); - - std::string database; - BSONObj body; - BSONObj metadata; -}; - - -OpMsgRequest opMsgRequestFromCommandRequest(const Message& message); - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/command_request_builder.cpp b/src/mongo/rpc/command_request_builder.cpp deleted file mode 100644 index 68b39a460de..00000000000 --- a/src/mongo/rpc/command_request_builder.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/rpc/command_request_builder.h" - -#include "mongo/client/read_preference.h" -#include "mongo/db/command_generic_argument.h" -#include "mongo/db/commands.h" -#include "mongo/util/assert_util.h" - -namespace mongo { -namespace rpc { - -namespace { -// OP_COMMAND put some generic arguments in the metadata and some in the body. -bool fieldGoesInMetadata(StringData commandName, StringData field) { - if (!isGenericArgument(field)) - return false; // All non-generic arguments go to the body. - - // For some reason this goes in the body only for a single command... - if (field == "$replData") - return commandName != "replSetUpdatePosition"; - - // These generic arguments went in the body. - return !(field == "maxTimeMS" || field == "readConcern" || field == "writeConcern" || - field == "shardVersion"); -} -} // namespace - -Message opCommandRequestFromOpMsgRequest(const OpMsgRequest& request) { - const auto commandName = request.getCommandName(); - - BufBuilder builder; - builder.skip(mongo::MsgData::MsgDataHeaderSize); // Leave room for message header. - builder.appendStr(request.getDatabase()); - builder.appendStr(commandName); - - // OP_COMMAND is only used when communicating with 3.4 nodes and they serialize their metadata - // fields differently. In addition to field-level differences, some generic arguments are pulled - // out to a metadata object, separate from the body. We do all down-conversion here so that the - // rest of the code only has to deal with the current format. - BSONObjBuilder metadataBuilder; // Will be appended to the message after we finish the body. - { - BSONObjBuilder bodyBuilder(builder); - for (auto elem : request.body) { - const auto fieldName = elem.fieldNameStringData(); - if (fieldName == "$configServerState") { - metadataBuilder.appendAs(elem, "configsvr"); - } else if (fieldName == "$readPreference") { - BSONObjBuilder ssmBuilder(metadataBuilder.subobjStart("$ssm")); - ssmBuilder.append(elem); - ssmBuilder.append("$secondaryOk", - uassertStatusOK(ReadPreferenceSetting::fromInnerBSON(elem)) - .canRunOnSecondary()); - } else if (fieldName == "$db") { - // skip - } else if (fieldGoesInMetadata(commandName, fieldName)) { - metadataBuilder.append(elem); - } else { - bodyBuilder.append(elem); - } - } - for (auto&& seq : request.sequences) { - invariant(seq.name.find('.') == std::string::npos); // Only support top-level for now. - dassert(!bodyBuilder.asTempObj().hasField(seq.name)); - bodyBuilder.append(seq.name, seq.objs); - } - } - metadataBuilder.obj().appendSelfToBufBuilder(builder); - - MsgData::View msg = builder.buf(); - msg.setLen(builder.len()); - msg.setOperation(dbCommand); - return Message(builder.release()); -} - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/command_request_builder.h b/src/mongo/rpc/command_request_builder.h deleted file mode 100644 index e890dd978b1..00000000000 --- a/src/mongo/rpc/command_request_builder.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include "mongo/rpc/message.h" -#include "mongo/rpc/op_msg.h" - -namespace mongo { -namespace rpc { - -Message opCommandRequestFromOpMsgRequest(const OpMsgRequest& request); - -} // rpc -} // mongo diff --git a/src/mongo/rpc/command_request_builder_test.cpp b/src/mongo/rpc/command_request_builder_test.cpp deleted file mode 100644 index e635cc5910e..00000000000 --- a/src/mongo/rpc/command_request_builder_test.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/db/jsobj.h" -#include "mongo/rpc/command_request.h" -#include "mongo/rpc/command_request_builder.h" -#include "mongo/unittest/unittest.h" - -namespace { - -using namespace mongo; - -TEST(CommandRequestBuilder, RoundTrip) { - auto databaseName = "barbaz"; - auto commandName = "foobar"; - - BSONObjBuilder metadataBob{}; - metadataBob.append("$replData", BSONObj()); - auto metadata = metadataBob.done(); - - BSONObjBuilder commandArgsBob{}; - commandArgsBob.append(commandName, "baz"); - auto commandArgs = commandArgsBob.done(); - - auto request = OpMsgRequest::fromDBAndBody(databaseName, commandArgs, metadata); - request.sequences.push_back({"sequence", {BSON("a" << 1), BSON("b" << 2)}}); - auto msg = rpc::opCommandRequestFromOpMsgRequest(request); - - auto bodyAndSequence = BSONObjBuilder(commandArgs) - .append("sequence", BSON_ARRAY(BSON("a" << 1) << BSON("b" << 2))) - .obj(); - - auto parsed = mongo::rpc::ParsedOpCommand::parse(msg); - - ASSERT_EQUALS(parsed.database, databaseName); - ASSERT_EQUALS(StringData(parsed.body.firstElementFieldName()), commandName); - ASSERT_BSONOBJ_EQ(parsed.metadata, metadata); - ASSERT_BSONOBJ_EQ(parsed.body, bodyAndSequence); -} - -TEST(CommandRequestBuilder, DownconvertSecondaryReadPreferenceToSSM) { - auto readPref = BSON("mode" - << "secondary"); - auto msg = rpc::opCommandRequestFromOpMsgRequest( - OpMsgRequest::fromDBAndBody("admin", BSON("ping" << 1 << "$readPreference" << readPref))); - auto parsed = mongo::rpc::ParsedOpCommand::parse(msg); - - ASSERT(!parsed.body.hasField("$readPreference")); - ASSERT(!parsed.body.hasField("$ssm")); - ASSERT(!parsed.metadata.hasField("$readPreference")); - - ASSERT_BSONOBJ_EQ(parsed.metadata["$ssm"]["$readPreference"].Obj(), readPref); - ASSERT(parsed.metadata["$ssm"]["$secondaryOk"].trueValue()); -} - -TEST(CommandRequestBuilder, DownconvertPrimaryReadPreferenceToSSM) { - auto readPref = BSON("mode" - << "primary"); - auto msg = rpc::opCommandRequestFromOpMsgRequest( - OpMsgRequest::fromDBAndBody("admin", BSON("ping" << 1 << "$readPreference" << readPref))); - auto parsed = mongo::rpc::ParsedOpCommand::parse(msg); - - ASSERT(!parsed.body.hasField("$readPreference")); - ASSERT(!parsed.body.hasField("$ssm")); - ASSERT(!parsed.metadata.hasField("$readPreference")); - - ASSERT(!parsed.metadata["$ssm"]["$secondaryOk"].trueValue()); -} - -} // namespace diff --git a/src/mongo/rpc/command_request_test.cpp b/src/mongo/rpc/command_request_test.cpp deleted file mode 100644 index 5902766c2be..00000000000 --- a/src/mongo/rpc/command_request_test.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/** - * Copyright (C) 2015 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects - * for all of the code used other than as permitted herein. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you do not - * wish to do so, delete this exception statement from your version. If you - * delete this exception statement from all source files in the program, - * then also delete it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include <iterator> -#include <string> -#include <vector> - -#include "mongo/db/jsobj.h" -#include "mongo/rpc/command_request.h" -#include "mongo/rpc/command_request_builder.h" -#include "mongo/rpc/message.h" -#include "mongo/unittest/unittest.h" -#include "mongo/util/assert_util.h" - -namespace { - -using namespace mongo; - -TEST(CommandRequest, ParseAllFields) { - std::vector<char> opCommandData; - - using std::begin; - using std::end; - - auto writeString = [&opCommandData](const std::string& str) { - opCommandData.insert(end(opCommandData), begin(str), end(str)); - opCommandData.push_back('\0'); - }; - - auto writeObj = [&opCommandData](const BSONObj& obj) { - opCommandData.insert(end(opCommandData), obj.objdata(), obj.objdata() + obj.objsize()); - }; - - auto database = std::string{"ookokokokok"}; - writeString(database); - - auto commandName = std::string{"baz"}; - writeString(commandName); - - BSONObjBuilder commandArgsBob{}; - commandArgsBob.append("baz", "garply"); - auto commandArgs = commandArgsBob.done(); - writeObj(commandArgs); - - BSONObjBuilder metadataBob{}; - metadataBob.append("foo", "bar"); - auto metadata = metadataBob.done(); - writeObj(metadata); - - Message toSend; - toSend.setData(dbCommand, opCommandData.data(), opCommandData.size()); - - auto opCmd = rpc::ParsedOpCommand::parse(toSend); - - ASSERT_EQUALS(opCmd.body.firstElementFieldName(), commandName); - ASSERT_EQUALS(opCmd.database, database); - ASSERT_BSONOBJ_EQ(opCmd.metadata, metadata); - ASSERT_BSONOBJ_EQ(opCmd.body, commandArgs); -} - -TEST(CommandRequest, EmptyCommandObjThrows) { - std::vector<char> opCommandData; - - using std::begin; - using std::end; - - auto writeString = [&opCommandData](const std::string& str) { - opCommandData.insert(end(opCommandData), begin(str), end(str)); - opCommandData.push_back('\0'); - }; - - auto writeObj = [&opCommandData](const BSONObj& obj) { - opCommandData.insert(end(opCommandData), obj.objdata(), obj.objdata() + obj.objsize()); - }; - - auto database = std::string{"someDb"}; - writeString(database); - - auto commandName = std::string{"baz"}; - writeString(commandName); - - auto commandArgs = BSONObj(); - writeObj(commandArgs); - - BSONObjBuilder metadataBob{}; - metadataBob.append("foo", "bar"); - auto metadata = metadataBob.done(); - writeObj(metadata); - - Message msg; - msg.setData(dbCommand, opCommandData.data(), opCommandData.size()); - - ASSERT_THROWS_CODE(rpc::ParsedOpCommand::parse(msg), AssertionException, 39950); -} - -TEST(CommandRequest, MismatchBetweenCommandNamesThrows) { - std::vector<char> opCommandData; - - using std::begin; - using std::end; - - auto writeString = [&opCommandData](const std::string& str) { - opCommandData.insert(end(opCommandData), begin(str), end(str)); - opCommandData.push_back('\0'); - }; - - auto writeObj = [&opCommandData](const BSONObj& obj) { - opCommandData.insert(end(opCommandData), obj.objdata(), obj.objdata() + obj.objsize()); - }; - - auto database = std::string{"someDb"}; - writeString(database); - - auto commandName = std::string{"fakeName"}; - writeString(commandName); - - auto commandArgs = BSON("realName" << 1); - writeObj(commandArgs); - - BSONObjBuilder metadataBob{}; - metadataBob.append("foo", "bar"); - auto metadata = metadataBob.done(); - writeObj(metadata); - - Message msg; - msg.setData(dbCommand, opCommandData.data(), opCommandData.size()); - - ASSERT_THROWS_CODE(rpc::ParsedOpCommand::parse(msg), AssertionException, 39950); -} - -} // namespace diff --git a/src/mongo/rpc/factory.cpp b/src/mongo/rpc/factory.cpp index 94bd71f6c39..4d58677f8fd 100644 --- a/src/mongo/rpc/factory.cpp +++ b/src/mongo/rpc/factory.cpp @@ -30,10 +30,6 @@ #include "mongo/rpc/factory.h" -#include "mongo/rpc/command_reply.h" -#include "mongo/rpc/command_reply_builder.h" -#include "mongo/rpc/command_request.h" -#include "mongo/rpc/command_request_builder.h" #include "mongo/rpc/legacy_reply.h" #include "mongo/rpc/legacy_reply_builder.h" #include "mongo/rpc/legacy_request.h" @@ -54,11 +50,8 @@ Message messageFromOpMsgRequest(Protocol proto, const OpMsgRequest& request) { return request.serialize(); case Protocol::kOpQuery: return legacyRequestFromOpMsgRequest(request); - case Protocol::kOpCommandV1: - return opCommandRequestFromOpMsgRequest(request); - default: - MONGO_UNREACHABLE; } + MONGO_UNREACHABLE; } std::unique_ptr<ReplyInterface> makeReply(const Message* unownedMessage) { @@ -67,8 +60,6 @@ std::unique_ptr<ReplyInterface> makeReply(const Message* unownedMessage) { return stdx::make_unique<OpMsgReply>(OpMsg::parseOwned(*unownedMessage)); case mongo::opReply: return stdx::make_unique<LegacyReply>(unownedMessage); - case mongo::dbCommandReply: - return stdx::make_unique<CommandReply>(unownedMessage); default: uasserted(ErrorCodes::UnsupportedFormat, str::stream() << "Received a reply message with unexpected opcode: " @@ -82,8 +73,6 @@ OpMsgRequest opMsgRequestFromAnyProtocol(const Message& unownedMessage) { return OpMsgRequest::parse(unownedMessage); case mongo::dbQuery: return opMsgRequestFromLegacyRequest(unownedMessage); - case mongo::dbCommand: - return opMsgRequestFromCommandRequest(unownedMessage); default: uasserted(ErrorCodes::UnsupportedFormat, str::stream() << "Received a reply message with unexpected opcode: " @@ -97,11 +86,8 @@ std::unique_ptr<ReplyBuilderInterface> makeReplyBuilder(Protocol protocol) { return stdx::make_unique<OpMsgReplyBuilder>(); case Protocol::kOpQuery: return stdx::make_unique<LegacyReplyBuilder>(); - case Protocol::kOpCommandV1: - return stdx::make_unique<CommandReplyBuilder>(); - default: - MONGO_UNREACHABLE; } + MONGO_UNREACHABLE; } } // namespace rpc diff --git a/src/mongo/rpc/message.h b/src/mongo/rpc/message.h index a2fe2ec8c9d..4f2502f97bc 100644 --- a/src/mongo/rpc/message.h +++ b/src/mongo/rpc/message.h @@ -53,10 +53,10 @@ enum NetworkOp : int32_t { dbGetMore = 2005, dbDelete = 2006, dbKillCursors = 2007, - // dbCommand_DEPRECATED = 2008, // - // dbCommandReply_DEPRECATED = 2009, // - dbCommand = 2010, - dbCommandReply = 2011, + // dbCommand_DEPRECATED = 2008, // These were used during 3.2 development, but never in a + // dbCommandReply_DEPRECATED = 2009, // stable release. + // dbCommand = 2010, // These were used for intra-cluster communication in 3.2, but never + // dbCommandReply = 2011, // by any driver. Deprecated in 3.6 by OP_MSG and removed in 4.2. dbCompressed = 2012, dbMsg = 2013, }; @@ -69,15 +69,15 @@ inline bool isSupportedRequestNetworkOp(NetworkOp op) { case dbGetMore: case dbDelete: case dbKillCursors: - case dbCommand: - case dbCompressed: case dbMsg: return true; - case dbCommandReply: + + case dbCompressed: // Can be used in requests, but must be decompressed prior to handling. case opReply: - default: + case opInvalid: return false; } + return false; } enum class LogicalOp { @@ -88,7 +88,7 @@ enum class LogicalOp { opGetMore, opDelete, opKillCursors, - opCommand, + opCommand, // This just means a "command" is being run. Not related to the old OP_COMMAND. opCompressed, }; @@ -107,15 +107,16 @@ inline LogicalOp networkOpToLogicalOp(NetworkOp networkOp) { case dbKillCursors: return LogicalOp::opKillCursors; case dbMsg: - case dbCommand: return LogicalOp::opCommand; case dbCompressed: return LogicalOp::opCompressed; - default: - int op = int(networkOp); - massert(34348, str::stream() << "cannot translate opcode " << op, !op); + case opInvalid: return LogicalOp::opInvalid; + + case opReply: + break; // This has no logical op since it should never be used in a request. } + msgasserted(34348, str::stream() << "cannot translate opcode " << int32_t(networkOp)); } inline const char* networkOpToString(NetworkOp networkOp) { @@ -136,19 +137,12 @@ inline const char* networkOpToString(NetworkOp networkOp) { return "remove"; case dbKillCursors: return "killcursors"; - case dbCommand: - return "command"; - case dbCommandReply: - return "commandReply"; case dbCompressed: return "compressed"; case dbMsg: return "msg"; - default: - int op = static_cast<int>(networkOp); - massert(16141, str::stream() << "cannot translate opcode " << op, !op); - return ""; } + msgasserted(16141, str::stream() << "cannot translate opcode " << int32_t(networkOp)); } inline const char* logicalOpToString(LogicalOp logicalOp) { @@ -171,9 +165,11 @@ inline const char* logicalOpToString(LogicalOp logicalOp) { return "command"; case LogicalOp::opCompressed: return "compressed"; - default: - MONGO_UNREACHABLE; } + + // Logical ops are always created in this process and never pulled out of network requests. + // Therefore, this could only be reached by memory corruptions or other severe bugs. + MONGO_UNREACHABLE; } namespace MSGHEADER { diff --git a/src/mongo/rpc/metadata.h b/src/mongo/rpc/metadata.h index b2b3ff13a3e..0231cfcebf5 100644 --- a/src/mongo/rpc/metadata.h +++ b/src/mongo/rpc/metadata.h @@ -41,8 +41,7 @@ class OperationContext; class StringData; /** - * Utilities for converting metadata between the legacy OP_QUERY format and the new - * OP_COMMAND format. + * Utilities for dealing with what used to be called metadata. */ namespace rpc { diff --git a/src/mongo/rpc/metadata/client_metadata.h b/src/mongo/rpc/metadata/client_metadata.h index 5e3b6dc69d4..288210539af 100644 --- a/src/mongo/rpc/metadata/client_metadata.h +++ b/src/mongo/rpc/metadata/client_metadata.h @@ -190,7 +190,7 @@ public: void logClientMetadata(Client* client) const; /** - * Field name for OP_Command metadata that contains client metadata. + * Field name for requests that contains client metadata. */ static StringData fieldName(); diff --git a/src/mongo/rpc/metadata/client_metadata_ismaster.h b/src/mongo/rpc/metadata/client_metadata_ismaster.h index d50f94728e4..ed7ae555802 100644 --- a/src/mongo/rpc/metadata/client_metadata_ismaster.h +++ b/src/mongo/rpc/metadata/client_metadata_ismaster.h @@ -74,7 +74,7 @@ public: void setSeenIsMaster(); /** - * Read from the $client section of OP_Command's metadata. + * Read from the $client field in requests. * * Returns an error if the $client section is not valid. It is valid for it to not exist though. * @@ -84,7 +84,7 @@ public: static Status readFromMetadata(OperationContext* opCtx, BSONElement& elem); /** - * Write the $client section to OP_Command's metadata if there is a non-empty client metadata + * Write the $client section to request bodies if there is a non-empty client metadata * connection with the current client. * * Thread-Safety: @@ -94,7 +94,7 @@ public: private: // Optional client metadata document. - // Set if client sees isMaster cmd or as part of OP_Command processing. + // Set if client sees isMaster cmd or the $client field. // Thread-Safety: // Can be read and written from the thread owning "Client". // Can be read from other threads if they hold the "Client" lock. diff --git a/src/mongo/rpc/protocol.cpp b/src/mongo/rpc/protocol.cpp index 00fa6159ad4..4f531264400 100644 --- a/src/mongo/rpc/protocol.cpp +++ b/src/mongo/rpc/protocol.cpp @@ -47,7 +47,7 @@ namespace { /** * Protocols supported by order of preference. */ -const Protocol kPreferredProtos[] = {Protocol::kOpMsg, Protocol::kOpCommandV1, Protocol::kOpQuery}; +const Protocol kPreferredProtos[] = {Protocol::kOpMsg, Protocol::kOpQuery}; struct ProtocolSetAndName { StringData name; @@ -56,14 +56,11 @@ struct ProtocolSetAndName { constexpr ProtocolSetAndName protocolSetNames[] = { // Most common ones go first. - {"all"_sd, supports::kAll}, // new mongod. - {"opQueryAndOpMsg"_sd, supports::kOpQueryOnly | supports::kOpMsgOnly}, // new mongos. - {"opQueryAndOpCommand"_sd, supports::kOpQueryOnly | supports::kOpCommandOnly}, // old mongod. - {"opQueryOnly"_sd, supports::kOpQueryOnly}, // old mongos or very old client or mongod. + {"all"_sd, supports::kAll}, // new mongod and mongos or very new client. + {"opQueryOnly"_sd, supports::kOpQueryOnly}, // old mongos or mongod or moderately old client. // Then the rest (these should never happen in production). {"none"_sd, supports::kNone}, - {"opCommandOnly"_sd, supports::kOpCommandOnly}, {"opMsgOnly"_sd, supports::kOpMsgOnly}, }; @@ -75,8 +72,6 @@ Protocol protocolForMessage(const Message& message) { return Protocol::kOpMsg; case mongo::dbQuery: return Protocol::kOpQuery; - case mongo::dbCommand: - return Protocol::kOpCommandV1; default: uasserted(ErrorCodes::UnsupportedFormat, str::stream() << "Received a reply message with unexpected opcode: " @@ -139,19 +134,6 @@ StatusWith<ProtocolSetAndWireVersionInfo> parseProtocolSetFromIsMasterReply( return minWireExtractStatus; } - bool isMongos = false; - - std::string msgField; - auto msgFieldExtractStatus = bsonExtractStringField(isMasterReply, "msg", &msgField); - - if (msgFieldExtractStatus == ErrorCodes::NoSuchKey) { - isMongos = false; - } else if (!msgFieldExtractStatus.isOK()) { - return msgFieldExtractStatus; - } else { - isMongos = (msgField == "isdbgrid"); - } - if (minWireVersion < 0 || maxWireVersion < 0 || minWireVersion >= std::numeric_limits<int>::max() || maxWireVersion >= std::numeric_limits<int>::max()) { @@ -166,11 +148,6 @@ StatusWith<ProtocolSetAndWireVersionInfo> parseProtocolSetFromIsMasterReply( WireVersionInfo version{static_cast<int>(minWireVersion), static_cast<int>(maxWireVersion)}; auto protos = computeProtocolSet(version); - if (isMongos) { - // Remove support for protocols that mongos doesn't support. - protos &= ~supports::kOpCommandOnly; - } - return {{protos, version}}; } @@ -180,14 +157,12 @@ ProtocolSet computeProtocolSet(const WireVersionInfo version) { if (version.maxWireVersion >= WireVersion::SUPPORTS_OP_MSG) { result |= supports::kOpMsgOnly; } - if (version.maxWireVersion >= WireVersion::FIND_COMMAND && - version.maxWireVersion <= WireVersion::SHARDED_TRANSACTIONS) { - // Future versions may remove support for OP_COMMAND. - result |= supports::kOpCommandOnly; - } if (version.minWireVersion <= WireVersion::RELEASE_2_4_AND_BEFORE) { result |= supports::kOpQueryOnly; } + // Note: this means anything using the internal handshake cannot talk to servers between 2.6 + // and 3.6, since the servers will reply with higher minWireVersions. The shell should still + // be able to connect to those versions but will just use OP_QUERY to run commands. } return result; } diff --git a/src/mongo/rpc/protocol.h b/src/mongo/rpc/protocol.h index 10e770271d3..e8eab90abb6 100644 --- a/src/mongo/rpc/protocol.h +++ b/src/mongo/rpc/protocol.h @@ -57,14 +57,9 @@ enum class Protocol : std::uint64_t { kOpQuery = 1 << 0, /** - * The 3.2-3.6 OP_COMMAND protocol. - */ - kOpCommandV1 = 1 << 1, - - /** * The 3.6+ OP_MSG protocol. */ - kOpMsg = 1 << 2, + kOpMsg = 1 << 1, }; /** @@ -79,9 +74,8 @@ namespace supports { const ProtocolSet kNone = ProtocolSet{0}; const ProtocolSet kOpQueryOnly = static_cast<ProtocolSet>(Protocol::kOpQuery); -const ProtocolSet kOpCommandOnly = static_cast<ProtocolSet>(Protocol::kOpCommandV1); const ProtocolSet kOpMsgOnly = static_cast<ProtocolSet>(Protocol::kOpMsg); -const ProtocolSet kAll = kOpQueryOnly | kOpCommandOnly | kOpMsgOnly; +const ProtocolSet kAll = kOpQueryOnly | kOpMsgOnly; } // namespace supports diff --git a/src/mongo/rpc/protocol_test.cpp b/src/mongo/rpc/protocol_test.cpp index daa9e27a1b7..127b67bfb8c 100644 --- a/src/mongo/rpc/protocol_test.cpp +++ b/src/mongo/rpc/protocol_test.cpp @@ -51,7 +51,6 @@ const auto assert_negotiated = [](ProtocolSet fst, ProtocolSet snd, Protocol pro TEST(Protocol, SuccessfulNegotiation) { assert_negotiated(supports::kAll, supports::kAll, Protocol::kOpMsg); assert_negotiated(supports::kAll, supports::kOpMsgOnly, Protocol::kOpMsg); - assert_negotiated(supports::kAll, supports::kOpCommandOnly, Protocol::kOpCommandV1); assert_negotiated(supports::kAll, supports::kOpQueryOnly, Protocol::kOpQuery); } @@ -63,21 +62,21 @@ const auto assert_not_negotiated = [](ProtocolSet fst, ProtocolSet snd) { }; TEST(Protocol, FailedNegotiation) { - assert_not_negotiated(supports::kOpQueryOnly, supports::kOpCommandOnly); + assert_not_negotiated(supports::kOpQueryOnly, supports::kOpMsgOnly); assert_not_negotiated(supports::kAll, supports::kNone); assert_not_negotiated(supports::kOpQueryOnly, supports::kNone); - assert_not_negotiated(supports::kOpCommandOnly, supports::kNone); + assert_not_negotiated(supports::kOpMsgOnly, supports::kNone); } TEST(Protocol, parseProtocolSetFromIsMasterReply) { { - // MongoDB 3.8 - auto mongod38 = + // MongoDB 4.0 + auto mongod40 = BSON("maxWireVersion" << static_cast<int>(WireVersion::REPLICA_SET_TRANSACTIONS) << "minWireVersion" << static_cast<int>(WireVersion::RELEASE_2_4_AND_BEFORE)); - ASSERT_EQ(assertGet(parseProtocolSetFromIsMasterReply(mongod38)).protocolSet, + ASSERT_EQ(assertGet(parseProtocolSetFromIsMasterReply(mongod40)).protocolSet, supports::kAll); } { @@ -98,7 +97,7 @@ TEST(Protocol, parseProtocolSetFromIsMasterReply) { << static_cast<int>(WireVersion::RELEASE_2_4_AND_BEFORE)); ASSERT_EQ(assertGet(parseProtocolSetFromIsMasterReply(mongod32)).protocolSet, - supports::kOpQueryOnly | supports::kOpCommandOnly); + supports::kOpQueryOnly); // This used to also include OP_COMMAND. } { // MongoDB 3.2 (mongos) diff --git a/src/mongo/rpc/reply_builder_test.cpp b/src/mongo/rpc/reply_builder_test.cpp index f4f8ac58ef4..dd0d36a5739 100644 --- a/src/mongo/rpc/reply_builder_test.cpp +++ b/src/mongo/rpc/reply_builder_test.cpp @@ -31,8 +31,6 @@ #include "mongo/bson/util/builder.h" #include "mongo/db/jsobj.h" #include "mongo/db/json.h" -#include "mongo/rpc/command_reply.h" -#include "mongo/rpc/command_reply_builder.h" #include "mongo/rpc/get_status_from_command_result.h" #include "mongo/rpc/legacy_reply.h" #include "mongo/rpc/legacy_reply_builder.h" @@ -55,11 +53,6 @@ TEST(LegacyReplyBuilder, RoundTrip) { testRoundTrip<rpc::LegacyReply>(r, true); } -TEST(CommandReplyBuilder, RoundTrip) { - rpc::CommandReplyBuilder r; - testRoundTrip<rpc::CommandReply>(r, false); -} - TEST(OpMsgReplyBuilder, RoundTrip) { rpc::OpMsgReplyBuilder r; testRoundTrip<rpc::OpMsgReply>(r, true); @@ -73,11 +66,6 @@ TEST(LegacyReplyBuilder, Errors) { testErrors<rpc::LegacyReply>(r); } -TEST(CommandReplyBuilder, Errors) { - rpc::CommandReplyBuilder r; - testErrors<rpc::CommandReply>(r); -} - TEST(OpMsgReplyBuilder, Errors) { rpc::OpMsgReplyBuilder r; testErrors<rpc::OpMsgReply>(r); @@ -128,20 +116,6 @@ BSONObj buildErrReply(const Status status, const BSONObj& extraInfo = {}) { return bob.obj(); } -TEST(CommandReplyBuilder, CommandError) { - const Status status(ErrorCodes::InvalidLength, "Response payload too long"); - BSONObj metadata = buildMetadata(); - rpc::CommandReplyBuilder replyBuilder; - replyBuilder.setCommandReply(status); - replyBuilder.setMetadata(metadata); - auto msg = replyBuilder.done(); - - rpc::CommandReply parsed(&msg); - - ASSERT_BSONOBJ_EQ(parsed.getMetadata(), metadata); - ASSERT_BSONOBJ_EQ(parsed.getCommandReply(), buildErrReply(status)); -} - TEST(LegacyReplyBuilder, CommandError) { const Status status(ErrorCodes::InvalidLength, "Response payload too long"); BSONObj metadata = buildMetadata(); diff --git a/src/mongo/s/service_entry_point_mongos.cpp b/src/mongo/s/service_entry_point_mongos.cpp index 366c05d3f60..1172f20058e 100644 --- a/src/mongo/s/service_entry_point_mongos.cpp +++ b/src/mongo/s/service_entry_point_mongos.cpp @@ -72,7 +72,6 @@ DbResponse ServiceEntryPointMongos::handleRequest(OperationContext* opCtx, const uassert(ErrorCodes::IllegalOperation, str::stream() << "Message type " << op << " is not supported.", isSupportedRequestNetworkOp(op) && - op != dbCommand && // mongos never implemented OP_COMMAND ingress support. op != dbCompressed); // Decompression should be handled above us. // Start a new LastError session. Any exceptions thrown from here onwards will be returned diff --git a/src/mongo/shell/shell_options.cpp b/src/mongo/shell/shell_options.cpp index 311d7a22a0d..fd195020840 100644 --- a/src/mongo/shell/shell_options.cpp +++ b/src/mongo/shell/shell_options.cpp @@ -216,7 +216,7 @@ Status addMongoShellOptions(moe::OptionSection* options) { options ->addOptionChaining( - "rpcProtocols", "rpcProtocols", moe::String, " none, opQueryOnly, opCommandOnly, all") + "rpcProtocols", "rpcProtocols", moe::String, " none, opQueryOnly, opMsgOnly, all") .hidden(); auto ret = addMessageCompressionOptions(options, true); @@ -379,8 +379,7 @@ Status storeMongoShellOptions(const moe::Environment& params, if (!parsedRPCProtos.isOK()) { uasserted(28653, str::stream() << "Unknown RPC Protocols: '" << protos - << "'. Valid values are {none, opQueryOnly, " - << "opCommandOnly, all}"); + << "'. Valid values are {none, opQueryOnly, opMsgOnly, all}"); } shellGlobalParams.rpcProtocols = parsedRPCProtos.getValue(); } diff --git a/src/mongo/tools/bridge.cpp b/src/mongo/tools/bridge.cpp index 01093145986..6938882953d 100644 --- a/src/mongo/tools/bridge.cpp +++ b/src/mongo/tools/bridge.cpp @@ -40,7 +40,6 @@ #include "mongo/db/service_context.h" #include "mongo/platform/atomic_word.h" #include "mongo/platform/random.h" -#include "mongo/rpc/command_request.h" #include "mongo/rpc/factory.h" #include "mongo/rpc/message.h" #include "mongo/rpc/reply_builder_interface.h" @@ -288,7 +287,7 @@ DbResponse ServiceEntryPointBridge::handleRequest(OperationContext* opCtx, const boost::optional<OpMsgRequest> cmdRequest; if ((request.operation() == dbQuery && NamespaceString(DbMessage(request).getns()).isCommand()) || - request.operation() == dbCommand || request.operation() == dbMsg) { + request.operation() == dbMsg) { cmdRequest = rpc::opMsgRequestFromAnyProtocol(request); dest.extractHostInfo(*cmdRequest); @@ -350,10 +349,10 @@ DbResponse ServiceEntryPointBridge::handleRequest(OperationContext* opCtx, const uassertStatusOK(dest->sinkMessage(request)); // Send the message we received from 'source' to 'dest'. 'dest' returns a response for - // OP_QUERY, OP_GET_MORE, and OP_COMMAND messages that we respond with. + // OP_QUERY, OP_GET_MORE, and OP_MSG messages that we respond with. if (!isFireAndForgetCommand && (request.operation() == dbQuery || request.operation() == dbGetMore || - request.operation() == dbCommand || request.operation() == dbMsg)) { + request.operation() == dbMsg)) { // TODO dbMsg moreToCome // Forward the message to 'dest' and receive its reply in 'response'. auto response = uassertStatusOK(dest->sourceMessage()); diff --git a/src/mongo/transport/SConscript b/src/mongo/transport/SConscript index 0f61fbcf12c..2990aede9ea 100644 --- a/src/mongo/transport/SConscript +++ b/src/mongo/transport/SConscript @@ -187,8 +187,7 @@ env.CppUnitTest( 'transport_layer_mock', '$BUILD_DIR/mongo/db/dbmessage', '$BUILD_DIR/mongo/db/service_context', - '$BUILD_DIR/mongo/rpc/command_reply', - '$BUILD_DIR/mongo/rpc/command_request', + '$BUILD_DIR/mongo/rpc/rpc', '$BUILD_DIR/mongo/unittest/unittest', '$BUILD_DIR/mongo/util/clock_source_mock', ], |