0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 01:21:03 +01:00

SERVER-16436 cleanup unused connections in the NetworkInterface's ConenctionPool

This commit is contained in:
matt dannenberg 2015-02-20 10:42:51 -05:00
parent f974b0e963
commit 1b64013e01

View File

@ -58,6 +58,9 @@ namespace {
const size_t kMinThreads = 1;
const size_t kMaxThreads = 51; // Set to 1 + max repl set size, for heartbeat + wiggle room.
const unsigned long long kNeverTooStale = std::numeric_limits<unsigned long long>::max();
// 5 Minutes (Note: Must be larger than kMaxConnectionAge below)
const long long kCleanUpInterval = 5 * 60 * 1000;
const Seconds kMaxIdleThreadAge(30);
const Seconds kMaxConnectionAge(30);
@ -75,6 +78,7 @@ namespace {
typedef stdx::list<ConnectionInfo> ConnectionList;
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
@ -158,6 +162,11 @@ namespace {
*/
bool shouldKeepConnection(Date_t now, const ConnectionInfo& connInfo) const;
/**
* Apply cleanup policy to any host(s) not active in the last kCleanupInterval milliseconds.
*/
void cleanUpStaleHosts_inlock(Date_t now);
/**
* Implementation of cleanUpOlderThan which assumes that _mutex is already held.
*/
@ -183,6 +192,12 @@ namespace {
// List of non-idle connections.
ConnectionList _inUseConnections;
// Map of HostAndPorts to when they were last used.
HostLastUsedMap _lastUsedHosts;
// Time representing when the connections were last cleaned.
Date_t _lastCleanUpTime;
};
/**
@ -209,7 +224,7 @@ namespace {
return _connInfo->conn;
}
NetworkInterfaceImpl::ConnectionPool::ConnectionPool() {}
NetworkInterfaceImpl::ConnectionPool::ConnectionPool() : _lastCleanUpTime(0ULL) {}
NetworkInterfaceImpl::ConnectionPool::~ConnectionPool() {
cleanUpOlderThan(Date_t(~0ULL));
@ -271,17 +286,40 @@ namespace {
}
}
void NetworkInterfaceImpl::ConnectionPool::cleanUpStaleHosts_inlock(Date_t now) {
if (now > _lastCleanUpTime + kCleanUpInterval) {
for (HostLastUsedMap::iterator itr = _lastUsedHosts.begin();
itr != _lastUsedHosts.end();
itr++) {
if (itr->second <= _lastCleanUpTime) {
ConnectionList connList = _connections.find(itr->first)->second;
cleanUpOlderThan_inlock(now, &connList);
invariant(connList.empty());
itr->second = Date_t(kNeverTooStale);
}
}
_lastCleanUpTime = now;
}
}
NetworkInterfaceImpl::ConnectionPool::ConnectionList::iterator
NetworkInterfaceImpl::ConnectionPool::acquireConnection(
const HostAndPort& target,
Date_t now,
Milliseconds timeout) {
boost::unique_lock<boost::mutex> lk(_mutex);
// Clean up connections on stale/unused hosts
cleanUpStaleHosts_inlock(now);
for (HostConnectionMap::iterator hostConns;
((hostConns = _connections.find(target)) != _connections.end());) {
// Clean up the requested host to remove stale/unused connections
cleanUpOlderThan_inlock(now, &hostConns->second);
if (hostConns->second.empty()) {
// prevent host from causing unnecessary cleanups
_lastUsedHosts[hostConns->first] = Date_t(kNeverTooStale);
break;
}
_inUseConnections.splice(_inUseConnections.begin(),
@ -341,6 +379,7 @@ namespace {
ConnectionList& hostConns = _connections[iter->conn->getServerHostAndPort()];
cleanUpOlderThan_inlock(now, &hostConns);
hostConns.splice(hostConns.begin(), _inUseConnections, iter);
_lastUsedHosts[iter->conn->getServerHostAndPort()] = now;
}
void NetworkInterfaceImpl::ConnectionPool::destroyConnection(ConnectionList::iterator iter) {