summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorPavi Vetriselvan <pavithra.vetriselvan@mongodb.com>2020-10-20 19:32:23 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-03-17 01:12:55 +0000
commit0aa0aad87fdd50f98abe0640385ab5a2bc443928 (patch)
treed55769614ee03a57c13ba5780b20e7763a380080 /src/mongo/db
parent2a1fc45cc1d106be07da66300782420f8011ac1e (diff)
downloadmongo-0aa0aad87fdd50f98abe0640385ab5a2bc443928.tar.gz
SERVER-50412 implement helloOk protocol negotiation on mongod
(cherry picked from commit 1118ad680f76ac29795c8396beb11b0b50322f20) (cherry picked from commit 4dbefcfc9304a9ffa1fec8390dc2bd30e0dc9a54)
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/client.h20
-rw-r--r--src/mongo/db/repl/replication_info.cpp18
-rw-r--r--src/mongo/db/service_entry_point_common.cpp11
3 files changed, 46 insertions, 3 deletions
diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h
index 2c06e0e1453..7d63bb39b9f 100644
--- a/src/mongo/db/client.h
+++ b/src/mongo/db/client.h
@@ -243,6 +243,22 @@ public:
return _killed.loadRelaxed();
}
+ /**
+ * Whether this client supports the hello command, which indicates that the server
+ * can return "not primary" error messages.
+ */
+ bool supportsHello() const {
+ return _supportsHello;
+ }
+
+ /**
+ * Will be set to true if the client sent { helloOk: true } when opening a
+ * connection to the server. Defaults to false.
+ */
+ void setSupportsHello(bool newVal) {
+ _supportsHello = newVal;
+ }
+
private:
friend class ServiceContext;
friend class ThreadClient;
@@ -274,6 +290,10 @@ private:
PseudoRandom _prng;
AtomicWord<bool> _killed{false};
+
+ // Whether this client used { helloOk: true } when opening its connection, indicating that
+ // it supports the hello command.
+ bool _supportsHello = false;
};
/**
diff --git a/src/mongo/db/repl/replication_info.cpp b/src/mongo/db/repl/replication_info.cpp
index 594baf38b59..2446336e382 100644
--- a/src/mongo/db/repl/replication_info.cpp
+++ b/src/mongo/db/repl/replication_info.cpp
@@ -34,6 +34,7 @@
#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"
#include "mongo/db/auth/sasl_mechanism_registry.h"
@@ -370,6 +371,23 @@ public:
appendReplicationInfo(opCtx, result, 0, useLegacyResponseFields());
+ // Try to parse the optional 'helloOk' field. This should be provided on the initial
+ // handshake for an incoming connection if the client supports the hello command. Clients
+ // that specify 'helloOk' do not rely on "not master" error message parsing, which means
+ // that we can safely return "not primary" error messages instead.
+ bool helloOk = opCtx->getClient()->supportsHello();
+ Status status = bsonExtractBooleanField(cmdObj, "helloOk", &helloOk);
+ if (status.isOK()) {
+ // If the hello request contains a "helloOk" field, set _supportsHello on the Client
+ // to the value.
+ opCtx->getClient()->setSupportsHello(helloOk);
+ // Attach helloOk: true to the response so that the client knows the server supports
+ // the hello command.
+ result.append("helloOk", true);
+ } else if (status.code() != ErrorCodes::NoSuchKey) {
+ uassertStatusOK(status);
+ }
+
if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
const int configServerModeNumber = 2;
result.append("configsvr", configServerModeNumber);
diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp
index 9a4b200d37a..e6997ed7877 100644
--- a/src/mongo/db/service_entry_point_common.cpp
+++ b/src/mongo/db/service_entry_point_common.cpp
@@ -775,13 +775,18 @@ void execCommandDatabase(OperationContext* opCtx,
couldHaveOptedIn && ReadPreferenceSetting::get(opCtx).canRunOnSecondary();
bool canRunHere = commandCanRunHere(opCtx, dbname, command, inMultiDocumentTransaction);
if (!canRunHere && couldHaveOptedIn) {
- uasserted(ErrorCodes::NotPrimaryNoSecondaryOk, "not master and slaveOk=false");
+ const auto msg = opCtx->getClient()->supportsHello()
+ ? "not primary and secondaryOk=false"_sd
+ : "not master and slaveOk=false"_sd;
+ uasserted(ErrorCodes::NotPrimaryNoSecondaryOk, msg);
}
if (MONGO_FAIL_POINT(respondWithNotPrimaryInCommandDispatch)) {
uassert(ErrorCodes::NotWritablePrimary, "not primary", canRunHere);
} else {
- uassert(ErrorCodes::NotWritablePrimary, "not master", canRunHere);
+ const auto msg =
+ opCtx->getClient()->supportsHello() ? "not primary"_sd : "not master"_sd;
+ uassert(ErrorCodes::NotWritablePrimary, msg, canRunHere);
}
if (!command->maintenanceOk() &&
@@ -1074,7 +1079,7 @@ DbResponse receivedCommands(OperationContext* opCtx,
notPrimaryUnackWrites.increment();
uasserted(ErrorCodes::NotWritablePrimary,
str::stream()
- << "Not-master error while processing '" << request.getCommandName()
+ << "Not-primary error while processing '" << request.getCommandName()
<< "' operation on '" << request.getDatabase() << "' database via "
<< "fire-and-forget command execution.");
}