summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavi Vetriselvan <pavithra.vetriselvan@mongodb.com>2020-08-04 12:51:12 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-08-05 15:14:07 +0000
commit9e4b6e5c2f9e266ed05ce7c913631f12548e4160 (patch)
tree7f923e673965b6f846f6ecfa26272a8cbad2931a
parentea7de0274b3e5f3e63079f9507498d4a0915106a (diff)
downloadmongo-9e4b6e5c2f9e266ed05ce7c913631f12548e4160.tar.gz
SERVER-50097 isMaster aliases should correctly populate exhaustIsMasterMetrics
-rw-r--r--src/mongo/rpc/op_msg_integration_test.cpp59
-rw-r--r--src/mongo/s/commands/strategy.cpp23
2 files changed, 71 insertions, 11 deletions
diff --git a/src/mongo/rpc/op_msg_integration_test.cpp b/src/mongo/rpc/op_msg_integration_test.cpp
index 1c6400e2cba..0b2b4de6c31 100644
--- a/src/mongo/rpc/op_msg_integration_test.cpp
+++ b/src/mongo/rpc/op_msg_integration_test.cpp
@@ -767,6 +767,65 @@ TEST(OpMsg, ServerStatusCorrectlyShowsExhaustIsMasterMetrics) {
// The exhaust stream would continue indefinitely.
}
+TEST(OpMsg, ServerStatusCorrectlyShowsExhaustIsMasterMetricsWithIsMasterAlias) {
+ std::string errMsg;
+ auto conn = std::unique_ptr<DBClientBase>(
+ unittest::getFixtureConnectionString().connect("integration_test", errMsg));
+ uassert(ErrorCodes::SocketException, errMsg, conn);
+
+ if (conn->isReplicaSetMember()) {
+ // Don't run on replica sets as the RSM will use the streamable isMaster protocol by
+ // default. This can cause inconsistencies in our metrics tests.
+ return;
+ }
+
+ // Wait for stale exhuast streams to finish closing before testing the exhaust isMaster metrics.
+ ASSERT(waitForCondition([&] {
+ auto serverStatusCmd = BSON("serverStatus" << 1);
+ BSONObj serverStatusReply;
+ ASSERT(conn->runCommand("admin", serverStatusCmd, serverStatusReply));
+ return serverStatusReply["connections"]["exhaustIsMaster"].numberInt() == 0;
+ }));
+
+ // Issue an isMaster command with the "ismaster" alias without a topology version.
+ auto lowerCaseIsMasterCmd = BSON("ismaster" << 1);
+ auto opMsgRequest = OpMsgRequest::fromDBAndBody("admin", lowerCaseIsMasterCmd);
+ auto request = opMsgRequest.serialize();
+
+ Message reply;
+ ASSERT(conn->call(request, reply));
+ auto res = OpMsg::parse(reply).body;
+ ASSERT_OK(getStatusFromCommandResult(res));
+ auto topologyVersion = res["topologyVersion"].Obj().getOwned();
+ ASSERT(!OpMsg::isFlagSet(reply, OpMsg::kMoreToCome));
+
+ lowerCaseIsMasterCmd =
+ BSON("ismaster" << 1 << "topologyVersion" << topologyVersion << "maxAwaitTimeMS" << 100);
+ opMsgRequest = OpMsgRequest::fromDBAndBody("admin", lowerCaseIsMasterCmd);
+ request = opMsgRequest.serialize();
+ OpMsg::setFlag(&request, OpMsg::kExhaustSupported);
+
+ // Run the isMaster command with the "ismaster" alias. The aliased command should work
+ // identically to the default "isMaster" command name and initiate the the exhaust stream.
+ ASSERT(conn->call(request, reply));
+ ASSERT(OpMsg::isFlagSet(reply, OpMsg::kMoreToCome));
+ res = OpMsg::parse(reply).body;
+ ASSERT_OK(getStatusFromCommandResult(res));
+
+ // Start a new connection to the server to check the serverStatus metrics.
+ std::string newErrMsg;
+ auto conn2 = std::unique_ptr<DBClientBase>(
+ unittest::getFixtureConnectionString().connect("integration_test", newErrMsg));
+ uassert(ErrorCodes::SocketException, newErrMsg, conn2);
+
+ auto serverStatusCmd = BSON("serverStatus" << 1);
+ BSONObj serverStatusReply;
+ ASSERT(conn2->runCommand("admin", serverStatusCmd, serverStatusReply));
+ ASSERT_EQUALS(1, serverStatusReply["connections"]["exhaustIsMaster"].numberInt());
+
+ // The exhaust stream would continue indefinitely.
+}
+
TEST(OpMsg, ExhaustIsMasterMetricDecrementsOnNewOpAfterTerminatingExhaustStream) {
std::string errMsg;
const auto conn1AppName = "integration_test";
diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp
index 81eee3ef4bc..f90d6d1beb6 100644
--- a/src/mongo/s/commands/strategy.cpp
+++ b/src/mongo/s/commands/strategy.cpp
@@ -296,9 +296,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) {
@@ -311,6 +312,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() != "isMaster"_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
@@ -1023,14 +1032,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 {
@@ -1040,7 +1041,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}",
@@ -1232,7 +1233,7 @@ void Strategy::writeOp(OperationContext* opCtx, DbMessage* dbm) {
MONGO_UNREACHABLE;
}
}(),
- msg.operation(),
+ msg,
&reply,
&errorBuilder); // built objects are ignored
}