diff options
Diffstat (limited to 'src/mongo/s/commands/cluster_is_master_cmd.cpp')
-rw-r--r-- | src/mongo/s/commands/cluster_is_master_cmd.cpp | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/src/mongo/s/commands/cluster_is_master_cmd.cpp b/src/mongo/s/commands/cluster_is_master_cmd.cpp index ccd0d7d00d5..7432b5b6e33 100644 --- a/src/mongo/s/commands/cluster_is_master_cmd.cpp +++ b/src/mongo/s/commands/cluster_is_master_cmd.cpp @@ -60,9 +60,9 @@ MONGO_INITIALIZER(GenerateMongosTopologyVersion)(InitializerContext*) { namespace { -class CmdIsMaster : public BasicCommand { +class CmdIsMaster : public BasicCommandWithReplyBuilderInterface { public: - CmdIsMaster() : BasicCommand("isMaster", "ismaster") {} + CmdIsMaster() : BasicCommandWithReplyBuilderInterface("isMaster", "ismaster") {} bool supportsWriteConcern(const BSONObj& cmd) const override { return false; @@ -86,10 +86,10 @@ public: return false; } - bool run(OperationContext* opCtx, - const std::string& dbname, - const BSONObj& cmdObj, - BSONObjBuilder& result) override { + bool runWithReplyBuilder(OperationContext* opCtx, + const std::string& dbname, + const BSONObj& cmdObj, + rpc::ReplyBuilderInterface* replyBuilder) final { CommandHelpers::handleMarkKillOnClientDisconnect(opCtx); waitInIsMaster.pauseWhileSet(opCtx); @@ -127,12 +127,13 @@ public: // present if and only if topologyVersion is present in the request. auto topologyVersionElement = cmdObj["topologyVersion"]; auto maxAwaitTimeMSField = cmdObj["maxAwaitTimeMS"]; + boost::optional<TopologyVersion> clientTopologyVersion; if (topologyVersionElement && maxAwaitTimeMSField) { - auto clientTopologyVersion = TopologyVersion::parse( - IDLParserErrorContext("TopologyVersion"), topologyVersionElement.Obj()); + clientTopologyVersion = TopologyVersion::parse(IDLParserErrorContext("TopologyVersion"), + topologyVersionElement.Obj()); uassert(51758, "topologyVersion must have a non-negative counter", - clientTopologyVersion.getCounter() >= 0); + clientTopologyVersion->getCounter() >= 0); long long maxAwaitTimeMS; uassertStatusOK(bsonExtractIntegerField(cmdObj, "maxAwaitTimeMS", &maxAwaitTimeMS)); @@ -140,14 +141,14 @@ public: LOG(3) << "Using maxAwaitTimeMS for awaitable isMaster protocol."; - if (clientTopologyVersion.getProcessId() == mongosTopologyVersion.getProcessId()) { + if (clientTopologyVersion->getProcessId() == mongosTopologyVersion.getProcessId()) { uassert(51761, str::stream() << "Received a topology version with counter: " - << clientTopologyVersion.getCounter() + << clientTopologyVersion->getCounter() << " which is greater than the mongos topology version counter: " << mongosTopologyVersion.getCounter(), - clientTopologyVersion.getCounter() == mongosTopologyVersion.getCounter()); + clientTopologyVersion->getCounter() == mongosTopologyVersion.getCounter()); // The topologyVersion never changes on a running mongos process, so just sleep for // maxAwaitTimeMS. @@ -161,6 +162,7 @@ public: !topologyVersionElement && !maxAwaitTimeMSField); } + auto result = replyBuilder->getBodyBuilder(); result.appendBool("ismaster", true); result.append("msg", "isdbgrid"); result.appendNumber("maxBsonObjectSize", BSONObjMaxUserSize); @@ -190,6 +192,34 @@ public: BSONObjBuilder topologyVersionBuilder(result.subobjStart("topologyVersion")); mongosTopologyVersion.serialize(&topologyVersionBuilder); + if (opCtx->isExhaust()) { + LOG(3) << "Using exhaust for isMaster protocol"; + + uassert(51763, + "An isMaster request with exhaust must specify 'maxAwaitTimeMS'", + maxAwaitTimeMSField); + invariant(clientTopologyVersion); + + if (clientTopologyVersion->getProcessId() == mongosTopologyVersion.getProcessId() && + clientTopologyVersion->getCounter() == mongosTopologyVersion.getCounter()) { + // Indicate that an exhaust message should be generated and the previous BSONObj + // command parameters should be reused as the next BSONObj command parameters. + replyBuilder->setNextInvocation(boost::none); + } else { + BSONObjBuilder nextInvocationBuilder; + for (auto&& elt : cmdObj) { + if (elt.fieldNameStringData() == "topologyVersion"_sd) { + BSONObjBuilder topologyVersionBuilder( + nextInvocationBuilder.subobjStart("topologyVersion")); + mongosTopologyVersion.serialize(&topologyVersionBuilder); + } else { + nextInvocationBuilder.append(elt); + } + } + replyBuilder->setNextInvocation(nextInvocationBuilder.obj()); + } + } + return true; } |