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 | |
parent | f75145df24d968c4c8b659f6528f7e86da02aa46 (diff) | |
download | mongo-4b51940f6e36878261dc18b8867c27f44c4975a9.tar.gz |
SERVER-52547 Avoid reparsing the command object multiple times
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/commands.h | 49 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_abort_transaction_cmd.cpp | 9 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_commit_transaction_cmd.cpp | 14 |
3 files changed, 52 insertions, 20 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. */ diff --git a/src/mongo/s/commands/cluster_abort_transaction_cmd.cpp b/src/mongo/s/commands/cluster_abort_transaction_cmd.cpp index 4ff806bede4..9c381802016 100644 --- a/src/mongo/s/commands/cluster_abort_transaction_cmd.cpp +++ b/src/mongo/s/commands/cluster_abort_transaction_cmd.cpp @@ -114,10 +114,11 @@ public: return Status::OK(); } - bool run(OperationContext* opCtx, - const std::string& dbName, - const BSONObj& cmdObj, - BSONObjBuilder& result) override { + bool runWithRequestParser(OperationContext* opCtx, + const std::string& dbName, + const BSONObj& cmdObj, + const RequestParser& requestParser, + BSONObjBuilder& result) final { auto txnRouter = TransactionRouter::get(opCtx); uassert(ErrorCodes::InvalidOptions, "abortTransaction can only be run within a session", diff --git a/src/mongo/s/commands/cluster_commit_transaction_cmd.cpp b/src/mongo/s/commands/cluster_commit_transaction_cmd.cpp index f393e22bdaf..be834d4f82c 100644 --- a/src/mongo/s/commands/cluster_commit_transaction_cmd.cpp +++ b/src/mongo/s/commands/cluster_commit_transaction_cmd.cpp @@ -97,18 +97,18 @@ public: return Status::OK(); } - bool run(OperationContext* opCtx, - const std::string& dbName, - const BSONObj& cmdObj, - BSONObjBuilder& result) override { + bool runWithRequestParser(OperationContext* opCtx, + const std::string& dbName, + const BSONObj& cmdObj, + const RequestParser& requestParser, + BSONObjBuilder& result) final { auto txnRouter = TransactionRouter::get(opCtx); uassert(ErrorCodes::InvalidOptions, "commitTransaction can only be run within a session", txnRouter); - const auto commitCmd = - CommitTransaction::parse(IDLParserErrorContext("commit cmd"), cmdObj); - auto commitRes = txnRouter.commitTransaction(opCtx, commitCmd.getRecoveryToken()); + auto commitRes = + txnRouter.commitTransaction(opCtx, requestParser.request().getRecoveryToken()); CommandHelpers::filterCommandReplyForPassthrough(commitRes, &result); return true; } |