summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavi Vetriselvan <pavithra.vetriselvan@mongodb.com>2020-07-30 12:39:35 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-08-20 11:55:10 +0000
commit694f98a8c171701ebb3af3f2b865e9f963a9983c (patch)
tree0bb9715c78c59442db3e05cd4002839a512ef2fa
parentf63a0a4204266c661e87ce704d91ade9511f1fd5 (diff)
downloadmongo-694f98a8c171701ebb3af3f2b865e9f963a9983c.tar.gz
SERVER-49986 Convert isMaster command to hello and keep isMaster, ismaster aliases
(cherry picked from commit 9a4be902441496be7ef40e5404a91ac30dc81f77)
-rw-r--r--etc/backports_required_for_multiversion_tests.yml16
-rw-r--r--jstests/core/ismaster.js96
-rw-r--r--jstests/core/list_commands.js14
-rw-r--r--jstests/core/views/views_all_commands.js2
-rw-r--r--jstests/replsets/db_reads_while_recovering_all_commands.js2
-rw-r--r--jstests/sharding/database_versioning_all_commands.js2
-rw-r--r--jstests/sharding/ismaster.js94
-rw-r--r--jstests/sharding/read_write_concern_defaults_application.js2
-rw-r--r--jstests/sharding/safe_secondary_reads_drop_recreate.js2
-rw-r--r--jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js2
-rw-r--r--jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js2
-rw-r--r--src/mongo/db/repl/replication_info.cpp15
-rw-r--r--src/mongo/db/service_entry_point_common.cpp5
-rw-r--r--src/mongo/s/commands/cluster_is_master_cmd.cpp15
-rw-r--r--src/mongo/s/commands/strategy.cpp23
15 files changed, 181 insertions, 111 deletions
diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml
index 849eb3d27f9..78eb527faeb 100644
--- a/etc/backports_required_for_multiversion_tests.yml
+++ b/etc/backports_required_for_multiversion_tests.yml
@@ -73,6 +73,22 @@ all:
test_file: jstests/sharding/retryable_writes.js
- ticket: SERVER-31368
test_file: jstests/sharding/log_remote_op_wait.js
+ - ticket: SERVER-49986
+ test_file: jstests/core/ismaster.js
+ - ticket: SERVER-49986
+ test_file: jstests/core/views/views_all_commands.js
+ - ticket: SERVER-49986
+ test_file: jstests/sharding/database_versioning_all_commands.js
+ - ticket: SERVER-49986
+ test_file: jstests/sharding/ismaster.js
+ - ticket: SERVER-49986
+ test_file: jstests/sharding/read_write_concern_defaults_application.js
+ - ticket: SERVER-49986
+ test_file: jstests/sharding/safe_secondary_reads_drop_recreate.js
+ - ticket: SERVER-49986
+ test_file: jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
+ - ticket: SERVER-49986
+ test_file: jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
suites:
diff --git a/jstests/core/ismaster.js b/jstests/core/ismaster.js
index a29be88331c..a8ed96a4ac1 100644
--- a/jstests/core/ismaster.js
+++ b/jstests/core/ismaster.js
@@ -1,45 +1,61 @@
+/**
+ * This test ensures that the hello command and its aliases, ismaster and isMaster, are all
+ * accepted.
+ */
"use strict";
-var res = db.isMaster();
-// check that the fields that should be there are there and have proper values
-assert(res.maxBsonObjectSize && isNumber(res.maxBsonObjectSize) && res.maxBsonObjectSize > 0,
- "maxBsonObjectSize possibly missing:" + tojson(res));
-assert(res.maxMessageSizeBytes && isNumber(res.maxMessageSizeBytes) && res.maxBsonObjectSize > 0,
- "maxMessageSizeBytes possibly missing:" + tojson(res));
-assert(res.maxWriteBatchSize && isNumber(res.maxWriteBatchSize) && res.maxWriteBatchSize > 0,
- "maxWriteBatchSize possibly missing:" + tojson(res));
-assert.eq("boolean", typeof res.ismaster, "ismaster field is not a boolean" + tojson(res));
-assert(res.ismaster === true, "ismaster field is false" + tojson(res));
-assert(res.localTime, "localTime possibly missing:" + tojson(res));
-assert(res.connectionId, "connectionId missing or false" + tojson(res));
-if (!testingReplication) {
- var badFields = [];
- var unwantedReplSetFields = [
- "setName",
- "setVersion",
- "secondary",
- "hosts",
- "passives",
- "arbiters",
- "primary",
- "aribterOnly",
- "passive",
- "slaveDelay",
- "hidden",
- "tags",
- "buildIndexes",
- "me"
- ];
- var field;
- // check that the fields that shouldn't be there are not there
- for (field in res) {
- if (!res.hasOwnProperty(field)) {
- continue;
- }
- if (Array.contains(unwantedReplSetFields, field)) {
- badFields.push(field);
+function checkResponseFields(commandString) {
+ var res = db.runCommand(commandString);
+ // check that the fields that should be there are there and have proper values
+ assert(res.maxBsonObjectSize && isNumber(res.maxBsonObjectSize) && res.maxBsonObjectSize > 0,
+ "maxBsonObjectSize possibly missing:" + tojson(res));
+ assert(
+ res.maxMessageSizeBytes && isNumber(res.maxMessageSizeBytes) && res.maxBsonObjectSize > 0,
+ "maxMessageSizeBytes possibly missing:" + tojson(res));
+ assert(res.maxWriteBatchSize && isNumber(res.maxWriteBatchSize) && res.maxWriteBatchSize > 0,
+ "maxWriteBatchSize possibly missing:" + tojson(res));
+ assert.eq("boolean", typeof res.ismaster, "ismaster field is not a boolean" + tojson(res));
+
+ // TODO SERVER-49988: Check for res.isWritablePrimary instead of res.ismaster if a hello command
+ // was executed.
+ assert(res.ismaster === true, "ismaster field is false" + tojson(res));
+ assert(res.localTime, "localTime possibly missing:" + tojson(res));
+ assert(res.connectionId, "connectionId missing or false" + tojson(res));
+
+ if (!testingReplication) {
+ var badFields = [];
+ var unwantedReplSetFields = [
+ "setName",
+ "setVersion",
+ "secondary",
+ "hosts",
+ "passives",
+ "arbiters",
+ "primary",
+ "aribterOnly",
+ "passive",
+ "slaveDelay",
+ "hidden",
+ "tags",
+ "buildIndexes",
+ "me"
+ ];
+ var field;
+ // check that the fields that shouldn't be there are not there
+ for (field in res) {
+ if (!res.hasOwnProperty(field)) {
+ continue;
+ }
+ if (Array.contains(unwantedReplSetFields, field)) {
+ badFields.push(field);
+ }
}
+ assert(
+ badFields.length === 0,
+ "\nthe result:\n" + tojson(res) + "\ncontained fields it shouldn't have: " + badFields);
}
- assert(badFields.length === 0,
- "\nthe result:\n" + tojson(res) + "\ncontained fields it shouldn't have: " + badFields);
}
+
+checkResponseFields("hello");
+checkResponseFields("ismaster");
+checkResponseFields("isMaster");
diff --git a/jstests/core/list_commands.js b/jstests/core/list_commands.js
index 6e63c179dfb..05c83db2b1f 100644
--- a/jstests/core/list_commands.js
+++ b/jstests/core/list_commands.js
@@ -22,19 +22,19 @@ assert(isSorted(commands));
// Test that result contains basic commands.
assert(commands.hasOwnProperty("commands"));
-assert(commands["commands"].hasOwnProperty("isMaster"));
+assert(commands["commands"].hasOwnProperty("hello"));
assert(commands["commands"].hasOwnProperty("insert"));
assert(commands["commands"].hasOwnProperty("ping"));
// Test that commands listed have required properties
-const isMaster = commands["commands"]["isMaster"];
-assert(isMaster.hasOwnProperty("help"));
-assert(isMaster.hasOwnProperty("slaveOk"));
-assert(isMaster.hasOwnProperty("adminOnly"));
-assert(isMaster.hasOwnProperty("requiresAuth"));
+const hello = commands["commands"]["hello"];
+assert(hello.hasOwnProperty("help"));
+assert(hello.hasOwnProperty("slaveOk"));
+assert(hello.hasOwnProperty("adminOnly"));
+assert(hello.hasOwnProperty("requiresAuth"));
// Test that requiresAuth outputs correct value
const insert = commands["commands"]["insert"];
-assert(isMaster["requiresAuth"] === false);
+assert(hello["requiresAuth"] === false);
assert(insert["requiresAuth"] === true);
})();
diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js
index e559096c280..a329ab9e1a1 100644
--- a/jstests/core/views/views_all_commands.js
+++ b/jstests/core/views/views_all_commands.js
@@ -346,13 +346,13 @@ let viewsCommandTests = {
grantRolesToRole: {skip: isUnrelated},
grantRolesToUser: {skip: isUnrelated},
handshake: {skip: isUnrelated},
+ hello: {skip: isUnrelated},
hostInfo: {skip: isUnrelated},
httpClientRequest: {skip: isAnInternalCommand},
insert: {command: {insert: "view", documents: [{x: 1}]}, expectFailure: true},
internalRenameIfOptionsAndIndexesMatch: {skip: isAnInternalCommand},
invalidateUserCache: {skip: isUnrelated},
isdbgrid: {skip: isUnrelated},
- isMaster: {skip: isUnrelated},
killCursors: {
setup: function(conn) {
assert.commandWorked(conn.collection.remove({}));
diff --git a/jstests/replsets/db_reads_while_recovering_all_commands.js b/jstests/replsets/db_reads_while_recovering_all_commands.js
index b85311a68b5..5486af549a2 100644
--- a/jstests/replsets/db_reads_while_recovering_all_commands.js
+++ b/jstests/replsets/db_reads_while_recovering_all_commands.js
@@ -184,12 +184,12 @@ const allCommands = {
grantPrivilegesToRole: {skip: isPrimaryOnly},
grantRolesToRole: {skip: isPrimaryOnly},
grantRolesToUser: {skip: isPrimaryOnly},
+ hello: {skip: isNotAUserDataRead},
hostInfo: {skip: isNotAUserDataRead},
httpClientRequest: {skip: isNotAUserDataRead},
insert: {skip: isPrimaryOnly},
internalRenameIfOptionsAndIndexesMatch: {skip: isAnInternalCommand},
invalidateUserCache: {skip: isNotAUserDataRead},
- isMaster: {skip: isNotAUserDataRead},
killAllSessions: {skip: isNotAUserDataRead},
killAllSessionsByPattern: {skip: isNotAUserDataRead},
killCursors: {skip: isNotAUserDataRead},
diff --git a/jstests/sharding/database_versioning_all_commands.js b/jstests/sharding/database_versioning_all_commands.js
index 3f385c8c5b3..8ca8f77976c 100644
--- a/jstests/sharding/database_versioning_all_commands.js
+++ b/jstests/sharding/database_versioning_all_commands.js
@@ -452,6 +452,7 @@ let testCases = {
grantPrivilegesToRole: {skip: "always targets the config server"},
grantRolesToRole: {skip: "always targets the config server"},
grantRolesToUser: {skip: "always targets the config server"},
+ hello: {skip: "executes locally on mongos (not sent to any remote node)"},
hostInfo: {skip: "executes locally on mongos (not sent to any remote node)"},
insert: {
run: {
@@ -463,7 +464,6 @@ let testCases = {
},
invalidateUserCache: {skip: "executes locally on mongos (not sent to any remote node)"},
isdbgrid: {skip: "executes locally on mongos (not sent to any remote node)"},
- isMaster: {skip: "executes locally on mongos (not sent to any remote node)"},
killCursors: {skip: "requires a previously established cursor"},
killAllSessions: {skip: "always broadcast to all hosts in the cluster"},
killAllSessionsByPattern: {skip: "always broadcast to all hosts in the cluster"},
diff --git a/jstests/sharding/ismaster.js b/jstests/sharding/ismaster.js
index 2d5cea7b586..a582f677241 100644
--- a/jstests/sharding/ismaster.js
+++ b/jstests/sharding/ismaster.js
@@ -1,42 +1,62 @@
+/**
+ * This test ensures that the hello command and its aliases, ismaster and isMaster, are all
+ * accepted by mongos.
+ */
"use strict";
var st = new ShardingTest({shards: 1, mongos: 1});
-var res = st.s0.getDB("admin").runCommand("ismaster");
-// check that the fields that should be there are there and have proper values
-assert(res.maxBsonObjectSize && isNumber(res.maxBsonObjectSize) && res.maxBsonObjectSize > 0,
- "maxBsonObjectSize possibly missing:" + tojson(res));
-assert(res.maxMessageSizeBytes && isNumber(res.maxMessageSizeBytes) && res.maxBsonObjectSize > 0,
- "maxMessageSizeBytes possibly missing:" + tojson(res));
-assert.eq("boolean", typeof res.ismaster, "ismaster field is not a boolean" + tojson(res));
-assert(res.ismaster === true, "ismaster field is false" + tojson(res));
-assert(res.localTime, "localTime possibly missing:" + tojson(res));
-assert(res.msg && res.msg == "isdbgrid", "msg possibly missing or wrong:" + tojson(res));
-var unwantedFields = [
- "setName",
- "setVersion",
- "secondary",
- "hosts",
- "passives",
- "arbiters",
- "primary",
- "aribterOnly",
- "passive",
- "slaveDelay",
- "hidden",
- "tags",
- "buildIndexes",
- "me"
-];
-// check that the fields that shouldn't be there are not there
-var badFields = [];
-var field;
-for (field in res) {
- if (!res.hasOwnProperty(field)) {
- continue;
- }
- if (Array.contains(unwantedFields, field)) {
- badFields.push(field);
+
+function checkResponseFields(commandString) {
+ jsTestLog("Running the " + commandString + " command");
+ var res = st.s0.getDB("admin").runCommand(commandString);
+
+ // check that the fields that should be there are there and have proper values
+ assert(res.maxBsonObjectSize && isNumber(res.maxBsonObjectSize) && res.maxBsonObjectSize > 0,
+ "maxBsonObjectSize possibly missing:" + tojson(res));
+ assert(
+ res.maxMessageSizeBytes && isNumber(res.maxMessageSizeBytes) && res.maxBsonObjectSize > 0,
+ "maxMessageSizeBytes possibly missing:" + tojson(res));
+
+ // TODO SERVER-49988: Check for res.isWritablePrimary instead of res.ismaster if a hello command
+ // was executed.
+ assert.eq("boolean", typeof res.ismaster, "ismaster field is not a boolean" + tojson(res));
+ assert(res.ismaster === true, "ismaster field is false" + tojson(res));
+
+ assert(res.localTime, "localTime possibly missing:" + tojson(res));
+ assert(res.msg && res.msg == "isdbgrid", "msg possibly missing or wrong:" + tojson(res));
+
+ var unwantedFields = [
+ "setName",
+ "setVersion",
+ "secondary",
+ "hosts",
+ "passives",
+ "arbiters",
+ "primary",
+ "aribterOnly",
+ "passive",
+ "slaveDelay",
+ "hidden",
+ "tags",
+ "buildIndexes",
+ "me"
+ ];
+ // check that the fields that shouldn't be there are not there
+ var badFields = [];
+ var field;
+ for (field in res) {
+ if (!res.hasOwnProperty(field)) {
+ continue;
+ }
+ if (Array.contains(unwantedFields, field)) {
+ badFields.push(field);
+ }
}
+ assert(badFields.length === 0,
+ "\nthe result:\n" + tojson(res) + "\ncontained fields it shouldn't have: " + badFields);
}
-assert(badFields.length === 0,
- "\nthe result:\n" + tojson(res) + "\ncontained fields it shouldn't have: " + badFields);
+
+checkResponseFields("hello");
+checkResponseFields("ismaster");
+checkResponseFields("isMaster");
+
st.stop();
diff --git a/jstests/sharding/read_write_concern_defaults_application.js b/jstests/sharding/read_write_concern_defaults_application.js
index d53cce7a65d..3f4b725572a 100644
--- a/jstests/sharding/read_write_concern_defaults_application.js
+++ b/jstests/sharding/read_write_concern_defaults_application.js
@@ -451,6 +451,7 @@ let testCases = {
useLogs: true,
},
handshake: {skip: "does not accept read or write concern"},
+ hello: {skip: "does not accept read or write concern"},
hostInfo: {skip: "does not accept read or write concern"},
httpClientRequest: {skip: "does not accept read or write concern"},
insert: {
@@ -463,7 +464,6 @@ let testCases = {
},
internalRenameIfOptionsAndIndexesMatch: {skip: "internal command"},
invalidateUserCache: {skip: "does not accept read or write concern"},
- isMaster: {skip: "does not accept read or write concern"},
isdbgrid: {skip: "does not accept read or write concern"},
killAllSessions: {skip: "does not accept read or write concern"},
killAllSessionsByPattern: {skip: "does not accept read or write concern"},
diff --git a/jstests/sharding/safe_secondary_reads_drop_recreate.js b/jstests/sharding/safe_secondary_reads_drop_recreate.js
index 7375971afd1..fc7e0906937 100644
--- a/jstests/sharding/safe_secondary_reads_drop_recreate.js
+++ b/jstests/sharding/safe_secondary_reads_drop_recreate.js
@@ -198,11 +198,11 @@ let testCases = {
grantRolesToRole: {skip: "primary only"},
grantRolesToUser: {skip: "primary only"},
handshake: {skip: "does not return user data"},
+ hello: {skip: "does not return user data"},
hostInfo: {skip: "does not return user data"},
insert: {skip: "primary only"},
invalidateUserCache: {skip: "does not return user data"},
isdbgrid: {skip: "does not return user data"},
- isMaster: {skip: "does not return user data"},
killAllSessions: {skip: "does not return user data"},
killAllSessionsByPattern: {skip: "does not return user data"},
killCursors: {skip: "does not return user data"},
diff --git a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
index 53de9bc7be6..7d192f7b377 100644
--- a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
+++ b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
@@ -232,11 +232,11 @@ let testCases = {
grantRolesToRole: {skip: "primary only"},
grantRolesToUser: {skip: "primary only"},
handshake: {skip: "does not return user data"},
+ hello: {skip: "does not return user data"},
hostInfo: {skip: "does not return user data"},
insert: {skip: "primary only"},
invalidateUserCache: {skip: "does not return user data"},
isdbgrid: {skip: "does not return user data"},
- isMaster: {skip: "does not return user data"},
killCursors: {skip: "does not return user data"},
killAllSessions: {skip: "does not return user data"},
killAllSessionsByPattern: {skip: "does not return user data"},
diff --git a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
index 5d4951c972e..dcf4313395e 100644
--- a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
+++ b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
@@ -203,11 +203,11 @@ let testCases = {
grantRolesToRole: {skip: "primary only"},
grantRolesToUser: {skip: "primary only"},
handshake: {skip: "does not return user data"},
+ hello: {skip: "does not return user data"},
hostInfo: {skip: "does not return user data"},
insert: {skip: "primary only"},
invalidateUserCache: {skip: "does not return user data"},
isdbgrid: {skip: "does not return user data"},
- isMaster: {skip: "does not return user data"},
killAllSessions: {skip: "does not return user data"},
killAllSessionsByPattern: {skip: "does not return user data"},
killCursors: {skip: "does not return user data"},
diff --git a/src/mongo/db/repl/replication_info.cpp b/src/mongo/db/repl/replication_info.cpp
index 617ac34bfc2..8685a30ecb8 100644
--- a/src/mongo/db/repl/replication_info.cpp
+++ b/src/mongo/db/repl/replication_info.cpp
@@ -33,6 +33,7 @@
#include <list>
#include <vector>
+#include "mongo/base/string_data.h"
#include "mongo/bson/util/bson_extract.h"
#include "mongo/client/connpool.h"
#include "mongo/client/dbclient_connection.h"
@@ -81,6 +82,12 @@ using std::unique_ptr;
namespace repl {
namespace {
+
+constexpr auto kHelloString = "hello"_sd;
+// Aliases for the hello command in order to provide backwards compatibility.
+constexpr auto kCamelCaseIsMasterString = "isMaster"_sd;
+constexpr auto kLowerCaseIsMasterString = "ismaster"_sd;
+
/**
* Appends replication-related fields to the isMaster response. Returns the topology version that
* was included in the response.
@@ -292,9 +299,11 @@ public:
}
} oplogInfoServerStatus;
-class CmdIsMaster final : public BasicCommandWithReplyBuilderInterface {
+class CmdHello final : public BasicCommandWithReplyBuilderInterface {
public:
- CmdIsMaster() : BasicCommandWithReplyBuilderInterface("isMaster", "ismaster") {}
+ CmdHello()
+ : BasicCommandWithReplyBuilderInterface(
+ kHelloString, {kCamelCaseIsMasterString, kLowerCaseIsMasterString}) {}
bool requiresAuth() const final {
return false;
@@ -552,7 +561,7 @@ public:
return true;
}
-} cmdismaster;
+} cmdhello;
OpCounterServerStatusSection replOpCounterServerStatusSection("opcountersRepl", &replOpCounters);
diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp
index 1a4c7fdf239..b14d1c88f38 100644
--- a/src/mongo/db/service_entry_point_common.cpp
+++ b/src/mongo/db/service_entry_point_common.cpp
@@ -1379,7 +1379,7 @@ DbResponse receivedCommands(OperationContext* opCtx,
const auto session = opCtx->getClient()->session();
if (session) {
- if (!opCtx->isExhaust() || c->getName() != "isMaster"_sd) {
+ if (!opCtx->isExhaust() || c->getName() != "hello"_sd) {
InExhaustIsMaster::get(session.get())->setInExhaustIsMaster(false);
}
}
@@ -1716,8 +1716,7 @@ DbResponse ServiceEntryPointCommon::handleRequest(OperationContext* opCtx,
if (op == dbMsg || (op == dbQuery && isCommand)) {
dbresponse = receivedCommands(opCtx, m, behaviors);
// IsMaster should take kMaxAwaitTimeMs at most, log if it takes twice that.
- if (auto command = currentOp.getCommand();
- command && (command->getName() == "ismaster" || command->getName() == "isMaster")) {
+ if (auto command = currentOp.getCommand(); command && (command->getName() == "hello")) {
slowMsOverride =
2 * durationCount<Milliseconds>(SingleServerIsMasterMonitor::kMaxAwaitTime);
}
diff --git a/src/mongo/s/commands/cluster_is_master_cmd.cpp b/src/mongo/s/commands/cluster_is_master_cmd.cpp
index a71c0c28ef2..bb0fb7fec3b 100644
--- a/src/mongo/s/commands/cluster_is_master_cmd.cpp
+++ b/src/mongo/s/commands/cluster_is_master_cmd.cpp
@@ -30,6 +30,7 @@
#include "mongo/platform/basic.h"
+#include "mongo/base/string_data.h"
#include "mongo/bson/util/bson_extract.h"
#include "mongo/db/auth/sasl_mechanism_registry.h"
#include "mongo/db/client.h"
@@ -66,9 +67,17 @@ MONGO_INITIALIZER(GenerateMongosTopologyVersion)(InitializerContext*) {
namespace {
-class CmdIsMaster : public BasicCommandWithReplyBuilderInterface {
+constexpr auto kHelloString = "hello"_sd;
+// Aliases for the hello command in order to provide backwards compatibility.
+constexpr auto kCamelCaseIsMasterString = "isMaster"_sd;
+constexpr auto kLowerCaseIsMasterString = "ismaster"_sd;
+
+
+class CmdHello : public BasicCommandWithReplyBuilderInterface {
public:
- CmdIsMaster() : BasicCommandWithReplyBuilderInterface("isMaster", "ismaster") {}
+ CmdHello()
+ : BasicCommandWithReplyBuilderInterface(
+ kHelloString, {kCamelCaseIsMasterString, kLowerCaseIsMasterString}) {}
bool supportsWriteConcern(const BSONObj& cmd) const override {
return false;
@@ -245,7 +254,7 @@ public:
return true;
}
-} isMaster;
+} hello;
} // namespace
} // namespace mongo
diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp
index 7d4e5912fa3..b08550220d6 100644
--- a/src/mongo/s/commands/strategy.cpp
+++ b/src/mongo/s/commands/strategy.cpp
@@ -354,9 +354,10 @@ MONGO_FAIL_POINT_DEFINE(doNotRefreshShardsOnRetargettingError);
*/
void runCommand(OperationContext* opCtx,
const OpMsgRequest& request,
- const NetworkOp opType,
+ const Message& m,
rpc::ReplyBuilderInterface* replyBuilder,
BSONObjBuilder* errorBuilder) {
+ auto const opType = m.operation();
auto const commandName = request.getCommandName();
auto const command = CommandHelpers::findCommand(commandName);
if (!command) {
@@ -369,6 +370,14 @@ void runCommand(OperationContext* opCtx,
return;
}
+ opCtx->setExhaust(OpMsg::isFlagSet(m, OpMsg::kExhaustSupported));
+ const auto session = opCtx->getClient()->session();
+ if (session) {
+ if (!opCtx->isExhaust() || command->getName() != "hello"_sd) {
+ InExhaustIsMaster::get(session.get())->setInExhaustIsMaster(false);
+ }
+ }
+
CommandHelpers::uassertShouldAttemptParse(opCtx, command, request);
// Parse the 'maxTimeMS' command option, and use it to set a deadline for the operation on
@@ -1038,14 +1047,6 @@ DbResponse Strategy::clientCommand(OperationContext* opCtx, const Message& m) {
}
}();
- opCtx->setExhaust(OpMsg::isFlagSet(m, OpMsg::kExhaustSupported));
- const auto session = opCtx->getClient()->session();
- if (session) {
- if (!opCtx->isExhaust() || request.getCommandName() != "isMaster"_sd) {
- InExhaustIsMaster::get(session.get())->setInExhaustIsMaster(false);
- }
- }
-
// Execute.
std::string db = request.getDatabase().toString();
try {
@@ -1055,7 +1056,7 @@ DbResponse Strategy::clientCommand(OperationContext* opCtx, const Message& m) {
"Command begin",
"db"_attr = db,
"headerId"_attr = m.header().getId());
- runCommand(opCtx, request, m.operation(), reply.get(), &errorBuilder);
+ runCommand(opCtx, request, m, reply.get(), &errorBuilder);
LOGV2_DEBUG(22771,
3,
"Command end db: {db} msg id: {headerId}",
@@ -1273,7 +1274,7 @@ void Strategy::writeOp(OperationContext* opCtx, DbMessage* dbm) {
MONGO_UNREACHABLE;
}
}(),
- msg.operation(),
+ msg,
&reply,
&errorBuilder); // built objects are ignored
}