summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmirsaman Memaripour <amirsaman.memaripour@10gen.com>2020-01-23 17:14:41 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-08-27 02:29:50 +0000
commite743135b6c87dc61ea91959633860f867aece528 (patch)
treeadc3d666e7cda38a42814b653912bacbd4ab4a61
parent1e62dde76309c37f8aae937f8782431177b90477 (diff)
downloadmongo-e743135b6c87dc61ea91959633860f867aece528.tar.gz
SERVER-45202 Improve command alias infrastructure
(cherry picked from commit 3cd3a6da3fe0b6f022b721094bda0b97c3527d23)
-rw-r--r--src/mongo/db/commands.cpp17
-rw-r--r--src/mongo/db/commands.h22
-rw-r--r--src/mongo/db/service_entry_point_common.cpp15
3 files changed, 40 insertions, 14 deletions
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp
index b449af1b84a..5ba3eb11db1 100644
--- a/src/mongo/db/commands.cpp
+++ b/src/mongo/db/commands.cpp
@@ -555,11 +555,16 @@ std::unique_ptr<CommandInvocation> BasicCommand::parse(OperationContext* opCtx,
return stdx::make_unique<Invocation>(opCtx, request, this);
}
-Command::Command(StringData name, StringData oldName)
+Command::Command(StringData name, std::vector<StringData> aliases)
: _name(name.toString()),
+ _aliases(std::move(aliases)),
_commandsExecutedMetric("commands." + _name + ".total", &_commandsExecuted),
_commandsFailedMetric("commands." + _name + ".failed", &_commandsFailed) {
- globalCommandRegistry()->registerCommand(this, name, oldName);
+ globalCommandRegistry()->registerCommand(this, _name, _aliases);
+}
+
+bool Command::hasAlias(const StringData& alias) const {
+ return globalCommandRegistry()->findCommand(alias) == this;
}
Status BasicCommand::explain(OperationContext* opCtx,
@@ -610,8 +615,12 @@ bool ErrmsgCommandDeprecated::run(OperationContext* opCtx,
//////////////////////////////////////////////////////////////
// CommandRegistry
-void CommandRegistry::registerCommand(Command* command, StringData name, StringData oldName) {
- for (StringData key : {name, oldName}) {
+void CommandRegistry::registerCommand(Command* command,
+ StringData name,
+ std::vector<StringData> aliases) {
+ aliases.push_back(name);
+
+ for (auto key : aliases) {
if (key.empty()) {
continue;
}
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index 1ecd810911c..bade5650496 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -259,9 +259,15 @@ public:
* Constructs a new command and causes it to be registered with the global commands list. It is
* not safe to construct commands other than when the server is starting up.
*
- * @param oldName an optional old, deprecated name for the command
+ * @param oldName an old, deprecated name for the command
*/
- Command(StringData name, StringData oldName = StringData());
+ Command(StringData name, StringData oldName)
+ : Command(name, std::vector<StringData>({oldName})) {}
+
+ /**
+ * @param aliases the optional list of aliases (e.g., old names) for the command
+ */
+ Command(StringData name, std::vector<StringData> aliases = {});
// Do not remove or relocate the definition of this "key function".
// See https://gcc.gnu.org/wiki/VerboseDiagnostics#missing_vtable
@@ -330,7 +336,7 @@ public:
/**
* Return true if the command requires auth.
- */
+ */
virtual bool requiresAuth() const {
return true;
}
@@ -409,10 +415,18 @@ public:
rpc::ReplyBuilderInterface* replyBuilder,
const Command& command);
+ /**
+ * Checks if the command is also known by the provided alias.
+ */
+ bool hasAlias(const StringData& alias) const;
+
private:
// The full name of the command
const std::string _name;
+ // The list of aliases for the command
+ const std::vector<StringData> _aliases;
+
// Counters for how many times this command has been executed and failed
mutable Counter64 _commandsExecuted;
mutable Counter64 _commandsFailed;
@@ -851,7 +865,7 @@ public:
return _commands;
}
- void registerCommand(Command* command, StringData name, StringData oldName);
+ void registerCommand(Command* command, StringData name, std::vector<StringData> aliases);
Command* findCommand(StringData name) const;
diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp
index a9a4958701d..a50743e0f1d 100644
--- a/src/mongo/db/service_entry_point_common.cpp
+++ b/src/mongo/db/service_entry_point_common.cpp
@@ -131,7 +131,10 @@ const StringMap<int> sessionCheckoutWhitelist = {{"abortTransaction", 1},
{"refreshLogicalSessionCacheNow", 1},
{"update", 1}};
-bool shouldActivateFailCommandFailPoint(const BSONObj& data, StringData cmdName, Client* client) {
+bool shouldActivateFailCommandFailPoint(const BSONObj& data,
+ const CommandInvocation* invocation,
+ Client* client) {
+ auto cmdName = invocation->definition()->getName();
if (cmdName == "configureFailPoint"_sd) // Banned even if in failCommands.
return false;
@@ -569,8 +572,7 @@ bool runCommandImpl(OperationContext* opCtx,
auto waitForWriteConcern = [&](auto&& bb) {
MONGO_FAIL_POINT_BLOCK_IF(failCommand, data, [&](const BSONObj& data) {
- return shouldActivateFailCommandFailPoint(
- data, request.getCommandName(), opCtx->getClient()) &&
+ return shouldActivateFailCommandFailPoint(data, invocation, opCtx->getClient()) &&
data.hasField("writeConcernError");
}) {
bb.append(data.getData()["writeConcernError"]);
@@ -635,12 +637,13 @@ bool runCommandImpl(OperationContext* opCtx,
/**
* Maybe uassert according to the 'failCommand' fail point.
*/
-void evaluateFailCommandFailPoint(OperationContext* opCtx, StringData commandName) {
+void evaluateFailCommandFailPoint(OperationContext* opCtx, const CommandInvocation* invocation) {
MONGO_FAIL_POINT_BLOCK_IF(failCommand, data, [&](const BSONObj& data) {
- return shouldActivateFailCommandFailPoint(data, commandName, opCtx->getClient()) &&
+ return shouldActivateFailCommandFailPoint(data, invocation, opCtx->getClient()) &&
(data.hasField("closeConnection") || data.hasField("errorCode"));
}) {
bool closeConnection;
+ auto commandName = invocation->definition()->getName();
if (bsonExtractBooleanField(data.getData(), "closeConnection", &closeConnection).isOK() &&
closeConnection) {
opCtx->getClient()->session()->end();
@@ -697,7 +700,7 @@ void execCommandDatabase(OperationContext* opCtx,
replCoord->getReplicationMode() == repl::ReplicationCoordinator::modeReplSet,
opCtx->getServiceContext()->getStorageEngine()->supportsDocLocking());
- evaluateFailCommandFailPoint(opCtx, command->getName());
+ evaluateFailCommandFailPoint(opCtx, invocation.get());
const auto dbname = request.getDatabase().toString();
uassert(