diff options
author | Moustafa Maher <m.maher@10gen.com> | 2021-01-15 01:52:57 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-01-20 00:16:26 +0000 |
commit | 4b51940f6e36878261dc18b8867c27f44c4975a9 (patch) | |
tree | 3565b85c42b595567f21303af1ac3658c6fd0d07 /src/mongo/db/commands.h | |
parent | f75145df24d968c4c8b659f6528f7e86da02aa46 (diff) | |
download | mongo-4b51940f6e36878261dc18b8867c27f44c4975a9.tar.gz |
SERVER-52547 Avoid reparsing the command object multiple times
Diffstat (limited to 'src/mongo/db/commands.h')
-rw-r--r-- | src/mongo/db/commands.h | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index dc1a53f2e8f..5dcd2d94b77 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -958,10 +958,11 @@ public: * */ template <typename Derived> -class BasicCommandWithRequestParser : public BasicCommand { -public: +class BasicCommandWithRequestParser : public BasicCommandWithReplyBuilderInterface { +protected: // Commands that only have a single name don't need to define any constructors. - BasicCommandWithRequestParser() : BasicCommand(Derived::Request::kCommandName) {} + BasicCommandWithRequestParser() + : BasicCommandWithReplyBuilderInterface(Derived::Request::kCommandName) {} bool runWithReplyBuilder(OperationContext* opCtx, const std::string& db, @@ -970,21 +971,51 @@ public: auto result = replyBuilder->getBodyBuilder(); // To enforce API versioning - using RequestType = typename Derived::Request; - auto request = RequestType::parse( - IDLParserErrorContext(Derived::Request::kCommandName, - APIParameters::get(opCtx).getAPIStrict().value_or(false)), - cmdObj); + auto requestParser = RequestParser(opCtx, cmdObj); - auto cmdDone = run(opCtx, db, request.toBSON(cmdObj), result); + auto cmdDone = runWithRequestParser(opCtx, db, cmdObj, requestParser, result); validateResult(result.asTempObj()); return cmdDone; } + class RequestParser; + + /** + * Runs the given command. Returns true upon success. + */ + virtual bool runWithRequestParser(OperationContext* opCtx, + const std::string& db, + const BSONObj& cmdObj, + const RequestParser& requestParser, + BSONObjBuilder& result) = 0; + // Custom logic to validate results to enforce API versioning. virtual void validateResult(const BSONObj& resultObj) = 0; }; +template <typename Derived> +class BasicCommandWithRequestParser<Derived>::RequestParser { +public: + using RequestType = typename Derived::Request; + + RequestParser(OperationContext* opCtx, const BSONObj& cmdObj) + : _request{_parseRequest(opCtx, cmdObj)} {} + + const RequestType& request() const { + return _request; + } + +private: + static RequestType _parseRequest(OperationContext* opCtx, const BSONObj& cmdObj) { + return RequestType::parse( + IDLParserErrorContext(RequestType::kCommandName, + APIParameters::get(opCtx).getAPIStrict().value_or(false)), + cmdObj); + } + + RequestType _request; +}; + /** * Deprecated. Do not add new subclasses. */ |