diff options
author | Pavi Vetriselvan <pavithra.vetriselvan@mongodb.com> | 2020-10-20 19:32:23 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-03-17 01:12:55 +0000 |
commit | 0aa0aad87fdd50f98abe0640385ab5a2bc443928 (patch) | |
tree | d55769614ee03a57c13ba5780b20e7763a380080 /src/mongo/db | |
parent | 2a1fc45cc1d106be07da66300782420f8011ac1e (diff) | |
download | mongo-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.h | 20 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_info.cpp | 18 | ||||
-rw-r--r-- | src/mongo/db/service_entry_point_common.cpp | 11 |
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."); } |