summaryrefslogtreecommitdiff
path: root/src/mongo/rpc
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2015-06-20 00:22:50 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2015-06-20 10:56:02 -0400
commit9c2ed42daa8fbbef4a919c21ec564e2db55e8d60 (patch)
tree3814f79c10d7b490948d8cb7b112ac1dd41ceff1 /src/mongo/rpc
parent01965cf52bce6976637ecb8f4a622aeb05ab256a (diff)
downloadmongo-9c2ed42daa8fbbef4a919c21ec564e2db55e8d60.tar.gz
SERVER-18579: Clang-Format - reformat code, no comment reflow
Diffstat (limited to 'src/mongo/rpc')
-rw-r--r--src/mongo/rpc/command_reply.cpp82
-rw-r--r--src/mongo/rpc/command_reply.h92
-rw-r--r--src/mongo/rpc/command_reply_builder.cpp141
-rw-r--r--src/mongo/rpc/command_reply_builder.h65
-rw-r--r--src/mongo/rpc/command_reply_test.cpp231
-rw-r--r--src/mongo/rpc/command_request.cpp141
-rw-r--r--src/mongo/rpc/command_request.h104
-rw-r--r--src/mongo/rpc/command_request_builder.cpp132
-rw-r--r--src/mongo/rpc/command_request_builder.h65
-rw-r--r--src/mongo/rpc/command_request_builder_test.cpp79
-rw-r--r--src/mongo/rpc/command_request_test.cpp153
-rw-r--r--src/mongo/rpc/document_range.cpp127
-rw-r--r--src/mongo/rpc/document_range.h111
-rw-r--r--src/mongo/rpc/factory.cpp15
-rw-r--r--src/mongo/rpc/factory.h30
-rw-r--r--src/mongo/rpc/get_status_from_command_result.cpp65
-rw-r--r--src/mongo/rpc/get_status_from_command_result.h28
-rw-r--r--src/mongo/rpc/legacy_reply.cpp90
-rw-r--r--src/mongo/rpc/legacy_reply.h77
-rw-r--r--src/mongo/rpc/legacy_reply_builder.cpp165
-rw-r--r--src/mongo/rpc/legacy_reply_builder.h42
-rw-r--r--src/mongo/rpc/legacy_request.cpp84
-rw-r--r--src/mongo/rpc/legacy_request.h102
-rw-r--r--src/mongo/rpc/legacy_request_builder.cpp152
-rw-r--r--src/mongo/rpc/legacy_request_builder.h46
-rw-r--r--src/mongo/rpc/legacy_request_test.cpp20
-rw-r--r--src/mongo/rpc/metadata.cpp175
-rw-r--r--src/mongo/rpc/metadata.h148
-rw-r--r--src/mongo/rpc/metadata/audit_metadata.cpp69
-rw-r--r--src/mongo/rpc/metadata/audit_metadata.h74
-rw-r--r--src/mongo/rpc/metadata/server_selection_metadata.cpp378
-rw-r--r--src/mongo/rpc/metadata/server_selection_metadata.h133
-rw-r--r--src/mongo/rpc/metadata/server_selection_metadata_test.cpp265
-rw-r--r--src/mongo/rpc/metadata/sharding_metadata.cpp176
-rw-r--r--src/mongo/rpc/metadata/sharding_metadata.h90
-rw-r--r--src/mongo/rpc/metadata/sharding_metadata_test.cpp309
-rw-r--r--src/mongo/rpc/object_check.cpp12
-rw-r--r--src/mongo/rpc/object_check.h21
-rw-r--r--src/mongo/rpc/object_check_test.cpp76
-rw-r--r--src/mongo/rpc/protocol.cpp86
-rw-r--r--src/mongo/rpc/protocol.h82
-rw-r--r--src/mongo/rpc/protocol_test.cpp48
-rw-r--r--src/mongo/rpc/reply_builder_interface.cpp73
-rw-r--r--src/mongo/rpc/reply_builder_interface.h193
-rw-r--r--src/mongo/rpc/reply_builder_test.cpp354
-rw-r--r--src/mongo/rpc/reply_interface.h75
-rw-r--r--src/mongo/rpc/request_builder_interface.h155
-rw-r--r--src/mongo/rpc/request_interface.h95
-rw-r--r--src/mongo/rpc/unique_message.h85
49 files changed, 2728 insertions, 2883 deletions
diff --git a/src/mongo/rpc/command_reply.cpp b/src/mongo/rpc/command_reply.cpp
index dc8e22d8b89..954d6b051d6 100644
--- a/src/mongo/rpc/command_reply.cpp
+++ b/src/mongo/rpc/command_reply.cpp
@@ -41,48 +41,46 @@
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);
-
- _metadata = std::move(uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val);
- _commandReply = std::move(uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val);
- _outputDocs = DocumentRange(cur.data(), messageEnd);
- }
-
- const BSONObj& CommandReply::getMetadata() const {
- return _metadata;
- }
-
- const BSONObj& CommandReply::getCommandReply() const {
- return _commandReply;
- }
-
- DocumentRange CommandReply::getOutputDocs() const {
- return _outputDocs;
- }
-
- Protocol CommandReply::getProtocol() const {
- return rpc::Protocol::kOpCommandV1;
- }
-
- bool operator==(const CommandReply& lhs, const CommandReply& rhs) {
- return std::tie(lhs._metadata, lhs._commandReply, lhs._outputDocs) ==
- std::tie(rhs._metadata, rhs._commandReply, rhs._outputDocs);
- }
-
- bool operator!=(const CommandReply& lhs, const CommandReply& rhs) {
- return !(lhs == rhs);
- }
+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);
+
+ _metadata = std::move(uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val);
+ _commandReply = std::move(uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val);
+ _outputDocs = DocumentRange(cur.data(), messageEnd);
+}
+
+const BSONObj& CommandReply::getMetadata() const {
+ return _metadata;
+}
+
+const BSONObj& CommandReply::getCommandReply() const {
+ return _commandReply;
+}
+
+DocumentRange CommandReply::getOutputDocs() const {
+ return _outputDocs;
+}
+
+Protocol CommandReply::getProtocol() const {
+ return rpc::Protocol::kOpCommandV1;
+}
+
+bool operator==(const CommandReply& lhs, const CommandReply& rhs) {
+ return std::tie(lhs._metadata, lhs._commandReply, lhs._outputDocs) ==
+ std::tie(rhs._metadata, rhs._commandReply, rhs._outputDocs);
+}
+
+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
index 73a3fe60ccf..1e092d6db5d 100644
--- a/src/mongo/rpc/command_reply.h
+++ b/src/mongo/rpc/command_reply.h
@@ -33,65 +33,65 @@
#include "mongo/rpc/reply_interface.h"
namespace mongo {
- class Message;
+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:
/**
- * 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.
+ * Construct a Reply from a Message.
+ * The underlying message MUST outlive the Reply.
+ * Required fields are parsed eagerly, outputDocs are parsed lazily.
*
- * 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.
+ * The underlying Message also handles the wire-protocol header.
*/
- 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);
+ 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;
+ /**
+ * 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;
+ /**
+ * The result of executing the command.
+ */
+ const BSONObj& getCommandReply() const final;
- /**
- * A variable number of BSON documents returned by the command. It is valid for the
- * returned range to be empty.
- *
- * Example usage:
- *
- * for (auto&& doc : reply.getOutputDocs()) {
- * ... do stuff with doc
- * }
- */
- DocumentRange getOutputDocs() const final;
+ /**
+ * A variable number of BSON documents returned by the command. It is valid for the
+ * returned range to be empty.
+ *
+ * Example usage:
+ *
+ * for (auto&& doc : reply.getOutputDocs()) {
+ * ... do stuff with doc
+ * }
+ */
+ DocumentRange getOutputDocs() const final;
- Protocol getProtocol() const final;
+ Protocol getProtocol() const final;
- friend bool operator==(const CommandReply& lhs, const CommandReply& rhs);
- friend bool operator!=(const CommandReply& lhs, const CommandReply& rhs);
+ friend bool operator==(const CommandReply& lhs, const CommandReply& rhs);
+ friend bool operator!=(const CommandReply& lhs, const CommandReply& rhs);
- private:
- const Message* _message;
+private:
+ const Message* _message;
- BSONObj _metadata;
- BSONObj _commandReply;
- DocumentRange _outputDocs;
- };
+ BSONObj _metadata;
+ BSONObj _commandReply;
+ DocumentRange _outputDocs;
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/command_reply_builder.cpp b/src/mongo/rpc/command_reply_builder.cpp
index 0fe84ecf424..d21358e053a 100644
--- a/src/mongo/rpc/command_reply_builder.cpp
+++ b/src/mongo/rpc/command_reply_builder.cpp
@@ -37,79 +37,76 @@
namespace mongo {
namespace rpc {
- CommandReplyBuilder::CommandReplyBuilder()
- : _message{stdx::make_unique<Message>()}
- {}
-
- CommandReplyBuilder::CommandReplyBuilder(std::unique_ptr<Message> message)
- : _message{std::move(message)}
- {}
-
- CommandReplyBuilder& CommandReplyBuilder::setMetadata(BSONObj metadata) {
- invariant(_state == State::kMetadata);
- metadata.appendSelfToBufBuilder(_builder);
- _state = State::kCommandReply;
- return *this;
- }
-
- CommandReplyBuilder& CommandReplyBuilder::setRawCommandReply(BSONObj commandReply) {
- invariant(_state == State::kCommandReply);
- commandReply.appendSelfToBufBuilder(_builder);
- _state = State::kOutputDocs;
- return *this;
- }
-
- CommandReplyBuilder& CommandReplyBuilder::addOutputDocs(DocumentRange outputDocs) {
- invariant(_state == State::kOutputDocs);
- auto rangeData = outputDocs.data();
- _builder.appendBuf(rangeData.data(), rangeData.length());
- // leave state as is as we can add as many outputDocs as we want.
- return *this;
- }
-
- CommandReplyBuilder& CommandReplyBuilder::addOutputDoc(BSONObj outputDoc) {
- invariant(_state == State::kOutputDocs);
- outputDoc.appendSelfToBufBuilder(_builder);
- return *this;
- }
-
- ReplyBuilderInterface::State CommandReplyBuilder::getState() const {
- return _state;
- }
-
- Protocol CommandReplyBuilder::getProtocol() const {
- return rpc::Protocol::kOpCommandV1;
- }
-
- void CommandReplyBuilder::reset() {
- // If we are in State::kMetadata, we are already in the 'start' state, so by
- // immediately returning, we save a heap allocation.
- if (_state == State::kMetadata) {
- return;
- }
- _builder.reset();
- _message = stdx::make_unique<Message>();
- _state = State::kMetadata;
- }
-
- std::unique_ptr<Message> CommandReplyBuilder::done() {
- invariant(_state == State::kOutputDocs);
- // TODO: we can elide a large copy here by transferring the internal buffer of
- // the BufBuilder to the Message.
- _message->setData(dbCommandReply, _builder.buf(), _builder.len());
- _state = State::kDone;
- return std::move(_message);
- }
-
- std::size_t CommandReplyBuilder::availableSpaceForOutputDocs() const {
- invariant (State::kDone != _state);
- int intLen = _builder.len();
- invariant(0 <= intLen);
- std::size_t len = static_cast<std::size_t>(intLen);
- std::size_t msgHeaderSz = static_cast<std::size_t>(MsgData::MsgDataHeaderSize);
- invariant(len + msgHeaderSz <= mongo::MaxMessageSizeBytes);
- return mongo::MaxMessageSizeBytes - len - msgHeaderSz;
+CommandReplyBuilder::CommandReplyBuilder() : _message{stdx::make_unique<Message>()} {}
+
+CommandReplyBuilder::CommandReplyBuilder(std::unique_ptr<Message> message)
+ : _message{std::move(message)} {}
+
+CommandReplyBuilder& CommandReplyBuilder::setMetadata(BSONObj metadata) {
+ invariant(_state == State::kMetadata);
+ metadata.appendSelfToBufBuilder(_builder);
+ _state = State::kCommandReply;
+ return *this;
+}
+
+CommandReplyBuilder& CommandReplyBuilder::setRawCommandReply(BSONObj commandReply) {
+ invariant(_state == State::kCommandReply);
+ commandReply.appendSelfToBufBuilder(_builder);
+ _state = State::kOutputDocs;
+ return *this;
+}
+
+CommandReplyBuilder& CommandReplyBuilder::addOutputDocs(DocumentRange outputDocs) {
+ invariant(_state == State::kOutputDocs);
+ auto rangeData = outputDocs.data();
+ _builder.appendBuf(rangeData.data(), rangeData.length());
+ // leave state as is as we can add as many outputDocs as we want.
+ return *this;
+}
+
+CommandReplyBuilder& CommandReplyBuilder::addOutputDoc(BSONObj outputDoc) {
+ invariant(_state == State::kOutputDocs);
+ outputDoc.appendSelfToBufBuilder(_builder);
+ return *this;
+}
+
+ReplyBuilderInterface::State CommandReplyBuilder::getState() const {
+ return _state;
+}
+
+Protocol CommandReplyBuilder::getProtocol() const {
+ return rpc::Protocol::kOpCommandV1;
+}
+
+void CommandReplyBuilder::reset() {
+ // If we are in State::kMetadata, we are already in the 'start' state, so by
+ // immediately returning, we save a heap allocation.
+ if (_state == State::kMetadata) {
+ return;
}
+ _builder.reset();
+ _message = stdx::make_unique<Message>();
+ _state = State::kMetadata;
+}
+
+std::unique_ptr<Message> CommandReplyBuilder::done() {
+ invariant(_state == State::kOutputDocs);
+ // TODO: we can elide a large copy here by transferring the internal buffer of
+ // the BufBuilder to the Message.
+ _message->setData(dbCommandReply, _builder.buf(), _builder.len());
+ _state = State::kDone;
+ return std::move(_message);
+}
+
+std::size_t CommandReplyBuilder::availableSpaceForOutputDocs() const {
+ invariant(State::kDone != _state);
+ int intLen = _builder.len();
+ invariant(0 <= intLen);
+ std::size_t len = static_cast<std::size_t>(intLen);
+ std::size_t msgHeaderSz = static_cast<std::size_t>(MsgData::MsgDataHeaderSize);
+ invariant(len + msgHeaderSz <= mongo::MaxMessageSizeBytes);
+ return mongo::MaxMessageSizeBytes - len - msgHeaderSz;
+}
} // rpc
} // mongo
diff --git a/src/mongo/rpc/command_reply_builder.h b/src/mongo/rpc/command_reply_builder.h
index 55292eb6da4..2433a283e04 100644
--- a/src/mongo/rpc/command_reply_builder.h
+++ b/src/mongo/rpc/command_reply_builder.h
@@ -40,51 +40,50 @@
namespace mongo {
namespace rpc {
+/**
+ * Constructs an OP_COMMANDREPLY message.
+ */
+class CommandReplyBuilder : public ReplyBuilderInterface {
+public:
/**
- * Constructs an OP_COMMANDREPLY message.
+ * Constructs an OP_COMMANDREPLY in a new buffer.
*/
- class CommandReplyBuilder : public ReplyBuilderInterface {
- public:
-
- /**
- * Constructs an OP_COMMANDREPLY in a new buffer.
- */
- CommandReplyBuilder();
+ CommandReplyBuilder();
- /*
- * Constructs an OP_COMMANDREPLY in an existing buffer. Ownership of the buffer
- * will be transfered to the CommandReplyBuilder.
- */
- CommandReplyBuilder(std::unique_ptr<Message> message);
+ /*
+ * Constructs an OP_COMMANDREPLY in an existing buffer. Ownership of the buffer
+ * will be transfered to the CommandReplyBuilder.
+ */
+ CommandReplyBuilder(std::unique_ptr<Message> message);
- CommandReplyBuilder& setMetadata(BSONObj metadata) final;
- CommandReplyBuilder& setRawCommandReply(BSONObj commandReply) final;
+ CommandReplyBuilder& setMetadata(BSONObj metadata) final;
+ CommandReplyBuilder& setRawCommandReply(BSONObj commandReply) final;
- CommandReplyBuilder& addOutputDocs(DocumentRange outputDocs) final;
- CommandReplyBuilder& addOutputDoc(BSONObj outputDoc) final;
+ CommandReplyBuilder& addOutputDocs(DocumentRange outputDocs) final;
+ CommandReplyBuilder& addOutputDoc(BSONObj outputDoc) final;
- State getState() const final;
+ State getState() const final;
- Protocol getProtocol() const final;
+ Protocol getProtocol() const final;
- void reset() 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.
- */
- std::unique_ptr<Message> done() final;
+ /**
+ * Writes data then transfers ownership of the message to the caller.
+ * The behavior of calling any methods on the object is subsequently
+ * undefined.
+ */
+ std::unique_ptr<Message> done() final;
- std::size_t availableSpaceForOutputDocs() const final;
+ std::size_t availableSpaceForOutputDocs() const final;
- private:
- // Default values are all empty.
- BufBuilder _builder{};
- std::unique_ptr<Message> _message;
+private:
+ // Default values are all empty.
+ BufBuilder _builder{};
+ std::unique_ptr<Message> _message;
- State _state{State::kMetadata};
- };
+ State _state{State::kMetadata};
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/command_reply_test.cpp b/src/mongo/rpc/command_reply_test.cpp
index 48930bbe1b9..e00b8df5ec5 100644
--- a/src/mongo/rpc/command_reply_test.cpp
+++ b/src/mongo/rpc/command_reply_test.cpp
@@ -43,133 +43,126 @@
namespace {
- using namespace mongo;
-
- using std::begin;
- using std::end;
-
- class ReplyTest : public mongo::unittest::Test {
- protected:
- std::vector<char> _cmdData{};
- // using unique ptr so we can destroy and replace easily
- // since message does not have operator= or swap defined...
- std::unique_ptr<Message> _message{};
-
- virtual void setUp() override {
- _message = stdx::make_unique<Message>();
- }
-
- 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.get();
- }
-
- };
-
- TEST_F(ReplyTest, ParseAllFields) {
-
- BSONObjBuilder metadataBob{};
- metadataBob.append("foo", "bar");
- auto metadata = metadataBob.done();
- writeObj(metadata);
-
- BSONObjBuilder commandReplyBob{};
- commandReplyBob.append("baz", "garply");
- auto commandReply = commandReplyBob.done();
- writeObj(commandReply);
-
- BSONObjBuilder outputDoc1Bob{};
- outputDoc1Bob.append("meep", "boop").append("meow", "chirp");
- auto outputDoc1 = outputDoc1Bob.done();
- writeObj(outputDoc1);
-
- BSONObjBuilder outputDoc2Bob{};
- outputDoc1Bob.append("bleep", "bop").append("woof", "squeak");
- auto outputDoc2 = outputDoc2Bob.done();
- writeObj(outputDoc2);
-
- rpc::CommandReply opCmdReply{buildMessage()};
-
- ASSERT_EQUALS(opCmdReply.getMetadata(), metadata);
- ASSERT_EQUALS(opCmdReply.getCommandReply(), commandReply);
-
- auto outputDocRange = opCmdReply.getOutputDocs();
- auto outputDocRangeIter = outputDocRange.begin();
-
- ASSERT_EQUALS(*outputDocRangeIter, outputDoc1);
- // can't use assert equals since we don't have an op to print the iter.
- ASSERT_FALSE(outputDocRangeIter == outputDocRange.end());
- ++outputDocRangeIter;
- ASSERT_EQUALS(*outputDocRangeIter, outputDoc2);
- ASSERT_FALSE(outputDocRangeIter == outputDocRange.end());
- ++outputDocRangeIter;
-
- ASSERT_TRUE(outputDocRangeIter == outputDocRange.end());
- }
+using namespace mongo;
+
+using std::begin;
+using std::end;
- TEST_F(ReplyTest, EmptyMessageThrows) {
- ASSERT_THROWS(rpc::CommandReply{buildMessage()}, UserException);
+class ReplyTest : public mongo::unittest::Test {
+protected:
+ std::vector<char> _cmdData{};
+ // using unique ptr so we can destroy and replace easily
+ // since message does not have operator= or swap defined...
+ std::unique_ptr<Message> _message{};
+
+ virtual void setUp() override {
+ _message = stdx::make_unique<Message>();
}
- TEST_F(ReplyTest, MetadataOnlyThrows) {
- BSONObjBuilder metadataBob{};
- metadataBob.append("foo", "bar");
- auto metadata = metadataBob.done();
- writeObj(metadata);
+ virtual void tearDown() override {
+ _cmdData.clear();
+ }
- ASSERT_THROWS(rpc::CommandReply{buildMessage()}, UserException);
+ void writeObj(const BSONObj& obj) {
+ _cmdData.insert(end(_cmdData), obj.objdata(), obj.objdata() + obj.objsize());
}
- 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()}, UserException);
+ void writeObj(const BSONObj& obj, std::size_t length) {
+ _cmdData.insert(end(_cmdData), obj.objdata(), obj.objdata() + length);
}
- 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()}, UserException);
+ const Message* buildMessage() {
+ _cmdData.shrink_to_fit();
+ _message->setData(dbCommandReply, _cmdData.data(), _cmdData.size());
+ return _message.get();
}
+};
+
+TEST_F(ReplyTest, ParseAllFields) {
+ BSONObjBuilder metadataBob{};
+ metadataBob.append("foo", "bar");
+ auto metadata = metadataBob.done();
+ writeObj(metadata);
+
+ BSONObjBuilder commandReplyBob{};
+ commandReplyBob.append("baz", "garply");
+ auto commandReply = commandReplyBob.done();
+ writeObj(commandReply);
+
+ BSONObjBuilder outputDoc1Bob{};
+ outputDoc1Bob.append("meep", "boop").append("meow", "chirp");
+ auto outputDoc1 = outputDoc1Bob.done();
+ writeObj(outputDoc1);
+
+ BSONObjBuilder outputDoc2Bob{};
+ outputDoc1Bob.append("bleep", "bop").append("woof", "squeak");
+ auto outputDoc2 = outputDoc2Bob.done();
+ writeObj(outputDoc2);
+
+ rpc::CommandReply opCmdReply{buildMessage()};
+
+ ASSERT_EQUALS(opCmdReply.getMetadata(), metadata);
+ ASSERT_EQUALS(opCmdReply.getCommandReply(), commandReply);
+
+ auto outputDocRange = opCmdReply.getOutputDocs();
+ auto outputDocRangeIter = outputDocRange.begin();
+
+ ASSERT_EQUALS(*outputDocRangeIter, outputDoc1);
+ // can't use assert equals since we don't have an op to print the iter.
+ ASSERT_FALSE(outputDocRangeIter == outputDocRange.end());
+ ++outputDocRangeIter;
+ ASSERT_EQUALS(*outputDocRangeIter, outputDoc2);
+ ASSERT_FALSE(outputDocRangeIter == outputDocRange.end());
+ ++outputDocRangeIter;
+
+ ASSERT_TRUE(outputDocRangeIter == outputDocRange.end());
+}
+
+TEST_F(ReplyTest, EmptyMessageThrows) {
+ ASSERT_THROWS(rpc::CommandReply{buildMessage()}, UserException);
+}
+TEST_F(ReplyTest, MetadataOnlyThrows) {
+ BSONObjBuilder metadataBob{};
+ metadataBob.append("foo", "bar");
+ auto metadata = metadataBob.done();
+ writeObj(metadata);
+
+ ASSERT_THROWS(rpc::CommandReply{buildMessage()}, UserException);
+}
+
+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()}, UserException);
+}
+
+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()}, UserException);
+}
}
diff --git a/src/mongo/rpc/command_request.cpp b/src/mongo/rpc/command_request.cpp
index d5fd8fa4515..961c4ba7d93 100644
--- a/src/mongo/rpc/command_request.cpp
+++ b/src/mongo/rpc/command_request.cpp
@@ -47,93 +47,86 @@
namespace mongo {
namespace rpc {
- namespace {
- // None of these include null byte
- const std::size_t kMaxDatabaseLength = 63;
- const std::size_t kMinDatabaseLength = 1;
+namespace {
+// None of these include null byte
+const std::size_t kMaxDatabaseLength = 63;
+const std::size_t kMinDatabaseLength = 1;
- const std::size_t kMinCommandNameLength = 1;
- const std::size_t kMaxCommandNameLength = 128;
+const std::size_t kMinCommandNameLength = 1;
+const std::size_t kMaxCommandNameLength = 128;
- } // namespace
+} // namespace
- CommandRequest::CommandRequest(const Message* message)
- : _message(message) {
- char* begin = _message->singleData().data();
- std::size_t length = _message->singleData().dataLen();
+CommandRequest::CommandRequest(const Message* message) : _message(message) {
+ char* begin = _message->singleData().data();
+ std::size_t length = _message->singleData().dataLen();
- // checked in message_port.cpp
- invariant(length <= MaxMessageSizeBytes);
+ // checked in message_port.cpp
+ invariant(length <= MaxMessageSizeBytes);
- const char* messageEnd = begin + length;
+ const char* messageEnd = begin + length;
- ConstDataRangeCursor cur(begin, messageEnd);
+ ConstDataRangeCursor cur(begin, messageEnd);
- _database = uassertStatusOK(cur.readAndAdvance<Terminated<'\0', StringData>>());
+ _database = uassertStatusOK(cur.readAndAdvance<Terminated<'\0', StringData>>());
- uassert(28636, str::stream() << "Database parsed in OP_COMMAND message must be between"
- << kMinDatabaseLength << " and " << kMaxDatabaseLength
- << " bytes. Got: " << _database,
- (_database.size() >= kMinDatabaseLength) &&
- (_database.size() <= kMaxDatabaseLength));
+ uassert(28636,
+ str::stream() << "Database parsed in OP_COMMAND message must be between"
+ << kMinDatabaseLength << " and " << kMaxDatabaseLength
+ << " bytes. Got: " << _database,
+ (_database.size() >= kMinDatabaseLength) && (_database.size() <= kMaxDatabaseLength));
- uassert(ErrorCodes::InvalidNamespace,
- str::stream() << "Invalid database name: '" << _database << "'",
- NamespaceString::validDBName(_database));
+ uassert(ErrorCodes::InvalidNamespace,
+ str::stream() << "Invalid database name: '" << _database << "'",
+ NamespaceString::validDBName(_database));
- _commandName = uassertStatusOK(cur.readAndAdvance<Terminated<'\0', StringData>>());
+ _commandName = uassertStatusOK(cur.readAndAdvance<Terminated<'\0', StringData>>());
- uassert(28637, str::stream() << "Command name parsed in OP_COMMAND message must be between"
- << kMinCommandNameLength << " and " << kMaxCommandNameLength
- << " bytes. Got: " << _database,
- (_commandName.size() >= kMinCommandNameLength) &&
+ uassert(28637,
+ str::stream() << "Command name parsed in OP_COMMAND message must be between"
+ << kMinCommandNameLength << " and " << kMaxCommandNameLength
+ << " bytes. Got: " << _database,
+ (_commandName.size() >= kMinCommandNameLength) &&
(_commandName.size() <= kMaxCommandNameLength));
- _metadata = std::move(uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val);
- _commandArgs = std::move(uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val);
- _inputDocs = DocumentRange{cur.data(), messageEnd};
- }
-
- StringData CommandRequest::getDatabase() const {
- return _database;
- }
-
- StringData CommandRequest::getCommandName() const {
- return _commandName;
- }
-
- const BSONObj& CommandRequest::getMetadata() const {
- return _metadata;
- }
-
- const BSONObj& CommandRequest::getCommandArgs() const {
- return _commandArgs;
- }
-
- DocumentRange CommandRequest::getInputDocs() const {
- return _inputDocs;
- }
-
- bool operator==(const CommandRequest& lhs, const CommandRequest& rhs) {
- return std::tie(lhs._database,
- lhs._commandName,
- lhs._metadata,
- lhs._commandArgs,
- lhs._inputDocs) ==
- std::tie(rhs._database,
- rhs._commandName,
- rhs._metadata,
- rhs._commandArgs,
- rhs._inputDocs);
- }
-
- bool operator!=(const CommandRequest& lhs, const CommandRequest& rhs) {
- return !(lhs == rhs);
- }
-
- Protocol CommandRequest::getProtocol() const {
- return rpc::Protocol::kOpCommandV1;
- }
+ _metadata = std::move(uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val);
+ _commandArgs = std::move(uassertStatusOK(cur.readAndAdvance<Validated<BSONObj>>()).val);
+ _inputDocs = DocumentRange{cur.data(), messageEnd};
+}
+
+StringData CommandRequest::getDatabase() const {
+ return _database;
+}
+
+StringData CommandRequest::getCommandName() const {
+ return _commandName;
+}
+
+const BSONObj& CommandRequest::getMetadata() const {
+ return _metadata;
+}
+
+const BSONObj& CommandRequest::getCommandArgs() const {
+ return _commandArgs;
+}
+
+DocumentRange CommandRequest::getInputDocs() const {
+ return _inputDocs;
+}
+
+bool operator==(const CommandRequest& lhs, const CommandRequest& rhs) {
+ return std::tie(
+ lhs._database, lhs._commandName, lhs._metadata, lhs._commandArgs, lhs._inputDocs) ==
+ std::tie(rhs._database, rhs._commandName, rhs._metadata, rhs._commandArgs, rhs._inputDocs);
+}
+
+bool operator!=(const CommandRequest& lhs, const CommandRequest& rhs) {
+ return !(lhs == rhs);
+}
+
+Protocol CommandRequest::getProtocol() const {
+ return rpc::Protocol::kOpCommandV1;
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/command_request.h b/src/mongo/rpc/command_request.h
index cf2b54a7d42..bd29ca30597 100644
--- a/src/mongo/rpc/command_request.h
+++ b/src/mongo/rpc/command_request.h
@@ -35,72 +35,72 @@
#include "mongo/rpc/request_interface.h"
namespace mongo {
- class Message;
+class Message;
namespace rpc {
+/**
+ * An immutable view of an OP_COMMAND message. The underlying bytes are owned
+ * by a mongo::Message, which must outlive any Reply instances created from it.
+ *
+ * TODO: BSON validation. See SERVER-18167 for details.
+ */
+class CommandRequest : public RequestInterface {
+public:
/**
- * An immutable view of an OP_COMMAND message. The underlying bytes are owned
- * by a mongo::Message, which must outlive any Reply instances created from it.
- *
- * TODO: BSON validation. See SERVER-18167 for details.
+ * Construct a Request from a Message. Underlying message MUST outlive the Request.
+ * Required fields are parsed eagerly, inputDocs are parsed lazily.
*/
- class CommandRequest : public RequestInterface {
- public:
- /**
- * Construct a Request from a Message. Underlying message MUST outlive the Request.
- * Required fields are parsed eagerly, inputDocs are parsed lazily.
- */
- explicit CommandRequest(const Message* message);
+ explicit CommandRequest(const Message* message);
- ~CommandRequest() = default;
+ ~CommandRequest() = default;
- /**
- * The database that the command is to be executed on.
- */
- StringData getDatabase() const final;
+ /**
+ * The database that the command is to be executed on.
+ */
+ StringData getDatabase() const final;
- /**
- * The name of the command to execute.
- */
- StringData getCommandName() const final;
+ /**
+ * The name of the command to execute.
+ */
+ StringData getCommandName() const final;
- /**
- * The metadata associated with the command request. This is information that is
- * independent of any specific command, i.e. auditing information.
- */
- const BSONObj& getMetadata() const final;
+ /**
+ * The metadata associated with the command request. This is information that is
+ * independent of any specific command, i.e. auditing information.
+ */
+ const BSONObj& getMetadata() const final;
- /**
- * The arguments to the command - this is passed to the command's run() method.
- */
- const BSONObj& getCommandArgs() const final;
+ /**
+ * The arguments to the command - this is passed to the command's run() method.
+ */
+ const BSONObj& getCommandArgs() const final;
- /**
- * A variable number of BSON documents to pass to the command. It is valid for
- * the returned range to be empty.
- *
- * Example usage:
- *
- * for (auto&& doc : req.getInputDocs()) {
- * ... do stuff with doc
- * }
- */
- DocumentRange getInputDocs() const final;
+ /**
+ * A variable number of BSON documents to pass to the command. It is valid for
+ * the returned range to be empty.
+ *
+ * Example usage:
+ *
+ * for (auto&& doc : req.getInputDocs()) {
+ * ... do stuff with doc
+ * }
+ */
+ DocumentRange getInputDocs() const final;
- Protocol getProtocol() const final;
+ Protocol getProtocol() const final;
- friend bool operator==(const CommandRequest& lhs, const CommandRequest& rhs);
- friend bool operator!=(const CommandRequest& lhs, const CommandRequest& rhs);
+ friend bool operator==(const CommandRequest& lhs, const CommandRequest& rhs);
+ friend bool operator!=(const CommandRequest& lhs, const CommandRequest& rhs);
- private:
- const Message* _message;
- StringData _database;
- StringData _commandName;
- BSONObj _metadata;
- BSONObj _commandArgs;
- DocumentRange _inputDocs;
- };
+private:
+ const Message* _message;
+ StringData _database;
+ StringData _commandName;
+ BSONObj _metadata;
+ BSONObj _commandArgs;
+ DocumentRange _inputDocs;
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/command_request_builder.cpp b/src/mongo/rpc/command_request_builder.cpp
index b06fe47075d..da280c3054c 100644
--- a/src/mongo/rpc/command_request_builder.cpp
+++ b/src/mongo/rpc/command_request_builder.cpp
@@ -38,74 +38,70 @@
namespace mongo {
namespace rpc {
- CommandRequestBuilder::CommandRequestBuilder()
- : _message{stdx::make_unique<Message>()}
- {}
-
- CommandRequestBuilder::~CommandRequestBuilder()
- {}
-
- CommandRequestBuilder::CommandRequestBuilder(std::unique_ptr<Message> message)
- : _message{std::move(message)}
- {}
-
- CommandRequestBuilder& CommandRequestBuilder::setDatabase(StringData database) {
- invariant(_state == State::kDatabase);
- _builder.appendStr(database);
- _state = State::kCommandName;
- return *this;
- }
-
- CommandRequestBuilder& CommandRequestBuilder::setCommandName(StringData commandName) {
- invariant(_state == State::kCommandName);
- _builder.appendStr(commandName);
- _state = State::kMetadata;
- return *this;
- }
-
- CommandRequestBuilder& CommandRequestBuilder::setMetadata(BSONObj metadata) {
- invariant(_state == State::kMetadata);
- metadata.appendSelfToBufBuilder(_builder);
- _state = State::kCommandArgs;
- return *this;
- }
-
- CommandRequestBuilder& CommandRequestBuilder::setCommandArgs(BSONObj commandArgs) {
- invariant(_state == State::kCommandArgs);
- commandArgs.appendSelfToBufBuilder(_builder);
- _state = State::kInputDocs;
- return *this;
- }
-
- CommandRequestBuilder& CommandRequestBuilder::addInputDocs(DocumentRange inputDocs) {
- invariant(_state == State::kInputDocs);
- auto rangeData = inputDocs.data();
- _builder.appendBuf(rangeData.data(), rangeData.length());
- return *this;
- }
-
- CommandRequestBuilder& CommandRequestBuilder::addInputDoc(BSONObj inputDoc) {
- invariant(_state == State::kInputDocs);
- inputDoc.appendSelfToBufBuilder(_builder);
- return *this;
- }
-
- RequestBuilderInterface::State CommandRequestBuilder::getState() const {
- return _state;
- }
-
- Protocol CommandRequestBuilder::getProtocol() const {
- return rpc::Protocol::kOpCommandV1;
- }
-
- std::unique_ptr<Message> CommandRequestBuilder::done() {
- invariant(_state == State::kInputDocs);
- // TODO: we can elide a large copy here by transferring the internal buffer of
- // the BufBuilder to the Message.
- _message->setData(dbCommand, _builder.buf(), _builder.len());
- _state = State::kDone;
- return std::move(_message);
- }
+CommandRequestBuilder::CommandRequestBuilder() : _message{stdx::make_unique<Message>()} {}
+
+CommandRequestBuilder::~CommandRequestBuilder() {}
+
+CommandRequestBuilder::CommandRequestBuilder(std::unique_ptr<Message> message)
+ : _message{std::move(message)} {}
+
+CommandRequestBuilder& CommandRequestBuilder::setDatabase(StringData database) {
+ invariant(_state == State::kDatabase);
+ _builder.appendStr(database);
+ _state = State::kCommandName;
+ return *this;
+}
+
+CommandRequestBuilder& CommandRequestBuilder::setCommandName(StringData commandName) {
+ invariant(_state == State::kCommandName);
+ _builder.appendStr(commandName);
+ _state = State::kMetadata;
+ return *this;
+}
+
+CommandRequestBuilder& CommandRequestBuilder::setMetadata(BSONObj metadata) {
+ invariant(_state == State::kMetadata);
+ metadata.appendSelfToBufBuilder(_builder);
+ _state = State::kCommandArgs;
+ return *this;
+}
+
+CommandRequestBuilder& CommandRequestBuilder::setCommandArgs(BSONObj commandArgs) {
+ invariant(_state == State::kCommandArgs);
+ commandArgs.appendSelfToBufBuilder(_builder);
+ _state = State::kInputDocs;
+ return *this;
+}
+
+CommandRequestBuilder& CommandRequestBuilder::addInputDocs(DocumentRange inputDocs) {
+ invariant(_state == State::kInputDocs);
+ auto rangeData = inputDocs.data();
+ _builder.appendBuf(rangeData.data(), rangeData.length());
+ return *this;
+}
+
+CommandRequestBuilder& CommandRequestBuilder::addInputDoc(BSONObj inputDoc) {
+ invariant(_state == State::kInputDocs);
+ inputDoc.appendSelfToBufBuilder(_builder);
+ return *this;
+}
+
+RequestBuilderInterface::State CommandRequestBuilder::getState() const {
+ return _state;
+}
+
+Protocol CommandRequestBuilder::getProtocol() const {
+ return rpc::Protocol::kOpCommandV1;
+}
+
+std::unique_ptr<Message> CommandRequestBuilder::done() {
+ invariant(_state == State::kInputDocs);
+ // TODO: we can elide a large copy here by transferring the internal buffer of
+ // the BufBuilder to the Message.
+ _message->setData(dbCommand, _builder.buf(), _builder.len());
+ _state = State::kDone;
+ return std::move(_message);
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/command_request_builder.h b/src/mongo/rpc/command_request_builder.h
index 453b48f9cad..cf00e3f9652 100644
--- a/src/mongo/rpc/command_request_builder.h
+++ b/src/mongo/rpc/command_request_builder.h
@@ -40,54 +40,53 @@
namespace mongo {
namespace rpc {
+/**
+ * Constructs an OP_COMMAND message.
+ */
+class CommandRequestBuilder : public RequestBuilderInterface {
+public:
/**
- * Constructs an OP_COMMAND message.
+ * Constructs an OP_COMMAND in a new buffer.
*/
- class CommandRequestBuilder : public RequestBuilderInterface {
- public:
+ CommandRequestBuilder();
- /**
- * Constructs an OP_COMMAND in a new buffer.
- */
- CommandRequestBuilder();
+ ~CommandRequestBuilder() final;
- ~CommandRequestBuilder() final;
-
- /**
- * Construct an OP_COMMAND in an existing buffer. Ownership of the buffer will be
- * transfered to the CommandRequestBuilder.
- */
- CommandRequestBuilder(std::unique_ptr<Message> message);
+ /**
+ * Construct an OP_COMMAND in an existing buffer. Ownership of the buffer will be
+ * transfered to the CommandRequestBuilder.
+ */
+ CommandRequestBuilder(std::unique_ptr<Message> message);
- CommandRequestBuilder& setDatabase(StringData database) final;
+ CommandRequestBuilder& setDatabase(StringData database) final;
- CommandRequestBuilder& setCommandName(StringData commandName) final;
+ CommandRequestBuilder& setCommandName(StringData commandName) final;
- CommandRequestBuilder& setMetadata(BSONObj metadata) final;
+ CommandRequestBuilder& setMetadata(BSONObj metadata) final;
- CommandRequestBuilder& setCommandArgs(BSONObj commandArgs) final;
+ CommandRequestBuilder& setCommandArgs(BSONObj commandArgs) final;
- CommandRequestBuilder& addInputDocs(DocumentRange inputDocs) final;
+ CommandRequestBuilder& addInputDocs(DocumentRange inputDocs) final;
- CommandRequestBuilder& addInputDoc(BSONObj inputDoc) final;
+ CommandRequestBuilder& addInputDoc(BSONObj inputDoc) final;
- State getState() const final;
+ State getState() const final;
- Protocol getProtocol() const final;
+ Protocol getProtocol() const final;
- /**
- * Writes data then transfers ownership of the message to the caller.
- * The behavior of calling any methods on the object is subsequently
- * undefined.
- */
- std::unique_ptr<Message> done() final;
+ /**
+ * Writes data then transfers ownership of the message to the caller.
+ * The behavior of calling any methods on the object is subsequently
+ * undefined.
+ */
+ std::unique_ptr<Message> done() final;
- private:
- BufBuilder _builder{};
- std::unique_ptr<Message> _message;
+private:
+ BufBuilder _builder{};
+ std::unique_ptr<Message> _message;
- State _state{State::kDatabase};
- };
+ State _state{State::kDatabase};
+};
} // rpc
} // mongo
diff --git a/src/mongo/rpc/command_request_builder_test.cpp b/src/mongo/rpc/command_request_builder_test.cpp
index 10a4f2d8795..cdfbc9d01a9 100644
--- a/src/mongo/rpc/command_request_builder_test.cpp
+++ b/src/mongo/rpc/command_request_builder_test.cpp
@@ -36,57 +36,56 @@
namespace {
- using namespace mongo;
+using namespace mongo;
- TEST(RequestBuilder, RoundTrip) {
+TEST(RequestBuilder, RoundTrip) {
+ auto databaseName = "barbaz";
+ auto commandName = "foobar";
- auto databaseName = "barbaz";
- auto commandName = "foobar";
+ BSONObjBuilder metadataBob{};
+ metadataBob.append("foo", "bar");
+ auto metadata = metadataBob.done();
- BSONObjBuilder metadataBob{};
- metadataBob.append("foo", "bar");
- auto metadata = metadataBob.done();
+ BSONObjBuilder commandArgsBob{};
+ commandArgsBob.append("bar", "baz");
+ auto commandArgs = commandArgsBob.done();
- BSONObjBuilder commandArgsBob{};
- commandArgsBob.append("bar", "baz");
- auto commandArgs = commandArgsBob.done();
+ BSONObjBuilder inputDoc1Bob{};
+ inputDoc1Bob.append("z", "t");
+ auto inputDoc1 = inputDoc1Bob.done();
- BSONObjBuilder inputDoc1Bob{};
- inputDoc1Bob.append("z", "t");
- auto inputDoc1 = inputDoc1Bob.done();
+ BSONObjBuilder inputDoc2Bob{};
+ inputDoc2Bob.append("h", "j");
+ auto inputDoc2 = inputDoc2Bob.done();
- BSONObjBuilder inputDoc2Bob{};
- inputDoc2Bob.append("h", "j");
- auto inputDoc2 = inputDoc2Bob.done();
+ BSONObjBuilder inputDoc3Bob{};
+ inputDoc3Bob.append("g", "p");
+ auto inputDoc3 = inputDoc3Bob.done();
- BSONObjBuilder inputDoc3Bob{};
- inputDoc3Bob.append("g", "p");
- auto inputDoc3 = inputDoc3Bob.done();
+ BufBuilder inputDocs;
+ inputDoc1.appendSelfToBufBuilder(inputDocs);
+ inputDoc2.appendSelfToBufBuilder(inputDocs);
+ inputDoc3.appendSelfToBufBuilder(inputDocs);
- BufBuilder inputDocs;
- inputDoc1.appendSelfToBufBuilder(inputDocs);
- inputDoc2.appendSelfToBufBuilder(inputDocs);
- inputDoc3.appendSelfToBufBuilder(inputDocs);
+ rpc::DocumentRange inputDocRange{inputDocs.buf(), inputDocs.buf() + inputDocs.len()};
- rpc::DocumentRange inputDocRange{inputDocs.buf(), inputDocs.buf() + inputDocs.len()};
+ rpc::CommandRequestBuilder r;
- rpc::CommandRequestBuilder r;
+ auto msg = r.setDatabase(databaseName)
+ .setCommandName(commandName)
+ .setMetadata(metadata)
+ .setCommandArgs(commandArgs)
+ .addInputDocs(inputDocRange)
+ .done();
- auto msg = r.setDatabase(databaseName)
- .setCommandName(commandName)
- .setMetadata(metadata)
- .setCommandArgs(commandArgs)
- .addInputDocs(inputDocRange)
- .done();
+ rpc::CommandRequest parsed(msg.get());
- rpc::CommandRequest parsed(msg.get());
-
- ASSERT_EQUALS(parsed.getDatabase(), databaseName);
- ASSERT_EQUALS(parsed.getCommandName(), commandName);
- ASSERT_EQUALS(parsed.getMetadata(), metadata);
- ASSERT_EQUALS(parsed.getCommandArgs(), commandArgs);
- // need ostream overloads for ASSERT_EQUALS
- ASSERT_TRUE(parsed.getInputDocs() == inputDocRange);
- }
+ ASSERT_EQUALS(parsed.getDatabase(), databaseName);
+ ASSERT_EQUALS(parsed.getCommandName(), commandName);
+ ASSERT_EQUALS(parsed.getMetadata(), metadata);
+ ASSERT_EQUALS(parsed.getCommandArgs(), commandArgs);
+ // need ostream overloads for ASSERT_EQUALS
+ ASSERT_TRUE(parsed.getInputDocs() == inputDocRange);
+}
} // namespace
diff --git a/src/mongo/rpc/command_request_test.cpp b/src/mongo/rpc/command_request_test.cpp
index 64732735d6f..8f681655b56 100644
--- a/src/mongo/rpc/command_request_test.cpp
+++ b/src/mongo/rpc/command_request_test.cpp
@@ -41,82 +41,81 @@
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{"abababa"};
- writeString(commandName);
-
- BSONObjBuilder metadataBob{};
- metadataBob.append("foo", "bar");
- auto metadata = metadataBob.done();
- writeObj(metadata);
-
- BSONObjBuilder commandArgsBob{};
- commandArgsBob.append("baz", "garply");
- auto commandArgs = commandArgsBob.done();
- writeObj(commandArgs);
-
- BSONObjBuilder inputDoc1Bob{};
- inputDoc1Bob.append("meep", "boop").append("meow", "chirp");
- auto inputDoc1 = inputDoc1Bob.done();
- writeObj(inputDoc1);
-
- BSONObjBuilder inputDoc2Bob{};
- inputDoc1Bob.append("bleep", "bop").append("woof", "squeak");
- auto inputDoc2 = inputDoc2Bob.done();
- writeObj(inputDoc2);
-
- Message toSend;
- toSend.setData(dbCommand, opCommandData.data(), opCommandData.size());
-
- rpc::CommandRequest opCmd{&toSend};
-
- ASSERT_EQUALS(opCmd.getCommandName(), commandName);
- ASSERT_EQUALS(opCmd.getDatabase(), database);
- ASSERT_EQUALS(opCmd.getMetadata(), metadata);
- ASSERT_EQUALS(opCmd.getCommandArgs(), commandArgs);
-
- auto inputDocRange = opCmd.getInputDocs();
- auto inputDocRangeIter = inputDocRange.begin();
-
- ASSERT_EQUALS(*inputDocRangeIter, inputDoc1);
- // can't use assert equals since we don't have an op to print the iter.
- ASSERT_FALSE(inputDocRangeIter == inputDocRange.end());
- ++inputDocRangeIter;
- ASSERT_EQUALS(*inputDocRangeIter, inputDoc2);
- ASSERT_FALSE(inputDocRangeIter == inputDocRange.end());
- ++inputDocRangeIter;
-
- ASSERT_TRUE(inputDocRangeIter == inputDocRange.end());
- }
-
- TEST(CommandRequest, InvalidNSThrows) {
- rpc::CommandRequestBuilder crb;
- crb.setDatabase("foo////!!!!<><><>");
- crb.setCommandName("foo");
- crb.setMetadata(BSONObj());
- crb.setCommandArgs(BSON("ping" << 1));
- auto msg = crb.done();
- ASSERT_THROWS(rpc::CommandRequest{msg.get()}, AssertionException);
- }
+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{"abababa"};
+ writeString(commandName);
+
+ BSONObjBuilder metadataBob{};
+ metadataBob.append("foo", "bar");
+ auto metadata = metadataBob.done();
+ writeObj(metadata);
+
+ BSONObjBuilder commandArgsBob{};
+ commandArgsBob.append("baz", "garply");
+ auto commandArgs = commandArgsBob.done();
+ writeObj(commandArgs);
+
+ BSONObjBuilder inputDoc1Bob{};
+ inputDoc1Bob.append("meep", "boop").append("meow", "chirp");
+ auto inputDoc1 = inputDoc1Bob.done();
+ writeObj(inputDoc1);
+
+ BSONObjBuilder inputDoc2Bob{};
+ inputDoc1Bob.append("bleep", "bop").append("woof", "squeak");
+ auto inputDoc2 = inputDoc2Bob.done();
+ writeObj(inputDoc2);
+
+ Message toSend;
+ toSend.setData(dbCommand, opCommandData.data(), opCommandData.size());
+
+ rpc::CommandRequest opCmd{&toSend};
+
+ ASSERT_EQUALS(opCmd.getCommandName(), commandName);
+ ASSERT_EQUALS(opCmd.getDatabase(), database);
+ ASSERT_EQUALS(opCmd.getMetadata(), metadata);
+ ASSERT_EQUALS(opCmd.getCommandArgs(), commandArgs);
+
+ auto inputDocRange = opCmd.getInputDocs();
+ auto inputDocRangeIter = inputDocRange.begin();
+
+ ASSERT_EQUALS(*inputDocRangeIter, inputDoc1);
+ // can't use assert equals since we don't have an op to print the iter.
+ ASSERT_FALSE(inputDocRangeIter == inputDocRange.end());
+ ++inputDocRangeIter;
+ ASSERT_EQUALS(*inputDocRangeIter, inputDoc2);
+ ASSERT_FALSE(inputDocRangeIter == inputDocRange.end());
+ ++inputDocRangeIter;
+
+ ASSERT_TRUE(inputDocRangeIter == inputDocRange.end());
+}
+
+TEST(CommandRequest, InvalidNSThrows) {
+ rpc::CommandRequestBuilder crb;
+ crb.setDatabase("foo////!!!!<><><>");
+ crb.setCommandName("foo");
+ crb.setMetadata(BSONObj());
+ crb.setCommandArgs(BSON("ping" << 1));
+ auto msg = crb.done();
+ ASSERT_THROWS(rpc::CommandRequest{msg.get()}, AssertionException);
+}
} // namespace
diff --git a/src/mongo/rpc/document_range.cpp b/src/mongo/rpc/document_range.cpp
index 56e5d8c1add..aff2cf6dfec 100644
--- a/src/mongo/rpc/document_range.cpp
+++ b/src/mongo/rpc/document_range.cpp
@@ -42,74 +42,67 @@
namespace mongo {
namespace rpc {
- DocumentRange::DocumentRange(const char* begin, const char* end)
- : _range{begin, end}
- {}
-
- DocumentRange::const_iterator DocumentRange::begin() const {
- return const_iterator{ConstDataRangeCursor{_range}};
- }
-
- DocumentRange::const_iterator DocumentRange::end() const {
- return const_iterator{};
- }
-
- ConstDataRange DocumentRange::data() const {
- return _range;
- }
-
- bool operator==(const DocumentRange& lhs, const DocumentRange& rhs) {
- // We might want to change this to use std::equal in the future if
- // we ever allow non-contigious document ranges
- return (lhs._range.length() == rhs._range.length()) &&
- (std::memcmp(lhs._range.data(), rhs._range.data(), lhs._range.length()) == 0);
- }
-
- bool operator!=(const DocumentRange& lhs, const DocumentRange& rhs) {
- return !(lhs == rhs);
- }
-
- DocumentRange::const_iterator::const_iterator(ConstDataRangeCursor cursor)
- : _cursor{cursor} {
- operator++();
- }
-
- DocumentRange::const_iterator::reference
- DocumentRange::const_iterator::operator*() const {
- return _obj;
- }
-
- DocumentRange::const_iterator::pointer
- DocumentRange::const_iterator::operator->() const {
- return &_obj;
- }
-
- DocumentRange::const_iterator&
- DocumentRange::const_iterator::operator++() {
- if (_cursor.length() == 0) {
- *this = const_iterator{};
- } else {
- _obj = std::move(uassertStatusOK(_cursor.readAndAdvance<Validated<BSONObj>>()).val);
- }
- return *this;
- }
-
- DocumentRange::const_iterator
- DocumentRange::const_iterator::operator++(int) {
- auto pre = const_iterator{_cursor};
- operator++();
- return pre;
- }
-
- bool operator==(const DocumentRange::const_iterator& lhs,
- const DocumentRange::const_iterator& rhs) {
- return lhs._cursor == rhs._cursor;
- }
-
- bool operator!=(const DocumentRange::const_iterator& lhs,
- const DocumentRange::const_iterator& rhs) {
- return !(lhs == rhs);
+DocumentRange::DocumentRange(const char* begin, const char* end) : _range{begin, end} {}
+
+DocumentRange::const_iterator DocumentRange::begin() const {
+ return const_iterator{ConstDataRangeCursor{_range}};
+}
+
+DocumentRange::const_iterator DocumentRange::end() const {
+ return const_iterator{};
+}
+
+ConstDataRange DocumentRange::data() const {
+ return _range;
+}
+
+bool operator==(const DocumentRange& lhs, const DocumentRange& rhs) {
+ // We might want to change this to use std::equal in the future if
+ // we ever allow non-contigious document ranges
+ return (lhs._range.length() == rhs._range.length()) &&
+ (std::memcmp(lhs._range.data(), rhs._range.data(), lhs._range.length()) == 0);
+}
+
+bool operator!=(const DocumentRange& lhs, const DocumentRange& rhs) {
+ return !(lhs == rhs);
+}
+
+DocumentRange::const_iterator::const_iterator(ConstDataRangeCursor cursor) : _cursor{cursor} {
+ operator++();
+}
+
+DocumentRange::const_iterator::reference DocumentRange::const_iterator::operator*() const {
+ return _obj;
+}
+
+DocumentRange::const_iterator::pointer DocumentRange::const_iterator::operator->() const {
+ return &_obj;
+}
+
+DocumentRange::const_iterator& DocumentRange::const_iterator::operator++() {
+ if (_cursor.length() == 0) {
+ *this = const_iterator{};
+ } else {
+ _obj = std::move(uassertStatusOK(_cursor.readAndAdvance<Validated<BSONObj>>()).val);
}
+ return *this;
+}
+
+DocumentRange::const_iterator DocumentRange::const_iterator::operator++(int) {
+ auto pre = const_iterator{_cursor};
+ operator++();
+ return pre;
+}
+
+bool operator==(const DocumentRange::const_iterator& lhs,
+ const DocumentRange::const_iterator& rhs) {
+ return lhs._cursor == rhs._cursor;
+}
+
+bool operator!=(const DocumentRange::const_iterator& lhs,
+ const DocumentRange::const_iterator& rhs) {
+ return !(lhs == rhs);
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/document_range.h b/src/mongo/rpc/document_range.h
index aa8d3131b13..95d23d82b4c 100644
--- a/src/mongo/rpc/document_range.h
+++ b/src/mongo/rpc/document_range.h
@@ -38,62 +38,61 @@
namespace mongo {
namespace rpc {
- /**
- * A read-only view over a sequence of BSON documents.
- *
- * TODO:
- * - Handle document validation
- * - Currently this only supports a contiguous buffer of BSON documents,
- * in the future it should support non-contiguous buffers as well.
- */
- class DocumentRange {
- public:
- class const_iterator;
-
- DocumentRange() = default;
-
- DocumentRange(const char* begin, const char* end);
-
- const_iterator begin() const;
- const_iterator end() const;
-
- // Get a ConstDataRange over the underlying raw buffer.
- ConstDataRange data() const;
-
- // Deep equality of all documents in both ranges.
- friend bool operator==(const DocumentRange& lhs, const DocumentRange& rhs);
- friend bool operator!=(const DocumentRange& lhs, const DocumentRange& rhs);
-
- private:
- ConstDataRange _range{nullptr, nullptr};
- };
-
- class DocumentRange::const_iterator
- : public std::iterator<std::forward_iterator_tag,
- BSONObj,
- std::ptrdiff_t,
- const BSONObj*,
- const BSONObj&> {
- public:
- const_iterator() = default;
-
- reference operator*() const;
- pointer operator->() const;
-
- const_iterator& operator++();
- const_iterator operator++(int);
-
- friend bool operator==(const const_iterator&, const const_iterator&);
- friend bool operator!=(const const_iterator&, const const_iterator&);
-
- private:
- // The only way to get a non-end iterator is from DocumentRange begin().
- friend class DocumentRange;
- explicit const_iterator(ConstDataRangeCursor cursor);
-
- ConstDataRangeCursor _cursor{nullptr, nullptr};
- BSONObj _obj;
- };
+/**
+ * A read-only view over a sequence of BSON documents.
+ *
+ * TODO:
+ * - Handle document validation
+ * - Currently this only supports a contiguous buffer of BSON documents,
+ * in the future it should support non-contiguous buffers as well.
+ */
+class DocumentRange {
+public:
+ class const_iterator;
+
+ DocumentRange() = default;
+
+ DocumentRange(const char* begin, const char* end);
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ // Get a ConstDataRange over the underlying raw buffer.
+ ConstDataRange data() const;
+
+ // Deep equality of all documents in both ranges.
+ friend bool operator==(const DocumentRange& lhs, const DocumentRange& rhs);
+ friend bool operator!=(const DocumentRange& lhs, const DocumentRange& rhs);
+
+private:
+ ConstDataRange _range{nullptr, nullptr};
+};
+
+class DocumentRange::const_iterator : public std::iterator<std::forward_iterator_tag,
+ BSONObj,
+ std::ptrdiff_t,
+ const BSONObj*,
+ const BSONObj&> {
+public:
+ const_iterator() = default;
+
+ reference operator*() const;
+ pointer operator->() const;
+
+ const_iterator& operator++();
+ const_iterator operator++(int);
+
+ friend bool operator==(const const_iterator&, const const_iterator&);
+ friend bool operator!=(const const_iterator&, const const_iterator&);
+
+private:
+ // The only way to get a non-end iterator is from DocumentRange begin().
+ friend class DocumentRange;
+ explicit const_iterator(ConstDataRangeCursor cursor);
+
+ ConstDataRangeCursor _cursor{nullptr, nullptr};
+ BSONObj _obj;
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/factory.cpp b/src/mongo/rpc/factory.cpp
index 81bcf42c969..085fa9e7a7b 100644
--- a/src/mongo/rpc/factory.cpp
+++ b/src/mongo/rpc/factory.cpp
@@ -43,21 +43,20 @@
namespace mongo {
namespace rpc {
- std::unique_ptr<RequestBuilderInterface> makeRequestBuilder(ProtocolSet clientProtos,
- ProtocolSet serverProtos) {
- switch (uassertStatusOK(negotiate(clientProtos, serverProtos))) {
+std::unique_ptr<RequestBuilderInterface> makeRequestBuilder(ProtocolSet clientProtos,
+ ProtocolSet serverProtos) {
+ switch (uassertStatusOK(negotiate(clientProtos, serverProtos))) {
case Protocol::kOpQuery:
return stdx::make_unique<LegacyRequestBuilder>();
case Protocol::kOpCommandV1:
return stdx::make_unique<CommandRequestBuilder>();
default:
MONGO_UNREACHABLE;
- }
}
+}
- std::unique_ptr<ReplyInterface> makeReply(const Message* unownedMessage) {
-
- switch (unownedMessage->operation()) {
+std::unique_ptr<ReplyInterface> makeReply(const Message* unownedMessage) {
+ switch (unownedMessage->operation()) {
case mongo::opReply:
return stdx::make_unique<LegacyReply>(unownedMessage);
case mongo::dbCommandReply:
@@ -66,8 +65,8 @@ namespace rpc {
uasserted(ErrorCodes::UnsupportedFormat,
str::stream() << "Received a reply message with unexpected opcode: "
<< unownedMessage->operation());
- }
}
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/factory.h b/src/mongo/rpc/factory.h
index 93398d86e50..7de92664b69 100644
--- a/src/mongo/rpc/factory.h
+++ b/src/mongo/rpc/factory.h
@@ -38,23 +38,23 @@
*/
namespace mongo {
- class Message;
+class Message;
namespace rpc {
- class ReplyInterface;
- class RequestBuilderInterface;
-
- /**
- * Returns the appropriate concrete RequestBuilder. Throws if one cannot be chosen.
- */
- std::unique_ptr<RequestBuilderInterface> makeRequestBuilder(ProtocolSet clientProtos,
- ProtocolSet serverProtos);
-
- /**
- * Returns the appropriate concrete Reply according to the contents of the message.
- * Throws if one cannot be chosen.
- */
- std::unique_ptr<ReplyInterface> makeReply(const Message* unownedMessage);
+class ReplyInterface;
+class RequestBuilderInterface;
+
+/**
+ * Returns the appropriate concrete RequestBuilder. Throws if one cannot be chosen.
+ */
+std::unique_ptr<RequestBuilderInterface> makeRequestBuilder(ProtocolSet clientProtos,
+ ProtocolSet serverProtos);
+
+/**
+ * Returns the appropriate concrete Reply according to the contents of the message.
+ * Throws if one cannot be chosen.
+ */
+std::unique_ptr<ReplyInterface> makeReply(const Message* unownedMessage);
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/get_status_from_command_result.cpp b/src/mongo/rpc/get_status_from_command_result.cpp
index e7366abedcc..4aa06db1b3b 100644
--- a/src/mongo/rpc/get_status_from_command_result.cpp
+++ b/src/mongo/rpc/get_status_from_command_result.cpp
@@ -36,43 +36,40 @@
namespace mongo {
- Status getStatusFromCommandResult(const BSONObj& result) {
- BSONElement okElement = result["ok"];
- BSONElement codeElement = result["code"];
- BSONElement errmsgElement = result["errmsg"];
+Status getStatusFromCommandResult(const BSONObj& result) {
+ BSONElement okElement = result["ok"];
+ BSONElement codeElement = result["code"];
+ BSONElement errmsgElement = result["errmsg"];
- // StaleConfigException doesn't pass "ok" in legacy servers
- BSONElement dollarErrElement = result["$err"];
+ // StaleConfigException doesn't pass "ok" in legacy servers
+ BSONElement dollarErrElement = result["$err"];
- if (okElement.eoo() && dollarErrElement.eoo()) {
- return Status(ErrorCodes::CommandResultSchemaViolation,
- mongoutils::str::stream() << "No \"ok\" field in command result " <<
- result);
- }
- if (okElement.trueValue()) {
- return Status::OK();
- }
- int code = codeElement.numberInt();
- if (0 == code) {
- code = ErrorCodes::UnknownError;
- }
- std::string errmsg;
- if (errmsgElement.type() == String) {
- errmsg = errmsgElement.String();
- }
- else if (!errmsgElement.eoo()) {
- errmsg = errmsgElement.toString();
- }
-
- // we can't use startsWith(errmsg, "no such")
- // as we have errors such as "no such collection"
- if (code == ErrorCodes::UnknownError &&
- (str::startsWith(errmsg, "no such cmd") ||
- str::startsWith(errmsg, "no such command"))) {
- code = ErrorCodes::CommandNotFound;
- }
+ if (okElement.eoo() && dollarErrElement.eoo()) {
+ return Status(ErrorCodes::CommandResultSchemaViolation,
+ mongoutils::str::stream() << "No \"ok\" field in command result " << result);
+ }
+ if (okElement.trueValue()) {
+ return Status::OK();
+ }
+ int code = codeElement.numberInt();
+ if (0 == code) {
+ code = ErrorCodes::UnknownError;
+ }
+ std::string errmsg;
+ if (errmsgElement.type() == String) {
+ errmsg = errmsgElement.String();
+ } else if (!errmsgElement.eoo()) {
+ errmsg = errmsgElement.toString();
+ }
- return Status(ErrorCodes::Error(code), errmsg);
+ // we can't use startsWith(errmsg, "no such")
+ // as we have errors such as "no such collection"
+ if (code == ErrorCodes::UnknownError &&
+ (str::startsWith(errmsg, "no such cmd") || str::startsWith(errmsg, "no such command"))) {
+ code = ErrorCodes::CommandNotFound;
}
+ return Status(ErrorCodes::Error(code), errmsg);
+}
+
} // namespace mongo
diff --git a/src/mongo/rpc/get_status_from_command_result.h b/src/mongo/rpc/get_status_from_command_result.h
index 6c930ccd017..e1477436e55 100644
--- a/src/mongo/rpc/get_status_from_command_result.h
+++ b/src/mongo/rpc/get_status_from_command_result.h
@@ -29,20 +29,20 @@
#pragma once
namespace mongo {
- class BSONObj;
- class Status;
+class BSONObj;
+class Status;
- /**
- * Converts "result" into a Status object. The input is expected to be the object returned
- * by running a command. Returns ErrorCodes::CommandResultSchemaViolation if "result" does
- * not look like the result of a command.
- *
- * Command results must have a field called "ok" whose value may be interpreted as a boolean.
- * If the value interpreted as a boolean is true, the resultant status is Status::OK().
- * Otherwise, it is an error status. The code comes from the "code" field, if present and
- * number-ish, while the reason message will come from the errmsg field, if present and
- * string-ish.
- */
- Status getStatusFromCommandResult(const BSONObj& result);
+/**
+ * Converts "result" into a Status object. The input is expected to be the object returned
+ * by running a command. Returns ErrorCodes::CommandResultSchemaViolation if "result" does
+ * not look like the result of a command.
+ *
+ * Command results must have a field called "ok" whose value may be interpreted as a boolean.
+ * If the value interpreted as a boolean is true, the resultant status is Status::OK().
+ * Otherwise, it is an error status. The code comes from the "code" field, if present and
+ * number-ish, while the reason message will come from the errmsg field, if present and
+ * string-ish.
+ */
+Status getStatusFromCommandResult(const BSONObj& result);
} // namespace mongo
diff --git a/src/mongo/rpc/legacy_reply.cpp b/src/mongo/rpc/legacy_reply.cpp
index 3c16df28426..62a45ea1286 100644
--- a/src/mongo/rpc/legacy_reply.cpp
+++ b/src/mongo/rpc/legacy_reply.cpp
@@ -40,52 +40,50 @@
namespace mongo {
namespace rpc {
- LegacyReply::LegacyReply(const Message* message)
- : _message(std::move(message)) {
- invariant(message->operation() == opReply);
-
- QueryResult::View qr = _message->singleData().view2ptr();
-
- // should be checked by caller.
- invariant(qr.msgdata().getOperation() == opReply);
-
- uassert(ErrorCodes::BadValue,
- str::stream() << "Got legacy command reply with a bad cursorId field,"
- << " expected a value of 0 but got " << qr.getCursorId(),
- qr.getCursorId() == 0);
-
- uassert(ErrorCodes::BadValue,
- str::stream() << "Got legacy command reply with a bad nReturned field,"
- << " expected a value of 1 but got " << qr.getNReturned(),
- qr.getNReturned() == 1);
-
- uassert(ErrorCodes::BadValue,
- str::stream() << "Got legacy command reply with a bad startingFrom field,"
- << " expected a value of 0 but got " << qr.getStartingFrom(),
- qr.getStartingFrom() == 0);
-
- // TODO bson validation
- std::tie(_commandReply, _metadata) = uassertStatusOK(
- rpc::upconvertReplyMetadata(BSONObj(qr.data()))
- );
- }
-
- const BSONObj& LegacyReply::getMetadata() const {
- return _metadata;
- }
-
- const BSONObj& LegacyReply::getCommandReply() const {
- return _commandReply;
- }
-
- DocumentRange LegacyReply::getOutputDocs() const {
- // return empty range
- return DocumentRange{};
- }
-
- Protocol LegacyReply::getProtocol() const {
- return rpc::Protocol::kOpQuery;
- }
+LegacyReply::LegacyReply(const Message* message) : _message(std::move(message)) {
+ invariant(message->operation() == opReply);
+
+ QueryResult::View qr = _message->singleData().view2ptr();
+
+ // should be checked by caller.
+ invariant(qr.msgdata().getOperation() == opReply);
+
+ uassert(ErrorCodes::BadValue,
+ str::stream() << "Got legacy command reply with a bad cursorId field,"
+ << " expected a value of 0 but got " << qr.getCursorId(),
+ qr.getCursorId() == 0);
+
+ uassert(ErrorCodes::BadValue,
+ str::stream() << "Got legacy command reply with a bad nReturned field,"
+ << " expected a value of 1 but got " << qr.getNReturned(),
+ qr.getNReturned() == 1);
+
+ uassert(ErrorCodes::BadValue,
+ str::stream() << "Got legacy command reply with a bad startingFrom field,"
+ << " expected a value of 0 but got " << qr.getStartingFrom(),
+ qr.getStartingFrom() == 0);
+
+ // TODO bson validation
+ std::tie(_commandReply, _metadata) =
+ uassertStatusOK(rpc::upconvertReplyMetadata(BSONObj(qr.data())));
+}
+
+const BSONObj& LegacyReply::getMetadata() const {
+ return _metadata;
+}
+
+const BSONObj& LegacyReply::getCommandReply() const {
+ return _commandReply;
+}
+
+DocumentRange LegacyReply::getOutputDocs() const {
+ // return empty range
+ return DocumentRange{};
+}
+
+Protocol LegacyReply::getProtocol() const {
+ return rpc::Protocol::kOpQuery;
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/legacy_reply.h b/src/mongo/rpc/legacy_reply.h
index e839d305b42..86258c2642b 100644
--- a/src/mongo/rpc/legacy_reply.h
+++ b/src/mongo/rpc/legacy_reply.h
@@ -35,56 +35,55 @@
#include "mongo/rpc/protocol.h"
namespace mongo {
- class Message;
+class Message;
namespace rpc {
+/**
+ * Immutable view of an OP_REPLY legacy-style command reply.
+ *
+ * TODO: BSON validation (SERVER-18167)
+ */
+class LegacyReply : public ReplyInterface {
+public:
/**
- * Immutable view of an OP_REPLY legacy-style command reply.
- *
- * TODO: BSON validation (SERVER-18167)
+ * Construct a Reply from a Message.
+ * The underlying message MUST outlive the Reply.
*/
- class LegacyReply : public ReplyInterface {
- public:
+ explicit LegacyReply(const Message* message);
- /**
- * Construct a Reply from a Message.
- * The underlying message MUST outlive the Reply.
- */
- explicit LegacyReply(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;
+ /**
+ * 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;
+ /**
+ * The result of executing the command.
+ */
+ const BSONObj& getCommandReply() const final;
- /**
- * A variable number of BSON documents returned by the command. It is valid for the
- * returned range to be empty.
- *
- * Example usage:
- *
- * for (auto&& doc : reply.getOutputDocs()) {
- * ... do stuff with doc
- * }
- */
- DocumentRange getOutputDocs() const final;
+ /**
+ * A variable number of BSON documents returned by the command. It is valid for the
+ * returned range to be empty.
+ *
+ * Example usage:
+ *
+ * for (auto&& doc : reply.getOutputDocs()) {
+ * ... do stuff with doc
+ * }
+ */
+ DocumentRange getOutputDocs() const final;
- Protocol getProtocol() const final;
+ Protocol getProtocol() const final;
- private:
- const Message* _message;
+private:
+ const Message* _message;
- // TODO: SERVER-18236
- BSONObj _metadata{};
- BSONObj _commandReply{}; // will hold unowned
- };
+ // TODO: SERVER-18236
+ BSONObj _metadata{};
+ BSONObj _commandReply{}; // will hold unowned
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/legacy_reply_builder.cpp b/src/mongo/rpc/legacy_reply_builder.cpp
index 0712c0d5fee..4448f1e9810 100644
--- a/src/mongo/rpc/legacy_reply_builder.cpp
+++ b/src/mongo/rpc/legacy_reply_builder.cpp
@@ -38,91 +38,88 @@
namespace mongo {
namespace rpc {
- LegacyReplyBuilder::LegacyReplyBuilder()
- : LegacyReplyBuilder(stdx::make_unique<Message>())
- {}
-
- LegacyReplyBuilder::LegacyReplyBuilder(std::unique_ptr<Message> message)
- : _message{std::move(message)} {
- _builder.skip(sizeof(QueryResult::Value));
- }
-
- LegacyReplyBuilder::~LegacyReplyBuilder() {}
-
- LegacyReplyBuilder& LegacyReplyBuilder::setMetadata(BSONObj metadata) {
- invariant(_state == State::kMetadata);
- _metadata = std::move(metadata);
- _state = State::kCommandReply;
- return *this;
- }
-
- LegacyReplyBuilder& LegacyReplyBuilder::setRawCommandReply(BSONObj commandReply) {
- invariant(_state == State::kCommandReply);
- BSONObj downconvertedCommandReply = uassertStatusOK(
- rpc::downconvertReplyMetadata(std::move(commandReply), std::move(_metadata))
- );
- downconvertedCommandReply.appendSelfToBufBuilder(_builder);
- _state = State::kOutputDocs;
- return *this;
- }
-
- LegacyReplyBuilder& LegacyReplyBuilder::addOutputDocs(DocumentRange outputDocs) {
- invariant(_state == State::kOutputDocs);
- // no op
- return *this;
- }
-
- LegacyReplyBuilder& LegacyReplyBuilder::addOutputDoc(BSONObj outputDoc) {
- invariant(_state == State::kOutputDocs);
- // no op
- return *this;
- }
-
- ReplyBuilderInterface::State LegacyReplyBuilder::getState() const {
- return _state;
- }
-
- Protocol LegacyReplyBuilder::getProtocol() const {
- return rpc::Protocol::kOpQuery;
- }
-
- void LegacyReplyBuilder::reset() {
- // If we are in State::kMetadata, we are already in the 'start' state, so by
- // immediately returning, we save a heap allocation.
- if (_state == State::kMetadata) {
- return;
- }
- _builder.reset();
- _metadata = BSONObj();
- _message = stdx::make_unique<Message>();
- _state = State::kMetadata;
- }
-
-
- std::unique_ptr<Message> LegacyReplyBuilder::done() {
- invariant(_state == State::kOutputDocs);
- std::unique_ptr<Message> message = stdx::make_unique<Message>();
-
- QueryResult::View qr = _builder.buf();
- qr.setResultFlagsToOk();
- qr.msgdata().setLen(_builder.len());
- qr.msgdata().setOperation(opReply);
- qr.setCursorId(0);
- qr.setStartingFrom(0);
- qr.setNReturned(1);
- _builder.decouple();
-
- message->setData(qr.view2ptr(), true);
-
- _state = State::kDone;
- return std::move(message);
- }
-
- std::size_t LegacyReplyBuilder::availableSpaceForOutputDocs() const {
- invariant (State::kDone != _state);
- // LegacyReplyBuilder currently does not support addOutputDoc(s)
- return 0u;
+LegacyReplyBuilder::LegacyReplyBuilder() : LegacyReplyBuilder(stdx::make_unique<Message>()) {}
+
+LegacyReplyBuilder::LegacyReplyBuilder(std::unique_ptr<Message> message)
+ : _message{std::move(message)} {
+ _builder.skip(sizeof(QueryResult::Value));
+}
+
+LegacyReplyBuilder::~LegacyReplyBuilder() {}
+
+LegacyReplyBuilder& LegacyReplyBuilder::setMetadata(BSONObj metadata) {
+ invariant(_state == State::kMetadata);
+ _metadata = std::move(metadata);
+ _state = State::kCommandReply;
+ return *this;
+}
+
+LegacyReplyBuilder& LegacyReplyBuilder::setRawCommandReply(BSONObj commandReply) {
+ invariant(_state == State::kCommandReply);
+ BSONObj downconvertedCommandReply = uassertStatusOK(
+ rpc::downconvertReplyMetadata(std::move(commandReply), std::move(_metadata)));
+ downconvertedCommandReply.appendSelfToBufBuilder(_builder);
+ _state = State::kOutputDocs;
+ return *this;
+}
+
+LegacyReplyBuilder& LegacyReplyBuilder::addOutputDocs(DocumentRange outputDocs) {
+ invariant(_state == State::kOutputDocs);
+ // no op
+ return *this;
+}
+
+LegacyReplyBuilder& LegacyReplyBuilder::addOutputDoc(BSONObj outputDoc) {
+ invariant(_state == State::kOutputDocs);
+ // no op
+ return *this;
+}
+
+ReplyBuilderInterface::State LegacyReplyBuilder::getState() const {
+ return _state;
+}
+
+Protocol LegacyReplyBuilder::getProtocol() const {
+ return rpc::Protocol::kOpQuery;
+}
+
+void LegacyReplyBuilder::reset() {
+ // If we are in State::kMetadata, we are already in the 'start' state, so by
+ // immediately returning, we save a heap allocation.
+ if (_state == State::kMetadata) {
+ return;
}
+ _builder.reset();
+ _metadata = BSONObj();
+ _message = stdx::make_unique<Message>();
+ _state = State::kMetadata;
+}
+
+
+std::unique_ptr<Message> LegacyReplyBuilder::done() {
+ invariant(_state == State::kOutputDocs);
+ std::unique_ptr<Message> message = stdx::make_unique<Message>();
+
+ QueryResult::View qr = _builder.buf();
+ qr.setResultFlagsToOk();
+ qr.msgdata().setLen(_builder.len());
+ qr.msgdata().setOperation(opReply);
+ qr.setCursorId(0);
+ qr.setStartingFrom(0);
+ qr.setNReturned(1);
+ _builder.decouple();
+
+ message->setData(qr.view2ptr(), true);
+
+ _state = State::kDone;
+ return std::move(message);
+}
+
+std::size_t LegacyReplyBuilder::availableSpaceForOutputDocs() const {
+ invariant(State::kDone != _state);
+ // LegacyReplyBuilder currently does not support addOutputDoc(s)
+ return 0u;
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/legacy_reply_builder.h b/src/mongo/rpc/legacy_reply_builder.h
index d777c97203f..417a6db8492 100644
--- a/src/mongo/rpc/legacy_reply_builder.h
+++ b/src/mongo/rpc/legacy_reply_builder.h
@@ -39,36 +39,34 @@
namespace mongo {
namespace rpc {
- class LegacyReplyBuilder : public ReplyBuilderInterface {
- public:
+class LegacyReplyBuilder : public ReplyBuilderInterface {
+public:
+ LegacyReplyBuilder();
+ LegacyReplyBuilder(std::unique_ptr<Message>);
+ ~LegacyReplyBuilder() final;
- LegacyReplyBuilder();
- LegacyReplyBuilder(std::unique_ptr<Message>);
- ~LegacyReplyBuilder() final;
+ LegacyReplyBuilder& setMetadata(BSONObj metadata) final;
+ LegacyReplyBuilder& setRawCommandReply(BSONObj commandReply) final;
- LegacyReplyBuilder& setMetadata(BSONObj metadata) final;
- LegacyReplyBuilder& setRawCommandReply(BSONObj commandReply) final;
+ LegacyReplyBuilder& addOutputDocs(DocumentRange outputDocs) final;
+ LegacyReplyBuilder& addOutputDoc(BSONObj outputDoc) final;
- LegacyReplyBuilder& addOutputDocs(DocumentRange outputDocs) final;
- LegacyReplyBuilder& addOutputDoc(BSONObj outputDoc) final;
+ State getState() const final;
- State getState() const final;
+ void reset() final;
- void reset() final;
+ std::unique_ptr<Message> done() final;
- std::unique_ptr<Message> done() final;
+ Protocol getProtocol() const final;
- Protocol getProtocol() const final;
+ std::size_t availableSpaceForOutputDocs() const final;
- std::size_t availableSpaceForOutputDocs() const final;
-
- private:
-
- BufBuilder _builder{};
- BSONObj _metadata{};
- std::unique_ptr<Message> _message;
- State _state{State::kMetadata};
- };
+private:
+ BufBuilder _builder{};
+ BSONObj _metadata{};
+ std::unique_ptr<Message> _message;
+ State _state{State::kMetadata};
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/legacy_request.cpp b/src/mongo/rpc/legacy_request.cpp
index 57f3f12cb58..d0340b0b831 100644
--- a/src/mongo/rpc/legacy_request.cpp
+++ b/src/mongo/rpc/legacy_request.cpp
@@ -38,50 +38,46 @@
namespace mongo {
namespace rpc {
- LegacyRequest::LegacyRequest(const Message *message)
- : _message(std::move(message))
- , _dbMessage(*message)
- , _queryMessage(_dbMessage) {
-
- _database = nsToDatabaseSubstring(_queryMessage.ns);
-
- uassert(ErrorCodes::InvalidNamespace,
- str::stream() << "Invalid database name: '" << _database << "'",
- NamespaceString::validDBName(_database));
-
- std::tie(_upconvertedCommandArgs, _upconvertedMetadata) = uassertStatusOK(
- rpc::upconvertRequestMetadata(std::move(_queryMessage.query),
- std::move(_queryMessage.queryOptions))
- );
- }
-
- LegacyRequest::~LegacyRequest() = default;
-
- StringData LegacyRequest::getDatabase() const {
- return _database;
- }
-
- StringData LegacyRequest::getCommandName() const {
- return _upconvertedCommandArgs.firstElement().fieldNameStringData();
- }
-
- const BSONObj& LegacyRequest::getMetadata() const {
- // TODO SERVER-18236
- return _upconvertedMetadata;
- }
-
- const BSONObj& LegacyRequest::getCommandArgs() const {
- return _upconvertedCommandArgs;
- }
-
- DocumentRange LegacyRequest::getInputDocs() const {
- // return an empty document range.
- return DocumentRange{};
- }
-
- Protocol LegacyRequest::getProtocol() const {
- return rpc::Protocol::kOpQuery;
- }
+LegacyRequest::LegacyRequest(const Message* message)
+ : _message(std::move(message)), _dbMessage(*message), _queryMessage(_dbMessage) {
+ _database = nsToDatabaseSubstring(_queryMessage.ns);
+
+ uassert(ErrorCodes::InvalidNamespace,
+ str::stream() << "Invalid database name: '" << _database << "'",
+ NamespaceString::validDBName(_database));
+
+ std::tie(_upconvertedCommandArgs, _upconvertedMetadata) =
+ uassertStatusOK(rpc::upconvertRequestMetadata(std::move(_queryMessage.query),
+ std::move(_queryMessage.queryOptions)));
+}
+
+LegacyRequest::~LegacyRequest() = default;
+
+StringData LegacyRequest::getDatabase() const {
+ return _database;
+}
+
+StringData LegacyRequest::getCommandName() const {
+ return _upconvertedCommandArgs.firstElement().fieldNameStringData();
+}
+
+const BSONObj& LegacyRequest::getMetadata() const {
+ // TODO SERVER-18236
+ return _upconvertedMetadata;
+}
+
+const BSONObj& LegacyRequest::getCommandArgs() const {
+ return _upconvertedCommandArgs;
+}
+
+DocumentRange LegacyRequest::getInputDocs() const {
+ // return an empty document range.
+ return DocumentRange{};
+}
+
+Protocol LegacyRequest::getProtocol() const {
+ return rpc::Protocol::kOpQuery;
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/legacy_request.h b/src/mongo/rpc/legacy_request.h
index 59371600894..9312c59639d 100644
--- a/src/mongo/rpc/legacy_request.h
+++ b/src/mongo/rpc/legacy_request.h
@@ -36,71 +36,71 @@
#include "mongo/rpc/request_interface.h"
namespace mongo {
- class Message;
+class Message;
namespace rpc {
+/**
+ * An immutable view of an OP_QUERY command request. The underlying bytes are owned
+ * by a mongo::Message, which must outlive any LegacyRequest instances created from it.
+ *
+ */
+class LegacyRequest : public RequestInterface {
+public:
/**
- * An immutable view of an OP_QUERY command request. The underlying bytes are owned
- * by a mongo::Message, which must outlive any LegacyRequest instances created from it.
- *
+ * Construct a Request from a Message. Underlying message MUST outlive the Request.
+ * Required fields are parsed eagerly, inputDocs are parsed lazily.
*/
- class LegacyRequest : public RequestInterface {
- public:
- /**
- * Construct a Request from a Message. Underlying message MUST outlive the Request.
- * Required fields are parsed eagerly, inputDocs are parsed lazily.
- */
- explicit LegacyRequest(const Message* message);
+ explicit LegacyRequest(const Message* message);
- ~LegacyRequest() final;
+ ~LegacyRequest() final;
- /**
- * The database that the command is to be executed on.
- */
- StringData getDatabase() const final;
+ /**
+ * The database that the command is to be executed on.
+ */
+ StringData getDatabase() const final;
- /**
- * The name of the command to execute.
- */
- StringData getCommandName() const final;
+ /**
+ * The name of the command to execute.
+ */
+ StringData getCommandName() const final;
- /**
- * The metadata associated with the command request. This is information that is
- * independent of any specific command, i.e. auditing information.
- */
- const BSONObj& getMetadata() const final;
+ /**
+ * The metadata associated with the command request. This is information that is
+ * independent of any specific command, i.e. auditing information.
+ */
+ const BSONObj& getMetadata() const final;
- /**
- * The arguments to the command - this is passed to the command's run() method.
- */
- const BSONObj& getCommandArgs() const final;
+ /**
+ * The arguments to the command - this is passed to the command's run() method.
+ */
+ const BSONObj& getCommandArgs() const final;
- /**
- * A variable number of BSON documents to pass to the command. It is valid for
- * the returned range to be empty.
- *
- * Example usage:
- *
- * for (auto&& doc : req.getInputDocs()) {
- * ... do stuff with doc
- * }
- */
- DocumentRange getInputDocs() const final;
+ /**
+ * A variable number of BSON documents to pass to the command. It is valid for
+ * the returned range to be empty.
+ *
+ * Example usage:
+ *
+ * for (auto&& doc : req.getInputDocs()) {
+ * ... do stuff with doc
+ * }
+ */
+ DocumentRange getInputDocs() const final;
- Protocol getProtocol() const final;
+ Protocol getProtocol() const final;
- private:
- const Message* _message;
- // TODO: metadata will be handled in SERVER-18236
- // for now getMetadata() is a no op
- DbMessage _dbMessage;
- QueryMessage _queryMessage;
- StringData _database;
+private:
+ const Message* _message;
+ // TODO: metadata will be handled in SERVER-18236
+ // for now getMetadata() is a no op
+ DbMessage _dbMessage;
+ QueryMessage _queryMessage;
+ StringData _database;
- BSONObj _upconvertedMetadata;
- BSONObj _upconvertedCommandArgs;
- };
+ BSONObj _upconvertedMetadata;
+ BSONObj _upconvertedCommandArgs;
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/legacy_request_builder.cpp b/src/mongo/rpc/legacy_request_builder.cpp
index fc96d738905..05f1fe79ce3 100644
--- a/src/mongo/rpc/legacy_request_builder.cpp
+++ b/src/mongo/rpc/legacy_request_builder.cpp
@@ -41,85 +41,79 @@
namespace mongo {
namespace rpc {
- LegacyRequestBuilder::LegacyRequestBuilder()
- : _message{stdx::make_unique<Message>()}
- {}
-
- LegacyRequestBuilder::~LegacyRequestBuilder()
- {}
-
- LegacyRequestBuilder::LegacyRequestBuilder(std::unique_ptr<Message> message)
- : _message{std::move(message)}
- {}
-
- LegacyRequestBuilder& LegacyRequestBuilder::setDatabase(StringData database) {
- invariant(_state == State::kDatabase);
- _ns = NamespaceString(database, "$cmd").toString();
- _state = State::kCommandName;
- return *this;
- }
-
- LegacyRequestBuilder& LegacyRequestBuilder::setCommandName(StringData commandName) {
- invariant(_state == State::kCommandName);
- // no op, as commandName is the first element of commandArgs
- _state = State::kMetadata;
- return *this;
- }
-
- LegacyRequestBuilder& LegacyRequestBuilder::setMetadata(BSONObj metadata) {
- invariant(_state == State::kMetadata);
- _metadata = std::move(metadata);
- _state = State::kCommandArgs;
- return *this;
- }
-
- LegacyRequestBuilder& LegacyRequestBuilder::setCommandArgs(BSONObj commandArgs) {
- invariant(_state == State::kCommandArgs);
-
- BSONObj legacyCommandArgs;
- int queryOptions;
-
- std::tie(legacyCommandArgs, queryOptions) = uassertStatusOK(
- rpc::downconvertRequestMetadata(std::move(commandArgs),
- std::move(_metadata))
- );
-
- _builder.appendNum(queryOptions); // queryOptions
- _builder.appendStr(_ns);
- _builder.appendNum(0); // nToSkip
- _builder.appendNum(1); // nToReturn
-
- legacyCommandArgs.appendSelfToBufBuilder(_builder);
- _state = State::kInputDocs;
- return *this;
- }
-
- LegacyRequestBuilder& LegacyRequestBuilder::addInputDocs(DocumentRange inputDocs) {
- invariant(_state == State::kInputDocs);
- // no op
- return *this;
- }
-
- LegacyRequestBuilder& LegacyRequestBuilder::addInputDoc(BSONObj inputDoc) {
- invariant(_state == State::kInputDocs);
- // no op
- return *this;
- }
-
- RequestBuilderInterface::State LegacyRequestBuilder::getState() const {
- return _state;
- }
-
- Protocol LegacyRequestBuilder::getProtocol() const {
- return rpc::Protocol::kOpQuery;
- }
-
- std::unique_ptr<Message> LegacyRequestBuilder::done() {
- invariant(_state == State::kInputDocs);
- _message->setData(dbQuery, _builder.buf(), _builder.len());
- _state = State::kDone;
- return std::move(_message);
- }
+LegacyRequestBuilder::LegacyRequestBuilder() : _message{stdx::make_unique<Message>()} {}
+
+LegacyRequestBuilder::~LegacyRequestBuilder() {}
+
+LegacyRequestBuilder::LegacyRequestBuilder(std::unique_ptr<Message> message)
+ : _message{std::move(message)} {}
+
+LegacyRequestBuilder& LegacyRequestBuilder::setDatabase(StringData database) {
+ invariant(_state == State::kDatabase);
+ _ns = NamespaceString(database, "$cmd").toString();
+ _state = State::kCommandName;
+ return *this;
+}
+
+LegacyRequestBuilder& LegacyRequestBuilder::setCommandName(StringData commandName) {
+ invariant(_state == State::kCommandName);
+ // no op, as commandName is the first element of commandArgs
+ _state = State::kMetadata;
+ return *this;
+}
+
+LegacyRequestBuilder& LegacyRequestBuilder::setMetadata(BSONObj metadata) {
+ invariant(_state == State::kMetadata);
+ _metadata = std::move(metadata);
+ _state = State::kCommandArgs;
+ return *this;
+}
+
+LegacyRequestBuilder& LegacyRequestBuilder::setCommandArgs(BSONObj commandArgs) {
+ invariant(_state == State::kCommandArgs);
+
+ BSONObj legacyCommandArgs;
+ int queryOptions;
+
+ std::tie(legacyCommandArgs, queryOptions) = uassertStatusOK(
+ rpc::downconvertRequestMetadata(std::move(commandArgs), std::move(_metadata)));
+
+ _builder.appendNum(queryOptions); // queryOptions
+ _builder.appendStr(_ns);
+ _builder.appendNum(0); // nToSkip
+ _builder.appendNum(1); // nToReturn
+
+ legacyCommandArgs.appendSelfToBufBuilder(_builder);
+ _state = State::kInputDocs;
+ return *this;
+}
+
+LegacyRequestBuilder& LegacyRequestBuilder::addInputDocs(DocumentRange inputDocs) {
+ invariant(_state == State::kInputDocs);
+ // no op
+ return *this;
+}
+
+LegacyRequestBuilder& LegacyRequestBuilder::addInputDoc(BSONObj inputDoc) {
+ invariant(_state == State::kInputDocs);
+ // no op
+ return *this;
+}
+
+RequestBuilderInterface::State LegacyRequestBuilder::getState() const {
+ return _state;
+}
+
+Protocol LegacyRequestBuilder::getProtocol() const {
+ return rpc::Protocol::kOpQuery;
+}
+
+std::unique_ptr<Message> LegacyRequestBuilder::done() {
+ invariant(_state == State::kInputDocs);
+ _message->setData(dbQuery, _builder.buf(), _builder.len());
+ _state = State::kDone;
+ return std::move(_message);
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/legacy_request_builder.h b/src/mongo/rpc/legacy_request_builder.h
index 83890df45e2..0d44c47a513 100644
--- a/src/mongo/rpc/legacy_request_builder.h
+++ b/src/mongo/rpc/legacy_request_builder.h
@@ -39,39 +39,39 @@
namespace mongo {
namespace rpc {
- class LegacyRequestBuilder : public RequestBuilderInterface {
- public:
- LegacyRequestBuilder();
- ~LegacyRequestBuilder() final;
+class LegacyRequestBuilder : public RequestBuilderInterface {
+public:
+ LegacyRequestBuilder();
+ ~LegacyRequestBuilder() final;
- LegacyRequestBuilder(std::unique_ptr<Message>);
+ LegacyRequestBuilder(std::unique_ptr<Message>);
- LegacyRequestBuilder& setDatabase(StringData database) final;
- LegacyRequestBuilder& setCommandName(StringData commandName) final;
- LegacyRequestBuilder& setMetadata(BSONObj metadata) final;
- LegacyRequestBuilder& setCommandArgs(BSONObj commandArgs) final;
+ LegacyRequestBuilder& setDatabase(StringData database) final;
+ LegacyRequestBuilder& setCommandName(StringData commandName) final;
+ LegacyRequestBuilder& setMetadata(BSONObj metadata) final;
+ LegacyRequestBuilder& setCommandArgs(BSONObj commandArgs) final;
- LegacyRequestBuilder& addInputDocs(DocumentRange inputDocs) final;
- LegacyRequestBuilder& addInputDoc(BSONObj inputDoc) final;
+ LegacyRequestBuilder& addInputDocs(DocumentRange inputDocs) final;
+ LegacyRequestBuilder& addInputDoc(BSONObj inputDoc) final;
- State getState() const final;
+ State getState() const final;
- Protocol getProtocol() const final;
+ Protocol getProtocol() const final;
- std::unique_ptr<Message> done() final;
+ std::unique_ptr<Message> done() final;
- private:
- std::unique_ptr<Message> _message;
- BufBuilder _builder{};
+private:
+ std::unique_ptr<Message> _message;
+ BufBuilder _builder{};
- // we need to stash this as we need commandArgs to
- // upconvert.
- BSONObj _metadata;
+ // we need to stash this as we need commandArgs to
+ // upconvert.
+ BSONObj _metadata;
- std::string _ns{}; // copied to in setDatabase
+ std::string _ns{}; // copied to in setDatabase
- State _state{State::kDatabase};
- };
+ State _state{State::kDatabase};
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/legacy_request_test.cpp b/src/mongo/rpc/legacy_request_test.cpp
index a24b8eba072..caadc74e3e8 100644
--- a/src/mongo/rpc/legacy_request_test.cpp
+++ b/src/mongo/rpc/legacy_request_test.cpp
@@ -37,16 +37,16 @@
namespace {
- using namespace mongo;
+using namespace mongo;
- TEST(LegacyRequest, InvalidNSThrows) {
- rpc::LegacyRequestBuilder crb;
- crb.setDatabase("foo////!!!!<><><>");
- crb.setCommandName("foo");
- crb.setMetadata(BSONObj());
- crb.setCommandArgs(BSON("ping" << 1));
- auto msg = crb.done();
- ASSERT_THROWS(rpc::LegacyRequest{msg.get()}, AssertionException);
- }
+TEST(LegacyRequest, InvalidNSThrows) {
+ rpc::LegacyRequestBuilder crb;
+ crb.setDatabase("foo////!!!!<><><>");
+ crb.setCommandName("foo");
+ crb.setMetadata(BSONObj());
+ crb.setCommandArgs(BSON("ping" << 1));
+ auto msg = crb.done();
+ ASSERT_THROWS(rpc::LegacyRequest{msg.get()}, AssertionException);
+}
} // namespace
diff --git a/src/mongo/rpc/metadata.cpp b/src/mongo/rpc/metadata.cpp
index c65953790ec..87db6ce5389 100644
--- a/src/mongo/rpc/metadata.cpp
+++ b/src/mongo/rpc/metadata.cpp
@@ -39,122 +39,111 @@
namespace mongo {
namespace rpc {
- BSONObj makeEmptyMetadata() {
- return BSONObj();
+BSONObj makeEmptyMetadata() {
+ return BSONObj();
+}
+
+Status readRequestMetadata(OperationContext* txn, const BSONObj& metadataObj) {
+ auto swServerSelectionMetadata = ServerSelectionMetadata::readFromMetadata(metadataObj);
+ if (!swServerSelectionMetadata.isOK()) {
+ return swServerSelectionMetadata.getStatus();
}
+ ServerSelectionMetadata::get(txn) = std::move(swServerSelectionMetadata.getValue());
- Status readRequestMetadata(OperationContext* txn, const BSONObj& metadataObj) {
- auto swServerSelectionMetadata = ServerSelectionMetadata::readFromMetadata(metadataObj);
- if (!swServerSelectionMetadata.isOK()) {
- return swServerSelectionMetadata.getStatus();
- }
- ServerSelectionMetadata::get(txn) = std::move(swServerSelectionMetadata.getValue());
+ auto swAuditMetadata = AuditMetadata::readFromMetadata(metadataObj);
+ if (!swAuditMetadata.isOK()) {
+ return swAuditMetadata.getStatus();
+ }
+ AuditMetadata::get(txn) = std::move(swAuditMetadata.getValue());
- auto swAuditMetadata = AuditMetadata::readFromMetadata(metadataObj);
- if (!swAuditMetadata.isOK()) {
- return swAuditMetadata.getStatus();
- }
- AuditMetadata::get(txn) = std::move(swAuditMetadata.getValue());
+ return Status::OK();
+}
- return Status::OK();
+Status writeRequestMetadata(OperationContext* txn, BSONObjBuilder* metadataBob) {
+ auto ssStatus = ServerSelectionMetadata::get(txn).writeToMetadata(metadataBob);
+ if (!ssStatus.isOK()) {
+ return ssStatus;
}
-
- Status writeRequestMetadata(OperationContext* txn, BSONObjBuilder* metadataBob) {
- auto ssStatus = ServerSelectionMetadata::get(txn).writeToMetadata(metadataBob);
- if (!ssStatus.isOK()) {
- return ssStatus;
- }
- return Status::OK();
+ return Status::OK();
+}
+
+StatusWith<CommandAndMetadata> upconvertRequestMetadata(BSONObj legacyCmdObj, int queryFlags) {
+ // We can reuse the same metadata BOB for every upconvert call, but we need to keep
+ // making new command BOBs as each metadata bob will need to remove fields. We can not use
+ // mutablebson here because the ServerSelectionMetadata upconvert routine performs
+ // manipulations (replacing a root with its child) that mutablebson doesn't
+ // support.
+ BSONObjBuilder metadataBob;
+
+ // Ordering is important here - ServerSelectionMetadata must be upconverted
+ // first, then AuditMetadata.
+ BSONObjBuilder ssmCommandBob;
+ auto upconvertStatus =
+ ServerSelectionMetadata::upconvert(legacyCmdObj, queryFlags, &ssmCommandBob, &metadataBob);
+ if (!upconvertStatus.isOK()) {
+ return upconvertStatus;
}
- StatusWith<CommandAndMetadata> upconvertRequestMetadata(BSONObj legacyCmdObj, int queryFlags) {
- // We can reuse the same metadata BOB for every upconvert call, but we need to keep
- // making new command BOBs as each metadata bob will need to remove fields. We can not use
- // mutablebson here because the ServerSelectionMetadata upconvert routine performs
- // manipulations (replacing a root with its child) that mutablebson doesn't
- // support.
- BSONObjBuilder metadataBob;
-
- // Ordering is important here - ServerSelectionMetadata must be upconverted
- // first, then AuditMetadata.
- BSONObjBuilder ssmCommandBob;
- auto upconvertStatus = ServerSelectionMetadata::upconvert(legacyCmdObj,
- queryFlags,
- &ssmCommandBob,
- &metadataBob);
- if (!upconvertStatus.isOK()) {
- return upconvertStatus;
- }
-
-
- BSONObjBuilder auditCommandBob;
- upconvertStatus = AuditMetadata::upconvert(ssmCommandBob.done(),
- queryFlags,
- &auditCommandBob,
- &metadataBob);
-
- if (!upconvertStatus.isOK()) {
- return upconvertStatus;
- }
-
-
- return std::make_tuple(auditCommandBob.obj(), metadataBob.obj());
+
+ BSONObjBuilder auditCommandBob;
+ upconvertStatus =
+ AuditMetadata::upconvert(ssmCommandBob.done(), queryFlags, &auditCommandBob, &metadataBob);
+
+ if (!upconvertStatus.isOK()) {
+ return upconvertStatus;
}
- StatusWith<LegacyCommandAndFlags> downconvertRequestMetadata(BSONObj cmdObj, BSONObj metadata) {
- int legacyQueryFlags = 0;
- BSONObjBuilder auditCommandBob;
- // Ordering is important here - AuditingMetadata must be downconverted first,
- // then ServerSelectionMetadata.
- auto downconvertStatus = AuditMetadata::downconvert(cmdObj,
- metadata,
- &auditCommandBob,
- &legacyQueryFlags);
- if (!downconvertStatus.isOK()) {
- return downconvertStatus;
- }
+ return std::make_tuple(auditCommandBob.obj(), metadataBob.obj());
+}
+StatusWith<LegacyCommandAndFlags> downconvertRequestMetadata(BSONObj cmdObj, BSONObj metadata) {
+ int legacyQueryFlags = 0;
+ BSONObjBuilder auditCommandBob;
+ // Ordering is important here - AuditingMetadata must be downconverted first,
+ // then ServerSelectionMetadata.
+ auto downconvertStatus =
+ AuditMetadata::downconvert(cmdObj, metadata, &auditCommandBob, &legacyQueryFlags);
- BSONObjBuilder ssmCommandBob;
- downconvertStatus = ServerSelectionMetadata::downconvert(auditCommandBob.done(),
- metadata,
- &ssmCommandBob,
- &legacyQueryFlags);
- if (!downconvertStatus.isOK()) {
- return downconvertStatus;
- }
+ if (!downconvertStatus.isOK()) {
+ return downconvertStatus;
+ }
- return std::make_tuple(ssmCommandBob.obj(), std::move(legacyQueryFlags));
+ BSONObjBuilder ssmCommandBob;
+ downconvertStatus = ServerSelectionMetadata::downconvert(
+ auditCommandBob.done(), metadata, &ssmCommandBob, &legacyQueryFlags);
+ if (!downconvertStatus.isOK()) {
+ return downconvertStatus;
}
- StatusWith<CommandReplyWithMetadata> upconvertReplyMetadata(BSONObj legacyReply) {
- BSONObjBuilder commandReplyBob;
- BSONObjBuilder metadataBob;
- auto upconvertStatus = ShardingMetadata::upconvert(legacyReply,
- &commandReplyBob,
- &metadataBob);
- if (!upconvertStatus.isOK()) {
- return upconvertStatus;
- }
+ return std::make_tuple(ssmCommandBob.obj(), std::move(legacyQueryFlags));
+}
+
+StatusWith<CommandReplyWithMetadata> upconvertReplyMetadata(BSONObj legacyReply) {
+ BSONObjBuilder commandReplyBob;
+ BSONObjBuilder metadataBob;
- return std::make_tuple(commandReplyBob.obj(), metadataBob.obj());
+ auto upconvertStatus = ShardingMetadata::upconvert(legacyReply, &commandReplyBob, &metadataBob);
+ if (!upconvertStatus.isOK()) {
+ return upconvertStatus;
}
- StatusWith<BSONObj> downconvertReplyMetadata(BSONObj commandReply, BSONObj replyMetadata) {
- BSONObjBuilder legacyCommandReplyBob;
+ return std::make_tuple(commandReplyBob.obj(), metadataBob.obj());
+}
- auto downconvertStatus = ShardingMetadata::downconvert(commandReply,
- replyMetadata,
- &legacyCommandReplyBob);
- if (!downconvertStatus.isOK()) {
- return downconvertStatus;
- }
+StatusWith<BSONObj> downconvertReplyMetadata(BSONObj commandReply, BSONObj replyMetadata) {
+ BSONObjBuilder legacyCommandReplyBob;
- return legacyCommandReplyBob.obj();
+ auto downconvertStatus =
+ ShardingMetadata::downconvert(commandReply, replyMetadata, &legacyCommandReplyBob);
+ if (!downconvertStatus.isOK()) {
+ return downconvertStatus;
}
+ return legacyCommandReplyBob.obj();
+}
+
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/metadata.h b/src/mongo/rpc/metadata.h
index ea0277059a3..393c3c57234 100644
--- a/src/mongo/rpc/metadata.h
+++ b/src/mongo/rpc/metadata.h
@@ -34,9 +34,9 @@
#include "mongo/stdx/functional.h"
namespace mongo {
- class BSONObj;
- class BSONObjBuilder;
- class OperationContext;
+class BSONObj;
+class BSONObjBuilder;
+class OperationContext;
/**
* Utilities for converting metadata between the legacy OP_QUERY format and the new
@@ -57,77 +57,77 @@ namespace mongo {
*/
namespace rpc {
- /**
- * Returns an empty metadata object.
- */
- BSONObj makeEmptyMetadata();
-
- /**
- * Reads metadata from a metadata object and sets it on this OperationContext.
- */
- Status readRequestMetadata(OperationContext* txn, const BSONObj& metadataObj);
-
- /**
- * Writes metadata from an OperationContext to a metadata object.
- */
- Status writeRequestMetadata(OperationContext* txn, BSONObjBuilder* metadataBob);
-
- /**
- * A command object and a corresponding metadata object.
- */
- using CommandAndMetadata = std::tuple<BSONObj, BSONObj>;
-
- /**
- * A legacy command object and a corresponding query flags bitfield. The legacy command object
- * may contain metadata fields, so it cannot safely be passed to a command's run method.
- */
- using LegacyCommandAndFlags = std::tuple<BSONObj, int>;
-
- /**
- * Given a legacy command object and a query flags bitfield, attempts to parse and remove
- * the metadata from the command object and construct a corresponding metadata object.
- */
- StatusWith<CommandAndMetadata> upconvertRequestMetadata(BSONObj legacyCmdObj, int queryFlags);
-
- /**
- * Given a command object and a metadata object, attempts to construct a legacy command
- * object and query flags bitfield augmented with the given metadata.
- */
- StatusWith<LegacyCommandAndFlags> downconvertRequestMetadata(BSONObj cmdObj, BSONObj metadata);
-
- /**
- * A command reply and associated metadata object.
- */
- using CommandReplyWithMetadata = std::tuple<BSONObj, BSONObj>;
-
- /**
- * Given a legacy command reply, attempts to strip the metadata from the reply and construct
- * a metadata object.
- */
- StatusWith<CommandReplyWithMetadata> upconvertReplyMetadata(BSONObj legacyReply);
-
- /**
- * Given a command reply object and an associated metadata object,
- * attempts to construct a legacy command object.
- */
- StatusWith<BSONObj> downconvertReplyMetadata(BSONObj commandReply, BSONObj replyMetadata);
-
- /**
- * A function type for writing request metadata. The function takes a pointer to a
- * BSONObjBuilder used to construct the metadata object and returns a Status indicating
- * if the metadata was written successfully.
- */
- using RequestMetadataWriter = stdx::function<Status(BSONObjBuilder*)>;
-
- /**
- * A function type for reading reply metadata. The function takes a a reference to a
- * metadata object received in a command reply and a string containing the server address of the
- * host that executed the command and returns a Status indicating if the
- * metadata was read successfully.
- *
- * TODO: would it be a layering violation if this hook took an OperationContext* ?
- */
- using ReplyMetadataReader = stdx::function<Status(const BSONObj&, StringData)>;
+/**
+ * Returns an empty metadata object.
+ */
+BSONObj makeEmptyMetadata();
+
+/**
+ * Reads metadata from a metadata object and sets it on this OperationContext.
+ */
+Status readRequestMetadata(OperationContext* txn, const BSONObj& metadataObj);
+
+/**
+ * Writes metadata from an OperationContext to a metadata object.
+ */
+Status writeRequestMetadata(OperationContext* txn, BSONObjBuilder* metadataBob);
+
+/**
+ * A command object and a corresponding metadata object.
+ */
+using CommandAndMetadata = std::tuple<BSONObj, BSONObj>;
+
+/**
+ * A legacy command object and a corresponding query flags bitfield. The legacy command object
+ * may contain metadata fields, so it cannot safely be passed to a command's run method.
+ */
+using LegacyCommandAndFlags = std::tuple<BSONObj, int>;
+
+/**
+ * Given a legacy command object and a query flags bitfield, attempts to parse and remove
+ * the metadata from the command object and construct a corresponding metadata object.
+ */
+StatusWith<CommandAndMetadata> upconvertRequestMetadata(BSONObj legacyCmdObj, int queryFlags);
+
+/**
+ * Given a command object and a metadata object, attempts to construct a legacy command
+ * object and query flags bitfield augmented with the given metadata.
+ */
+StatusWith<LegacyCommandAndFlags> downconvertRequestMetadata(BSONObj cmdObj, BSONObj metadata);
+
+/**
+ * A command reply and associated metadata object.
+ */
+using CommandReplyWithMetadata = std::tuple<BSONObj, BSONObj>;
+
+/**
+ * Given a legacy command reply, attempts to strip the metadata from the reply and construct
+ * a metadata object.
+ */
+StatusWith<CommandReplyWithMetadata> upconvertReplyMetadata(BSONObj legacyReply);
+
+/**
+ * Given a command reply object and an associated metadata object,
+ * attempts to construct a legacy command object.
+ */
+StatusWith<BSONObj> downconvertReplyMetadata(BSONObj commandReply, BSONObj replyMetadata);
+
+/**
+ * A function type for writing request metadata. The function takes a pointer to a
+ * BSONObjBuilder used to construct the metadata object and returns a Status indicating
+ * if the metadata was written successfully.
+ */
+using RequestMetadataWriter = stdx::function<Status(BSONObjBuilder*)>;
+
+/**
+ * A function type for reading reply metadata. The function takes a a reference to a
+ * metadata object received in a command reply and a string containing the server address of the
+ * host that executed the command and returns a Status indicating if the
+ * metadata was read successfully.
+ *
+ * TODO: would it be a layering violation if this hook took an OperationContext* ?
+ */
+using ReplyMetadataReader = stdx::function<Status(const BSONObj&, StringData)>;
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/metadata/audit_metadata.cpp b/src/mongo/rpc/metadata/audit_metadata.cpp
index 4b17101147f..7d064dec466 100644
--- a/src/mongo/rpc/metadata/audit_metadata.cpp
+++ b/src/mongo/rpc/metadata/audit_metadata.cpp
@@ -40,50 +40,47 @@
namespace mongo {
namespace rpc {
- const OperationContext::Decoration<AuditMetadata> AuditMetadata::get =
- OperationContext::declareDecoration<AuditMetadata>();
+const OperationContext::Decoration<AuditMetadata> AuditMetadata::get =
+ OperationContext::declareDecoration<AuditMetadata>();
- AuditMetadata::AuditMetadata(
- boost::optional<UsersAndRoles> impersonatedUsersAndRoles
- )
- : _impersonatedUsersAndRoles(std::move(impersonatedUsersAndRoles))
- {}
+AuditMetadata::AuditMetadata(boost::optional<UsersAndRoles> impersonatedUsersAndRoles)
+ : _impersonatedUsersAndRoles(std::move(impersonatedUsersAndRoles)) {}
#if !defined(MONGO_ENTERPRISE_VERSION)
- StatusWith<AuditMetadata> AuditMetadata::readFromMetadata(const BSONObj&) {
- return AuditMetadata(boost::none);
- }
-
- Status AuditMetadata::writeToMetadata(BSONObjBuilder*) const {
- return Status::OK();
- }
-
- Status AuditMetadata::downconvert(const BSONObj& command,
- const BSONObj&,
- BSONObjBuilder* commandBob,
- int*) {
- commandBob->appendElements(command);
- return Status::OK();
- }
-
- Status AuditMetadata::upconvert(const BSONObj& command,
- const int,
- BSONObjBuilder* commandBob,
- BSONObjBuilder*) {
- commandBob->appendElements(command);
- return Status::OK();
- }
+StatusWith<AuditMetadata> AuditMetadata::readFromMetadata(const BSONObj&) {
+ return AuditMetadata(boost::none);
+}
+
+Status AuditMetadata::writeToMetadata(BSONObjBuilder*) const {
+ return Status::OK();
+}
+
+Status AuditMetadata::downconvert(const BSONObj& command,
+ const BSONObj&,
+ BSONObjBuilder* commandBob,
+ int*) {
+ commandBob->appendElements(command);
+ return Status::OK();
+}
+
+Status AuditMetadata::upconvert(const BSONObj& command,
+ const int,
+ BSONObjBuilder* commandBob,
+ BSONObjBuilder*) {
+ commandBob->appendElements(command);
+ return Status::OK();
+}
#endif
- const boost::optional<AuditMetadata::UsersAndRoles>&
- AuditMetadata::getImpersonatedUsersAndRoles() const {
- return _impersonatedUsersAndRoles;
- }
+const boost::optional<AuditMetadata::UsersAndRoles>& AuditMetadata::getImpersonatedUsersAndRoles()
+ const {
+ return _impersonatedUsersAndRoles;
+}
- const char kLegacyImpersonatedUsersFieldName[] = "impersonatedUsers";
- const char kLegacyImpersonatedRolesFieldName[] = "impersonatedRoles";
+const char kLegacyImpersonatedUsersFieldName[] = "impersonatedUsers";
+const char kLegacyImpersonatedRolesFieldName[] = "impersonatedRoles";
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/metadata/audit_metadata.h b/src/mongo/rpc/metadata/audit_metadata.h
index 70cc54d7482..9ad983ca30e 100644
--- a/src/mongo/rpc/metadata/audit_metadata.h
+++ b/src/mongo/rpc/metadata/audit_metadata.h
@@ -37,57 +37,57 @@
#include "mongo/db/auth/role_name.h"
namespace mongo {
- class BSONObj;
- class BSONObjBuilder;
- class Status;
- template <typename T> class StatusWith;
+class BSONObj;
+class BSONObjBuilder;
+class Status;
+template <typename T>
+class StatusWith;
namespace rpc {
- /**
- * This class comprises the request metadata fields involving auditing.
- */
- class AuditMetadata {
- public:
- static const OperationContext::Decoration<AuditMetadata> get;
+/**
+ * This class comprises the request metadata fields involving auditing.
+ */
+class AuditMetadata {
+public:
+ static const OperationContext::Decoration<AuditMetadata> get;
- // Decorable requires a default constructor.
- AuditMetadata() = default;
+ // Decorable requires a default constructor.
+ AuditMetadata() = default;
- static StatusWith<AuditMetadata> readFromMetadata(const BSONObj& metadataObj);
+ static StatusWith<AuditMetadata> readFromMetadata(const BSONObj& metadataObj);
- Status writeToMetadata(BSONObjBuilder* metadataBob) const;
+ Status writeToMetadata(BSONObjBuilder* metadataBob) const;
- static Status downconvert(const BSONObj& command,
- const BSONObj& metadata,
- BSONObjBuilder* legacyCommandBob,
- int* legacyQueryFlags);
+ static Status downconvert(const BSONObj& command,
+ const BSONObj& metadata,
+ BSONObjBuilder* legacyCommandBob,
+ int* legacyQueryFlags);
- static Status upconvert(const BSONObj& legacyCommand,
- const int legacyQueryFlags,
- BSONObjBuilder* commandBob,
- BSONObjBuilder* metadataBob);
+ static Status upconvert(const BSONObj& legacyCommand,
+ const int legacyQueryFlags,
+ BSONObjBuilder* commandBob,
+ BSONObjBuilder* metadataBob);
- using UsersAndRoles = std::tuple<std::vector<UserName>,
- std::vector<RoleName>>;
+ using UsersAndRoles = std::tuple<std::vector<UserName>, std::vector<RoleName>>;
- const boost::optional<UsersAndRoles>& getImpersonatedUsersAndRoles() const;
+ const boost::optional<UsersAndRoles>& getImpersonatedUsersAndRoles() const;
- AuditMetadata(boost::optional<UsersAndRoles> impersonatedUsersAndRoles);
+ AuditMetadata(boost::optional<UsersAndRoles> impersonatedUsersAndRoles);
- private:
- boost::optional<UsersAndRoles> _impersonatedUsersAndRoles;
- };
+private:
+ boost::optional<UsersAndRoles> _impersonatedUsersAndRoles;
+};
- /**
- * The legacy field name used to hold impersonated users.
- */
- extern const char kLegacyImpersonatedUsersFieldName[];
+/**
+ * The legacy field name used to hold impersonated users.
+ */
+extern const char kLegacyImpersonatedUsersFieldName[];
- /**
- * The legacy field name used to hold impersonated roles.
- */
- extern const char kLegacyImpersonatedRolesFieldName[];
+/**
+ * The legacy field name used to hold impersonated roles.
+ */
+extern const char kLegacyImpersonatedRolesFieldName[];
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/metadata/server_selection_metadata.cpp b/src/mongo/rpc/metadata/server_selection_metadata.cpp
index 4222c88e895..1441243a4e7 100644
--- a/src/mongo/rpc/metadata/server_selection_metadata.cpp
+++ b/src/mongo/rpc/metadata/server_selection_metadata.cpp
@@ -45,244 +45,220 @@ namespace rpc {
namespace {
- const char kSecondaryOkFieldName[] = "$secondaryOk";
- const char kReadPreferenceFieldName[] = "$readPreference";
-
- const char kQueryOptionsFieldName[] = "$queryOptions";
-
- const char kDollarQueryWrapper[] = "$query";
- const char kQueryWrapper[] = "query";
-
- /**
- * Utility to unwrap a '$query' or 'query' wrapped command object. The first element of the
- * return value indicates whether the command was unwrapped, and the second element is either
- * the unwrapped command (if it was wrapped), or the original command if it was not.
- */
- std::tuple<bool, BSONObj> unwrapCommand(const BSONObj& maybeWrapped) {
- const auto firstElFieldName = maybeWrapped.firstElementFieldName();
- if ((firstElFieldName == StringData(kDollarQueryWrapper)) ||
- (firstElFieldName == StringData(kQueryWrapper))) {
- // TODO: do we need getOwned here?
- return std::make_tuple(true, maybeWrapped.firstElement().embeddedObject());
- }
- return std::make_tuple(false, maybeWrapped);
- }
+const char kSecondaryOkFieldName[] = "$secondaryOk";
+const char kReadPreferenceFieldName[] = "$readPreference";
- /**
- * Reads a top-level $readPreference field from a wrapped command.
- */
- Status extractWrappedReadPreference(const BSONObj& wrappedCommand,
- BSONObjBuilder* metadataBob) {
- BSONElement readPrefEl;
- auto rpExtractStatus = bsonExtractTypedField(wrappedCommand,
- kReadPreferenceFieldName,
- mongo::Object,
- &readPrefEl);
- if (rpExtractStatus.isOK()) {
- metadataBob->append(readPrefEl);
- }
- else if (rpExtractStatus != ErrorCodes::NoSuchKey) {
- return rpExtractStatus;
- }
+const char kQueryOptionsFieldName[] = "$queryOptions";
- return Status::OK();
- }
+const char kDollarQueryWrapper[] = "$query";
+const char kQueryWrapper[] = "query";
- /**
- * Reads a $readPreference from a $queryOptions subobject, if it exists, and writes it to
- * metadataBob. Writes out the original command excluding the $queryOptions subobject.
- */
- Status extractUnwrappedReadPreference(const BSONObj& unwrappedCommand,
- BSONObjBuilder* commandBob,
- BSONObjBuilder* metadataBob) {
- BSONElement queryOptionsEl;
- BSONElement readPrefEl;
-
- auto queryOptionsExtractStatus = bsonExtractTypedField(unwrappedCommand,
- kQueryOptionsFieldName,
- mongo::Object,
- &queryOptionsEl);
-
- // If there is no queryOptions subobject, we write out the command and return.
- if (queryOptionsExtractStatus == ErrorCodes::NoSuchKey) {
- commandBob->appendElements(unwrappedCommand);
- return Status::OK();
- }
- else if (!queryOptionsExtractStatus.isOK()) {
- return queryOptionsExtractStatus;
- }
-
- // Write out the command excluding the $queryOptions field.
- for (const auto& elem : unwrappedCommand) {
- if (elem.fieldNameStringData() != kQueryOptionsFieldName) {
- commandBob->append(elem);
- }
- }
+/**
+ * Utility to unwrap a '$query' or 'query' wrapped command object. The first element of the
+ * return value indicates whether the command was unwrapped, and the second element is either
+ * the unwrapped command (if it was wrapped), or the original command if it was not.
+ */
+std::tuple<bool, BSONObj> unwrapCommand(const BSONObj& maybeWrapped) {
+ const auto firstElFieldName = maybeWrapped.firstElementFieldName();
+ if ((firstElFieldName == StringData(kDollarQueryWrapper)) ||
+ (firstElFieldName == StringData(kQueryWrapper))) {
+ // TODO: do we need getOwned here?
+ return std::make_tuple(true, maybeWrapped.firstElement().embeddedObject());
+ }
+ return std::make_tuple(false, maybeWrapped);
+}
- auto rpExtractStatus = bsonExtractTypedField(queryOptionsEl.embeddedObject(),
- kReadPreferenceFieldName,
- mongo::Object,
- &readPrefEl);
+/**
+ * Reads a top-level $readPreference field from a wrapped command.
+ */
+Status extractWrappedReadPreference(const BSONObj& wrappedCommand, BSONObjBuilder* metadataBob) {
+ BSONElement readPrefEl;
+ auto rpExtractStatus =
+ bsonExtractTypedField(wrappedCommand, kReadPreferenceFieldName, mongo::Object, &readPrefEl);
+ if (rpExtractStatus.isOK()) {
+ metadataBob->append(readPrefEl);
+ } else if (rpExtractStatus != ErrorCodes::NoSuchKey) {
+ return rpExtractStatus;
+ }
- // If there is a $queryOptions field, we expect there to be a $readPreference.
- if (!rpExtractStatus.isOK()) {
- return rpExtractStatus;
- }
+ return Status::OK();
+}
- metadataBob->append(readPrefEl);
+/**
+ * Reads a $readPreference from a $queryOptions subobject, if it exists, and writes it to
+ * metadataBob. Writes out the original command excluding the $queryOptions subobject.
+ */
+Status extractUnwrappedReadPreference(const BSONObj& unwrappedCommand,
+ BSONObjBuilder* commandBob,
+ BSONObjBuilder* metadataBob) {
+ BSONElement queryOptionsEl;
+ BSONElement readPrefEl;
+
+ auto queryOptionsExtractStatus = bsonExtractTypedField(
+ unwrappedCommand, kQueryOptionsFieldName, mongo::Object, &queryOptionsEl);
+
+ // If there is no queryOptions subobject, we write out the command and return.
+ if (queryOptionsExtractStatus == ErrorCodes::NoSuchKey) {
+ commandBob->appendElements(unwrappedCommand);
return Status::OK();
+ } else if (!queryOptionsExtractStatus.isOK()) {
+ return queryOptionsExtractStatus;
}
-} // namespace
-
- const OperationContext::Decoration<ServerSelectionMetadata> ServerSelectionMetadata::get =
- OperationContext::declareDecoration<ServerSelectionMetadata>();
+ // Write out the command excluding the $queryOptions field.
+ for (const auto& elem : unwrappedCommand) {
+ if (elem.fieldNameStringData() != kQueryOptionsFieldName) {
+ commandBob->append(elem);
+ }
+ }
- ServerSelectionMetadata::ServerSelectionMetadata(
- bool secondaryOk,
- boost::optional<ReadPreferenceSetting> readPreference
- )
- : _secondaryOk(secondaryOk)
- , _readPreference(std::move(readPreference))
- {}
+ auto rpExtractStatus = bsonExtractTypedField(
+ queryOptionsEl.embeddedObject(), kReadPreferenceFieldName, mongo::Object, &readPrefEl);
- StatusWith<ServerSelectionMetadata>
- ServerSelectionMetadata::readFromMetadata(const BSONObj& metadata) {
- auto secondaryOkField = metadata.getField(kSecondaryOkFieldName);
+ // If there is a $queryOptions field, we expect there to be a $readPreference.
+ if (!rpExtractStatus.isOK()) {
+ return rpExtractStatus;
+ }
- bool secondaryOk = !secondaryOkField.eoo();
+ metadataBob->append(readPrefEl);
+ return Status::OK();
+}
- boost::optional<ReadPreferenceSetting> readPreference;
- BSONElement rpElem;
- auto readPrefExtractStatus = bsonExtractTypedField(metadata,
- kReadPreferenceFieldName,
- mongo::Object,
- &rpElem);
+} // namespace
- if (readPrefExtractStatus == ErrorCodes::NoSuchKey) {
- // Do nothing, it's valid to have no ReadPreference
- }
- else if (!readPrefExtractStatus.isOK()) {
- return readPrefExtractStatus;
- }
- else {
- // We have a read preference in the metadata object.
- auto parsedRps = ReadPreferenceSetting::fromBSON(rpElem.Obj());
- if (!parsedRps.isOK()) {
- return parsedRps.getStatus();
- }
- readPreference.emplace(std::move(parsedRps.getValue()));
+const OperationContext::Decoration<ServerSelectionMetadata> ServerSelectionMetadata::get =
+ OperationContext::declareDecoration<ServerSelectionMetadata>();
+
+ServerSelectionMetadata::ServerSelectionMetadata(
+ bool secondaryOk, boost::optional<ReadPreferenceSetting> readPreference)
+ : _secondaryOk(secondaryOk), _readPreference(std::move(readPreference)) {}
+
+StatusWith<ServerSelectionMetadata> ServerSelectionMetadata::readFromMetadata(
+ const BSONObj& metadata) {
+ auto secondaryOkField = metadata.getField(kSecondaryOkFieldName);
+
+ bool secondaryOk = !secondaryOkField.eoo();
+
+ boost::optional<ReadPreferenceSetting> readPreference;
+ BSONElement rpElem;
+ auto readPrefExtractStatus =
+ bsonExtractTypedField(metadata, kReadPreferenceFieldName, mongo::Object, &rpElem);
+
+ if (readPrefExtractStatus == ErrorCodes::NoSuchKey) {
+ // Do nothing, it's valid to have no ReadPreference
+ } else if (!readPrefExtractStatus.isOK()) {
+ return readPrefExtractStatus;
+ } else {
+ // We have a read preference in the metadata object.
+ auto parsedRps = ReadPreferenceSetting::fromBSON(rpElem.Obj());
+ if (!parsedRps.isOK()) {
+ return parsedRps.getStatus();
}
-
- return ServerSelectionMetadata(secondaryOk, std::move(readPreference));
+ readPreference.emplace(std::move(parsedRps.getValue()));
}
- Status ServerSelectionMetadata::writeToMetadata(BSONObjBuilder* metadataBob) const {
- if (isSecondaryOk()) {
- metadataBob->append(kSecondaryOkFieldName, 1);
- }
-
- if (getReadPreference()) {
- metadataBob->append(kReadPreferenceFieldName, getReadPreference()->toBSON());
- }
+ return ServerSelectionMetadata(secondaryOk, std::move(readPreference));
+}
- return Status::OK();
+Status ServerSelectionMetadata::writeToMetadata(BSONObjBuilder* metadataBob) const {
+ if (isSecondaryOk()) {
+ metadataBob->append(kSecondaryOkFieldName, 1);
}
- Status ServerSelectionMetadata::downconvert(const BSONObj& command,
- const BSONObj& metadata,
- BSONObjBuilder* legacyCommand,
- int* legacyQueryFlags) {
+ if (getReadPreference()) {
+ metadataBob->append(kReadPreferenceFieldName, getReadPreference()->toBSON());
+ }
- BSONElement secondaryOkElem = metadata.getField(kSecondaryOkFieldName);
- BSONElement readPrefElem = metadata.getField(kReadPreferenceFieldName);
+ return Status::OK();
+}
- if (!secondaryOkElem.eoo()) {
- *legacyQueryFlags |= mongo::QueryOption_SlaveOk;
- }
- else {
- *legacyQueryFlags &= ~mongo::QueryOption_SlaveOk;
- }
+Status ServerSelectionMetadata::downconvert(const BSONObj& command,
+ const BSONObj& metadata,
+ BSONObjBuilder* legacyCommand,
+ int* legacyQueryFlags) {
+ BSONElement secondaryOkElem = metadata.getField(kSecondaryOkFieldName);
+ BSONElement readPrefElem = metadata.getField(kReadPreferenceFieldName);
- if (!readPrefElem.eoo()) {
- // Use 'query' to wrap query, then append read preference.
+ if (!secondaryOkElem.eoo()) {
+ *legacyQueryFlags |= mongo::QueryOption_SlaveOk;
+ } else {
+ *legacyQueryFlags &= ~mongo::QueryOption_SlaveOk;
+ }
- // NOTE(amidvidy): Oddly, the _isSecondaryQuery implementation in dbclient_rs does
- // not unwrap the query properly - it only checks for 'query', and not
- // '$query'. We should probably standardize on one - drivers use '$query',
- // and the shell uses 'query'. See SERVER-18705 for details.
+ if (!readPrefElem.eoo()) {
+ // Use 'query' to wrap query, then append read preference.
- // TODO: this may need to use the $queryOptions hack on mongos.
- legacyCommand->append(kQueryWrapper, command);
- legacyCommand->append(readPrefElem);
- }
- else {
- legacyCommand->appendElements(command);
- }
+ // NOTE(amidvidy): Oddly, the _isSecondaryQuery implementation in dbclient_rs does
+ // not unwrap the query properly - it only checks for 'query', and not
+ // '$query'. We should probably standardize on one - drivers use '$query',
+ // and the shell uses 'query'. See SERVER-18705 for details.
- return Status::OK();
+ // TODO: this may need to use the $queryOptions hack on mongos.
+ legacyCommand->append(kQueryWrapper, command);
+ legacyCommand->append(readPrefElem);
+ } else {
+ legacyCommand->appendElements(command);
}
- Status ServerSelectionMetadata::upconvert(const BSONObj& legacyCommand,
- const int legacyQueryFlags,
- BSONObjBuilder* commandBob,
- BSONObjBuilder* metadataBob) {
+ return Status::OK();
+}
- // The secondaryOK option is equivalent to the slaveOk bit being set on legacy commands.
- if (legacyQueryFlags & QueryOption_SlaveOk) {
- metadataBob->append(kSecondaryOkFieldName, 1);
- }
+Status ServerSelectionMetadata::upconvert(const BSONObj& legacyCommand,
+ const int legacyQueryFlags,
+ BSONObjBuilder* commandBob,
+ BSONObjBuilder* metadataBob) {
+ // The secondaryOK option is equivalent to the slaveOk bit being set on legacy commands.
+ if (legacyQueryFlags & QueryOption_SlaveOk) {
+ metadataBob->append(kSecondaryOkFieldName, 1);
+ }
- // First we need to check if we have a wrapped command. That is, a command of the form
- // {'$query': { 'commandName': 1, ...}, '$someOption': 5, ....}. Curiously, the field name
- // of the wrapped query can be either '$query', or 'query'.
- BSONObj maybeUnwrapped;
- bool wasWrapped;
- std::tie(wasWrapped, maybeUnwrapped) = unwrapCommand(legacyCommand);
-
- if (wasWrapped) {
- // Check if legacyCommand has an invalid $maxTimeMS option.
- // TODO: Move this check elsewhere when we handle upconverting/downconverting maxTimeMS.
- if (legacyCommand.hasField("$maxTimeMS")) {
- return Status(ErrorCodes::InvalidOptions,
- "cannot use $maxTimeMS query option with "
- "commands; use maxTimeMS command option "
- "instead");
- }
-
- // If the command was wrapped, we can write out the upconverted command now, as there
- // is nothing else we need to remove from it.
- commandBob->appendElements(maybeUnwrapped);
-
- return extractWrappedReadPreference(legacyCommand, metadataBob);
+ // First we need to check if we have a wrapped command. That is, a command of the form
+ // {'$query': { 'commandName': 1, ...}, '$someOption': 5, ....}. Curiously, the field name
+ // of the wrapped query can be either '$query', or 'query'.
+ BSONObj maybeUnwrapped;
+ bool wasWrapped;
+ std::tie(wasWrapped, maybeUnwrapped) = unwrapCommand(legacyCommand);
+
+ if (wasWrapped) {
+ // Check if legacyCommand has an invalid $maxTimeMS option.
+ // TODO: Move this check elsewhere when we handle upconverting/downconverting maxTimeMS.
+ if (legacyCommand.hasField("$maxTimeMS")) {
+ return Status(ErrorCodes::InvalidOptions,
+ "cannot use $maxTimeMS query option with "
+ "commands; use maxTimeMS command option "
+ "instead");
}
- // If the command was not wrapped, we need to check for a readPreference sent by mongos
- // on the $queryOptions field of the command. If it is set, we remove it from the
- // upconverted command, so we need to pass the command builder along.
- return extractUnwrappedReadPreference(maybeUnwrapped, commandBob, metadataBob);
- }
+ // If the command was wrapped, we can write out the upconverted command now, as there
+ // is nothing else we need to remove from it.
+ commandBob->appendElements(maybeUnwrapped);
- bool ServerSelectionMetadata::isSecondaryOk() const {
- return _secondaryOk;
+ return extractWrappedReadPreference(legacyCommand, metadataBob);
}
- const boost::optional<ReadPreferenceSetting>&
- ServerSelectionMetadata::getReadPreference() const {
- return _readPreference;
- }
+ // If the command was not wrapped, we need to check for a readPreference sent by mongos
+ // on the $queryOptions field of the command. If it is set, we remove it from the
+ // upconverted command, so we need to pass the command builder along.
+ return extractUnwrappedReadPreference(maybeUnwrapped, commandBob, metadataBob);
+}
+
+bool ServerSelectionMetadata::isSecondaryOk() const {
+ return _secondaryOk;
+}
+
+const boost::optional<ReadPreferenceSetting>& ServerSelectionMetadata::getReadPreference() const {
+ return _readPreference;
+}
#if defined(_MSC_VER) && _MSC_VER < 1900
- ServerSelectionMetadata::ServerSelectionMetadata(ServerSelectionMetadata&& ssm)
- : _secondaryOk(ssm._secondaryOk)
- , _readPreference(std::move(ssm._readPreference))
- {}
-
- ServerSelectionMetadata& ServerSelectionMetadata::operator=(ServerSelectionMetadata&& ssm) {
- _secondaryOk = ssm._secondaryOk;
- _readPreference = std::move(ssm._readPreference);
- return *this;
- }
+ServerSelectionMetadata::ServerSelectionMetadata(ServerSelectionMetadata&& ssm)
+ : _secondaryOk(ssm._secondaryOk), _readPreference(std::move(ssm._readPreference)) {}
+
+ServerSelectionMetadata& ServerSelectionMetadata::operator=(ServerSelectionMetadata&& ssm) {
+ _secondaryOk = ssm._secondaryOk;
+ _readPreference = std::move(ssm._readPreference);
+ return *this;
+}
#endif
} // rpc
diff --git a/src/mongo/rpc/metadata/server_selection_metadata.h b/src/mongo/rpc/metadata/server_selection_metadata.h
index 4bdc700f20b..1f345af9a19 100644
--- a/src/mongo/rpc/metadata/server_selection_metadata.h
+++ b/src/mongo/rpc/metadata/server_selection_metadata.h
@@ -35,82 +35,85 @@
#include "mongo/db/operation_context.h"
namespace mongo {
- class BSONObj;
- class BSONObjBuilder;
- class Status;
- template <typename T> class StatusWith;
+class BSONObj;
+class BSONObjBuilder;
+class Status;
+template <typename T>
+class StatusWith;
namespace rpc {
- /**
- * This class comprises the request metadata fields that concern server selection, that is,
- * the conditions on which servers can execute this operation.
- */
- class ServerSelectionMetadata {
- MONGO_DISALLOW_COPYING(ServerSelectionMetadata);
- public:
- static const OperationContext::Decoration<ServerSelectionMetadata> get;
+/**
+ * This class comprises the request metadata fields that concern server selection, that is,
+ * the conditions on which servers can execute this operation.
+ */
+class ServerSelectionMetadata {
+ MONGO_DISALLOW_COPYING(ServerSelectionMetadata);
- // TODO: Remove when StatusWith supports default-constructible types (SERVER-18007).
- ServerSelectionMetadata() = default;
+public:
+ static const OperationContext::Decoration<ServerSelectionMetadata> get;
+
+ // TODO: Remove when StatusWith supports default-constructible types (SERVER-18007).
+ ServerSelectionMetadata() = default;
#if defined(_MSC_VER) && _MSC_VER < 1900
- ServerSelectionMetadata(ServerSelectionMetadata&&);
+ ServerSelectionMetadata(ServerSelectionMetadata&&);
- ServerSelectionMetadata& operator=(ServerSelectionMetadata&&);
+ ServerSelectionMetadata& operator=(ServerSelectionMetadata&&);
#else
- ServerSelectionMetadata(ServerSelectionMetadata&&) = default;
+ ServerSelectionMetadata(ServerSelectionMetadata&&) = default;
- ServerSelectionMetadata& operator=(ServerSelectionMetadata&&) = default;
+ ServerSelectionMetadata& operator=(ServerSelectionMetadata&&) = default;
#endif
- /**
- * Loads ServerSelectionMetadata from a metadata object.
- */
- static StatusWith<ServerSelectionMetadata> readFromMetadata(const BSONObj& metadataObj);
-
- /**
- * Writes this operation's ServerSelectionMetadata to a metadata object.
- */
- Status writeToMetadata(BSONObjBuilder* metadataBob) const;
-
- /**
- * Rewrites the ServerSelectionMetadata from the metadata object format to the legacy OP_QUERY
- * format. In particular, if secondaryOk is set, this will set QueryOption_SlaveOk
- * on the legacyQueryFlags. If a readPreference is set, the legacy command will be wrapped
- * in a 'query' element and a top-level $readPreference field will be set on the command.
- */
- static Status downconvert(const BSONObj& command,
- const BSONObj& metadata,
- BSONObjBuilder* legacyCommand,
- int* legacyQueryFlags);
-
- /**
- * Rewrites the ServerSelectionMetadata from the legacy OP_QUERY format to the metadata
- * object format.
- */
- static Status upconvert(const BSONObj& legacyCommand,
- const int legacyQueryFlags,
- BSONObjBuilder* commandBob,
- BSONObjBuilder* metadataBob);
- /**
- * Returns true if this operation has been explicitly overridden to run on a secondary.
- * This replaces previous usage of QueryOption_SlaveOk.
- */
- bool isSecondaryOk() const;
-
- /**
- * Returns the ReadPreference associated with this operation. See
- * mongo/client/read_preference.h for further details.
- */
- const boost::optional<ReadPreferenceSetting>& getReadPreference() const;
-
- ServerSelectionMetadata(bool secondaryOk,
- boost::optional<ReadPreferenceSetting> readPreference);
- private:
- bool _secondaryOk{false};
- boost::optional<ReadPreferenceSetting> _readPreference{};
- };
+ /**
+ * Loads ServerSelectionMetadata from a metadata object.
+ */
+ static StatusWith<ServerSelectionMetadata> readFromMetadata(const BSONObj& metadataObj);
+
+ /**
+ * Writes this operation's ServerSelectionMetadata to a metadata object.
+ */
+ Status writeToMetadata(BSONObjBuilder* metadataBob) const;
+
+ /**
+ * Rewrites the ServerSelectionMetadata from the metadata object format to the legacy OP_QUERY
+ * format. In particular, if secondaryOk is set, this will set QueryOption_SlaveOk
+ * on the legacyQueryFlags. If a readPreference is set, the legacy command will be wrapped
+ * in a 'query' element and a top-level $readPreference field will be set on the command.
+ */
+ static Status downconvert(const BSONObj& command,
+ const BSONObj& metadata,
+ BSONObjBuilder* legacyCommand,
+ int* legacyQueryFlags);
+
+ /**
+ * Rewrites the ServerSelectionMetadata from the legacy OP_QUERY format to the metadata
+ * object format.
+ */
+ static Status upconvert(const BSONObj& legacyCommand,
+ const int legacyQueryFlags,
+ BSONObjBuilder* commandBob,
+ BSONObjBuilder* metadataBob);
+ /**
+ * Returns true if this operation has been explicitly overridden to run on a secondary.
+ * This replaces previous usage of QueryOption_SlaveOk.
+ */
+ bool isSecondaryOk() const;
+
+ /**
+ * Returns the ReadPreference associated with this operation. See
+ * mongo/client/read_preference.h for further details.
+ */
+ const boost::optional<ReadPreferenceSetting>& getReadPreference() const;
+
+ ServerSelectionMetadata(bool secondaryOk,
+ boost::optional<ReadPreferenceSetting> readPreference);
+
+private:
+ bool _secondaryOk{false};
+ boost::optional<ReadPreferenceSetting> _readPreference{};
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/metadata/server_selection_metadata_test.cpp b/src/mongo/rpc/metadata/server_selection_metadata_test.cpp
index fe6de217b46..ae8d4057b45 100644
--- a/src/mongo/rpc/metadata/server_selection_metadata_test.cpp
+++ b/src/mongo/rpc/metadata/server_selection_metadata_test.cpp
@@ -38,138 +38,145 @@
#include "mongo/unittest/unittest.h"
namespace {
- using namespace mongo;
- using namespace mongo::rpc;
- using mongo::unittest::assertGet;
-
- ServerSelectionMetadata checkParse(const BSONObj& metadata) {
- return assertGet(ServerSelectionMetadata::readFromMetadata(metadata));
+using namespace mongo;
+using namespace mongo::rpc;
+using mongo::unittest::assertGet;
+
+ServerSelectionMetadata checkParse(const BSONObj& metadata) {
+ return assertGet(ServerSelectionMetadata::readFromMetadata(metadata));
+}
+
+TEST(ServerSelectionMetadata, ReadFromMetadata) {
+ {
+ // Empty object - should work just fine.
+ auto ss = checkParse(BSONObj());
+ ASSERT_FALSE(ss.isSecondaryOk());
+ ASSERT_FALSE(ss.getReadPreference().is_initialized());
}
-
- TEST(ServerSelectionMetadata, ReadFromMetadata) {
- {
- // Empty object - should work just fine.
- auto ss = checkParse(BSONObj());
- ASSERT_FALSE(ss.isSecondaryOk());
- ASSERT_FALSE(ss.getReadPreference().is_initialized());
- }
- {
- // Set secondaryOk but not readPreference.
- auto ss = checkParse(BSON("$secondaryOk" << 1));
- ASSERT_TRUE(ss.isSecondaryOk());
- ASSERT_FALSE(ss.getReadPreference().is_initialized());
- }
- {
- // Set readPreference but not secondaryOk.
- auto ss = checkParse(BSON("$readPreference" <<
- BSON("mode" << "primary")));
- ASSERT_FALSE(ss.isSecondaryOk());
- ASSERT_TRUE(ss.getReadPreference().is_initialized());
- ASSERT_TRUE(ss.getReadPreference()->pref == ReadPreference::PrimaryOnly);
- }
- {
- // Set both.
- auto ss = checkParse(BSON("$secondaryOk" << 1 <<
- "$readPreference" <<
- BSON("mode" << "secondaryPreferred")));
- ASSERT_TRUE(ss.isSecondaryOk());
- ASSERT_TRUE(ss.getReadPreference()->pref == ReadPreference::SecondaryPreferred);
- }
+ {
+ // Set secondaryOk but not readPreference.
+ auto ss = checkParse(BSON("$secondaryOk" << 1));
+ ASSERT_TRUE(ss.isSecondaryOk());
+ ASSERT_FALSE(ss.getReadPreference().is_initialized());
}
-
- void checkUpconvert(const BSONObj& legacyCommand,
- const int legacyQueryFlags,
- const BSONObj& upconvertedCommand,
- const BSONObj& upconvertedMetadata) {
- BSONObjBuilder upconvertedCommandBob;
- BSONObjBuilder upconvertedMetadataBob;
- auto convertStatus = ServerSelectionMetadata::upconvert(legacyCommand,
- legacyQueryFlags,
- &upconvertedCommandBob,
- &upconvertedMetadataBob);
- ASSERT_OK(convertStatus);
- // We don't care about the order of the fields in the metadata object
- const auto sorted = [](const BSONObj& obj) {
- BSONObjIteratorSorted iter(obj);
- BSONObjBuilder bob;
- while (iter.more()) {
- bob.append(iter.next());
- }
- return bob.obj();
- };
-
- ASSERT_EQ(upconvertedCommand, upconvertedCommandBob.done());
- ASSERT_EQ(sorted(upconvertedMetadata), sorted(upconvertedMetadataBob.done()));
+ {
+ // Set readPreference but not secondaryOk.
+ auto ss = checkParse(BSON("$readPreference" << BSON("mode"
+ << "primary")));
+ ASSERT_FALSE(ss.isSecondaryOk());
+ ASSERT_TRUE(ss.getReadPreference().is_initialized());
+ ASSERT_TRUE(ss.getReadPreference()->pref == ReadPreference::PrimaryOnly);
}
-
- TEST(ServerSelectionMetadata, UpconvertValidMetadata) {
- // Wrapped in $query, with readPref and slaveOk bit set.
- checkUpconvert(BSON("$query" << BSON("ping" << 1) <<
- "$readPreference" << BSON("mode" << "secondary")),
- mongo::QueryOption_SlaveOk,
- BSON("ping" << 1),
- BSON("$secondaryOk" << 1 <<
- "$readPreference" << BSON("mode" << "secondary")));
-
- // Wrapped in 'query', with readPref.
- checkUpconvert(BSON("query" << BSON("pong" << 1 << "foo" << "bar") <<
- "$readPreference" << BSON("mode" << "primary" <<
- "tags" << BSON("dc" << "ny"))),
- 0,
- BSON("pong" << 1 << "foo" << "bar"),
- BSON("$readPreference" << BSON("mode" << "primary" <<
- "tags" << BSON("dc" << "ny"))));
- // Unwrapped, no readPref, no slaveOk
- checkUpconvert(BSON("ping" << 1),
- 0,
- BSON("ping" << 1),
- BSONObj());
-
- // Readpref wrapped in $queryOptions
- checkUpconvert(BSON("pang" << "pong" <<
- "$queryOptions" <<
- BSON("$readPreference" << BSON("mode" << "nearest" <<
- "tags" << BSON("rack" << "city")))),
- 0,
- BSON("pang" << "pong"),
- BSON("$readPreference" << BSON("mode" << "nearest" <<
- "tags" << BSON("rack" << "city"))));
- }
-
- void checkUpconvertFails(const BSONObj& legacyCommand, ErrorCodes::Error error) {
- BSONObjBuilder upconvertedCommandBob;
- BSONObjBuilder upconvertedMetadataBob;
- auto upconvertStatus = ServerSelectionMetadata::upconvert(legacyCommand,
- 0,
- &upconvertedCommandBob,
- &upconvertedMetadataBob);
- ASSERT_NOT_OK(upconvertStatus);
- ASSERT_EQ(upconvertStatus.code(), error);
- }
-
- TEST(ServerSelectionMetadata, UpconvertInvalidMetadata) {
- // $readPreference not an object.
- checkUpconvertFails(BSON("$query" << BSON("pang" << "pong") <<
- "$readPreference" << 2),
- ErrorCodes::TypeMismatch);
-
- // has $maxTimeMS option
- checkUpconvertFails(BSON("query" << BSON("foo" << "bar") <<
- "$maxTimeMS" << 200),
- ErrorCodes::InvalidOptions);
- checkUpconvertFails(BSON("$query" << BSON("foo" << "bar") <<
- "$maxTimeMS" << 200),
- ErrorCodes::InvalidOptions);
-
- // has $queryOptions field, but invalid $readPreference
- checkUpconvertFails(BSON("ping" << "pong" <<
- "$queryOptions" << BSON("$readPreference" << 1.2)),
- ErrorCodes::TypeMismatch);
-
- // has $queryOptions field, but no $readPreference
- checkUpconvertFails(BSON("ping" << "pong" <<
- "$queryOptions" << BSONObj()),
- ErrorCodes::NoSuchKey);
+ {
+ // Set both.
+ auto ss = checkParse(
+ BSON("$secondaryOk" << 1 << "$readPreference" << BSON("mode"
+ << "secondaryPreferred")));
+ ASSERT_TRUE(ss.isSecondaryOk());
+ ASSERT_TRUE(ss.getReadPreference()->pref == ReadPreference::SecondaryPreferred);
}
+}
+
+void checkUpconvert(const BSONObj& legacyCommand,
+ const int legacyQueryFlags,
+ const BSONObj& upconvertedCommand,
+ const BSONObj& upconvertedMetadata) {
+ BSONObjBuilder upconvertedCommandBob;
+ BSONObjBuilder upconvertedMetadataBob;
+ auto convertStatus = ServerSelectionMetadata::upconvert(
+ legacyCommand, legacyQueryFlags, &upconvertedCommandBob, &upconvertedMetadataBob);
+ ASSERT_OK(convertStatus);
+ // We don't care about the order of the fields in the metadata object
+ const auto sorted = [](const BSONObj& obj) {
+ BSONObjIteratorSorted iter(obj);
+ BSONObjBuilder bob;
+ while (iter.more()) {
+ bob.append(iter.next());
+ }
+ return bob.obj();
+ };
+
+ ASSERT_EQ(upconvertedCommand, upconvertedCommandBob.done());
+ ASSERT_EQ(sorted(upconvertedMetadata), sorted(upconvertedMetadataBob.done()));
+}
+
+TEST(ServerSelectionMetadata, UpconvertValidMetadata) {
+ // Wrapped in $query, with readPref and slaveOk bit set.
+ checkUpconvert(BSON("$query" << BSON("ping" << 1) << "$readPreference" << BSON("mode"
+ << "secondary")),
+ mongo::QueryOption_SlaveOk,
+ BSON("ping" << 1),
+ BSON("$secondaryOk" << 1 << "$readPreference" << BSON("mode"
+ << "secondary")));
+
+ // Wrapped in 'query', with readPref.
+ checkUpconvert(BSON("query" << BSON("pong" << 1 << "foo"
+ << "bar") << "$readPreference"
+ << BSON("mode"
+ << "primary"
+ << "tags" << BSON("dc"
+ << "ny"))),
+ 0,
+ BSON("pong" << 1 << "foo"
+ << "bar"),
+ BSON("$readPreference" << BSON("mode"
+ << "primary"
+ << "tags" << BSON("dc"
+ << "ny"))));
+ // Unwrapped, no readPref, no slaveOk
+ checkUpconvert(BSON("ping" << 1), 0, BSON("ping" << 1), BSONObj());
+
+ // Readpref wrapped in $queryOptions
+ checkUpconvert(BSON("pang"
+ << "pong"
+ << "$queryOptions"
+ << BSON("$readPreference" << BSON("mode"
+ << "nearest"
+ << "tags" << BSON("rack"
+ << "city")))),
+ 0,
+ BSON("pang"
+ << "pong"),
+ BSON("$readPreference" << BSON("mode"
+ << "nearest"
+ << "tags" << BSON("rack"
+ << "city"))));
+}
+
+void checkUpconvertFails(const BSONObj& legacyCommand, ErrorCodes::Error error) {
+ BSONObjBuilder upconvertedCommandBob;
+ BSONObjBuilder upconvertedMetadataBob;
+ auto upconvertStatus = ServerSelectionMetadata::upconvert(
+ legacyCommand, 0, &upconvertedCommandBob, &upconvertedMetadataBob);
+ ASSERT_NOT_OK(upconvertStatus);
+ ASSERT_EQ(upconvertStatus.code(), error);
+}
+
+TEST(ServerSelectionMetadata, UpconvertInvalidMetadata) {
+ // $readPreference not an object.
+ checkUpconvertFails(BSON("$query" << BSON("pang"
+ << "pong") << "$readPreference" << 2),
+ ErrorCodes::TypeMismatch);
+
+ // has $maxTimeMS option
+ checkUpconvertFails(BSON("query" << BSON("foo"
+ << "bar") << "$maxTimeMS" << 200),
+ ErrorCodes::InvalidOptions);
+ checkUpconvertFails(BSON("$query" << BSON("foo"
+ << "bar") << "$maxTimeMS" << 200),
+ ErrorCodes::InvalidOptions);
+
+ // has $queryOptions field, but invalid $readPreference
+ checkUpconvertFails(BSON("ping"
+ << "pong"
+ << "$queryOptions" << BSON("$readPreference" << 1.2)),
+ ErrorCodes::TypeMismatch);
+
+ // has $queryOptions field, but no $readPreference
+ checkUpconvertFails(BSON("ping"
+ << "pong"
+ << "$queryOptions" << BSONObj()),
+ ErrorCodes::NoSuchKey);
+}
} // namespace
diff --git a/src/mongo/rpc/metadata/sharding_metadata.cpp b/src/mongo/rpc/metadata/sharding_metadata.cpp
index e33a4e075bd..4fc3a2feae2 100644
--- a/src/mongo/rpc/metadata/sharding_metadata.cpp
+++ b/src/mongo/rpc/metadata/sharding_metadata.cpp
@@ -41,115 +41,105 @@ namespace rpc {
namespace {
- const char kGLEStatsFieldName[] = "$gleStats";
- const char kGLEStatsLastOpTimeFieldName[] = "lastOpTime";
- const char kGLEStatsElectionIdFieldName[] = "electionId";
+const char kGLEStatsFieldName[] = "$gleStats";
+const char kGLEStatsLastOpTimeFieldName[] = "lastOpTime";
+const char kGLEStatsElectionIdFieldName[] = "electionId";
} // namespace
- StatusWith<ShardingMetadata> ShardingMetadata::readFromMetadata(const BSONObj& metadataObj) {
- BSONElement smElem;
- auto smExtractStatus = bsonExtractTypedField(metadataObj,
- kGLEStatsFieldName,
- mongo::Object,
- &smElem);
- if (!smExtractStatus.isOK()) {
- return smExtractStatus;
- }
-
- if (smElem.embeddedObject().nFields() != 2) {
- return Status(ErrorCodes::InvalidOptions,
- str::stream() << "The $gleStats object can only have 2 fields, but got "
- << smElem.embeddedObject().toString());
- }
-
- BSONElement lastOpTimeElem;
- auto lastOpTimeExtractStatus = bsonExtractTypedField(smElem.embeddedObject(),
- kGLEStatsLastOpTimeFieldName,
- mongo::bsonTimestamp,
- &lastOpTimeElem);
- if (!lastOpTimeExtractStatus.isOK()) {
- return lastOpTimeExtractStatus;
- }
-
- BSONElement lastElectionIdElem;
- auto lastElectionIdExtractStatus = bsonExtractTypedField(smElem.embeddedObject(),
- kGLEStatsElectionIdFieldName,
- mongo::jstOID,
- &lastElectionIdElem);
- if (!lastElectionIdExtractStatus.isOK()) {
- return lastElectionIdExtractStatus;
- }
-
- return ShardingMetadata(lastOpTimeElem.timestamp(), lastElectionIdElem.OID());
+StatusWith<ShardingMetadata> ShardingMetadata::readFromMetadata(const BSONObj& metadataObj) {
+ BSONElement smElem;
+ auto smExtractStatus =
+ bsonExtractTypedField(metadataObj, kGLEStatsFieldName, mongo::Object, &smElem);
+ if (!smExtractStatus.isOK()) {
+ return smExtractStatus;
}
- Status ShardingMetadata::writeToMetadata(BSONObjBuilder* metadataBob) const {
- BSONObjBuilder subobj(metadataBob->subobjStart(kGLEStatsFieldName));
- subobj.append(kGLEStatsLastOpTimeFieldName, getLastOpTime());
- subobj.append(kGLEStatsElectionIdFieldName, getLastElectionId());
- return Status::OK();
+ if (smElem.embeddedObject().nFields() != 2) {
+ return Status(ErrorCodes::InvalidOptions,
+ str::stream() << "The $gleStats object can only have 2 fields, but got "
+ << smElem.embeddedObject().toString());
}
- Status ShardingMetadata::downconvert(const BSONObj& commandReply,
- const BSONObj& replyMetadata,
- BSONObjBuilder* legacyCommandReplyBob) {
-
- legacyCommandReplyBob->appendElements(commandReply);
+ BSONElement lastOpTimeElem;
+ auto lastOpTimeExtractStatus = bsonExtractTypedField(smElem.embeddedObject(),
+ kGLEStatsLastOpTimeFieldName,
+ mongo::bsonTimestamp,
+ &lastOpTimeElem);
+ if (!lastOpTimeExtractStatus.isOK()) {
+ return lastOpTimeExtractStatus;
+ }
- auto swShardingMetadata = readFromMetadata(replyMetadata);
- if (swShardingMetadata.isOK()) {
- // We can reuse the same logic to write the sharding metadata out to the legacy
- // command as the element has the same format whether it is there or on the metadata
- // object.
- swShardingMetadata.getValue().writeToMetadata(legacyCommandReplyBob);
- }
- else if (swShardingMetadata.getStatus() == ErrorCodes::NoSuchKey) {
- // It is valid to not have a $gleStats field.
- }
- else {
- return swShardingMetadata.getStatus();
- }
- return Status::OK();
+ BSONElement lastElectionIdElem;
+ auto lastElectionIdExtractStatus = bsonExtractTypedField(
+ smElem.embeddedObject(), kGLEStatsElectionIdFieldName, mongo::jstOID, &lastElectionIdElem);
+ if (!lastElectionIdExtractStatus.isOK()) {
+ return lastElectionIdExtractStatus;
}
- Status ShardingMetadata::upconvert(const BSONObj& legacyCommand,
- BSONObjBuilder* commandBob,
- BSONObjBuilder* metadataBob) {
- // We can reuse the same logic to read the sharding metadata out from the legacy command
- // as it has the same format whether it is there or on the metadata object.
- auto swShardingMetadata = readFromMetadata(legacyCommand);
- if (swShardingMetadata.isOK()) {
- swShardingMetadata.getValue().writeToMetadata(metadataBob);
-
- // Write out the command excluding the $gleStats subobject.
- for (const auto& elem : legacyCommand) {
- if (elem.fieldNameStringData() != StringData(kGLEStatsFieldName)) {
- commandBob->append(elem);
- }
+ return ShardingMetadata(lastOpTimeElem.timestamp(), lastElectionIdElem.OID());
+}
+
+Status ShardingMetadata::writeToMetadata(BSONObjBuilder* metadataBob) const {
+ BSONObjBuilder subobj(metadataBob->subobjStart(kGLEStatsFieldName));
+ subobj.append(kGLEStatsLastOpTimeFieldName, getLastOpTime());
+ subobj.append(kGLEStatsElectionIdFieldName, getLastElectionId());
+ return Status::OK();
+}
+
+Status ShardingMetadata::downconvert(const BSONObj& commandReply,
+ const BSONObj& replyMetadata,
+ BSONObjBuilder* legacyCommandReplyBob) {
+ legacyCommandReplyBob->appendElements(commandReply);
+
+ auto swShardingMetadata = readFromMetadata(replyMetadata);
+ if (swShardingMetadata.isOK()) {
+ // We can reuse the same logic to write the sharding metadata out to the legacy
+ // command as the element has the same format whether it is there or on the metadata
+ // object.
+ swShardingMetadata.getValue().writeToMetadata(legacyCommandReplyBob);
+ } else if (swShardingMetadata.getStatus() == ErrorCodes::NoSuchKey) {
+ // It is valid to not have a $gleStats field.
+ } else {
+ return swShardingMetadata.getStatus();
+ }
+ return Status::OK();
+}
+
+Status ShardingMetadata::upconvert(const BSONObj& legacyCommand,
+ BSONObjBuilder* commandBob,
+ BSONObjBuilder* metadataBob) {
+ // We can reuse the same logic to read the sharding metadata out from the legacy command
+ // as it has the same format whether it is there or on the metadata object.
+ auto swShardingMetadata = readFromMetadata(legacyCommand);
+ if (swShardingMetadata.isOK()) {
+ swShardingMetadata.getValue().writeToMetadata(metadataBob);
+
+ // Write out the command excluding the $gleStats subobject.
+ for (const auto& elem : legacyCommand) {
+ if (elem.fieldNameStringData() != StringData(kGLEStatsFieldName)) {
+ commandBob->append(elem);
}
- } else if (swShardingMetadata.getStatus() == ErrorCodes::NoSuchKey) {
- // it is valid to not have a $gleStats field
- commandBob->appendElements(legacyCommand);
- }
- else {
- return swShardingMetadata.getStatus();
}
- return Status::OK();
+ } else if (swShardingMetadata.getStatus() == ErrorCodes::NoSuchKey) {
+ // it is valid to not have a $gleStats field
+ commandBob->appendElements(legacyCommand);
+ } else {
+ return swShardingMetadata.getStatus();
}
+ return Status::OK();
+}
- ShardingMetadata::ShardingMetadata(Timestamp lastOpTime, OID lastElectionId)
- : _lastOpTime(std::move(lastOpTime))
- , _lastElectionId(std::move(lastElectionId))
- {}
+ShardingMetadata::ShardingMetadata(Timestamp lastOpTime, OID lastElectionId)
+ : _lastOpTime(std::move(lastOpTime)), _lastElectionId(std::move(lastElectionId)) {}
- const Timestamp& ShardingMetadata::getLastOpTime() const {
- return _lastOpTime;
- }
+const Timestamp& ShardingMetadata::getLastOpTime() const {
+ return _lastOpTime;
+}
- const OID& ShardingMetadata::getLastElectionId() const {
- return _lastElectionId;
- }
+const OID& ShardingMetadata::getLastElectionId() const {
+ return _lastElectionId;
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/metadata/sharding_metadata.h b/src/mongo/rpc/metadata/sharding_metadata.h
index 00114624996..fba0fe8f992 100644
--- a/src/mongo/rpc/metadata/sharding_metadata.h
+++ b/src/mongo/rpc/metadata/sharding_metadata.h
@@ -29,62 +29,62 @@
#include "mongo/db/jsobj.h"
namespace mongo {
- class BSONObj;
- class BSONObjBuilder;
- class Status;
- template <typename T> class StatusWith;
+class BSONObj;
+class BSONObjBuilder;
+class Status;
+template <typename T>
+class StatusWith;
namespace rpc {
+/**
+ * This class compromises the reply metadata fields that concern sharding. MongoD attaches
+ * this information to a command reply, which MongoS uses to process getLastError.
+ */
+class ShardingMetadata {
+public:
/**
- * This class compromises the reply metadata fields that concern sharding. MongoD attaches
- * this information to a command reply, which MongoS uses to process getLastError.
+ * Reads ShardingMetadata from a metadata object.
*/
- class ShardingMetadata {
- public:
+ static StatusWith<ShardingMetadata> readFromMetadata(const BSONObj& metadataObj);
- /**
- * Reads ShardingMetadata from a metadata object.
- */
- static StatusWith<ShardingMetadata> readFromMetadata(const BSONObj& metadataObj);
-
- /**
- * Writes ShardingMetadata to a metadata builder.
- */
- Status writeToMetadata(BSONObjBuilder* metadataBob) const;
+ /**
+ * Writes ShardingMetadata to a metadata builder.
+ */
+ Status writeToMetadata(BSONObjBuilder* metadataBob) const;
- /**
- * Rewrites the ShardingMetadata from the legacy OP_QUERY format to the metadata object
- * format.
- */
- static Status downconvert(const BSONObj& commandReply,
- const BSONObj& replyMetadata,
- BSONObjBuilder* legacyCommandReply);
+ /**
+ * Rewrites the ShardingMetadata from the legacy OP_QUERY format to the metadata object
+ * format.
+ */
+ static Status downconvert(const BSONObj& commandReply,
+ const BSONObj& replyMetadata,
+ BSONObjBuilder* legacyCommandReply);
- /**
- * Rewrites the ShardingMetadata from the legacy OP_QUERY format to the metadata object
- * format.
- */
- static Status upconvert(const BSONObj& legacyCommandReply,
- BSONObjBuilder* commandReplyBob,
- BSONObjBuilder* metadataBob);
+ /**
+ * Rewrites the ShardingMetadata from the legacy OP_QUERY format to the metadata object
+ * format.
+ */
+ static Status upconvert(const BSONObj& legacyCommandReply,
+ BSONObjBuilder* commandReplyBob,
+ BSONObjBuilder* metadataBob);
- /**
- * Gets the OpTime of the oplog entry of the last succssful write operation executed by the
- * server that produced the metadata.
- */
- const Timestamp& getLastOpTime() const;
+ /**
+ * Gets the OpTime of the oplog entry of the last succssful write operation executed by the
+ * server that produced the metadata.
+ */
+ const Timestamp& getLastOpTime() const;
- /**
- * Gets the most recent election id observed by the server that produced the metadata.
- */
- const OID& getLastElectionId() const;
+ /**
+ * Gets the most recent election id observed by the server that produced the metadata.
+ */
+ const OID& getLastElectionId() const;
- ShardingMetadata(Timestamp lastOpTime, OID lastElectionId);
+ ShardingMetadata(Timestamp lastOpTime, OID lastElectionId);
- private:
- Timestamp _lastOpTime;
- OID _lastElectionId;
- };
+private:
+ Timestamp _lastOpTime;
+ OID _lastElectionId;
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/metadata/sharding_metadata_test.cpp b/src/mongo/rpc/metadata/sharding_metadata_test.cpp
index 19df5a59bcc..739e41d7860 100644
--- a/src/mongo/rpc/metadata/sharding_metadata_test.cpp
+++ b/src/mongo/rpc/metadata/sharding_metadata_test.cpp
@@ -36,191 +36,156 @@
namespace {
- using namespace mongo;
- using namespace mongo::rpc;
- using mongo::unittest::assertGet;
-
- ShardingMetadata checkParse(const BSONObj& metadata) {
- return assertGet(ShardingMetadata::readFromMetadata(metadata));
+using namespace mongo;
+using namespace mongo::rpc;
+using mongo::unittest::assertGet;
+
+ShardingMetadata checkParse(const BSONObj& metadata) {
+ return assertGet(ShardingMetadata::readFromMetadata(metadata));
+}
+
+const auto kElectionId = OID{"541b1a00e8a23afa832b218e"};
+const auto kLastOpTime = Timestamp(stdx::chrono::seconds{1337}, 800u);
+
+TEST(ShardingMetadata, ReadFromMetadata) {
+ {
+ auto sm = checkParse(
+ BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime << "electionId" << kElectionId)));
+ ASSERT_EQ(sm.getLastElectionId(), kElectionId);
+ ASSERT_EQ(sm.getLastOpTime(), kLastOpTime);
}
+ {
+ // We don't care about order.
+ auto sm = checkParse(
+ BSON("$gleStats" << BSON("electionId" << kElectionId << "lastOpTime" << kLastOpTime)));
- const auto kElectionId = OID{"541b1a00e8a23afa832b218e"};
- const auto kLastOpTime = Timestamp(stdx::chrono::seconds{1337}, 800u);
-
- TEST(ShardingMetadata, ReadFromMetadata) {
- {
- auto sm = checkParse(BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << kElectionId)));
- ASSERT_EQ(sm.getLastElectionId(), kElectionId);
- ASSERT_EQ(sm.getLastOpTime(), kLastOpTime);
- }
- {
- // We don't care about order.
- auto sm = checkParse(BSON("$gleStats" << BSON("electionId" << kElectionId <<
- "lastOpTime" << kLastOpTime)));
-
- ASSERT_EQ(sm.getLastElectionId(), kElectionId);
- ASSERT_EQ(sm.getLastOpTime(), kLastOpTime);
- }
+ ASSERT_EQ(sm.getLastElectionId(), kElectionId);
+ ASSERT_EQ(sm.getLastOpTime(), kLastOpTime);
}
-
- void checkParseFails(const BSONObj& metadata, ErrorCodes::Error error) {
- auto sm = ShardingMetadata::readFromMetadata(metadata);
- ASSERT_NOT_OK(sm.getStatus());
- ASSERT_EQ(sm.getStatus(), error);
+}
+
+void checkParseFails(const BSONObj& metadata, ErrorCodes::Error error) {
+ auto sm = ShardingMetadata::readFromMetadata(metadata);
+ ASSERT_NOT_OK(sm.getStatus());
+ ASSERT_EQ(sm.getStatus(), error);
+}
+
+TEST(ShardingMetadata, ReadFromInvalidMetadata) {
+ { checkParseFails(BSONObj(), ErrorCodes::NoSuchKey); }
+ { checkParseFails(BSON("$gleStats" << 1), ErrorCodes::TypeMismatch); }
+ { checkParseFails(BSON("$gleStats" << BSONObj()), ErrorCodes::InvalidOptions); }
+ {
+ checkParseFails(BSON("$gleStats" << BSON("lastOpTime" << 3 << "electionId" << kElectionId)),
+ ErrorCodes::TypeMismatch);
+ }
+ {
+ checkParseFails(BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime << "electionId" << 3)),
+ ErrorCodes::TypeMismatch);
+ }
+ {
+ checkParseFails(
+ BSON("$gleStats" << BSON("lastOpTime" << kElectionId << "electionId" << kLastOpTime)),
+ ErrorCodes::TypeMismatch);
}
+ {
+ checkParseFails(BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime << "electionId"
+ << kElectionId << "extra"
+ << "this should not be here")),
+ ErrorCodes::InvalidOptions);
+ }
+}
+
+void checkUpconvert(const BSONObj& legacyCommandReply,
+ const BSONObj& upconvertedCommandReply,
+ const BSONObj& upconvertedReplyMetadata) {
+ {
+ BSONObjBuilder commandReplyBob;
+ BSONObjBuilder metadataBob;
+ ASSERT_OK(ShardingMetadata::upconvert(legacyCommandReply, &commandReplyBob, &metadataBob));
+ ASSERT_EQ(commandReplyBob.done(), upconvertedCommandReply);
+ ASSERT_EQ(metadataBob.done(), upconvertedReplyMetadata);
+ }
+}
- TEST(ShardingMetadata, ReadFromInvalidMetadata) {
- {
- checkParseFails(BSONObj(),
- ErrorCodes::NoSuchKey);
- }
- {
- checkParseFails(BSON("$gleStats" << 1),
- ErrorCodes::TypeMismatch);
+TEST(ShardingMetadata, UpconvertValidMetadata) {
+ {
+ checkUpconvert(BSON("ok" << 1),
- }
- {
- checkParseFails(BSON("$gleStats" << BSONObj()),
- ErrorCodes::InvalidOptions);
- }
- {
- checkParseFails(BSON("$gleStats" << BSON("lastOpTime" << 3 <<
- "electionId" << kElectionId)),
- ErrorCodes::TypeMismatch);
- }
- {
- checkParseFails(BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << 3)),
- ErrorCodes::TypeMismatch);
- }
- {
- checkParseFails(BSON("$gleStats" << BSON("lastOpTime" << kElectionId <<
- "electionId" << kLastOpTime)),
- ErrorCodes::TypeMismatch);
- }
- {
- checkParseFails(BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << kElectionId <<
- "extra" << "this should not be here")),
- ErrorCodes::InvalidOptions);
- }
- }
+ BSON("ok" << 1),
- void checkUpconvert(const BSONObj& legacyCommandReply,
- const BSONObj& upconvertedCommandReply,
- const BSONObj& upconvertedReplyMetadata) {
- {
- BSONObjBuilder commandReplyBob;
- BSONObjBuilder metadataBob;
- ASSERT_OK(ShardingMetadata::upconvert(legacyCommandReply,
- &commandReplyBob,
- &metadataBob));
- ASSERT_EQ(commandReplyBob.done(), upconvertedCommandReply);
- ASSERT_EQ(metadataBob.done(), upconvertedReplyMetadata);
- }
+ BSONObj());
}
+ {
+ checkUpconvert(
+ BSON("ok" << 1 << "$gleStats"
+ << BSON("lastOpTime" << kLastOpTime << "electionId" << kElectionId)),
- TEST(ShardingMetadata, UpconvertValidMetadata) {
- {
- checkUpconvert(BSON("ok" << 1),
-
- BSON("ok" << 1),
-
- BSONObj());
- }
- {
- checkUpconvert(BSON("ok" << 1 <<
- "$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << kElectionId)),
-
- BSON("ok" << 1),
-
- BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << kElectionId)));
- }
- {
- checkUpconvert(BSON("ok" << 1 <<
- "somestuff" << "some other stuff" <<
- "$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << kElectionId) <<
- "morestuff" << "more other stuff"),
-
- BSON("ok" << 1 <<
- "somestuff" << "some other stuff" <<
- "morestuff" << "more other stuff"),
-
- BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << kElectionId)));
- }
- }
+ BSON("ok" << 1),
- void checkUpconvertFails(const BSONObj& legacyCommandReply,
- ErrorCodes::Error why) {
- BSONObjBuilder ignoredCommand;
- BSONObjBuilder ignoredMetadata;
- auto status = ShardingMetadata::upconvert(legacyCommandReply,
- &ignoredCommand,
- &ignoredMetadata);
- ASSERT_NOT_OK(status);
- ASSERT_EQ(status, why);
+ BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime << "electionId" << kElectionId)));
}
-
- TEST(ShardingMetadata, UpconvertInvalidMetadata) {
- {
- checkUpconvertFails(BSON("ok" << 1 <<
- "$gleStats" << 1),
- ErrorCodes::TypeMismatch);
- }
- {
- checkUpconvertFails(BSON("ok" << 1 <<
- "$gleStats" << BSON("lastOpTime" << 1)),
- ErrorCodes::InvalidOptions);
- }
- {
- checkUpconvertFails(BSON("ok" << 1 <<
- "$gleStats" << BSON("lastOpTime" << 2 <<
- "foo" << 1)),
- ErrorCodes::TypeMismatch);
- }
- {
- checkUpconvertFails(BSON("ok" << 1 <<
- "$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << kElectionId <<
- "krandom" << "shouldnotbehere")),
- ErrorCodes::InvalidOptions);
- }
+ {
+ checkUpconvert(
+ BSON("ok" << 1 << "somestuff"
+ << "some other stuff"
+ << "$gleStats" << BSON("lastOpTime" << kLastOpTime << "electionId"
+ << kElectionId) << "morestuff"
+ << "more other stuff"),
+
+ BSON("ok" << 1 << "somestuff"
+ << "some other stuff"
+ << "morestuff"
+ << "more other stuff"),
+
+ BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime << "electionId" << kElectionId)));
}
-
- void checkDownconvert(const BSONObj& commandReply,
- const BSONObj& metadata,
- const BSONObj& downconvertedCommand) {
- BSONObjBuilder downconvertedCommandBob;
- ASSERT_OK(ShardingMetadata::downconvert(commandReply,
- metadata,
- &downconvertedCommandBob));
- ASSERT_EQ(downconvertedCommandBob.done(), downconvertedCommand);
+}
+
+void checkUpconvertFails(const BSONObj& legacyCommandReply, ErrorCodes::Error why) {
+ BSONObjBuilder ignoredCommand;
+ BSONObjBuilder ignoredMetadata;
+ auto status =
+ ShardingMetadata::upconvert(legacyCommandReply, &ignoredCommand, &ignoredMetadata);
+ ASSERT_NOT_OK(status);
+ ASSERT_EQ(status, why);
+}
+
+TEST(ShardingMetadata, UpconvertInvalidMetadata) {
+ { checkUpconvertFails(BSON("ok" << 1 << "$gleStats" << 1), ErrorCodes::TypeMismatch); }
+ {
+ checkUpconvertFails(BSON("ok" << 1 << "$gleStats" << BSON("lastOpTime" << 1)),
+ ErrorCodes::InvalidOptions);
}
-
- TEST(ShardingMetadata, Downconvert) {
- {
- checkDownconvert(BSON("ok" << 1),
- BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << kElectionId)),
- BSON("ok" << 1 <<
- "$gleStats" << BSON("lastOpTime" << kLastOpTime <<
- "electionId" << kElectionId)));
- }
- {
- checkDownconvert(BSON("ok" << 1),
- BSONObj(),
- BSON("ok" << 1));
- }
+ {
+ checkUpconvertFails(BSON("ok" << 1 << "$gleStats" << BSON("lastOpTime" << 2 << "foo" << 1)),
+ ErrorCodes::TypeMismatch);
+ }
+ {
+ checkUpconvertFails(
+ BSON("ok" << 1 << "$gleStats" << BSON("lastOpTime" << kLastOpTime << "electionId"
+ << kElectionId << "krandom"
+ << "shouldnotbehere")),
+ ErrorCodes::InvalidOptions);
}
+}
+
+void checkDownconvert(const BSONObj& commandReply,
+ const BSONObj& metadata,
+ const BSONObj& downconvertedCommand) {
+ BSONObjBuilder downconvertedCommandBob;
+ ASSERT_OK(ShardingMetadata::downconvert(commandReply, metadata, &downconvertedCommandBob));
+ ASSERT_EQ(downconvertedCommandBob.done(), downconvertedCommand);
+}
+
+TEST(ShardingMetadata, Downconvert) {
+ {
+ checkDownconvert(
+ BSON("ok" << 1),
+ BSON("$gleStats" << BSON("lastOpTime" << kLastOpTime << "electionId" << kElectionId)),
+ BSON("ok" << 1 << "$gleStats"
+ << BSON("lastOpTime" << kLastOpTime << "electionId" << kElectionId)));
+ }
+ { checkDownconvert(BSON("ok" << 1), BSONObj(), BSON("ok" << 1)); }
+}
} // namespace
-
-
-
-
-
diff --git a/src/mongo/rpc/object_check.cpp b/src/mongo/rpc/object_check.cpp
index 988a98ed31b..3338f074cbb 100644
--- a/src/mongo/rpc/object_check.cpp
+++ b/src/mongo/rpc/object_check.cpp
@@ -38,12 +38,12 @@
namespace mongo {
- Status Validator<BSONObj>::validateLoad(const char* ptr, size_t length) {
- return serverGlobalParams.objcheck ? validateBSON(ptr, length) : Status::OK();
- }
+Status Validator<BSONObj>::validateLoad(const char* ptr, size_t length) {
+ return serverGlobalParams.objcheck ? validateBSON(ptr, length) : Status::OK();
+}
- Status Validator<BSONObj>::validateStore(const BSONObj& toStore) {
- return Status::OK();
- }
+Status Validator<BSONObj>::validateStore(const BSONObj& toStore) {
+ return Status::OK();
+}
} // namespace mongo
diff --git a/src/mongo/rpc/object_check.h b/src/mongo/rpc/object_check.h
index 9db3e6f0015..3b3d77012a4 100644
--- a/src/mongo/rpc/object_check.h
+++ b/src/mongo/rpc/object_check.h
@@ -32,16 +32,17 @@
// We do not use the rpc namespace here so we can specialize Validator.
namespace mongo {
- class BSONObj;
- class Status;
+class BSONObj;
+class Status;
- /**
- * A validator for BSON objects. The implementation will validate the input object
- * if validation is enabled, or return Status::OK() otherwise.
- */
- template<> struct Validator<BSONObj> {
- static Status validateLoad(const char* ptr, size_t length);
- static Status validateStore(const BSONObj& toStore);
- };
+/**
+ * A validator for BSON objects. The implementation will validate the input object
+ * if validation is enabled, or return Status::OK() otherwise.
+ */
+template <>
+struct Validator<BSONObj> {
+ static Status validateLoad(const char* ptr, size_t length);
+ static Status validateStore(const BSONObj& toStore);
+};
} // namespace mongo
diff --git a/src/mongo/rpc/object_check_test.cpp b/src/mongo/rpc/object_check_test.cpp
index f0deff53f1c..03adedd0983 100644
--- a/src/mongo/rpc/object_check_test.cpp
+++ b/src/mongo/rpc/object_check_test.cpp
@@ -39,49 +39,51 @@
namespace {
- using namespace mongo;
+using namespace mongo;
- TEST(DataTypeValidated, BSONValidationEnabled) {
+TEST(DataTypeValidated, BSONValidationEnabled) {
+ using std::swap;
- using std::swap;
+ bool wasEnabled = serverGlobalParams.objcheck;
+ const auto setValidation = [&](bool enabled) { serverGlobalParams.objcheck = enabled; };
+ ON_BLOCK_EXIT(setValidation, wasEnabled);
- bool wasEnabled = serverGlobalParams.objcheck;
- const auto setValidation = [&](bool enabled){ serverGlobalParams.objcheck = enabled; };
- ON_BLOCK_EXIT(setValidation, wasEnabled);
+ using std::begin;
+ using std::end;
- using std::begin;
- using std::end;
-
- BSONObj valid = BSON("baz" << "bar" << "garply" << BSON("foo" << "bar"));
- char buf[1024] = { 0 };
- std::copy(valid.objdata(), valid.objdata() + valid.objsize(), begin(buf));
- {
- Validated<BSONObj> v;
- ConstDataRangeCursor cdrc(begin(buf), end(buf));
- ASSERT_OK(cdrc.readAndAdvance(&v));
- }
-
- {
- // mess up the data
- DataRangeCursor drc(begin(buf), end(buf));
- // skip past size so we don't trip any sanity checks.
- drc.advance(4); // skip size
- while (drc.writeAndAdvance(0xFF).isOK()) ;
- }
+ BSONObj valid = BSON("baz"
+ << "bar"
+ << "garply" << BSON("foo"
+ << "bar"));
+ char buf[1024] = {0};
+ std::copy(valid.objdata(), valid.objdata() + valid.objsize(), begin(buf));
+ {
+ Validated<BSONObj> v;
+ ConstDataRangeCursor cdrc(begin(buf), end(buf));
+ ASSERT_OK(cdrc.readAndAdvance(&v));
+ }
- {
- Validated<BSONObj> v;
- ConstDataRangeCursor cdrc(begin(buf), end(buf));
- ASSERT_NOT_OK(cdrc.readAndAdvance(&v));
- }
+ {
+ // mess up the data
+ DataRangeCursor drc(begin(buf), end(buf));
+ // skip past size so we don't trip any sanity checks.
+ drc.advance(4); // skip size
+ while (drc.writeAndAdvance(0xFF).isOK())
+ ;
+ }
- {
- // disable validation
- setValidation(false);
- Validated<BSONObj> v;
- ConstDataRangeCursor cdrc(begin(buf), end(buf));
- ASSERT_OK(cdrc.readAndAdvance(&v));
- }
+ {
+ Validated<BSONObj> v;
+ ConstDataRangeCursor cdrc(begin(buf), end(buf));
+ ASSERT_NOT_OK(cdrc.readAndAdvance(&v));
}
+ {
+ // disable validation
+ setValidation(false);
+ Validated<BSONObj> v;
+ ConstDataRangeCursor cdrc(begin(buf), end(buf));
+ ASSERT_OK(cdrc.readAndAdvance(&v));
+ }
+}
}
diff --git a/src/mongo/rpc/protocol.cpp b/src/mongo/rpc/protocol.cpp
index dae77abce3b..f50860b85fd 100644
--- a/src/mongo/rpc/protocol.cpp
+++ b/src/mongo/rpc/protocol.cpp
@@ -41,41 +41,36 @@ namespace rpc {
namespace {
- /**
- * Protocols supported by order of preference.
- */
- const Protocol kPreferredProtos[] = {
- Protocol::kOpCommandV1,
- Protocol::kOpQuery
- };
-
- const char kNone[] = "none";
- const char kOpQueryOnly[] = "opQueryOnly";
- const char kOpCommandOnly[] = "opCommandOnly";
- const char kAll[] = "all";
+/**
+ * Protocols supported by order of preference.
+ */
+const Protocol kPreferredProtos[] = {Protocol::kOpCommandV1, Protocol::kOpQuery};
+
+const char kNone[] = "none";
+const char kOpQueryOnly[] = "opQueryOnly";
+const char kOpCommandOnly[] = "opCommandOnly";
+const char kAll[] = "all";
} // namespace
- StatusWith<Protocol> negotiate(ProtocolSet fst, ProtocolSet snd) {
- using std::begin;
- using std::end;
+StatusWith<Protocol> negotiate(ProtocolSet fst, ProtocolSet snd) {
+ using std::begin;
+ using std::end;
- ProtocolSet common = fst & snd;
+ ProtocolSet common = fst & snd;
- auto it =
- std::find_if(begin(kPreferredProtos), end(kPreferredProtos), [common](Protocol p) {
- return common & static_cast<ProtocolSet>(p);
- });
+ auto it = std::find_if(begin(kPreferredProtos),
+ end(kPreferredProtos),
+ [common](Protocol p) { return common & static_cast<ProtocolSet>(p); });
- if (it == end(kPreferredProtos)) {
- return Status(ErrorCodes::RPCProtocolNegotiationFailed,
- "No common protocol found.");
- }
- return *it;
+ if (it == end(kPreferredProtos)) {
+ return Status(ErrorCodes::RPCProtocolNegotiationFailed, "No common protocol found.");
}
+ return *it;
+}
- StatusWith<StringData> toString(ProtocolSet protocols) {
- switch (protocols) {
+StatusWith<StringData> toString(ProtocolSet protocols) {
+ switch (protocols) {
case supports::kNone:
return StringData(kNone);
case supports::kOpQueryOnly:
@@ -90,28 +85,25 @@ namespace {
<< " to a string, only the predefined ProtocolSet "
<< "constants 'none' (0x0), 'opQueryOnly' (0x1), "
<< "'opCommandOnly' (0x2), and 'all' (0x3) are supported.");
- }
}
-
- StatusWith<ProtocolSet> parseProtocolSet(StringData repr) {
- if (repr == kNone) {
- return supports::kNone;
- }
- else if (repr == kOpQueryOnly) {
- return supports::kOpQueryOnly;
- }
- else if (repr == kOpCommandOnly) {
- return supports::kOpCommandOnly;
- }
- else if (repr == kAll) {
- return supports::kAll;
- }
- return Status(ErrorCodes::BadValue,
- str::stream() << "Can not parse a ProtocolSet from " << repr
- << " only the predefined ProtocolSet constants "
- << "'none' (0x0), 'opQueryOnly' (0x1), 'opCommandOnly' (0x2), "
- << "and 'all' (0x3) are supported.");
+}
+
+StatusWith<ProtocolSet> parseProtocolSet(StringData repr) {
+ if (repr == kNone) {
+ return supports::kNone;
+ } else if (repr == kOpQueryOnly) {
+ return supports::kOpQueryOnly;
+ } else if (repr == kOpCommandOnly) {
+ return supports::kOpCommandOnly;
+ } else if (repr == kAll) {
+ return supports::kAll;
}
+ return Status(ErrorCodes::BadValue,
+ str::stream() << "Can not parse a ProtocolSet from " << repr
+ << " only the predefined ProtocolSet constants "
+ << "'none' (0x0), 'opQueryOnly' (0x1), 'opCommandOnly' (0x2), "
+ << "and 'all' (0x3) are supported.");
+}
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/protocol.h b/src/mongo/rpc/protocol.h
index bb77caf5e85..99e6cacc92c 100644
--- a/src/mongo/rpc/protocol.h
+++ b/src/mongo/rpc/protocol.h
@@ -37,63 +37,63 @@
namespace mongo {
namespace rpc {
+/**
+ * Bit flags representing support for a particular RPC protocol.
+ * This is just an internal representation, and is never transmitted over the wire. It should
+ * never be used for any other feature detection in favor of max/min wire version.
+ *
+ * A new protocol must be added as the highest order bit flag so that it is prioritized in
+ * negotiation.
+ */
+enum class Protocol : std::uint64_t {
+
/**
- * Bit flags representing support for a particular RPC protocol.
- * This is just an internal representation, and is never transmitted over the wire. It should
- * never be used for any other feature detection in favor of max/min wire version.
- *
- * A new protocol must be added as the highest order bit flag so that it is prioritized in
- * negotiation.
+ * The pre-3.2 OP_QUERY on db.$cmd protocol
*/
- enum class Protocol : std::uint64_t {
-
- /**
- * The pre-3.2 OP_QUERY on db.$cmd protocol
- */
- kOpQuery = 1 << 0,
-
- /**
- * The post-3.2 OP_COMMAND protocol.
- */
- kOpCommandV1 = 1 << 1,
- };
+ kOpQuery = 1 << 0,
/**
- * Bitfield representing a set of supported RPC protocols.
+ * The post-3.2 OP_COMMAND protocol.
*/
- using ProtocolSet = std::underlying_type<Protocol>::type;
+ kOpCommandV1 = 1 << 1,
+};
+
+/**
+ * Bitfield representing a set of supported RPC protocols.
+ */
+using ProtocolSet = std::underlying_type<Protocol>::type;
/**
* This namespace contains predefined bitfields for common levels of protocol support.
*/
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 kAll = kOpQueryOnly | kOpCommandOnly;
+const ProtocolSet kNone = ProtocolSet{0};
+const ProtocolSet kOpQueryOnly = static_cast<ProtocolSet>(Protocol::kOpQuery);
+const ProtocolSet kOpCommandOnly = static_cast<ProtocolSet>(Protocol::kOpCommandV1);
+const ProtocolSet kAll = kOpQueryOnly | kOpCommandOnly;
} // namespace supports
- /**
- * Returns the newest protocol supported by two parties.
- */
- StatusWith<Protocol> negotiate(ProtocolSet fst, ProtocolSet snd);
+/**
+ * Returns the newest protocol supported by two parties.
+ */
+StatusWith<Protocol> negotiate(ProtocolSet fst, ProtocolSet snd);
- /**
- * Converts a ProtocolSet to a string. Currently only the predefined ProtocolSets in the
- * 'supports' namespace are supported.
- *
- * This intentionally does not conform to the STL 'to_string' convention so that it will
- * not conflict with the to_string overload for uint64_t.
- */
- StatusWith<StringData> toString(ProtocolSet protocols);
+/**
+ * Converts a ProtocolSet to a string. Currently only the predefined ProtocolSets in the
+ * 'supports' namespace are supported.
+ *
+ * This intentionally does not conform to the STL 'to_string' convention so that it will
+ * not conflict with the to_string overload for uint64_t.
+ */
+StatusWith<StringData> toString(ProtocolSet protocols);
- /**
- * Parses a ProtocolSet from a string. Currently only the predefined ProtocolSets in the
- * 'supports' namespace are supported
- */
- StatusWith<ProtocolSet> parseProtocolSet(StringData repr);
+/**
+ * Parses a ProtocolSet from a string. Currently only the predefined ProtocolSets in the
+ * 'supports' namespace are supported
+ */
+StatusWith<ProtocolSet> parseProtocolSet(StringData repr);
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/protocol_test.cpp b/src/mongo/rpc/protocol_test.cpp
index 86211717eb7..71ff1559fda 100644
--- a/src/mongo/rpc/protocol_test.cpp
+++ b/src/mongo/rpc/protocol_test.cpp
@@ -34,33 +34,33 @@
namespace {
- using namespace mongo::rpc;
+using namespace mongo::rpc;
- // Checks if negotiation of the first to protocol sets results in the 'proto'
- const auto assert_negotiated = [](ProtocolSet fst, ProtocolSet snd, Protocol proto) {
- auto negotiated = negotiate(fst, snd);
- ASSERT_TRUE(negotiated.isOK());
- ASSERT_TRUE(negotiated.getValue() == proto);
- };
+// Checks if negotiation of the first to protocol sets results in the 'proto'
+const auto assert_negotiated = [](ProtocolSet fst, ProtocolSet snd, Protocol proto) {
+ auto negotiated = negotiate(fst, snd);
+ ASSERT_TRUE(negotiated.isOK());
+ ASSERT_TRUE(negotiated.getValue() == proto);
+};
- TEST(Protocol, SuccessfulNegotiation) {
- assert_negotiated(supports::kAll, supports::kAll, Protocol::kOpCommandV1);
- assert_negotiated(supports::kAll, supports::kOpCommandOnly, Protocol::kOpCommandV1);
- assert_negotiated(supports::kAll, supports::kOpQueryOnly, Protocol::kOpQuery);
- }
+TEST(Protocol, SuccessfulNegotiation) {
+ assert_negotiated(supports::kAll, supports::kAll, Protocol::kOpCommandV1);
+ assert_negotiated(supports::kAll, supports::kOpCommandOnly, Protocol::kOpCommandV1);
+ assert_negotiated(supports::kAll, supports::kOpQueryOnly, Protocol::kOpQuery);
+}
- // Checks that negotiation fails
- const auto assert_not_negotiated = [](ProtocolSet fst, ProtocolSet snd) {
- auto proto = negotiate(fst, snd);
- ASSERT_TRUE(!proto.isOK());
- ASSERT_TRUE(proto.getStatus().code() == mongo::ErrorCodes::RPCProtocolNegotiationFailed);
- };
+// Checks that negotiation fails
+const auto assert_not_negotiated = [](ProtocolSet fst, ProtocolSet snd) {
+ auto proto = negotiate(fst, snd);
+ ASSERT_TRUE(!proto.isOK());
+ ASSERT_TRUE(proto.getStatus().code() == mongo::ErrorCodes::RPCProtocolNegotiationFailed);
+};
- TEST(Protocol, FailedNegotiation) {
- assert_not_negotiated(supports::kOpQueryOnly, supports::kOpCommandOnly);
- assert_not_negotiated(supports::kAll, supports::kNone);
- assert_not_negotiated(supports::kOpQueryOnly, supports::kNone);
- assert_not_negotiated(supports::kOpCommandOnly, supports::kNone);
- }
+TEST(Protocol, FailedNegotiation) {
+ assert_not_negotiated(supports::kOpQueryOnly, supports::kOpCommandOnly);
+ assert_not_negotiated(supports::kAll, supports::kNone);
+ assert_not_negotiated(supports::kOpQueryOnly, supports::kNone);
+ assert_not_negotiated(supports::kOpCommandOnly, supports::kNone);
+}
} // namespace
diff --git a/src/mongo/rpc/reply_builder_interface.cpp b/src/mongo/rpc/reply_builder_interface.cpp
index 100d63e2261..0bf5170d6ee 100644
--- a/src/mongo/rpc/reply_builder_interface.cpp
+++ b/src/mongo/rpc/reply_builder_interface.cpp
@@ -40,48 +40,47 @@
namespace mongo {
namespace rpc {
- namespace {
- const char kOKField[] = "ok";
- const char kCodeField[] = "code";
- const char kErrorField[] = "errmsg";
-
- // similar to appendCommandStatus (duplicating logic here to avoid cyclic library
- // dependency)
- BSONObj augmentReplyWithStatus(const Status& status, const BSONObj& reply) {
- BSONObjBuilder bob;
- bob.appendElements(reply);
-
- if (!reply.hasField(kOKField)) {
- bob.append(kOKField, status.isOK() ? 1.0 : 0.0);
- }
-
- if (status.isOK()) {
- return bob.obj();
- }
-
- if (!reply.hasField(kErrorField)) {
- bob.append(kErrorField, status.reason());
- }
-
- if (!reply.hasField(kCodeField)) {
- bob.append(kCodeField, status.code());
- }
-
- return bob.obj();
- }
+namespace {
+const char kOKField[] = "ok";
+const char kCodeField[] = "code";
+const char kErrorField[] = "errmsg";
+
+// similar to appendCommandStatus (duplicating logic here to avoid cyclic library
+// dependency)
+BSONObj augmentReplyWithStatus(const Status& status, const BSONObj& reply) {
+ BSONObjBuilder bob;
+ bob.appendElements(reply);
+
+ if (!reply.hasField(kOKField)) {
+ bob.append(kOKField, status.isOK() ? 1.0 : 0.0);
}
- ReplyBuilderInterface&
- ReplyBuilderInterface::setCommandReply(StatusWith<BSONObj> commandReply) {
- auto reply = commandReply.isOK() ? std::move(commandReply.getValue()) : BSONObj();
- return setRawCommandReply(augmentReplyWithStatus(commandReply.getStatus(), reply));
+ if (status.isOK()) {
+ return bob.obj();
}
- ReplyBuilderInterface&
- ReplyBuilderInterface::setCommandReply(Status nonOKStatus, BSONObj extraErrorInfo) {
- invariant(!nonOKStatus.isOK());
- return setRawCommandReply(augmentReplyWithStatus(nonOKStatus, extraErrorInfo));
+ if (!reply.hasField(kErrorField)) {
+ bob.append(kErrorField, status.reason());
}
+ if (!reply.hasField(kCodeField)) {
+ bob.append(kCodeField, status.code());
+ }
+
+ return bob.obj();
+}
+}
+
+ReplyBuilderInterface& ReplyBuilderInterface::setCommandReply(StatusWith<BSONObj> commandReply) {
+ auto reply = commandReply.isOK() ? std::move(commandReply.getValue()) : BSONObj();
+ return setRawCommandReply(augmentReplyWithStatus(commandReply.getStatus(), reply));
+}
+
+ReplyBuilderInterface& ReplyBuilderInterface::setCommandReply(Status nonOKStatus,
+ BSONObj extraErrorInfo) {
+ invariant(!nonOKStatus.isOK());
+ return setRawCommandReply(augmentReplyWithStatus(nonOKStatus, extraErrorInfo));
+}
+
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/reply_builder_interface.h b/src/mongo/rpc/reply_builder_interface.h
index 7a36ab8b622..e97e3e7fe9b 100644
--- a/src/mongo/rpc/reply_builder_interface.h
+++ b/src/mongo/rpc/reply_builder_interface.h
@@ -35,110 +35,105 @@
#include "mongo/rpc/protocol.h"
namespace mongo {
- class BSONObj;
- class Message;
+class BSONObj;
+class Message;
namespace rpc {
- class DocumentRange;
+class DocumentRange;
+
+/**
+ * Constructs an RPC Reply.
+ */
+class ReplyBuilderInterface {
+ MONGO_DISALLOW_COPYING(ReplyBuilderInterface);
+
+public:
+ /**
+ * Reply builders must have their fields set in order as they are immediately written into
+ * the underlying message buffer. This enum represents the next field that can be written
+ * into the builder. Note that when the builder is in state 'kInputDocs', multiple input
+ * docs can be added. After the builder's done() method is called it is in state 'kDone',
+ * and no further methods can be called.
+ */
+ enum class State { kMetadata, kCommandReply, kOutputDocs, kDone };
+
+ virtual ~ReplyBuilderInterface() = default;
+
+ virtual ReplyBuilderInterface& setMetadata(BSONObj metadata) = 0;
+
+ /**
+ * Sets the raw command reply. This should probably not be used in favor of the
+ * variants that accept a Status or StatusWith.
+ */
+ virtual ReplyBuilderInterface& setRawCommandReply(BSONObj reply) = 0;
+
+ /**
+ * Sets the reply for this command. If an engaged StatusWith<BSONObj> is passed, the command
+ * reply will be set to the contained BSONObj, augmented with the element {ok, 1.0} if it
+ * does not already have an "ok" field. If a disengaged StatusWith<BSONObj> is passed, the
+ * command reply will be set to {ok: 0.0, code: <code of status>,
+ * errmsg: <reason of status>}
+ */
+ ReplyBuilderInterface& setCommandReply(StatusWith<BSONObj> commandReply);
+
+ /**
+ * Sets the reply for this command. The status parameter must be non-OK. The reply for
+ * this command will be set to an object containing all the fields in extraErrorInfo,
+ * augmented with {ok: 0.0} , {code: <code of status>}, and {errmsg: <reason of status>}.
+ * If any of the fields "ok", "code", or "errmsg" already exist in extraErrorInfo, they
+ * will be left as-is in the command reply. This use of this form is intended for
+ * interfacing with legacy code that adds additional data to a failed command reply and
+ * its use is discouraged in new code.
+ */
+ ReplyBuilderInterface& setCommandReply(Status nonOKStatus, BSONObj extraErrorInfo);
+
+ /**
+ * Add a range of output documents to the reply. This method can be called multiple times
+ * before calling done().
+ */
+ virtual ReplyBuilderInterface& addOutputDocs(DocumentRange outputDocs) = 0;
+
+ /**
+ * Add a single output document to the reply. This method can be called multiple times
+ * before calling done().
+ */
+ virtual ReplyBuilderInterface& addOutputDoc(BSONObj outputDoc) = 0;
+
+ /**
+ * Gets the state of the builder. As the builder will simply crash the process if it is ever
+ * put in an invalid state, it isn't neccessary to call this method for correctness. Rather
+ * it may be helpful to explicitly assert that the builder is in a certain state to make
+ * code that manipulates the builder more readable.
+ */
+ virtual State getState() const = 0;
+
+ /**
+ * Gets the protocol used to serialize this reply. This should be used for validity checks
+ * only - runtime behavior changes should be implemented with polymorphism.
+ */
+ virtual Protocol getProtocol() const = 0;
+
+ /**
+ * Resets the state of the builder to kMetadata and clears any data that was previously
+ * written.
+ */
+ virtual void reset() = 0;
/**
- * Constructs an RPC Reply.
+ * Returns available space in bytes, should be used to verify that the message have enough
+ * space for ouput documents.
*/
- class ReplyBuilderInterface {
- MONGO_DISALLOW_COPYING(ReplyBuilderInterface);
- public:
-
- /**
- * Reply builders must have their fields set in order as they are immediately written into
- * the underlying message buffer. This enum represents the next field that can be written
- * into the builder. Note that when the builder is in state 'kInputDocs', multiple input
- * docs can be added. After the builder's done() method is called it is in state 'kDone',
- * and no further methods can be called.
- */
- enum class State {
- kMetadata,
- kCommandReply,
- kOutputDocs,
- kDone
- };
-
- virtual ~ReplyBuilderInterface() = default;
-
- virtual ReplyBuilderInterface& setMetadata(BSONObj metadata) = 0;
-
- /**
- * Sets the raw command reply. This should probably not be used in favor of the
- * variants that accept a Status or StatusWith.
- */
- virtual ReplyBuilderInterface& setRawCommandReply(BSONObj reply) = 0;
-
- /**
- * Sets the reply for this command. If an engaged StatusWith<BSONObj> is passed, the command
- * reply will be set to the contained BSONObj, augmented with the element {ok, 1.0} if it
- * does not already have an "ok" field. If a disengaged StatusWith<BSONObj> is passed, the
- * command reply will be set to {ok: 0.0, code: <code of status>,
- * errmsg: <reason of status>}
- */
- ReplyBuilderInterface& setCommandReply(StatusWith<BSONObj> commandReply);
-
- /**
- * Sets the reply for this command. The status parameter must be non-OK. The reply for
- * this command will be set to an object containing all the fields in extraErrorInfo,
- * augmented with {ok: 0.0} , {code: <code of status>}, and {errmsg: <reason of status>}.
- * If any of the fields "ok", "code", or "errmsg" already exist in extraErrorInfo, they
- * will be left as-is in the command reply. This use of this form is intended for
- * interfacing with legacy code that adds additional data to a failed command reply and
- * its use is discouraged in new code.
- */
- ReplyBuilderInterface& setCommandReply(Status nonOKStatus, BSONObj extraErrorInfo);
-
- /**
- * Add a range of output documents to the reply. This method can be called multiple times
- * before calling done().
- */
- virtual ReplyBuilderInterface& addOutputDocs(DocumentRange outputDocs) = 0;
-
- /**
- * Add a single output document to the reply. This method can be called multiple times
- * before calling done().
- */
- virtual ReplyBuilderInterface& addOutputDoc(BSONObj outputDoc) = 0;
-
- /**
- * Gets the state of the builder. As the builder will simply crash the process if it is ever
- * put in an invalid state, it isn't neccessary to call this method for correctness. Rather
- * it may be helpful to explicitly assert that the builder is in a certain state to make
- * code that manipulates the builder more readable.
- */
- virtual State getState() const = 0;
-
- /**
- * Gets the protocol used to serialize this reply. This should be used for validity checks
- * only - runtime behavior changes should be implemented with polymorphism.
- */
- virtual Protocol getProtocol() const = 0;
-
- /**
- * Resets the state of the builder to kMetadata and clears any data that was previously
- * written.
- */
- virtual void reset() = 0;
-
- /**
- * Returns available space in bytes, should be used to verify that the message have enough
- * space for ouput documents.
- */
- virtual std::size_t availableSpaceForOutputDocs() const = 0;
-
- /**
- * Writes data then transfers ownership of the message to the caller. The behavior of
- * calling any methods on the builder is subsequently undefined.
- */
- virtual std::unique_ptr<Message> done() = 0;
-
- protected:
- ReplyBuilderInterface() = default;
- };
+ virtual std::size_t availableSpaceForOutputDocs() const = 0;
+
+ /**
+ * Writes data then transfers ownership of the message to the caller. The behavior of
+ * calling any methods on the builder is subsequently undefined.
+ */
+ virtual std::unique_ptr<Message> done() = 0;
+
+protected:
+ ReplyBuilderInterface() = default;
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/reply_builder_test.cpp b/src/mongo/rpc/reply_builder_test.cpp
index 906f51f4bc0..218e8b24caa 100644
--- a/src/mongo/rpc/reply_builder_test.cpp
+++ b/src/mongo/rpc/reply_builder_test.cpp
@@ -38,232 +38,226 @@
namespace {
- using namespace mongo;
+using namespace mongo;
- static void _testMaxCommandReply(rpc::ReplyBuilderInterface& replyBuilder);
-
- TEST(CommandReplyBuilder, RoundTrip) {
+static void _testMaxCommandReply(rpc::ReplyBuilderInterface& replyBuilder);
- BSONObjBuilder metadataBob{};
- metadataBob.append("foo", "bar");
- auto metadata = metadataBob.done();
+TEST(CommandReplyBuilder, RoundTrip) {
+ BSONObjBuilder metadataBob{};
+ metadataBob.append("foo", "bar");
+ auto metadata = metadataBob.done();
- BSONObjBuilder commandReplyBob{};
- commandReplyBob.append("bar", "baz").append("ok", 1.0);
- auto commandReply = commandReplyBob.done();
+ BSONObjBuilder commandReplyBob{};
+ commandReplyBob.append("bar", "baz").append("ok", 1.0);
+ auto commandReply = commandReplyBob.done();
- BSONObjBuilder outputDoc1Bob{};
- outputDoc1Bob.append("z", "t");
- auto outputDoc1 = outputDoc1Bob.done();
+ BSONObjBuilder outputDoc1Bob{};
+ outputDoc1Bob.append("z", "t");
+ auto outputDoc1 = outputDoc1Bob.done();
- BSONObjBuilder outputDoc2Bob{};
- outputDoc2Bob.append("h", "j");
- auto outputDoc2 = outputDoc2Bob.done();
+ BSONObjBuilder outputDoc2Bob{};
+ outputDoc2Bob.append("h", "j");
+ auto outputDoc2 = outputDoc2Bob.done();
- BSONObjBuilder outputDoc3Bob{};
- outputDoc3Bob.append("g", "p");
- auto outputDoc3 = outputDoc3Bob.done();
+ BSONObjBuilder outputDoc3Bob{};
+ outputDoc3Bob.append("g", "p");
+ auto outputDoc3 = outputDoc3Bob.done();
- BufBuilder outputDocs;
- outputDoc1.appendSelfToBufBuilder(outputDocs);
- outputDoc2.appendSelfToBufBuilder(outputDocs);
- outputDoc3.appendSelfToBufBuilder(outputDocs);
+ BufBuilder outputDocs;
+ outputDoc1.appendSelfToBufBuilder(outputDocs);
+ outputDoc2.appendSelfToBufBuilder(outputDocs);
+ outputDoc3.appendSelfToBufBuilder(outputDocs);
- rpc::DocumentRange outputDocRange{outputDocs.buf(), outputDocs.buf() + outputDocs.len()};
+ rpc::DocumentRange outputDocRange{outputDocs.buf(), outputDocs.buf() + outputDocs.len()};
- rpc::CommandReplyBuilder r;
+ rpc::CommandReplyBuilder r;
- auto msg = r.setMetadata(metadata)
- .setCommandReply(commandReply)
- .addOutputDocs(outputDocRange)
- .done();
+ auto msg =
+ r.setMetadata(metadata).setCommandReply(commandReply).addOutputDocs(outputDocRange).done();
- rpc::CommandReply parsed(msg.get());
+ rpc::CommandReply parsed(msg.get());
- ASSERT_EQUALS(parsed.getMetadata(), metadata);
- ASSERT_EQUALS(parsed.getCommandReply(), commandReply);
- // need ostream overloads for ASSERT_EQUALS
- ASSERT_TRUE(parsed.getOutputDocs() == outputDocRange);
- }
+ ASSERT_EQUALS(parsed.getMetadata(), metadata);
+ ASSERT_EQUALS(parsed.getCommandReply(), commandReply);
+ // need ostream overloads for ASSERT_EQUALS
+ ASSERT_TRUE(parsed.getOutputDocs() == outputDocRange);
+}
- TEST(CommandReplyBuilder, MaxCommandReply) {
- rpc::CommandReplyBuilder replyBuilder;
- _testMaxCommandReply(replyBuilder);
- }
+TEST(CommandReplyBuilder, MaxCommandReply) {
+ rpc::CommandReplyBuilder replyBuilder;
+ _testMaxCommandReply(replyBuilder);
+}
- TEST(LegacyReplyBuilder, MaxCommandReply) {
- rpc::LegacyReplyBuilder replyBuilder;
- _testMaxCommandReply(replyBuilder);
- }
+TEST(LegacyReplyBuilder, MaxCommandReply) {
+ rpc::LegacyReplyBuilder replyBuilder;
+ _testMaxCommandReply(replyBuilder);
+}
- // verify current functionality - later will need to change
- TEST(LegacyReplyBuilderSpaceTest, DocSize) {
- rpc::LegacyReplyBuilder replyBuilder;
- replyBuilder.setMetadata(BSONObj()).setCommandReply(BSONObj());
+// verify current functionality - later will need to change
+TEST(LegacyReplyBuilderSpaceTest, DocSize) {
+ rpc::LegacyReplyBuilder replyBuilder;
+ replyBuilder.setMetadata(BSONObj()).setCommandReply(BSONObj());
- std::size_t spaceBefore = replyBuilder.availableSpaceForOutputDocs();
- ASSERT_EQUALS(spaceBefore, 0u);
+ std::size_t spaceBefore = replyBuilder.availableSpaceForOutputDocs();
+ ASSERT_EQUALS(spaceBefore, 0u);
- BSONObjBuilder docBuilder{};
- docBuilder.append("foo", "bar");
- auto doc = docBuilder.done();
+ BSONObjBuilder docBuilder{};
+ docBuilder.append("foo", "bar");
+ auto doc = docBuilder.done();
- replyBuilder.addOutputDoc(doc); //no-op
- std::size_t spaceAfter = replyBuilder.availableSpaceForOutputDocs();
- ASSERT_EQUALS(spaceAfter, 0u);
+ replyBuilder.addOutputDoc(doc); // no-op
+ std::size_t spaceAfter = replyBuilder.availableSpaceForOutputDocs();
+ ASSERT_EQUALS(spaceAfter, 0u);
+}
+
+class CommandReplyBuilderSpaceTest : public mongo::unittest::Test {
+protected:
+ // compute an empty doc size to use in follow up tests for payload size computation
+ virtual void setUp() override {
+ BSONObjBuilder docBuilder1{};
+ docBuilder1.append("x", "");
+ auto emptyDoc = docBuilder1.done();
+ emptyDocSize = emptyDoc.objsize();
}
- class CommandReplyBuilderSpaceTest : public mongo::unittest::Test {
- protected:
+ virtual void tearDown() override {}
- // compute an empty doc size to use in follow up tests for payload size computation
- virtual void setUp() override {
- BSONObjBuilder docBuilder1{};
- docBuilder1.append("x", "");
- auto emptyDoc = docBuilder1.done();
- emptyDocSize = emptyDoc.objsize();
- }
+ std::size_t emptyDocSize = 0u;
+};
- virtual void tearDown() override {
- }
+TEST_F(CommandReplyBuilderSpaceTest, DocSizeEq) {
+ rpc::CommandReplyBuilder replyBuilder;
+ replyBuilder.setMetadata(BSONObj()).setCommandReply(BSONObj());
- std::size_t emptyDocSize = 0u;
- };
+ std::size_t spaceBefore = replyBuilder.availableSpaceForOutputDocs();
- TEST_F(CommandReplyBuilderSpaceTest, DocSizeEq) {
- rpc::CommandReplyBuilder replyBuilder;
- replyBuilder.setMetadata(BSONObj()).setCommandReply(BSONObj());
+ BSONObjBuilder docBuilder{};
+ docBuilder.append("foo", "bar");
+ auto doc = docBuilder.done();
+ std::size_t docSize = doc.objsize();
- std::size_t spaceBefore = replyBuilder.availableSpaceForOutputDocs();
+ replyBuilder.addOutputDoc(doc);
+ std::size_t spaceAfter = replyBuilder.availableSpaceForOutputDocs();
+ ASSERT_EQUALS(spaceBefore - docSize, spaceAfter);
+}
+// multiple calls to addOutputDoc, no metadata
+TEST_F(CommandReplyBuilderSpaceTest, MaxDocSize1) {
+ rpc::CommandReplyBuilder replyBuilder;
+
+ replyBuilder.setMetadata(BSONObj()).setCommandReply(BSONObj());
+
+ std::size_t availSpace = replyBuilder.availableSpaceForOutputDocs();
+
+ while (availSpace > 0u) {
+ std::size_t payloadSz =
+ std::min(availSpace, static_cast<std::size_t>(mongo::BSONObjMaxUserSize)) -
+ emptyDocSize;
BSONObjBuilder docBuilder{};
- docBuilder.append("foo", "bar");
+ std::string payload = std::string(payloadSz, 'y');
+ docBuilder.append("x", payload);
auto doc = docBuilder.done();
- std::size_t docSize = doc.objsize();
-
replyBuilder.addOutputDoc(doc);
- std::size_t spaceAfter = replyBuilder.availableSpaceForOutputDocs();
- ASSERT_EQUALS(spaceBefore - docSize, spaceAfter);
+ availSpace = replyBuilder.availableSpaceForOutputDocs();
}
+ auto msg = replyBuilder.done();
+ auto sizeUInt = static_cast<std::size_t>(msg->size());
- // multiple calls to addOutputDoc, no metadata
- TEST_F(CommandReplyBuilderSpaceTest, MaxDocSize1) {
- rpc::CommandReplyBuilder replyBuilder;
-
- replyBuilder.setMetadata(BSONObj()).setCommandReply(BSONObj());
-
- std::size_t availSpace = replyBuilder.availableSpaceForOutputDocs();
-
- while (availSpace > 0u) {
- std::size_t payloadSz =
- std::min(availSpace, static_cast<std::size_t>(mongo::BSONObjMaxUserSize)) -
- emptyDocSize;
- BSONObjBuilder docBuilder{};
- std::string payload = std::string(payloadSz, 'y' );
- docBuilder.append("x", payload);
- auto doc = docBuilder.done();
- replyBuilder.addOutputDoc(doc);
- availSpace = replyBuilder.availableSpaceForOutputDocs();
- }
- auto msg = replyBuilder.done();
- auto sizeUInt = static_cast<std::size_t>(msg->size());
-
- ASSERT_EQUALS(sizeUInt, mongo::MaxMessageSizeBytes);
- }
+ ASSERT_EQUALS(sizeUInt, mongo::MaxMessageSizeBytes);
+}
- // multiple calls to addOutputDoc, some metadata
- TEST_F(CommandReplyBuilderSpaceTest, MaxDocSize2) {
- rpc::CommandReplyBuilder replyBuilder;
-
- BSONObjBuilder metadataBuilder{};
- metadataBuilder.append("foo", "bar");
- auto metadata = metadataBuilder.done();
-
- BSONObjBuilder commandReplyBuilder{};
- commandReplyBuilder.append("oof", "rab");
- auto commandReply = commandReplyBuilder.done();
-
- replyBuilder.setMetadata(metadata).setCommandReply(commandReply);
-
- std::size_t availSpace = replyBuilder.availableSpaceForOutputDocs();
-
- while (availSpace > 0u) {
- std::size_t payloadSz =
- std::min(availSpace, static_cast<std::size_t>(mongo::BSONObjMaxUserSize)) -
- emptyDocSize;
- BSONObjBuilder docBuilder{};
- std::string payload = std::string(payloadSz, 'y' );
- docBuilder.append("x", payload);
- auto doc = docBuilder.done();
- replyBuilder.addOutputDoc(doc);
- availSpace = replyBuilder.availableSpaceForOutputDocs();
- }
- auto msg = replyBuilder.done();
- auto sizeUInt = static_cast<std::size_t>(msg->size());
-
- ASSERT_EQUALS(sizeUInt, mongo::MaxMessageSizeBytes);
- }
+// multiple calls to addOutputDoc, some metadata
+TEST_F(CommandReplyBuilderSpaceTest, MaxDocSize2) {
+ rpc::CommandReplyBuilder replyBuilder;
+ BSONObjBuilder metadataBuilder{};
+ metadataBuilder.append("foo", "bar");
+ auto metadata = metadataBuilder.done();
- // single call to addOutputDocs
- TEST_F(CommandReplyBuilderSpaceTest, MaxDocSize3) {
- rpc::CommandReplyBuilder replyBuilder;
+ BSONObjBuilder commandReplyBuilder{};
+ commandReplyBuilder.append("oof", "rab");
+ auto commandReply = commandReplyBuilder.done();
- BSONObjBuilder metadataBuilder{};
- metadataBuilder.append("foo", "bar");
- auto metadata = metadataBuilder.done();
+ replyBuilder.setMetadata(metadata).setCommandReply(commandReply);
- BSONObjBuilder commandReplyBuilder{};
- commandReplyBuilder.append("oof", "rab");
- auto commandReply = commandReplyBuilder.done();
+ std::size_t availSpace = replyBuilder.availableSpaceForOutputDocs();
- replyBuilder.setMetadata(metadata).setCommandReply(commandReply);
+ while (availSpace > 0u) {
+ std::size_t payloadSz =
+ std::min(availSpace, static_cast<std::size_t>(mongo::BSONObjMaxUserSize)) -
+ emptyDocSize;
+ BSONObjBuilder docBuilder{};
+ std::string payload = std::string(payloadSz, 'y');
+ docBuilder.append("x", payload);
+ auto doc = docBuilder.done();
+ replyBuilder.addOutputDoc(doc);
+ availSpace = replyBuilder.availableSpaceForOutputDocs();
+ }
+ auto msg = replyBuilder.done();
+ auto sizeUInt = static_cast<std::size_t>(msg->size());
- std::size_t availSpace = replyBuilder.availableSpaceForOutputDocs();
+ ASSERT_EQUALS(sizeUInt, mongo::MaxMessageSizeBytes);
+}
- BufBuilder docs;
- while (availSpace > 0u) {
- std::size_t payloadSz =
- std::min(availSpace, static_cast<std::size_t>(mongo::BSONObjMaxUserSize)) -
- emptyDocSize;
- BSONObjBuilder docBuilder{};
- std::string payload = std::string(payloadSz, 'y' );
- docBuilder.append("x", payload);
- auto doc = docBuilder.done();
- availSpace -= doc.objsize();
- doc.appendSelfToBufBuilder(docs);
- }
- rpc::DocumentRange docRange{docs.buf(), docs.buf() + docs.len()};
- replyBuilder.addOutputDocs(docRange);
- auto msg = replyBuilder.done();
- auto sizeUInt = static_cast<std::size_t>(msg->size());
+// single call to addOutputDocs
+TEST_F(CommandReplyBuilderSpaceTest, MaxDocSize3) {
+ rpc::CommandReplyBuilder replyBuilder;
- ASSERT_EQUALS(sizeUInt, mongo::MaxMessageSizeBytes);
- }
+ BSONObjBuilder metadataBuilder{};
+ metadataBuilder.append("foo", "bar");
+ auto metadata = metadataBuilder.done();
- // call to addCommandReply
- void _testMaxCommandReply(rpc::ReplyBuilderInterface& replyBuilder) {
- BSONObjBuilder docBuilder1{};
- docBuilder1.append("x", "");
- auto emptyDoc = docBuilder1.done();
- std::size_t emptyDocSize = emptyDoc.objsize();
+ BSONObjBuilder commandReplyBuilder{};
+ commandReplyBuilder.append("oof", "rab");
+ auto commandReply = commandReplyBuilder.done();
- BSONObjBuilder metadataBuilder{};
- metadataBuilder.append("foo", "bar");
- auto metadata = metadataBuilder.done();
- replyBuilder.setMetadata(metadata);
+ replyBuilder.setMetadata(metadata).setCommandReply(commandReply);
- auto payloadSz = static_cast<std::size_t>(mongo::BSONObjMaxUserSize) -
+ std::size_t availSpace = replyBuilder.availableSpaceForOutputDocs();
+
+ BufBuilder docs;
+ while (availSpace > 0u) {
+ std::size_t payloadSz =
+ std::min(availSpace, static_cast<std::size_t>(mongo::BSONObjMaxUserSize)) -
emptyDocSize;
+ BSONObjBuilder docBuilder{};
+ std::string payload = std::string(payloadSz, 'y');
+ docBuilder.append("x", payload);
+ auto doc = docBuilder.done();
+ availSpace -= doc.objsize();
+ doc.appendSelfToBufBuilder(docs);
+ }
+ rpc::DocumentRange docRange{docs.buf(), docs.buf() + docs.len()};
+ replyBuilder.addOutputDocs(docRange);
- BSONObjBuilder commandReplyBuilder{};
- std::string payload = std::string(payloadSz, 'y' );
- commandReplyBuilder.append("x", payload);
- auto commandReply = commandReplyBuilder.done();
- ASSERT_EQUALS(commandReply.objsize(), mongo::BSONObjMaxUserSize);
+ auto msg = replyBuilder.done();
+ auto sizeUInt = static_cast<std::size_t>(msg->size());
- replyBuilder.setCommandReply(commandReply);
- }
+ ASSERT_EQUALS(sizeUInt, mongo::MaxMessageSizeBytes);
+}
+
+// call to addCommandReply
+void _testMaxCommandReply(rpc::ReplyBuilderInterface& replyBuilder) {
+ BSONObjBuilder docBuilder1{};
+ docBuilder1.append("x", "");
+ auto emptyDoc = docBuilder1.done();
+ std::size_t emptyDocSize = emptyDoc.objsize();
+
+ BSONObjBuilder metadataBuilder{};
+ metadataBuilder.append("foo", "bar");
+ auto metadata = metadataBuilder.done();
+ replyBuilder.setMetadata(metadata);
+
+ auto payloadSz = static_cast<std::size_t>(mongo::BSONObjMaxUserSize) - emptyDocSize;
+
+ BSONObjBuilder commandReplyBuilder{};
+ std::string payload = std::string(payloadSz, 'y');
+ commandReplyBuilder.append("x", payload);
+ auto commandReply = commandReplyBuilder.done();
+ ASSERT_EQUALS(commandReply.objsize(), mongo::BSONObjMaxUserSize);
+
+ replyBuilder.setCommandReply(commandReply);
+}
} // namespace
diff --git a/src/mongo/rpc/reply_interface.h b/src/mongo/rpc/reply_interface.h
index ac0514dc64f..7786c57cb26 100644
--- a/src/mongo/rpc/reply_interface.h
+++ b/src/mongo/rpc/reply_interface.h
@@ -32,52 +32,53 @@
#include "mongo/rpc/protocol.h"
namespace mongo {
- class BSONObj;
- class Message;
+class BSONObj;
+class Message;
namespace rpc {
- class DocumentRange;
+class DocumentRange;
+
+/**
+ * An immutable view of an RPC Reply.
+ */
+class ReplyInterface {
+ MONGO_DISALLOW_COPYING(ReplyInterface);
+
+public:
+ virtual ~ReplyInterface() = default;
/**
- * An immutable view of an RPC Reply.
+ * Accessor for the metadata object. Metadata is generally used for information
+ * that is independent of any specific command, e.g. auditing information.
*/
- class ReplyInterface {
- MONGO_DISALLOW_COPYING(ReplyInterface);
- public:
- virtual ~ReplyInterface() = default;
-
- /**
- * Accessor for the metadata object. Metadata is generally used for information
- * that is independent of any specific command, e.g. auditing information.
- */
- virtual const BSONObj& getMetadata() const = 0;
+ virtual const BSONObj& getMetadata() const = 0;
- /**
- * The result of executing the command.
- */
- virtual const BSONObj& getCommandReply() const = 0;
+ /**
+ * The result of executing the command.
+ */
+ virtual const BSONObj& getCommandReply() const = 0;
- /**
- * A variable number of BSON documents returned by the command. It is valid for the
- * returned range to be empty.
- *
- * Example usage:
- *
- * for (auto&& doc : reply.getOutputDocs()) {
- * ... do stuff with doc
- * }
- */
- virtual DocumentRange getOutputDocs() const = 0;
+ /**
+ * A variable number of BSON documents returned by the command. It is valid for the
+ * returned range to be empty.
+ *
+ * Example usage:
+ *
+ * for (auto&& doc : reply.getOutputDocs()) {
+ * ... do stuff with doc
+ * }
+ */
+ virtual DocumentRange getOutputDocs() const = 0;
- /**
- * Gets the protocol used to deserialize this reply. This should be used for validity
- * checks only - runtime behavior changes should be implemented with polymorphism.
- */
- virtual Protocol getProtocol() const = 0;
+ /**
+ * Gets the protocol used to deserialize this reply. This should be used for validity
+ * checks only - runtime behavior changes should be implemented with polymorphism.
+ */
+ virtual Protocol getProtocol() const = 0;
- protected:
- ReplyInterface() = default;
- };
+protected:
+ ReplyInterface() = default;
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/request_builder_interface.h b/src/mongo/rpc/request_builder_interface.h
index 7297bf393c5..f27c7e3e10d 100644
--- a/src/mongo/rpc/request_builder_interface.h
+++ b/src/mongo/rpc/request_builder_interface.h
@@ -34,92 +34,85 @@
#include "mongo/rpc/protocol.h"
namespace mongo {
- class Message;
- class BSONObj;
- class StringData;
+class Message;
+class BSONObj;
+class StringData;
namespace rpc {
- class DocumentRange;
+class DocumentRange;
+
+/**
+ * Constructs an RPC request.
+ */
+class RequestBuilderInterface {
+ MONGO_DISALLOW_COPYING(RequestBuilderInterface);
+
+public:
+ /**
+ * Request builders must have their fields set in order as they are immediately written into
+ * the underlying message buffer. This enum represents the next field that can be written
+ * into the builder. Note that when the builder is in state 'kInputDocs', multiple input
+ * docs can be added. After the builder's done() method is called it is in state 'kDone',
+ * and no further methods can be called.
+ */
+ enum class State { kDatabase, kCommandName, kMetadata, kCommandArgs, kInputDocs, kDone };
+
+ virtual ~RequestBuilderInterface() = default;
+
+ /**
+ * Sets the database that the command will be executed against.
+ */
+ virtual RequestBuilderInterface& setDatabase(StringData database) = 0;
+
+ /**
+ * Sets the name of the command to execute.
+ */
+ virtual RequestBuilderInterface& setCommandName(StringData commandName) = 0;
+
+ /**
+ * Sets the metadata associated with this command request - see metadata.h for details.
+ */
+ virtual RequestBuilderInterface& setMetadata(BSONObj metadata) = 0;
/**
- * Constructs an RPC request.
+ * Sets the arguments to pass to the command.
*/
- class RequestBuilderInterface {
- MONGO_DISALLOW_COPYING(RequestBuilderInterface);
- public:
-
- /**
- * Request builders must have their fields set in order as they are immediately written into
- * the underlying message buffer. This enum represents the next field that can be written
- * into the builder. Note that when the builder is in state 'kInputDocs', multiple input
- * docs can be added. After the builder's done() method is called it is in state 'kDone',
- * and no further methods can be called.
- */
- enum class State {
- kDatabase,
- kCommandName,
- kMetadata,
- kCommandArgs,
- kInputDocs,
- kDone
- };
-
- virtual ~RequestBuilderInterface() = default;
-
- /**
- * Sets the database that the command will be executed against.
- */
- virtual RequestBuilderInterface& setDatabase(StringData database) = 0;
-
- /**
- * Sets the name of the command to execute.
- */
- virtual RequestBuilderInterface& setCommandName(StringData commandName) = 0;
-
- /**
- * Sets the metadata associated with this command request - see metadata.h for details.
- */
- virtual RequestBuilderInterface& setMetadata(BSONObj metadata) = 0;
-
- /**
- * Sets the arguments to pass to the command.
- */
- virtual RequestBuilderInterface& setCommandArgs(BSONObj commandArgs) = 0;
-
- /**
- * Add a range of input documents to the request. This method can be called multiple times
- * before calling done().
- */
- virtual RequestBuilderInterface& addInputDocs(DocumentRange inputDocs) = 0;
-
- /**
- * Add a single output document to the request. This method can be called multiple times
- * before calling done().
- */
- virtual RequestBuilderInterface& addInputDoc(BSONObj inputDoc) = 0;
-
- /**
- * Get the state of the builder. This method is intended to enable debug or invariant
- * checks that the builder is in the correct state.
- */
- virtual State getState() const = 0;
-
- /**
- * Gets the protocol used to serialize this request. This should only be used for asserts,
- * and not for runtime behavior changes, which should be handled with polymorphism.
- */
- virtual Protocol getProtocol() const = 0;
-
- /**
- * Writes data then transfers ownership of the message to the caller.
- * The behavior of calling any methods on the object is subsequently
- * undefined.
- */
- virtual std::unique_ptr<Message> done() = 0;
-
- protected:
- RequestBuilderInterface() = default;
- };
+ virtual RequestBuilderInterface& setCommandArgs(BSONObj commandArgs) = 0;
+
+ /**
+ * Add a range of input documents to the request. This method can be called multiple times
+ * before calling done().
+ */
+ virtual RequestBuilderInterface& addInputDocs(DocumentRange inputDocs) = 0;
+
+ /**
+ * Add a single output document to the request. This method can be called multiple times
+ * before calling done().
+ */
+ virtual RequestBuilderInterface& addInputDoc(BSONObj inputDoc) = 0;
+
+ /**
+ * Get the state of the builder. This method is intended to enable debug or invariant
+ * checks that the builder is in the correct state.
+ */
+ virtual State getState() const = 0;
+
+ /**
+ * Gets the protocol used to serialize this request. This should only be used for asserts,
+ * and not for runtime behavior changes, which should be handled with polymorphism.
+ */
+ virtual Protocol getProtocol() const = 0;
+
+ /**
+ * Writes data then transfers ownership of the message to the caller.
+ * The behavior of calling any methods on the object is subsequently
+ * undefined.
+ */
+ virtual std::unique_ptr<Message> done() = 0;
+
+protected:
+ RequestBuilderInterface() = default;
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/request_interface.h b/src/mongo/rpc/request_interface.h
index 0933e728ab9..b5395012416 100644
--- a/src/mongo/rpc/request_interface.h
+++ b/src/mongo/rpc/request_interface.h
@@ -32,64 +32,65 @@
#include "mongo/rpc/protocol.h"
namespace mongo {
- class BSONObj;
- class Message;
- class StringData;
+class BSONObj;
+class Message;
+class StringData;
namespace rpc {
- class DocumentRange;
+class DocumentRange;
+
+/**
+ * An immutable view of an RPC message.
+ */
+class RequestInterface {
+ MONGO_DISALLOW_COPYING(RequestInterface);
+
+public:
+ virtual ~RequestInterface() = default;
/**
- * An immutable view of an RPC message.
+ * Gets the database that the command is to be executed on.
*/
- class RequestInterface {
- MONGO_DISALLOW_COPYING(RequestInterface);
- public:
- virtual ~RequestInterface() = default;
+ virtual StringData getDatabase() const = 0;
- /**
- * Gets the database that the command is to be executed on.
- */
- virtual StringData getDatabase() const = 0;
-
- /**
- * Gets the name of the command to execute.
- */
- virtual StringData getCommandName() const = 0;
+ /**
+ * Gets the name of the command to execute.
+ */
+ virtual StringData getCommandName() const = 0;
- /**
- * Gets the metadata associated with the command request. This is information that is
- * independent of any specific command, i.e. auditing information. See metadata.h for
- * further details.
- */
- virtual const BSONObj& getMetadata() const = 0;
+ /**
+ * Gets the metadata associated with the command request. This is information that is
+ * independent of any specific command, i.e. auditing information. See metadata.h for
+ * further details.
+ */
+ virtual const BSONObj& getMetadata() const = 0;
- /**
- * Gets the arguments to the command - this is passed to the command's run() method.
- */
- virtual const BSONObj& getCommandArgs() const = 0;
+ /**
+ * Gets the arguments to the command - this is passed to the command's run() method.
+ */
+ virtual const BSONObj& getCommandArgs() const = 0;
- /**
- * A variable number of BSON documents to pass to the command. It is valid for
- * the returned range to be empty.
- *
- * Example usage:
- *
- * for (auto&& doc : req.getInputDocs()) {
- * ... do stuff with doc
- * }
- */
- virtual DocumentRange getInputDocs() const = 0;
+ /**
+ * A variable number of BSON documents to pass to the command. It is valid for
+ * the returned range to be empty.
+ *
+ * Example usage:
+ *
+ * for (auto&& doc : req.getInputDocs()) {
+ * ... do stuff with doc
+ * }
+ */
+ virtual DocumentRange getInputDocs() const = 0;
- /**
- * Gets the RPC protocol used to deserialize this message. This should only be used for
- * asserts, and not for runtime behavior changes, which should be handled with polymorphism.
- */
- virtual Protocol getProtocol() const = 0;
+ /**
+ * Gets the RPC protocol used to deserialize this message. This should only be used for
+ * asserts, and not for runtime behavior changes, which should be handled with polymorphism.
+ */
+ virtual Protocol getProtocol() const = 0;
- protected:
- RequestInterface() = default;
- };
+protected:
+ RequestInterface() = default;
+};
} // namespace rpc
} // namespace mongo
diff --git a/src/mongo/rpc/unique_message.h b/src/mongo/rpc/unique_message.h
index 32799d41919..a763a82ec25 100644
--- a/src/mongo/rpc/unique_message.h
+++ b/src/mongo/rpc/unique_message.h
@@ -36,62 +36,59 @@
#include "mongo/rpc/request_interface.h"
namespace mongo {
- class Message;
+class Message;
namespace rpc {
- /**
- * A wrapper around an owned message that includes access to an associated
- * ReplyInterface or RequestInterface.
- */
- template <typename MessageViewType>
- class UniqueMessage {
- MONGO_DISALLOW_COPYING(UniqueMessage);
- public:
- UniqueMessage(std::unique_ptr<Message> message, std::unique_ptr<MessageViewType> view)
- : _message{std::move(message)}
- , _view{std::move(view)}
- {}
+/**
+ * A wrapper around an owned message that includes access to an associated
+ * ReplyInterface or RequestInterface.
+ */
+template <typename MessageViewType>
+class UniqueMessage {
+ MONGO_DISALLOW_COPYING(UniqueMessage);
+
+public:
+ UniqueMessage(std::unique_ptr<Message> message, std::unique_ptr<MessageViewType> view)
+ : _message{std::move(message)}, _view{std::move(view)} {}
#if defined(_MSC_VER) && _MSC_VER < 1900
- UniqueMessage(UniqueMessage&& other)
- : _message{std::move(other._message)}
- , _view{std::move(other._view)}
- {}
+ UniqueMessage(UniqueMessage&& other)
+ : _message{std::move(other._message)}, _view{std::move(other._view)} {}
- UniqueMessage& operator=(UniqueMessage&& other) {
- _message = std::move(other._message);
- _view = std::move(other._view);
- return *this;
- }
+ UniqueMessage& operator=(UniqueMessage&& other) {
+ _message = std::move(other._message);
+ _view = std::move(other._view);
+ return *this;
+ }
#else
- UniqueMessage(UniqueMessage&&) = default;
- UniqueMessage& operator=(UniqueMessage&&) = default;
+ UniqueMessage(UniqueMessage&&) = default;
+ UniqueMessage& operator=(UniqueMessage&&) = default;
#endif
- const MessageViewType* operator->() const {
- return _view.get();
- }
+ const MessageViewType* operator->() const {
+ return _view.get();
+ }
- const MessageViewType& operator*() const {
- return *_view;
- }
+ const MessageViewType& operator*() const {
+ return *_view;
+ }
- /**
- * Releases ownership of the underlying message. The result of calling any other methods
- * on the object afterward is undefined.
- */
- std::unique_ptr<Message> releaseMessage() {
- _view.reset();
- return std::move(_message);
- }
+ /**
+ * Releases ownership of the underlying message. The result of calling any other methods
+ * on the object afterward is undefined.
+ */
+ std::unique_ptr<Message> releaseMessage() {
+ _view.reset();
+ return std::move(_message);
+ }
- private:
- std::unique_ptr<Message> _message;
- std::unique_ptr<MessageViewType> _view;
- };
+private:
+ std::unique_ptr<Message> _message;
+ std::unique_ptr<MessageViewType> _view;
+};
- using UniqueReply = UniqueMessage<ReplyInterface>;
- using UniqueRequest = UniqueMessage<RequestInterface>;
+using UniqueReply = UniqueMessage<ReplyInterface>;
+using UniqueRequest = UniqueMessage<RequestInterface>;
} // namespace rpc
} // namespace mongo