summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam Midvidy <amidvidy@gmail.com>2015-07-28 17:57:02 -0400
committerAdam Midvidy <amidvidy@gmail.com>2015-07-31 13:55:41 -0400
commit6c6719e26051a950d67c99d2f0b5ab01d3d7d2d7 (patch)
tree9c274a559f3cd7a6569aca6dc8b4fae18d325779 /src
parent83f1d80c6f91f02b1f4df6f81de36976776eed62 (diff)
downloadmongo-6c6719e26051a950d67c99d2f0b5ab01d3d7d2d7.tar.gz
SERVER-19439 implement ConnectionHook API in NetworkInterfaceImpl
Diffstat (limited to 'src')
-rw-r--r--src/mongo/client/connection_pool.cpp44
-rw-r--r--src/mongo/client/connection_pool.h9
-rw-r--r--src/mongo/client/dbclient.cpp28
-rw-r--r--src/mongo/client/dbclientinterface.h22
-rw-r--r--src/mongo/client/remote_command_runner_impl.cpp8
-rw-r--r--src/mongo/client/remote_command_runner_impl.h7
-rw-r--r--src/mongo/executor/network_connection_hook.h112
-rw-r--r--src/mongo/executor/network_interface.h65
-rw-r--r--src/mongo/executor/network_interface_asio.cpp4
-rw-r--r--src/mongo/executor/network_interface_asio.h3
-rw-r--r--src/mongo/executor/network_interface_impl.cpp13
-rw-r--r--src/mongo/executor/network_interface_impl.h6
-rw-r--r--src/mongo/executor/network_interface_mock.cpp3
-rw-r--r--src/mongo/executor/network_interface_mock.h6
-rw-r--r--src/mongo/executor/network_interface_mock_test.cpp3
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,