diff options
31 files changed, 130 insertions, 116 deletions
diff --git a/src/mongo/client/dbclient.cpp b/src/mongo/client/dbclient.cpp index 78c052b01f2..7b252bde560 100644 --- a/src/mongo/client/dbclient.cpp +++ b/src/mongo/client/dbclient.cpp @@ -185,8 +185,8 @@ rpc::UniqueReply DBClientWithCommands::runCommandWithMetadata(StringData databas metadataBob.appendElements(metadata); if (_metadataWriter) { - uassertStatusOK( - _metadataWriter((haveClient() ? cc().getOperationContext() : nullptr), &metadataBob)); + uassertStatusOK(_metadataWriter( + (haveClient() ? cc().getOperationContext() : nullptr), &metadataBob, host)); } auto requestBuilder = rpc::makeRequestBuilder(getClientRPCProtocols(), getServerRPCProtocols()); @@ -223,16 +223,16 @@ rpc::UniqueReply DBClientWithCommands::runCommandWithMetadata(StringData databas << "' ", requestBuilder->getProtocol() == commandReply->getProtocol()); - if (_metadataReader) { - uassertStatusOK(_metadataReader(commandReply->getMetadata(), host)); - } - if (ErrorCodes::SendStaleConfig == getStatusFromCommandResult(commandReply->getCommandReply())) { throw RecvStaleConfigException("stale config in runCommand", commandReply->getCommandReply()); } + if (_metadataReader) { + uassertStatusOK(_metadataReader(commandReply->getMetadata(), host)); + } + return rpc::UniqueReply(std::move(replyMsg), std::move(commandReply)); } diff --git a/src/mongo/client/dbclientcursor.cpp b/src/mongo/client/dbclientcursor.cpp index 7a41a85765f..74bd272d147 100644 --- a/src/mongo/client/dbclientcursor.cpp +++ b/src/mongo/client/dbclientcursor.cpp @@ -81,8 +81,10 @@ Message assembleCommandRequest(DBClientWithCommands* cli, BSONObjBuilder metadataBob; metadataBob.appendElements(upconvertedMetadata); if (cli->getRequestMetadataWriter()) { - uassertStatusOK(cli->getRequestMetadataWriter()( - (haveClient() ? cc().getOperationContext() : nullptr), &metadataBob)); + uassertStatusOK( + cli->getRequestMetadataWriter()((haveClient() ? cc().getOperationContext() : nullptr), + &metadataBob, + cli->getServerAddress())); } requestBuilder->setDatabase(database); diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp index d7b8816891f..25e9590a6d9 100644 --- a/src/mongo/db/commands/mr.cpp +++ b/src/mongo/db/commands/mr.cpp @@ -1746,6 +1746,8 @@ public: if (shouldBypassDocumentValidationForCommand(cmdObj)) maybeDisableValidation.emplace(opCtx); + ShardedConnectionInfo::addHook(); + // legacy name const auto shardedOutputCollectionElt = cmdObj["shardedOutputCollection"]; uassert(ErrorCodes::InvalidNamespace, diff --git a/src/mongo/db/logical_time_metadata_hook.cpp b/src/mongo/db/logical_time_metadata_hook.cpp index f45e4fba9db..70acba1de5c 100644 --- a/src/mongo/db/logical_time_metadata_hook.cpp +++ b/src/mongo/db/logical_time_metadata_hook.cpp @@ -41,18 +41,20 @@ namespace rpc { LogicalTimeMetadataHook::LogicalTimeMetadataHook(ServiceContext* service) : _service(service) {} Status LogicalTimeMetadataHook::writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& requestDestination, BSONObjBuilder* metadataBob) { LogicalTimeMetadata metadata(LogicalClock::get(_service)->getClusterTime()); metadata.writeToMetadata(metadataBob); return Status::OK(); } -Status LogicalTimeMetadataHook::readReplyMetadata(StringData replySource, +Status LogicalTimeMetadataHook::readReplyMetadata(const HostAndPort& replySource, const BSONObj& metadataObj) { auto parseStatus = LogicalTimeMetadata::readFromMetadata(metadataObj); if (!parseStatus.isOK()) { return parseStatus.getStatus(); } + auto& signedTime = parseStatus.getValue().getSignedTime(); return LogicalClock::get(_service)->advanceClusterTimeFromTrustedSource(signedTime); } diff --git a/src/mongo/db/logical_time_metadata_hook.h b/src/mongo/db/logical_time_metadata_hook.h index 9ca9b0a4625..3fbd2260dd1 100644 --- a/src/mongo/db/logical_time_metadata_hook.h +++ b/src/mongo/db/logical_time_metadata_hook.h @@ -48,9 +48,11 @@ class LogicalTimeMetadataHook : public EgressMetadataHook { public: explicit LogicalTimeMetadataHook(ServiceContext* service); - Status writeRequestMetadata(OperationContext* opCtx, BSONObjBuilder* metadataBob) override; + Status writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& requestDestination, + BSONObjBuilder* metadataBob) override; - Status readReplyMetadata(StringData replySource, const BSONObj& metadataObj) override; + Status readReplyMetadata(const HostAndPort& replySource, const BSONObj& metadataObj) override; private: ServiceContext* _service; diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp index c1d6dc743ac..b976e25f865 100644 --- a/src/mongo/db/pipeline/pipeline_d.cpp +++ b/src/mongo/db/pipeline/pipeline_d.cpp @@ -355,6 +355,13 @@ void PipelineD::prepareCursorSource(Collection* collection, if (!sources.empty()) { if (sources.front()->isValidInitialSource()) { + if (dynamic_cast<DocumentSourceMergeCursors*>(sources.front().get())) { + // Enable the hooks for setting up authentication on the subsequent internal + // connections we are going to create. This would normally have been done + // when SetShardVersion was called, but since SetShardVersion is never called + // on secondaries, this is needed. + ShardedConnectionInfo::addHook(); + } return; // don't need a cursor } diff --git a/src/mongo/db/s/migration_destination_manager.cpp b/src/mongo/db/s/migration_destination_manager.cpp index 8239842289f..470afdd6d02 100644 --- a/src/mongo/db/s/migration_destination_manager.cpp +++ b/src/mongo/db/s/migration_destination_manager.cpp @@ -390,6 +390,7 @@ void MigrationDestinationManager::_migrateThread(BSONObj min, auto opCtx = getGlobalServiceContext()->makeOperationContext(&cc()); if (getGlobalAuthorizationManager()->isAuthEnabled()) { + ShardedConnectionInfo::addHook(); AuthorizationSession::get(opCtx->getClient())->grantInternalAuthorization(); } diff --git a/src/mongo/db/s/sharded_connection_info.cpp b/src/mongo/db/s/sharded_connection_info.cpp index fea550317aa..336cb68c1ea 100644 --- a/src/mongo/db/s/sharded_connection_info.cpp +++ b/src/mongo/db/s/sharded_connection_info.cpp @@ -37,12 +37,9 @@ #include "mongo/client/global_conn_pool.h" #include "mongo/db/client.h" -#include "mongo/db/logical_time_metadata_hook.h" #include "mongo/db/operation_context.h" #include "mongo/db/s/sharding_egress_metadata_hook_for_mongod.h" -#include "mongo/db/service_context.h" #include "mongo/platform/atomic_word.h" -#include "mongo/rpc/metadata/egress_metadata_hook_list.h" #include "mongo/s/chunk_version.h" #include "mongo/s/client/shard_connection.h" #include "mongo/s/client/sharding_connection_hook.h" @@ -94,7 +91,7 @@ void ShardedConnectionInfo::setVersion(const std::string& ns, const ChunkVersion _versions[ns] = version; } -void ShardedConnectionInfo::addHook(ServiceContext* service) { +void ShardedConnectionInfo::addHook() { if (alreadyAddedHook.loadRelaxed()) { return; } @@ -107,17 +104,11 @@ void ShardedConnectionInfo::addHook(ServiceContext* service) { log() << "first cluster operation detected, adding sharding hook to enable versioning " "and authentication to remote servers"; - auto unshardedHookList = stdx::make_unique<rpc::EgressMetadataHookList>(); - unshardedHookList->addHook(stdx::make_unique<rpc::LogicalTimeMetadataHook>(service)); - unshardedHookList->addHook(stdx::make_unique<rpc::ShardingEgressMetadataHookForMongod>(false)); + globalConnPool.addHook(new ShardingConnectionHook( + false, stdx::make_unique<rpc::ShardingEgressMetadataHookForMongod>())); - globalConnPool.addHook(new ShardingConnectionHook(false, std::move(unshardedHookList))); - - auto shardedHookList = stdx::make_unique<rpc::EgressMetadataHookList>(); - shardedHookList->addHook(stdx::make_unique<rpc::LogicalTimeMetadataHook>(service)); - shardedHookList->addHook(stdx::make_unique<rpc::ShardingEgressMetadataHookForMongod>(true)); - - shardConnectionPool.addHook(new ShardingConnectionHook(true, std::move(shardedHookList))); + shardConnectionPool.addHook(new ShardingConnectionHook( + true, stdx::make_unique<rpc::ShardingEgressMetadataHookForMongod>())); alreadyAddedHook.store(1); } diff --git a/src/mongo/db/s/sharded_connection_info.h b/src/mongo/db/s/sharded_connection_info.h index 9efc734fe2c..4cfae41c263 100644 --- a/src/mongo/db/s/sharded_connection_info.h +++ b/src/mongo/db/s/sharded_connection_info.h @@ -37,7 +37,6 @@ namespace mongo { struct ChunkVersion; class Client; -class ServiceContext; /** * There is one instance of these per each connection from mongos. Holds version state for each @@ -64,7 +63,7 @@ public: void setVersion(const std::string& ns, const ChunkVersion& version); static void reset(Client* client); - static void addHook(ServiceContext* service); + static void addHook(); private: typedef std::map<std::string, ChunkVersion> NSVersionMap; diff --git a/src/mongo/db/s/sharding_egress_metadata_hook_for_mongod.cpp b/src/mongo/db/s/sharding_egress_metadata_hook_for_mongod.cpp index 24295466ed9..99603ce0ed4 100644 --- a/src/mongo/db/s/sharding_egress_metadata_hook_for_mongod.cpp +++ b/src/mongo/db/s/sharding_egress_metadata_hook_for_mongod.cpp @@ -40,9 +40,6 @@ namespace mongo { namespace rpc { -ShardingEgressMetadataHookForMongod::ShardingEgressMetadataHookForMongod(bool shardedConnection) - : ShardingEgressMetadataHook(shardedConnection) {} - void ShardingEgressMetadataHookForMongod::_saveGLEStats(const BSONObj& metadata, StringData hostString) {} diff --git a/src/mongo/db/s/sharding_egress_metadata_hook_for_mongod.h b/src/mongo/db/s/sharding_egress_metadata_hook_for_mongod.h index 3c07f847f72..f9032ef6945 100644 --- a/src/mongo/db/s/sharding_egress_metadata_hook_for_mongod.h +++ b/src/mongo/db/s/sharding_egress_metadata_hook_for_mongod.h @@ -34,9 +34,6 @@ namespace mongo { namespace rpc { class ShardingEgressMetadataHookForMongod final : public ShardingEgressMetadataHook { -public: - ShardingEgressMetadataHookForMongod(bool shardedConnection); - private: void _saveGLEStats(const BSONObj& metadata, StringData hostString) override; diff --git a/src/mongo/db/s/sharding_initialization_mongod.cpp b/src/mongo/db/s/sharding_initialization_mongod.cpp index 2e536dbbb0b..b329a325423 100644 --- a/src/mongo/db/s/sharding_initialization_mongod.cpp +++ b/src/mongo/db/s/sharding_initialization_mongod.cpp @@ -92,7 +92,7 @@ Status initializeGlobalShardingStateForMongod(OperationContext* opCtx, auto hookList = stdx::make_unique<rpc::EgressMetadataHookList>(); hookList->addHook( stdx::make_unique<rpc::LogicalTimeMetadataHook>(opCtx->getServiceContext())); - hookList->addHook(stdx::make_unique<rpc::ShardingEgressMetadataHookForMongod>(false)); + hookList->addHook(stdx::make_unique<rpc::ShardingEgressMetadataHookForMongod>()); return hookList; }, [](ShardingCatalogClient* catalogClient, std::unique_ptr<executor::TaskExecutor> executor) diff --git a/src/mongo/db/s/sharding_state.cpp b/src/mongo/db/s/sharding_state.cpp index 5bbb6d9c925..567877c216a 100644 --- a/src/mongo/db/s/sharding_state.cpp +++ b/src/mongo/db/s/sharding_state.cpp @@ -357,7 +357,7 @@ Status ShardingState::initializeFromShardIdentity(OperationContext* opCtx, << causedBy(_initializationStatus)}; } - ShardedConnectionInfo::addHook(opCtx->getServiceContext()); + ShardedConnectionInfo::addHook(); try { Status status = _globalInit(opCtx, configSvrConnStr, generateDistLockProcessId(opCtx)); diff --git a/src/mongo/executor/network_interface_asio.cpp b/src/mongo/executor/network_interface_asio.cpp index d60bc787731..8fb4733bbb6 100644 --- a/src/mongo/executor/network_interface_asio.cpp +++ b/src/mongo/executor/network_interface_asio.cpp @@ -233,6 +233,7 @@ Status attachMetadataIfNeeded(RemoteCommandRequest& request, auto writeStatus = callNoexcept(*metadataHook, &rpc::EgressMetadataHook::writeRequestMetadata, request.opCtx, + request.target, &augmentedBob); if (!writeStatus.isOK()) { return writeStatus; diff --git a/src/mongo/executor/network_interface_asio_command.cpp b/src/mongo/executor/network_interface_asio_command.cpp index 9498c292b22..c72a7b74505 100644 --- a/src/mongo/executor/network_interface_asio_command.cpp +++ b/src/mongo/executor/network_interface_asio_command.cpp @@ -159,10 +159,8 @@ ResponseStatus decodeRPC(Message* received, // Handle incoming reply metadata. if (metadataHook) { - auto listenStatus = callNoexcept(*metadataHook, - &rpc::EgressMetadataHook::readReplyMetadata, - source.toString(), - replyMetadata); + auto listenStatus = callNoexcept( + *metadataHook, &rpc::EgressMetadataHook::readReplyMetadata, source, replyMetadata); if (!listenStatus.isOK()) { return {listenStatus, elapsed}; } diff --git a/src/mongo/executor/network_interface_asio_test.cpp b/src/mongo/executor/network_interface_asio_test.cpp index 1f14d4063f5..f7e6d4a091e 100644 --- a/src/mongo/executor/network_interface_asio_test.cpp +++ b/src/mongo/executor/network_interface_asio_test.cpp @@ -988,13 +988,15 @@ public: TestMetadataHook(bool* wroteRequestMetadata, bool* gotReplyMetadata) : _wroteRequestMetadata(wroteRequestMetadata), _gotReplyMetadata(gotReplyMetadata) {} - Status writeRequestMetadata(OperationContext* opCtx, BSONObjBuilder* metadataBob) override { + Status writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& requestDestination, + BSONObjBuilder* metadataBob) override { metadataBob->append("foo", "bar"); *_wroteRequestMetadata = true; return Status::OK(); } - Status readReplyMetadata(StringData replySource, const BSONObj& metadataObj) override { + Status readReplyMetadata(const HostAndPort& replySource, const BSONObj& metadataObj) override { *_gotReplyMetadata = (metadataObj["baz"].str() == "garply"); return Status::OK(); } diff --git a/src/mongo/executor/network_interface_mock.cpp b/src/mongo/executor/network_interface_mock.cpp index 81198e74ee2..8a0c44d90fc 100644 --- a/src/mongo/executor/network_interface_mock.cpp +++ b/src/mongo/executor/network_interface_mock.cpp @@ -302,7 +302,7 @@ void NetworkInterfaceMock::scheduleResponse(NetworkOperationIterator noi, // If no RemoteCommandResponse was returned (for example, on a simulated network error), then // do not attempt to run the metadata hook, since there is no returned metadata. if (_metadataHook && response.isOK()) { - _metadataHook->readReplyMetadata(noi->getRequest().target.toString(), response.metadata); + _metadataHook->readReplyMetadata(noi->getRequest().target, response.metadata); } noi->setResponse(when, response); diff --git a/src/mongo/rpc/metadata.h b/src/mongo/rpc/metadata.h index 42c10bb3d24..d8956de30f7 100644 --- a/src/mongo/rpc/metadata.h +++ b/src/mongo/rpc/metadata.h @@ -104,11 +104,11 @@ StatusWith<BSONObj> downconvertReplyMetadata(const BSONObj& commandReply, /** * A function type for writing request metadata. The function takes a pointer to an optional * OperationContext so metadata associated with a Client can be appended, a pointer to a - * BSONObjBuilder used to construct the metadata object and returns a Status indicating if the - * metadata was written successfully. + * BSONObjBuilder used to construct the metadata object and the server address of the target of the + * request and returns a Status indicating if the metadata was written successfully. */ using RequestMetadataWriter = - stdx::function<Status(OperationContext* opCtx, BSONObjBuilder* metadataBuilder)>; + stdx::function<Status(OperationContext*, BSONObjBuilder*, StringData)>; /** * A function type for reading reply metadata. The function takes a a reference to a @@ -118,8 +118,7 @@ using RequestMetadataWriter = * * TODO: would it be a layering violation if this hook took an OperationContext* ? */ -using ReplyMetadataReader = - stdx::function<Status(const BSONObj& replyMetadata, StringData sourceHost)>; +using ReplyMetadataReader = stdx::function<Status(const BSONObj&, StringData)>; } // namespace rpc } // namespace mongo diff --git a/src/mongo/rpc/metadata/egress_metadata_hook_list.cpp b/src/mongo/rpc/metadata/egress_metadata_hook_list.cpp index 2c2ae6d3349..5e11c84eb60 100644 --- a/src/mongo/rpc/metadata/egress_metadata_hook_list.cpp +++ b/src/mongo/rpc/metadata/egress_metadata_hook_list.cpp @@ -41,9 +41,10 @@ void EgressMetadataHookList::addHook(std::unique_ptr<EgressMetadataHook>&& newHo } Status EgressMetadataHookList::writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& requestDestination, BSONObjBuilder* metadataBob) { for (auto&& hook : _hooks) { - auto status = hook->writeRequestMetadata(opCtx, metadataBob); + auto status = hook->writeRequestMetadata(opCtx, requestDestination, metadataBob); if (!status.isOK()) { return status; } @@ -52,7 +53,7 @@ Status EgressMetadataHookList::writeRequestMetadata(OperationContext* opCtx, return Status::OK(); } -Status EgressMetadataHookList::readReplyMetadata(StringData replySource, +Status EgressMetadataHookList::readReplyMetadata(const HostAndPort& replySource, const BSONObj& metadataObj) { for (auto&& hook : _hooks) { auto status = hook->readReplyMetadata(replySource, metadataObj); diff --git a/src/mongo/rpc/metadata/egress_metadata_hook_list.h b/src/mongo/rpc/metadata/egress_metadata_hook_list.h index 64087bc0e25..54b03b80c5e 100644 --- a/src/mongo/rpc/metadata/egress_metadata_hook_list.h +++ b/src/mongo/rpc/metadata/egress_metadata_hook_list.h @@ -58,14 +58,16 @@ public: * early if one of hooks returned a non OK status and return it. Note that metadataBob should * not be used if Status is not OK as the contents can be partial. */ - Status writeRequestMetadata(OperationContext* opCtx, BSONObjBuilder* metadataBob) override; + Status writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& requestDestination, + BSONObjBuilder* metadataBob) override; /** * Calls readReplyMetadata on every hook in the order they were added. This will terminate * early if one of hooks returned a non OK status and return it. Note that metadataBob should * not be used if Status is not OK as the contents can be partial. */ - Status readReplyMetadata(StringData replySource, const BSONObj& metadataObj) override; + Status readReplyMetadata(const HostAndPort& replySource, const BSONObj& metadataObj) override; private: std::vector<std::unique_ptr<EgressMetadataHook>> _hooks; diff --git a/src/mongo/rpc/metadata/egress_metadata_hook_list_test.cpp b/src/mongo/rpc/metadata/egress_metadata_hook_list_test.cpp index 63293347428..159a78412fb 100644 --- a/src/mongo/rpc/metadata/egress_metadata_hook_list_test.cpp +++ b/src/mongo/rpc/metadata/egress_metadata_hook_list_test.cpp @@ -43,7 +43,7 @@ namespace { struct ReadReplyArgs { public: - StringData replySource; + HostAndPort replySource; BSONObj metadataObj; }; @@ -51,12 +51,14 @@ class TestHook : public EgressMetadataHook { public: TestHook(string fieldName, ReadReplyArgs* arg) : _fieldName(fieldName), _arg(arg) {} - Status writeRequestMetadata(OperationContext* opCtx, BSONObjBuilder* metadataBob) override { - metadataBob->append(_fieldName, ""); + Status writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& requestDestination, + BSONObjBuilder* metadataBob) override { + metadataBob->append(_fieldName, requestDestination.toString()); return Status::OK(); } - Status readReplyMetadata(StringData replySource, const BSONObj& metadataObj) { + Status readReplyMetadata(const HostAndPort& replySource, const BSONObj& metadataObj) { invariant(_arg != nullptr); _arg->replySource = replySource; _arg->metadataObj = metadataObj; @@ -72,11 +74,13 @@ class FixedStatusTestHook : public EgressMetadataHook { public: FixedStatusTestHook(Status status) : _toRet(status) {} - Status writeRequestMetadata(OperationContext* opCtx, BSONObjBuilder* metadataBob) override { + Status writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& requestDestination, + BSONObjBuilder* metadataBob) override { return _toRet; } - Status readReplyMetadata(StringData replySource, const BSONObj& metadataObj) { + Status readReplyMetadata(const HostAndPort& replySource, const BSONObj& metadataObj) { return _toRet; } @@ -86,10 +90,11 @@ private: TEST(EgressMetadataHookListTest, EmptyHookShouldNotFail) { EgressMetadataHookList hookList; - ASSERT_OK(hookList.writeRequestMetadata(nullptr, nullptr)); + HostAndPort emptyHost; + ASSERT_OK(hookList.writeRequestMetadata(nullptr, emptyHost, nullptr)); BSONObj emptyObj; - ASSERT_OK(hookList.readReplyMetadata("", emptyObj)); + ASSERT_OK(hookList.readReplyMetadata(emptyHost, emptyObj)); } TEST(EgressMetadataHookListTest, SingleHook) { @@ -99,12 +104,12 @@ TEST(EgressMetadataHookListTest, SingleHook) { hookList.addHook(std::move(hook1)); BSONObjBuilder builder; - ASSERT_OK(hookList.writeRequestMetadata(nullptr, &builder)); + ASSERT_OK(hookList.writeRequestMetadata(nullptr, HostAndPort("a:123"), &builder)); ASSERT_BSONOBJ_EQ(BSON("h1" - << ""), + << "a:123"), builder.obj()); - string testHost("b:456"); + HostAndPort testHost("b:456"); BSONObj testObj(BSON("x" << 1)); ASSERT_OK(hookList.readReplyMetadata(testHost, testObj)); ASSERT_EQ(testHost, hook1Args.replySource); @@ -122,14 +127,14 @@ TEST(EgressMetadataHookListTest, MultipleHooks) { hookList.addHook(std::move(hook2)); BSONObjBuilder builder; - ASSERT_OK(hookList.writeRequestMetadata(nullptr, &builder)); + ASSERT_OK(hookList.writeRequestMetadata(nullptr, HostAndPort("a:123"), &builder)); ASSERT_BSONOBJ_EQ(BSON("foo" - << "" + << "a:123" << "bar" - << ""), + << "a:123"), builder.obj()); - string testHost("b:456"); + HostAndPort testHost("b:456"); BSONObj testObj(BSON("x" << 1)); ASSERT_OK(hookList.readReplyMetadata(testHost, testObj)); @@ -151,8 +156,8 @@ TEST(EgressMetadataHookListTest, SingleBadHookShouldReturnError) { hookList.addHook(std::move(hook2)); BSONObjBuilder builder; - ASSERT_NOT_OK(hookList.writeRequestMetadata(nullptr, &builder)); - ASSERT_NOT_OK(hookList.readReplyMetadata("b:456", BSON("x" << 1))); + ASSERT_NOT_OK(hookList.writeRequestMetadata(nullptr, HostAndPort("a:123"), &builder)); + ASSERT_NOT_OK(hookList.readReplyMetadata(HostAndPort("b:456"), BSON("x" << 1))); } } // unnamed namespace diff --git a/src/mongo/rpc/metadata/metadata_hook.h b/src/mongo/rpc/metadata/metadata_hook.h index 1bb050e0eda..81f0001f548 100644 --- a/src/mongo/rpc/metadata/metadata_hook.h +++ b/src/mongo/rpc/metadata/metadata_hook.h @@ -35,7 +35,6 @@ class BSONObjBuilder; struct HostAndPort; class OperationContext; class Status; -class StringData; namespace rpc { @@ -59,13 +58,16 @@ public: * not * have an OperationContext as a result. */ - virtual Status writeRequestMetadata(OperationContext* opCtx, BSONObjBuilder* metadataBob) = 0; + virtual Status writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& requestDestination, + BSONObjBuilder* metadataBob) = 0; /** * Reads metadata from an incoming command reply. This method must not throw or block on * database or network operations and can be called by multiple concurrent threads. */ - virtual Status readReplyMetadata(StringData replySource, const BSONObj& metadataObj) = 0; + virtual Status readReplyMetadata(const HostAndPort& replySource, + const BSONObj& metadataObj) = 0; protected: EgressMetadataHook() = default; diff --git a/src/mongo/s/client/sharding_connection_hook.cpp b/src/mongo/s/client/sharding_connection_hook.cpp index 057a9de1c4d..36cb24bf9fc 100644 --- a/src/mongo/s/client/sharding_connection_hook.cpp +++ b/src/mongo/s/client/sharding_connection_hook.cpp @@ -48,8 +48,8 @@ namespace mongo { using std::string; -ShardingConnectionHook::ShardingConnectionHook(bool shardedConnections, - std::unique_ptr<rpc::EgressMetadataHook> egressHook) +ShardingConnectionHook::ShardingConnectionHook( + bool shardedConnections, std::unique_ptr<rpc::ShardingEgressMetadataHook> egressHook) : _shardedConnections(shardedConnections), _egressHook(std::move(egressHook)) {} void ShardingConnectionHook::onCreate(DBClientBase* conn) { @@ -77,9 +77,11 @@ void ShardingConnectionHook::onCreate(DBClientBase* conn) { return _egressHook->readReplyMetadata(target, metadataObj); }); } - conn->setRequestMetadataWriter([this](OperationContext* opCtx, BSONObjBuilder* metadataBob) { - return _egressHook->writeRequestMetadata(opCtx, metadataBob); - }); + conn->setRequestMetadataWriter( + [this](OperationContext* opCtx, BSONObjBuilder* metadataBob, StringData hostStringData) { + return _egressHook->writeRequestMetadata( + _shardedConnections, opCtx, hostStringData, metadataBob); + }); if (conn->type() == ConnectionString::MASTER) { diff --git a/src/mongo/s/client/sharding_connection_hook.h b/src/mongo/s/client/sharding_connection_hook.h index c344a0ba6cb..02c300b026b 100644 --- a/src/mongo/s/client/sharding_connection_hook.h +++ b/src/mongo/s/client/sharding_connection_hook.h @@ -43,7 +43,7 @@ class DBClientBase; class ShardingConnectionHook : public DBConnectionHook { public: ShardingConnectionHook(bool shardedConnections, - std::unique_ptr<rpc::EgressMetadataHook> egressHook); + std::unique_ptr<rpc::ShardingEgressMetadataHook> egressHook); void onCreate(DBClientBase* conn) override; void onDestroy(DBClientBase* conn) override; @@ -54,7 +54,7 @@ private: // Use the implementation of the metadata readers and writers in ShardingEgressMetadataHook, // since that is the hook for Network Interface ASIO and this hook is to be deprecated. - std::unique_ptr<rpc::EgressMetadataHook> _egressHook; + std::unique_ptr<rpc::ShardingEgressMetadataHook> _egressHook; }; } // namespace mongo diff --git a/src/mongo/s/commands/dbclient_multi_command.cpp b/src/mongo/s/commands/dbclient_multi_command.cpp index 131c40d0b13..2bceb5a4993 100644 --- a/src/mongo/s/commands/dbclient_multi_command.cpp +++ b/src/mongo/s/commands/dbclient_multi_command.cpp @@ -90,7 +90,8 @@ static void sayAsCmd(DBClientBase* conn, StringData dbName, const BSONObj& cmdOb metadataBob.appendElements(upconvertedMetadata); if (conn->getRequestMetadataWriter()) { conn->getRequestMetadataWriter()((haveClient() ? cc().getOperationContext() : nullptr), - &metadataBob); + &metadataBob, + conn->getServerAddress()); } requestBuilder->setDatabase(dbName); diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp index d3a797b3a49..bd177748fcf 100644 --- a/src/mongo/s/server.cpp +++ b/src/mongo/s/server.cpp @@ -207,7 +207,7 @@ static Status initializeSharding(OperationContext* opCtx) { auto hookList = stdx::make_unique<rpc::EgressMetadataHookList>(); hookList->addHook( stdx::make_unique<rpc::LogicalTimeMetadataHook>(opCtx->getServiceContext())); - hookList->addHook(stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>(false)); + hookList->addHook(stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>()); return hookList; }, [](ShardingCatalogClient* catalogClient, std::unique_ptr<executor::TaskExecutor> executor) { @@ -257,20 +257,12 @@ static ExitCode runMongosServer() { return EXIT_NET_ERROR; } - auto unshardedHookList = stdx::make_unique<rpc::EgressMetadataHookList>(); - unshardedHookList->addHook( - stdx::make_unique<rpc::LogicalTimeMetadataHook>(getGlobalServiceContext())); - unshardedHookList->addHook(stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>(false)); - // Add sharding hooks to both connection pools - ShardingConnectionHook includes auth hooks - globalConnPool.addHook(new ShardingConnectionHook(false, std::move(unshardedHookList))); - - auto shardedHookList = stdx::make_unique<rpc::EgressMetadataHookList>(); - shardedHookList->addHook( - stdx::make_unique<rpc::LogicalTimeMetadataHook>(getGlobalServiceContext())); - shardedHookList->addHook(stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>(true)); + globalConnPool.addHook(new ShardingConnectionHook( + false, stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>())); - shardConnectionPool.addHook(new ShardingConnectionHook(true, std::move(shardedHookList))); + shardConnectionPool.addHook(new ShardingConnectionHook( + true, stdx::make_unique<rpc::ShardingEgressMetadataHookForMongos>())); ReplicaSetMonitor::setAsynchronousConfigChangeHook( &ShardRegistry::replicaSetChangeConfigServerUpdateHook); diff --git a/src/mongo/s/sharding_egress_metadata_hook.cpp b/src/mongo/s/sharding_egress_metadata_hook.cpp index cc4823a3384..af263360a0d 100644 --- a/src/mongo/s/sharding_egress_metadata_hook.cpp +++ b/src/mongo/s/sharding_egress_metadata_hook.cpp @@ -50,16 +50,15 @@ namespace rpc { using std::shared_ptr; -ShardingEgressMetadataHook::ShardingEgressMetadataHook(bool shardedConnection) - : _isShardedConnection(shardedConnection) {} - -Status ShardingEgressMetadataHook::writeRequestMetadata(OperationContext* opCtx, +Status ShardingEgressMetadataHook::writeRequestMetadata(bool shardedConnection, + OperationContext* opCtx, + const StringData target, BSONObjBuilder* metadataBob) { try { audit::writeImpersonatedUsersToMetadata(opCtx, metadataBob); ClientMetadataIsMasterState::writeToMetadata(opCtx, metadataBob); - if (!_isShardedConnection) { + if (!shardedConnection) { return Status::OK(); } rpc::ConfigServerMetadata(_getConfigServerOpTime()).writeToMetadata(metadataBob); @@ -69,7 +68,13 @@ Status ShardingEgressMetadataHook::writeRequestMetadata(OperationContext* opCtx, } } -Status ShardingEgressMetadataHook::readReplyMetadata(StringData replySource, +Status ShardingEgressMetadataHook::writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& target, + BSONObjBuilder* metadataBob) { + return writeRequestMetadata(true, opCtx, target.toString(), metadataBob); +} + +Status ShardingEgressMetadataHook::readReplyMetadata(const StringData replySource, const BSONObj& metadataObj) { try { _saveGLEStats(metadataObj, replySource); @@ -79,6 +84,11 @@ Status ShardingEgressMetadataHook::readReplyMetadata(StringData replySource, } } +Status ShardingEgressMetadataHook::readReplyMetadata(const HostAndPort& replySource, + const BSONObj& metadataObj) { + return readReplyMetadata(replySource.toString(), metadataObj); +} + Status ShardingEgressMetadataHook::_advanceConfigOptimeFromShard(ShardId shardId, const BSONObj& metadataObj) { try { diff --git a/src/mongo/s/sharding_egress_metadata_hook.h b/src/mongo/s/sharding_egress_metadata_hook.h index 87442ebe0f3..1c8849dcea3 100644 --- a/src/mongo/s/sharding_egress_metadata_hook.h +++ b/src/mongo/s/sharding_egress_metadata_hook.h @@ -43,14 +43,23 @@ namespace rpc { class ShardingEgressMetadataHook : public rpc::EgressMetadataHook { public: - /** - * Pass true to shardedConnection if the hook is intended for connections with shard versions. - */ - ShardingEgressMetadataHook(bool shardedConnection); virtual ~ShardingEgressMetadataHook() = default; - Status readReplyMetadata(StringData replySource, const BSONObj& metadataObj) override; - Status writeRequestMetadata(OperationContext* opCtx, BSONObjBuilder* metadataBob) override; + Status readReplyMetadata(const HostAndPort& replySource, const BSONObj& metadataObj) override; + Status writeRequestMetadata(OperationContext* opCtx, + const HostAndPort& target, + BSONObjBuilder* metadataBob) override; + + // These overloaded methods exist to allow ShardingConnectionHook, which is soon to be + // deprecated, to use the logic in ShardingEgressMetadataHook instead of duplicating the + // logic. ShardingConnectionHook must provide the replySource and target as strings rather than + // HostAndPorts, since DBClientReplicaSet uses the hook before it decides on the actual host to + // contact. + Status readReplyMetadata(const StringData replySource, const BSONObj& metadataObj); + Status writeRequestMetadata(bool shardedConnection, + OperationContext* opCtx, + const StringData target, + BSONObjBuilder* metadataBob); protected: /** @@ -74,9 +83,6 @@ protected: * metadata in the response object from running a command. */ virtual Status _advanceConfigOptimeFromShard(ShardId shardId, const BSONObj& metadataObj); - -private: - bool _isShardedConnection; }; } // namespace rpc diff --git a/src/mongo/s/sharding_egress_metadata_hook_for_mongos.cpp b/src/mongo/s/sharding_egress_metadata_hook_for_mongos.cpp index 1ae82a7c64e..f355054f92b 100644 --- a/src/mongo/s/sharding_egress_metadata_hook_for_mongos.cpp +++ b/src/mongo/s/sharding_egress_metadata_hook_for_mongos.cpp @@ -41,9 +41,6 @@ namespace mongo { namespace rpc { -ShardingEgressMetadataHookForMongos::ShardingEgressMetadataHookForMongos(bool shardedConnection) - : ShardingEgressMetadataHook(shardedConnection) {} - void ShardingEgressMetadataHookForMongos::_saveGLEStats(const BSONObj& metadata, StringData hostString) { if (!haveClient()) { diff --git a/src/mongo/s/sharding_egress_metadata_hook_for_mongos.h b/src/mongo/s/sharding_egress_metadata_hook_for_mongos.h index 2e5bfe62434..9cba4226df2 100644 --- a/src/mongo/s/sharding_egress_metadata_hook_for_mongos.h +++ b/src/mongo/s/sharding_egress_metadata_hook_for_mongos.h @@ -34,9 +34,6 @@ namespace mongo { namespace rpc { class ShardingEgressMetadataHookForMongos final : public ShardingEgressMetadataHook { -public: - ShardingEgressMetadataHookForMongos(bool shardedConnection); - private: void _saveGLEStats(const BSONObj& metadata, StringData hostString) override; diff --git a/src/mongo/s/sharding_test_fixture.cpp b/src/mongo/s/sharding_test_fixture.cpp index 4068545c113..59d3762925f 100644 --- a/src/mongo/s/sharding_test_fixture.cpp +++ b/src/mongo/s/sharding_test_fixture.cpp @@ -108,15 +108,14 @@ void ShardingTestFixture::setUp() { // Set up executor pool used for most operations. auto fixedNet = stdx::make_unique<executor::NetworkInterfaceMock>(); - fixedNet->setEgressMetadataHook(stdx::make_unique<ShardingEgressMetadataHookForMongos>(false)); + fixedNet->setEgressMetadataHook(stdx::make_unique<ShardingEgressMetadataHookForMongos>()); _mockNetwork = fixedNet.get(); auto fixedExec = makeThreadPoolTestExecutor(std::move(fixedNet)); _networkTestEnv = stdx::make_unique<NetworkTestEnv>(fixedExec.get(), _mockNetwork); _executor = fixedExec.get(); auto netForPool = stdx::make_unique<executor::NetworkInterfaceMock>(); - netForPool->setEgressMetadataHook( - stdx::make_unique<ShardingEgressMetadataHookForMongos>(false)); + netForPool->setEgressMetadataHook(stdx::make_unique<ShardingEgressMetadataHookForMongos>()); auto execForPool = makeThreadPoolTestExecutor(std::move(netForPool)); std::vector<std::unique_ptr<executor::TaskExecutor>> executorsForPool; executorsForPool.emplace_back(std::move(execForPool)); |