summaryrefslogtreecommitdiff
path: root/src/mongo/s/commands/cluster_is_master_cmd.cpp
diff options
context:
space:
mode:
authorTess Avitabile <tess.avitabile@mongodb.com>2020-01-17 15:39:42 +0000
committerevergreen <evergreen@mongodb.com>2020-01-17 15:39:42 +0000
commit5eea91ee17a4e4cbf339768d3494675142a18978 (patch)
tree7b0e2bd1fba18dd4d53d515885b2827c67656b4c /src/mongo/s/commands/cluster_is_master_cmd.cpp
parent82729cb76e65800e9e4eaaeaa0e41d1b5b0e9021 (diff)
downloadmongo-5eea91ee17a4e4cbf339768d3494675142a18978.tar.gz
SERVER-44520 Make mongo's isMaster wait maxAwaitTimeMS
Diffstat (limited to 'src/mongo/s/commands/cluster_is_master_cmd.cpp')
-rw-r--r--src/mongo/s/commands/cluster_is_master_cmd.cpp52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/mongo/s/commands/cluster_is_master_cmd.cpp b/src/mongo/s/commands/cluster_is_master_cmd.cpp
index af00e62bd09..ccd0d7d00d5 100644
--- a/src/mongo/s/commands/cluster_is_master_cmd.cpp
+++ b/src/mongo/s/commands/cluster_is_master_cmd.cpp
@@ -26,9 +26,11 @@
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kCommand
#include "mongo/platform/basic.h"
+#include "mongo/bson/util/bson_extract.h"
#include "mongo/db/auth/sasl_mechanism_registry.h"
#include "mongo/db/client.h"
#include "mongo/db/commands.h"
@@ -38,7 +40,9 @@
#include "mongo/db/wire_version.h"
#include "mongo/rpc/metadata/client_metadata.h"
#include "mongo/rpc/metadata/client_metadata_ismaster.h"
+#include "mongo/rpc/topology_version_gen.h"
#include "mongo/transport/message_compressor_manager.h"
+#include "mongo/util/log.h"
#include "mongo/util/map_util.h"
#include "mongo/util/net/socket_utils.h"
#include "mongo/util/version.h"
@@ -47,6 +51,13 @@ namespace mongo {
MONGO_FAIL_POINT_DEFINE(waitInIsMaster);
+TopologyVersion mongosTopologyVersion;
+
+MONGO_INITIALIZER(GenerateMongosTopologyVersion)(InitializerContext*) {
+ mongosTopologyVersion = TopologyVersion(OID::gen(), 0);
+ return Status::OK();
+}
+
namespace {
class CmdIsMaster : public BasicCommand {
@@ -112,6 +123,44 @@ public:
opCtx->getClient(), std::move(swParseClientMetadata.getValue()));
}
+ // If a client is following the awaitable isMaster protocol, maxAwaitTimeMS should be
+ // present if and only if topologyVersion is present in the request.
+ auto topologyVersionElement = cmdObj["topologyVersion"];
+ auto maxAwaitTimeMSField = cmdObj["maxAwaitTimeMS"];
+ if (topologyVersionElement && maxAwaitTimeMSField) {
+ auto clientTopologyVersion = TopologyVersion::parse(
+ IDLParserErrorContext("TopologyVersion"), topologyVersionElement.Obj());
+ uassert(51758,
+ "topologyVersion must have a non-negative counter",
+ clientTopologyVersion.getCounter() >= 0);
+
+ long long maxAwaitTimeMS;
+ uassertStatusOK(bsonExtractIntegerField(cmdObj, "maxAwaitTimeMS", &maxAwaitTimeMS));
+ uassert(51759, "maxAwaitTimeMS must be a non-negative integer", maxAwaitTimeMS >= 0);
+
+ LOG(3) << "Using maxAwaitTimeMS for awaitable isMaster protocol.";
+
+ if (clientTopologyVersion.getProcessId() == mongosTopologyVersion.getProcessId()) {
+ uassert(51761,
+ str::stream()
+ << "Received a topology version with counter: "
+ << clientTopologyVersion.getCounter()
+ << " which is greater than the mongos topology version counter: "
+ << mongosTopologyVersion.getCounter(),
+ clientTopologyVersion.getCounter() == mongosTopologyVersion.getCounter());
+
+ // The topologyVersion never changes on a running mongos process, so just sleep for
+ // maxAwaitTimeMS.
+ opCtx->sleepFor(Milliseconds(maxAwaitTimeMS));
+ }
+ } else {
+ uassert(51760,
+ (topologyVersionElement
+ ? "A request with a 'topologyVersion' must include 'maxAwaitTimeMS'"
+ : "A request with 'maxAwaitTimeMS' must include a 'topologyVersion'"),
+ !topologyVersionElement && !maxAwaitTimeMSField);
+ }
+
result.appendBool("ismaster", true);
result.append("msg", "isdbgrid");
result.appendNumber("maxBsonObjectSize", BSONObjMaxUserSize);
@@ -138,6 +187,9 @@ public:
auto& saslMechanismRegistry = SASLServerMechanismRegistry::get(opCtx->getServiceContext());
saslMechanismRegistry.advertiseMechanismNamesForUser(opCtx, cmdObj, &result);
+ BSONObjBuilder topologyVersionBuilder(result.subobjStart("topologyVersion"));
+ mongosTopologyVersion.serialize(&topologyVersionBuilder);
+
return true;
}