diff options
author | Greg Studer <greg@10gen.com> | 2013-03-28 16:26:16 -0400 |
---|---|---|
committer | Greg Studer <greg@10gen.com> | 2013-05-09 17:28:33 -0400 |
commit | 61b8f72884dc6fee89b91a30021f41e50cb9de0e (patch) | |
tree | 2218f54ec4e050e47ff3552434a2f2ba4a4f1158 /src/mongo/client/dbclient_rs.cpp | |
parent | c37f75c550b80eb060cb6f69bc9c3997532e6104 (diff) | |
download | mongo-61b8f72884dc6fee89b91a30021f41e50cb9de0e.tar.gz |
SERVER-9041 proactively detect background conn failures in conn pools
Diffstat (limited to 'src/mongo/client/dbclient_rs.cpp')
-rw-r--r-- | src/mongo/client/dbclient_rs.cpp | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/src/mongo/client/dbclient_rs.cpp b/src/mongo/client/dbclient_rs.cpp index 2008ed59c3e..ddc20496df4 100644 --- a/src/mongo/client/dbclient_rs.cpp +++ b/src/mongo/client/dbclient_rs.cpp @@ -260,19 +260,30 @@ namespace mongo { /** * @return the connection associated with the monitor node. Will also attempt - * to establish connection if NULL. Can still return NULL if reconnect failed. + * to establish connection if NULL or broken in background. + * Can still return NULL if reconnect failed. */ - shared_ptr<DBClientConnection> _getConnWithRefresh(ReplicaSetMonitor::Node& node) { - if (node.conn.get() == NULL) { - ConnectionString connStr(node.addr); + shared_ptr<DBClientConnection> _getConnWithRefresh( ReplicaSetMonitor::Node& node ) { + if ( node.conn.get() == NULL || !node.conn->isStillConnected() ) { + + // Note: This constructor only works with MASTER connections + ConnectionString connStr( node.addr ); string errmsg; try { - node.conn.reset(dynamic_cast<DBClientConnection*>( - connStr.connect(errmsg, ReplicaSetMonitor::SOCKET_TIMEOUT_SECS))); + DBClientBase* conn = connStr.connect( errmsg, + ReplicaSetMonitor::SOCKET_TIMEOUT_SECS ); + if ( conn == NULL ) { + node.ok = false; + node.conn.reset(); + } + else { + node.conn.reset( dynamic_cast<DBClientConnection*>( conn ) ); + } } - catch (const AssertionException&) { + catch ( const AssertionException& ) { node.ok = false; + node.conn.reset(); } } @@ -1318,6 +1329,30 @@ namespace mongo { return rsm->getServerAddress(); } + // A replica set connection is never disconnected, since it controls its own reconnection + // logic. + // + // Has the side effect of proactively clearing any cached connections which have been + // disconnected in the background. + bool DBClientReplicaSet::isStillConnected() { + + if ( _master && !_master->isStillConnected() ) { + _master.reset(); + _masterHost = HostAndPort(); + // Don't notify monitor of bg failure, since it's not clear how long ago it happened + } + + if ( _lastSlaveOkConn && !_lastSlaveOkConn->isStillConnected() ) { + _lastSlaveOkConn.reset(); + _lastSlaveOkHost = HostAndPort(); + // Reset read pref too, since we're re-selecting the slaveOk host anyway + _lastReadPref.reset(); + // Don't notify monitor of bg failure, since it's not clear how long ago it happened + } + + return true; + } + DBClientConnection * DBClientReplicaSet::checkMaster() { ReplicaSetMonitorPtr monitor = _getMonitor(); HostAndPort h = monitor->getMaster(); |