diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2021-02-10 14:30:01 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-02-10 15:26:00 +0000 |
commit | 87bcb24f50b65e08eb0d711edfb59b61ef3c1f91 (patch) | |
tree | 15385fc4b0c36072c95be9bb1fcb3e42b925c269 /src/mongo/rpc | |
parent | 7d5cf026105db1693724db155b4f409b267ab352 (diff) | |
download | mongo-87bcb24f50b65e08eb0d711edfb59b61ef3c1f91.tar.gz |
SERVER-53150 Specify input/output to hello command
Diffstat (limited to 'src/mongo/rpc')
-rw-r--r-- | src/mongo/rpc/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/client_metadata.cpp | 109 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/client_metadata.h | 20 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/client_metadata.idl | 44 |
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" + |