summaryrefslogtreecommitdiff
path: root/src/mongo/rpc
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2021-02-10 14:30:01 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-02-10 15:26:00 +0000
commit87bcb24f50b65e08eb0d711edfb59b61ef3c1f91 (patch)
tree15385fc4b0c36072c95be9bb1fcb3e42b925c269 /src/mongo/rpc
parent7d5cf026105db1693724db155b4f409b267ab352 (diff)
downloadmongo-87bcb24f50b65e08eb0d711edfb59b61ef3c1f91.tar.gz
SERVER-53150 Specify input/output to hello command
Diffstat (limited to 'src/mongo/rpc')
-rw-r--r--src/mongo/rpc/SConscript1
-rw-r--r--src/mongo/rpc/metadata/client_metadata.cpp109
-rw-r--r--src/mongo/rpc/metadata/client_metadata.h20
-rw-r--r--src/mongo/rpc/metadata/client_metadata.idl44
4 files changed, 95 insertions, 79 deletions
diff --git a/src/mongo/rpc/SConscript b/src/mongo/rpc/SConscript
index 957647e5721..257e556da03 100644
--- a/src/mongo/rpc/SConscript
+++ b/src/mongo/rpc/SConscript
@@ -135,6 +135,7 @@ env.Library(
target='client_metadata',
source=[
'metadata/client_metadata.cpp',
+ 'metadata/client_metadata.idl',
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
diff --git a/src/mongo/rpc/metadata/client_metadata.cpp b/src/mongo/rpc/metadata/client_metadata.cpp
index a4a8767aadc..6ea09b44b02 100644
--- a/src/mongo/rpc/metadata/client_metadata.cpp
+++ b/src/mongo/rpc/metadata/client_metadata.cpp
@@ -84,7 +84,7 @@ const auto getOperationState = OperationContext::declareDecoration<ClientMetadat
} // namespace
-StatusWith<boost::optional<ClientMetadata>> ClientMetadata::parse(const BSONElement& element) {
+StatusWith<boost::optional<ClientMetadata>> ClientMetadata::parse(const BSONElement& element) try {
if (element.eoo()) {
return {boost::none};
}
@@ -93,84 +93,50 @@ StatusWith<boost::optional<ClientMetadata>> ClientMetadata::parse(const BSONElem
return Status(ErrorCodes::TypeMismatch, "The client metadata document must be a document");
}
- ClientMetadata clientMetadata;
- Status s = clientMetadata.parseClientMetadataDocument(element.Obj());
- if (!s.isOK()) {
- return s;
- }
-
- return {std::move(clientMetadata)};
+ return boost::make_optional(parseFromBSON(element.Obj()));
+} catch (const DBException& ex) {
+ return ex.toStatus();
}
-Status ClientMetadata::parseClientMetadataDocument(const BSONObj& doc) {
+ClientMetadata::ClientMetadata(BSONObj doc) {
uint32_t maxLength = kMaxMongoDMetadataDocumentByteLength;
if (isMongos()) {
maxLength = kMaxMongoSMetadataDocumentByteLength;
}
- if (static_cast<uint32_t>(doc.objsize()) > maxLength) {
- return Status(ErrorCodes::ClientMetadataDocumentTooLarge,
- str::stream() << "The client metadata document must be less then or equal to "
- << maxLength << "bytes");
- }
+ uassert(ErrorCodes::ClientMetadataDocumentTooLarge,
+ str::stream() << "The client metadata document must be less then or equal to "
+ << maxLength << "bytes",
+ static_cast<uint32_t>(doc.objsize()) <= maxLength);
+
+ const auto isobj = [](StringData name, const BSONElement& e) {
+ uassert(ErrorCodes::TypeMismatch,
+ str::stream()
+ << "The '" << name
+ << "' field is required to be a BSON document in the client metadata document",
+ e.isABSONObj());
+ };
// Get a copy so that we can take a stable reference to the app name inside
- BSONObj docOwned = doc.getOwned();
+ _document = doc.getOwned();
- StringData appName;
bool foundDriver = false;
bool foundOperatingSystem = false;
-
- BSONObjIterator i(docOwned);
- while (i.more()) {
- BSONElement e = i.next();
- StringData name = e.fieldNameStringData();
+ for (const auto& e : _document) {
+ auto name = e.fieldNameStringData();
if (name == kApplication) {
// Application is an optional sub-document, but we require it to be a document if
// specified.
- if (!e.isABSONObj()) {
- return Status(ErrorCodes::TypeMismatch,
- str::stream() << "The '" << kApplication
- << "' field is required to be a BSON document in the "
- "client metadata document");
- }
-
- auto swAppName = parseApplicationDocument(e.Obj());
- if (!swAppName.getStatus().isOK()) {
- return swAppName.getStatus();
- }
-
- appName = swAppName.getValue();
-
+ isobj(kApplication, e);
+ _appName = uassertStatusOK(parseApplicationDocument(e.Obj()));
} else if (name == kDriver) {
- if (!e.isABSONObj()) {
- return Status(ErrorCodes::TypeMismatch,
- str::stream() << "The '" << kDriver
- << "' field is required to be a "
- "BSON document in the client "
- "metadata document");
- }
-
- Status s = validateDriverDocument(e.Obj());
- if (!s.isOK()) {
- return s;
- }
-
+ isobj(kDriver, e);
+ uassertStatusOK(validateDriverDocument(e.Obj()));
foundDriver = true;
} else if (name == kOperatingSystem) {
- if (!e.isABSONObj()) {
- return Status(ErrorCodes::TypeMismatch,
- str::stream() << "The '" << kOperatingSystem
- << "' field is required to be a BSON document in the "
- "client metadata document");
- }
-
- Status s = validateOperatingSystemDocument(e.Obj());
- if (!s.isOK()) {
- return s;
- }
-
+ isobj(kOperatingSystem, e);
+ uassertStatusOK(validateOperatingSystemDocument(e.Obj()));
foundOperatingSystem = true;
}
@@ -178,23 +144,16 @@ Status ClientMetadata::parseClientMetadataDocument(const BSONObj& doc) {
}
// Driver is a required sub document.
- if (!foundDriver) {
- return Status(ErrorCodes::ClientMetadataMissingField,
- str::stream() << "Missing required sub-document '" << kDriver
- << "' in the client metadata document");
- }
+ uassert(ErrorCodes::ClientMetadataMissingField,
+ str::stream() << "Missing required sub-document '" << kDriver
+ << "' in the client metadata document",
+ foundDriver);
// OS is a required sub document.
- if (!foundOperatingSystem) {
- return Status(ErrorCodes::ClientMetadataMissingField,
- str::stream() << "Missing required sub-document '" << kOperatingSystem
- << "' in the client metadata document");
- }
-
- _document = std::move(docOwned);
- _appName = std::move(appName);
-
- return Status::OK();
+ uassert(ErrorCodes::ClientMetadataMissingField,
+ str::stream() << "Missing required sub-document '" << kOperatingSystem
+ << "' in the client metadata document",
+ foundOperatingSystem);
}
StatusWith<StringData> ClientMetadata::parseApplicationDocument(const BSONObj& doc) {
diff --git a/src/mongo/rpc/metadata/client_metadata.h b/src/mongo/rpc/metadata/client_metadata.h
index cc3d870a4f0..309eb5668e0 100644
--- a/src/mongo/rpc/metadata/client_metadata.h
+++ b/src/mongo/rpc/metadata/client_metadata.h
@@ -80,10 +80,16 @@ constexpr auto kMetadataDocumentName = "client"_sd;
* See Driver Specification: "MongoDB Handshake" for more information.
*/
class ClientMetadata {
- ClientMetadata(const ClientMetadata&) = delete;
- ClientMetadata& operator=(const ClientMetadata&) = delete;
-
public:
+ explicit ClientMetadata(BSONObj obj);
+
+ ClientMetadata(const ClientMetadata& src) : ClientMetadata(src._document) {}
+ ClientMetadata& operator=(const ClientMetadata& src) {
+ ClientMetadata copy(src._document);
+ *this = std::move(copy);
+ return *this;
+ }
+
ClientMetadata(ClientMetadata&&) = default;
ClientMetadata& operator=(ClientMetadata&&) = default;
@@ -145,6 +151,13 @@ public:
static StatusWith<boost::optional<ClientMetadata>> parse(const BSONElement& element);
/**
+ * Wrapper for BSONObj constructor used by IDL parsers.
+ */
+ static ClientMetadata parseFromBSON(BSONObj obj) {
+ return ClientMetadata(obj);
+ }
+
+ /**
* Create a new client metadata document with os information from the ProcessInfo class.
*
* This method outputs the "client" field, and client metadata sub-document in the
@@ -311,7 +324,6 @@ public:
private:
ClientMetadata() = default;
- Status parseClientMetadataDocument(const BSONObj& doc);
static Status validateDriverDocument(const BSONObj& doc);
static Status validateOperatingSystemDocument(const BSONObj& doc);
static StatusWith<StringData> parseApplicationDocument(const BSONObj& doc);
diff --git a/src/mongo/rpc/metadata/client_metadata.idl b/src/mongo/rpc/metadata/client_metadata.idl
new file mode 100644
index 00000000000..d1726153d98
--- /dev/null
+++ b/src/mongo/rpc/metadata/client_metadata.idl
@@ -0,0 +1,44 @@
+# Copyright (C) 2021-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# As a special exception, the copyright holders give permission to link the
+# code of portions of this program with the OpenSSL library under certain
+# conditions as described in each individual source file and distribute
+# linked combinations including the program with the OpenSSL library. You
+# must comply with the Server Side Public License in all respects for
+# all of the code used other than as permitted herein. If you modify file(s)
+# with this exception, you may extend this exception to your version of the
+# file(s), but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version. If you delete this
+# exception statement from all source files in the program, then also delete
+# it in the license file.
+#
+
+global:
+ cpp_namespace: "mongo"
+ cpp_includes:
+ - "mongo/rpc/metadata/client_metadata.h"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+types:
+ ClientMetadata:
+ description: "Client metadata document"
+ bson_serialization_type: object
+ cpp_type: ClientMetadata
+ serializer: "mongo::ClientMetadata::getDocument"
+ deserializer: "mongo::ClientMetadata::parseFromBSON"
+