summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMoustafa Maher <m.maher@10gen.com>2021-01-15 01:52:57 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-01-20 00:16:26 +0000
commit4b51940f6e36878261dc18b8867c27f44c4975a9 (patch)
tree3565b85c42b595567f21303af1ac3658c6fd0d07 /src
parentf75145df24d968c4c8b659f6528f7e86da02aa46 (diff)
downloadmongo-4b51940f6e36878261dc18b8867c27f44c4975a9.tar.gz
SERVER-52547 Avoid reparsing the command object multiple times
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/commands.h49
-rw-r--r--src/mongo/s/commands/cluster_abort_transaction_cmd.cpp9
-rw-r--r--src/mongo/s/commands/cluster_commit_transaction_cmd.cpp14
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;
}