diff options
author | Adam Midvidy <amidvidy@gmail.com> | 2015-07-28 17:57:02 -0400 |
---|---|---|
committer | Adam Midvidy <amidvidy@gmail.com> | 2015-07-31 13:55:41 -0400 |
commit | 6c6719e26051a950d67c99d2f0b5ab01d3d7d2d7 (patch) | |
tree | 9c274a559f3cd7a6569aca6dc8b4fae18d325779 /src | |
parent | 83f1d80c6f91f02b1f4df6f81de36976776eed62 (diff) | |
download | mongo-6c6719e26051a950d67c99d2f0b5ab01d3d7d2d7.tar.gz |
SERVER-19439 implement ConnectionHook API in NetworkInterfaceImpl
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/client/connection_pool.cpp | 44 | ||||
-rw-r--r-- | src/mongo/client/connection_pool.h | 9 | ||||
-rw-r--r-- | src/mongo/client/dbclient.cpp | 28 | ||||
-rw-r--r-- | src/mongo/client/dbclientinterface.h | 22 | ||||
-rw-r--r-- | src/mongo/client/remote_command_runner_impl.cpp | 8 | ||||
-rw-r--r-- | src/mongo/client/remote_command_runner_impl.h | 7 | ||||
-rw-r--r-- | src/mongo/executor/network_connection_hook.h | 112 | ||||
-rw-r--r-- | src/mongo/executor/network_interface.h | 65 | ||||
-rw-r--r-- | src/mongo/executor/network_interface_asio.cpp | 4 | ||||
-rw-r--r-- | src/mongo/executor/network_interface_asio.h | 3 | ||||
-rw-r--r-- | src/mongo/executor/network_interface_impl.cpp | 13 | ||||
-rw-r--r-- | src/mongo/executor/network_interface_impl.h | 6 | ||||
-rw-r--r-- | src/mongo/executor/network_interface_mock.cpp | 3 | ||||
-rw-r--r-- | src/mongo/executor/network_interface_mock.h | 6 | ||||
-rw-r--r-- | src/mongo/executor/network_interface_mock_test.cpp | 3 |
15 files changed, 232 insertions, 101 deletions
diff --git a/src/mongo/client/connection_pool.cpp b/src/mongo/client/connection_pool.cpp index 5e9062ca831..d9c888ef37e 100644 --- a/src/mongo/client/connection_pool.cpp +++ b/src/mongo/client/connection_pool.cpp @@ -33,6 +33,11 @@ #include "mongo/client/connpool.h" #include "mongo/db/auth/authorization_manager_global.h" #include "mongo/db/auth/internal_user_auth.h" +#include "mongo/executor/network_connection_hook.h" +#include "mongo/executor/remote_command_request.h" +#include "mongo/executor/remote_command_response.h" +#include "mongo/rpc/reply_interface.h" +#include "mongo/rpc/unique_message.h" namespace mongo { namespace { @@ -45,7 +50,12 @@ const Minutes kMaxConnectionAge(30); } // namespace -ConnectionPool::ConnectionPool(int messagingPortTags) : _messagingPortTags(messagingPortTags) {} +ConnectionPool::ConnectionPool(int messagingPortTags, + std::unique_ptr<executor::NetworkConnectionHook> hook) + : _messagingPortTags(messagingPortTags), _hook(std::move(hook)) {} + +ConnectionPool::ConnectionPool(int messagingPortTags) + : ConnectionPool(messagingPortTags, nullptr) {} ConnectionPool::~ConnectionPool() { cleanUpOlderThan(Date_t::max()); @@ -163,10 +173,34 @@ ConnectionPool::ConnectionList::iterator ConnectionPool::acquireConnection( // timeouts. Thus, we must take count() and divide by 1000.0 to get the number // of seconds with a fractional part. conn->setSoTimeout(timeout.count() / 1000.0); - std::string errmsg; - uassert(ErrorCodes::HostUnreachable, - str::stream() << "Failed attempt to connect to " << target.toString() << "; " << errmsg, - conn->connect(target, errmsg)); + + if (_hook) { + uassertStatusOK( + conn->connect(target, + [this, &target](const executor::RemoteCommandResponse& isMasterReply) { + return _hook->validateHost(target, isMasterReply); + })); + + auto postConnectRequest = uassertStatusOK(_hook->makeRequest(target)); + + // We might not have a postConnectRequest + if (postConnectRequest != boost::none) { + auto start = Date_t::now(); + auto reply = + conn->runCommandWithMetadata(postConnectRequest->dbname, + postConnectRequest->cmdObj.firstElementFieldName(), + postConnectRequest->metadata, + postConnectRequest->cmdObj); + + auto rcr = executor::RemoteCommandResponse(reply->getCommandReply().getOwned(), + reply->getMetadata().getOwned(), + Date_t::now() - start); + + uassertStatusOK(_hook->handleReply(target, std::move(rcr))); + } + } else { + uassertStatusOK(conn->connect(target)); + } conn->port().tag |= _messagingPortTags; diff --git a/src/mongo/client/connection_pool.h b/src/mongo/client/connection_pool.h index 8db5ceddc5b..853911b69a7 100644 --- a/src/mongo/client/connection_pool.h +++ b/src/mongo/client/connection_pool.h @@ -39,6 +39,9 @@ #include "mongo/util/time_support.h" namespace mongo { +namespace executor { +class NetworkConnectionHook; +} /** * Represents a pool of connections to a MongoDB server. The pool is synchronized internally @@ -67,7 +70,6 @@ public: typedef unordered_map<HostAndPort, ConnectionList> HostConnectionMap; typedef std::map<HostAndPort, Date_t> HostLastUsedMap; - /** * RAII class for connections from the pool. To use the connection pool, instantiate one of * these with a pointer to the pool, the identity of the target node and the timeout for @@ -119,7 +121,6 @@ public: ConnectionList::iterator _connInfo; }; - /** * Instantiates a new connection pool with the specified tags to be applied to the * messaging ports that it opens. @@ -127,6 +128,7 @@ public: * @param messagingPortTags tags to be applied to the messaging ports for each of the * connections. If no tags are required, use 0. */ + ConnectionPool(int messagingPortTags, std::unique_ptr<executor::NetworkConnectionHook> hook); ConnectionPool(int messagingPortTags); ~ConnectionPool(); @@ -203,6 +205,9 @@ private: // Time representing when the connections were last cleaned. Date_t _lastCleanUpTime; + + // The connection hook for this pool. May be nullptr if there is no hook. + const std::unique_ptr<executor::NetworkConnectionHook> _hook; }; } // namespace mongo diff --git a/src/mongo/client/dbclient.cpp b/src/mongo/client/dbclient.cpp index 91b9562fd99..edbf462f9b3 100644 --- a/src/mongo/client/dbclient.cpp +++ b/src/mongo/client/dbclient.cpp @@ -46,6 +46,7 @@ #include "mongo/db/json.h" #include "mongo/db/namespace_string.h" #include "mongo/db/wire_version.h" +#include "mongo/executor/remote_command_response.h" #include "mongo/rpc/factory.h" #include "mongo/rpc/get_status_from_command_result.h" #include "mongo/rpc/metadata.h" @@ -927,15 +928,17 @@ private: /** * Initializes the wire version of conn, and returns the isMaster reply. */ -StatusWith<BSONObj> initWireVersion(DBClientBase* conn) { +StatusWith<executor::RemoteCommandResponse> initWireVersion(DBClientBase* conn) { try { // We need to force the usage of OP_QUERY on this command, even if we have previously // detected support for OP_COMMAND on a connection. This is necessary to handle the case // where we reconnect to an older version of MongoDB running at the same host/port. ScopedForceOpQuery forceOpQuery{conn}; + Date_t start{Date_t::now()}; auto result = conn->runCommandWithMetadata( "admin", "isMaster", rpc::makeEmptyMetadata(), BSON("isMaster" << 1)); + Date_t finish{Date_t::now()}; BSONObj isMasterObj = result->getCommandReply().getOwned(); @@ -945,7 +948,8 @@ StatusWith<BSONObj> initWireVersion(DBClientBase* conn) { conn->setWireVersions(minWireVersion, maxWireVersion); } - return isMasterObj; + return executor::RemoteCommandResponse{ + std::move(isMasterObj), result->getMetadata().getOwned(), finish - start}; } catch (...) { return exceptionToStatus(); @@ -963,8 +967,8 @@ bool DBClientConnection::connect(const HostAndPort& server, std::string& errmsg) return true; } - -Status DBClientConnection::connect(const HostAndPort& serverAddress) { +Status DBClientConnection::connect(const HostAndPort& serverAddress, + const HandshakeValidationHook& hook) { auto connectStatus = connectSocketOnly(serverAddress); if (!connectStatus.isOK()) { return connectStatus; @@ -976,13 +980,23 @@ Status DBClientConnection::connect(const HostAndPort& serverAddress) { return swIsMasterReply.getStatus(); } - auto swProtocolSet = rpc::parseProtocolSetFromIsMasterReply(swIsMasterReply.getValue()); + auto swProtocolSet = rpc::parseProtocolSetFromIsMasterReply(swIsMasterReply.getValue().data); if (!swProtocolSet.isOK()) { return swProtocolSet.getStatus(); } _setServerRPCProtocols(swProtocolSet.getValue()); + if (hook) { + auto validationStatus = hook(swIsMasterReply.getValue()); + if (!validationStatus.isOK()) { + // Disconnect and mark failed. + _failed = true; + _port.reset(); + return validationStatus; + } + } + return Status::OK(); } @@ -1016,7 +1030,7 @@ Status DBClientConnection::connectSocketOnly(const HostAndPort& serverAddress) { _resolvedAddress = osAddr.getAddr(); if (!_port->connect(osAddr)) { - return Status(ErrorCodes::OperationFailed, + return Status(ErrorCodes::HostUnreachable, str::stream() << "couldn't connect to server " << _serverAddress.toString() << ", connection attempt failed"); } @@ -1025,7 +1039,7 @@ Status DBClientConnection::connectSocketOnly(const HostAndPort& serverAddress) { int sslModeVal = sslGlobalParams.sslMode.load(); if (sslModeVal == SSLParams::SSLMode_preferSSL || sslModeVal == SSLParams::SSLMode_requireSSL) { if (!_port->secure(sslManager(), serverAddress.host())) { - return Status(ErrorCodes::OperationFailed, "Failed to initialize SSL on connection"); + return Status(ErrorCodes::SSLHandshakeFailed, "Failed to initialize SSL on connection"); } } #endif diff --git a/src/mongo/client/dbclientinterface.h b/src/mongo/client/dbclientinterface.h index 619e24c206e..e72fdbcefd8 100644 --- a/src/mongo/client/dbclientinterface.h +++ b/src/mongo/client/dbclientinterface.h @@ -45,6 +45,10 @@ namespace mongo { +namespace executor { +struct RemoteCommandResponse; +} + /** the query field 'options' can have these bits set: */ enum QueryOptions { /** Tailable means cursor is not closed when the last data is retrieved. rather, the cursor @@ -1137,12 +1141,26 @@ public: virtual bool connect(const HostAndPort& server, std::string& errmsg); /** + + * A hook used to validate the reply of an 'isMaster' command during connection. If the hook + * returns a non-OK Status, the DBClientConnection object will disconnect from the remote + * server. This function must not throw - it can only indicate failure by returning a non-OK + * status. + */ + using HandshakeValidationHook = + stdx::function<Status(const executor::RemoteCommandResponse& isMasterReply)>; + + /** * Semantically equivalent to the previous connect method, but returns a Status - * instead of taking an errmsg out parameter. + * instead of taking an errmsg out parameter. Also allows optional validation of the reply to + * the 'isMaster' command executed during connection. * * @param server The server to connect to. + * @param a hook to validate the 'isMaster' reply received during connection. If the hook + * fails, the connection will be terminated and a non-OK status will be returned. */ - Status connect(const HostAndPort& server); + Status connect(const HostAndPort& server, + const HandshakeValidationHook& hook = HandshakeValidationHook()); /** * This version of connect does not run 'isMaster' after creating a TCP connection to the diff --git a/src/mongo/client/remote_command_runner_impl.cpp b/src/mongo/client/remote_command_runner_impl.cpp index 67e960b44bd..f132509f184 100644 --- a/src/mongo/client/remote_command_runner_impl.cpp +++ b/src/mongo/client/remote_command_runner_impl.cpp @@ -30,13 +30,14 @@ #include "mongo/client/remote_command_runner_impl.h" +#include "mongo/base/status_with.h" #include "mongo/db/commands.h" #include "mongo/db/namespace_string.h" #include "mongo/db/query/cursor_responses.h" #include "mongo/db/query/getmore_request.h" +#include "mongo/executor/network_connection_hook.h" #include "mongo/rpc/get_status_from_command_result.h" #include "mongo/rpc/protocol.h" -#include "mongo/base/status_with.h" #include "mongo/util/assert_util.h" namespace mongo { @@ -217,8 +218,9 @@ Status runDownconvertedGetMoreCommand(DBClientConnection* conn, } // namespace -RemoteCommandRunnerImpl::RemoteCommandRunnerImpl(int messagingPortTags) - : _connPool(messagingPortTags), _shutDown(false) {} +RemoteCommandRunnerImpl::RemoteCommandRunnerImpl( + int messagingTags, std::unique_ptr<executor::NetworkConnectionHook> hook) + : _connPool(messagingTags, std::move(hook)), _shutDown(false) {} RemoteCommandRunnerImpl::~RemoteCommandRunnerImpl() { invariant(_shutDown); diff --git a/src/mongo/client/remote_command_runner_impl.h b/src/mongo/client/remote_command_runner_impl.h index 258bd3804a9..e2996302d37 100644 --- a/src/mongo/client/remote_command_runner_impl.h +++ b/src/mongo/client/remote_command_runner_impl.h @@ -34,12 +34,17 @@ namespace mongo { +namespace executor { +class NetworkConnectionHook; +} // namespace executor + template <typename T> class StatusWith; class RemoteCommandRunnerImpl { public: - RemoteCommandRunnerImpl(int messagingPortTags); + RemoteCommandRunnerImpl(int messagingTags, + std::unique_ptr<executor::NetworkConnectionHook> hook); virtual ~RemoteCommandRunnerImpl(); /** diff --git a/src/mongo/executor/network_connection_hook.h b/src/mongo/executor/network_connection_hook.h new file mode 100644 index 00000000000..6537dab7443 --- /dev/null +++ b/src/mongo/executor/network_connection_hook.h @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2015 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include <boost/optional.hpp> + +namespace mongo { + +class Status; +template <typename T> +class StatusWith; +struct HostAndPort; + +namespace executor { + +struct RemoteCommandResponse; +struct RemoteCommandRequest; + +/** + * An hooking interface for augmenting an implementation of NetworkInterface with domain-specific + * host validation and post-connection logic. + */ +class NetworkConnectionHook { +public: + virtual ~NetworkConnectionHook() = default; + + /** + * Runs optional validation logic on an isMaster reply from a remote host. If a non-OK + * Status is returned, it will be propagated up to the completion handler for the command + * that initiated the request that caused this connection to be created. This will + * be called once for each connection that is created, even if a remote host with the + * same HostAndPort has already successfully passed validation on a different connection. + * + * This method may be called on a different thread from the caller of startCommand that caused + * this connection to be created. + * + * This method must not throw any exceptions or block on network or disk-IO. However, in the + * event that an exception escapes, the NetworkInterface is responsible for calling + * std::terminate. + */ + virtual Status validateHost(const HostAndPort& remoteHost, + const RemoteCommandResponse& isMasterReply) = 0; + + /** + * Generates a command to run on the remote host immediately after connecting to it. + * If a non-OK StatusWith is returned, it will be propagated up to the completion handler + * for the command that initiated the request that caused this connection to be created. + * + * The command will be run after socket setup, SSL handshake, authentication, and wire + * protocol detection, but before any commands submitted to the NetworkInterface via + * startCommand are run. In the case that it isn't neccessary to run a command, makeRequest + * may return boost::none. + * + * This method may be called on a different thread from the caller of startCommand that caused + * this connection to be created. + * + * This method must not throw any exceptions or block on network or disk-IO. However, in the + * event that an exception escapes, the NetworkInterface is responsible for calling + * std::terminate. + */ + virtual StatusWith<boost::optional<RemoteCommandRequest>> makeRequest( + const HostAndPort& remoteHost) = 0; + + /** + * Handles a remote server's reply to the command generated with makeRequest. If a + * non-OK Status is returned, it will be propagated up to the completion handler for the + * command that initiated the request that caused this connection to be created. + * + * If the corresponding earlier call to makeRequest for this connection returned + * boost::none, the NetworkInterface will not call handleReply. + * + * This method may be called on a different thread from the caller of startCommand that caused + * this connection to be created. + * + * This method must not throw any exceptions or block on network or disk-IO. However, in the + * event that an exception escapes, the NetworkInterface is responsible for calling + * std::terminate. + */ + virtual Status handleReply(const HostAndPort& remoteHost, RemoteCommandResponse&& response) = 0; + +protected: + NetworkConnectionHook() = default; +}; + +} // namespace executor +} // namespace mongo diff --git a/src/mongo/executor/network_interface.h b/src/mongo/executor/network_interface.h index 6d715db20d0..4eeb6db1d8f 100644 --- a/src/mongo/executor/network_interface.h +++ b/src/mongo/executor/network_interface.h @@ -54,64 +54,6 @@ public: virtual ~NetworkInterface(); /** - * An interface for augmenting the NetworkInterface with domain-specific host validation and - * post-connection logic. - */ - class ConnectionHook { - public: - virtual ~ConnectionHook() = default; - - /** - * Runs optional validation logic on an isMaster reply from a remote host. If a non-OK - * Status is returned, it will be propagated up to the completion handler for the command - * that initiated the request that caused this connection to be created. This will - * be called once for each connection that is created, even if a remote host with the - * same HostAndPort has already successfully passed validation on a different connection. - * - * This method must not throw any exceptions or block on network or disk-IO. However, in the - * event that an exception escapes, the NetworkInterface is responsible for calling - * std::terminate. - */ - virtual Status validateHost(const HostAndPort& remoteHost, - const RemoteCommandResponse& isMasterReply) = 0; - - /** - * Generates a command to run on the remote host immediately after connecting to it. - * If a non-OK StatusWith is returned, it will be propagated up to the completion handler - * for the command that initiated the request that caused this connection to be created. - * - * The command will be run after socket setup, SSL handshake, authentication, and wire - * protocol detection, but before any commands submitted to the NetworkInterface via - * startCommand are run. In the case that it isn't neccessary to run a command, makeRequest - * may return boost::none. - * - * This method must not throw any exceptions or block on network or disk-IO. However, in the - * event that an exception escapes, the NetworkInterface is responsible for calling - * std::terminate. - */ - virtual StatusWith<boost::optional<RemoteCommandRequest>> makeRequest( - const HostAndPort& remoteHost) = 0; - - /** - * Handles a remote server's reply to the command generated with makeRequest. If a - * non-OK Status is returned, it will be propagated up to the completion handler for the - * command that initiated the request that caused this connection to be created. - * - * If the corresponding earlier call to makeRequest for this connection returned - * boost::none, the NetworkInterface will not call handleReply. - * - * This method must not throw any exceptions or block on network or disk-IO. However, in the - * event that an exception escapes, the NetworkInterface is responsible for calling - * std::terminate. - */ - virtual Status handleReply(const HostAndPort& remoteHost, - RemoteCommandResponse&& response) = 0; - - protected: - ConnectionHook() = default; - }; - - /** * Returns diagnostic info. */ virtual std::string getDiagnosticString() = 0; @@ -147,13 +89,6 @@ public: virtual void waitForWorkUntil(Date_t when) = 0; /** - * Sets a connection hook for this NetworkInterface. This method can only be - * called once, and must be called before startup() or the result - * is undefined. - */ - virtual void setConnectionHook(std::unique_ptr<ConnectionHook> hook) = 0; - - /** * Signals to the network interface that there is new work (such as a signaled event) for * the executor to process. Wakes the executor from waitForWork() and friends. */ diff --git a/src/mongo/executor/network_interface_asio.cpp b/src/mongo/executor/network_interface_asio.cpp index 768621e681a..9ef278971af 100644 --- a/src/mongo/executor/network_interface_asio.cpp +++ b/src/mongo/executor/network_interface_asio.cpp @@ -109,10 +109,6 @@ void NetworkInterfaceASIO::waitForWorkUntil(Date_t when) { _isExecutorRunnable = false; } -void NetworkInterfaceASIO::setConnectionHook(std::unique_ptr<ConnectionHook> hook) { - MONGO_UNREACHABLE; -} - void NetworkInterfaceASIO::signalWorkAvailable() { stdx::unique_lock<stdx::mutex> lk(_executorMutex); _signalWorkAvailable_inlock(); diff --git a/src/mongo/executor/network_interface_asio.h b/src/mongo/executor/network_interface_asio.h index b10120d2d9e..b73a1a36a6a 100644 --- a/src/mongo/executor/network_interface_asio.h +++ b/src/mongo/executor/network_interface_asio.h @@ -58,6 +58,8 @@ namespace mongo { namespace executor { +class NetworkConnectionHook; + /** * A two-way stream supporting asynchronous reads and writes. */ @@ -95,7 +97,6 @@ public: void shutdown() override; void waitForWork() override; void waitForWorkUntil(Date_t when) override; - void setConnectionHook(std::unique_ptr<ConnectionHook> hook) override; void signalWorkAvailable() override; Date_t now() override; void startCommand(const TaskExecutor::CallbackHandle& cbHandle, diff --git a/src/mongo/executor/network_interface_impl.cpp b/src/mongo/executor/network_interface_impl.cpp index 7f63d5f25da..7835754130e 100644 --- a/src/mongo/executor/network_interface_impl.cpp +++ b/src/mongo/executor/network_interface_impl.cpp @@ -35,7 +35,9 @@ #include <memory> #include "mongo/client/connection_pool.h" +#include "mongo/executor/network_connection_hook.h" #include "mongo/rpc/get_status_from_command_result.h" +#include "mongo/stdx/memory.h" #include "mongo/stdx/thread.h" #include "mongo/util/assert_util.h" #include "mongo/util/log.h" @@ -63,7 +65,12 @@ ThreadPool::Options makeOptions() { } // namespace -NetworkInterfaceImpl::NetworkInterfaceImpl() : NetworkInterface(), _pool(makeOptions()) {} +NetworkInterfaceImpl::NetworkInterfaceImpl() : NetworkInterfaceImpl(nullptr){}; + +NetworkInterfaceImpl::NetworkInterfaceImpl(std::unique_ptr<NetworkConnectionHook> hook) + : NetworkInterface(), + _pool(makeOptions()), + _commandRunner(kMessagingPortKeepOpen, std::move(hook)) {} NetworkInterfaceImpl::~NetworkInterfaceImpl() {} @@ -131,10 +138,6 @@ void NetworkInterfaceImpl::waitForWorkUntil(Date_t when) { _isExecutorRunnable = false; } -void NetworkInterfaceImpl::setConnectionHook(std::unique_ptr<ConnectionHook> hook) { - MONGO_UNREACHABLE; -} - void NetworkInterfaceImpl::_runOneCommand() { stdx::unique_lock<stdx::mutex> lk(_mutex); if (_pending.empty()) { diff --git a/src/mongo/executor/network_interface_impl.h b/src/mongo/executor/network_interface_impl.h index 63a71f1150a..f9c9ce0b856 100644 --- a/src/mongo/executor/network_interface_impl.h +++ b/src/mongo/executor/network_interface_impl.h @@ -43,6 +43,8 @@ namespace mongo { namespace executor { +class NetworkConnectionHook; + /** * Implementation of the network interface for use by classes implementing TaskExecutor * inside mongod. @@ -72,13 +74,13 @@ namespace executor { class NetworkInterfaceImpl final : public NetworkInterface { public: NetworkInterfaceImpl(); + NetworkInterfaceImpl(std::unique_ptr<NetworkConnectionHook> hook); ~NetworkInterfaceImpl(); std::string getDiagnosticString() override; void startup() override; void shutdown() override; void waitForWork() override; void waitForWorkUntil(Date_t when) override; - void setConnectionHook(std::unique_ptr<ConnectionHook> hook) override; void signalWorkAvailable() override; Date_t now() override; std::string getHostName() override; @@ -153,7 +155,7 @@ private: bool _inShutdown = false; // Interface for running remote commands - RemoteCommandRunnerImpl _commandRunner{kMessagingPortKeepOpen}; + RemoteCommandRunnerImpl _commandRunner; // Number of active network requests size_t _numActiveNetworkRequests = 0; diff --git a/src/mongo/executor/network_interface_mock.cpp b/src/mongo/executor/network_interface_mock.cpp index 4e8c427d12e..6bb52d829d8 100644 --- a/src/mongo/executor/network_interface_mock.cpp +++ b/src/mongo/executor/network_interface_mock.cpp @@ -31,6 +31,7 @@ #include "mongo/platform/basic.h" #include "mongo/executor/network_interface_mock.h" +#include "mongo/executor/network_connection_hook.h" #include <algorithm> #include <iterator> @@ -390,7 +391,7 @@ void NetworkInterfaceMock::_connectThenEnqueueOperation_inlock(const HostAndPort _enqueueOperation_inlock(std::move(postconnectOp)); } -void NetworkInterfaceMock::setConnectionHook(std::unique_ptr<ConnectionHook> hook) { +void NetworkInterfaceMock::setConnectionHook(std::unique_ptr<NetworkConnectionHook> hook) { stdx::lock_guard<stdx::mutex> lk(_mutex); invariant(!_hasStarted); invariant(!_hook); diff --git a/src/mongo/executor/network_interface_mock.h b/src/mongo/executor/network_interface_mock.h index f8fc61840f8..4a7da1a6b0a 100644 --- a/src/mongo/executor/network_interface_mock.h +++ b/src/mongo/executor/network_interface_mock.h @@ -44,6 +44,8 @@ namespace mongo { namespace executor { +class NetworkConnectionHook; + /** * Mock network implementation for use in unit tests. * @@ -85,7 +87,7 @@ public: virtual void shutdown(); virtual void waitForWork(); virtual void waitForWorkUntil(Date_t when); - virtual void setConnectionHook(std::unique_ptr<ConnectionHook> hook); + virtual void setConnectionHook(std::unique_ptr<NetworkConnectionHook> hook); virtual void signalWorkAvailable(); virtual Date_t now(); virtual std::string getHostName(); @@ -301,7 +303,7 @@ private: std::priority_queue<AlarmInfo, std::vector<AlarmInfo>, std::greater<AlarmInfo>> _alarms; // (M) // The connection hook. - std::unique_ptr<ConnectionHook> _hook; // (R) + std::unique_ptr<NetworkConnectionHook> _hook; // (R) // The set of hosts we have seen so far. If we see a new host, we will execute the // ConnectionHook's validation and post-connection logic. diff --git a/src/mongo/executor/network_interface_mock_test.cpp b/src/mongo/executor/network_interface_mock_test.cpp index 8e623778458..011e0f0924e 100644 --- a/src/mongo/executor/network_interface_mock_test.cpp +++ b/src/mongo/executor/network_interface_mock_test.cpp @@ -34,6 +34,7 @@ #include "mongo/base/status.h" #include "mongo/executor/network_interface.h" +#include "mongo/executor/network_connection_hook.h" #include "mongo/executor/network_interface_mock.h" #include "mongo/executor/thread_pool_mock.h" #include "mongo/stdx/memory.h" @@ -44,7 +45,7 @@ namespace executor { namespace { template <typename ValidateFunc, typename RequestFunc, typename ReplyFunc> -class TestConnectionHook final : public NetworkInterface::ConnectionHook { +class TestConnectionHook final : public NetworkConnectionHook { public: TestConnectionHook(ValidateFunc&& validateFunc, RequestFunc&& requestFunc, |