summaryrefslogtreecommitdiff
path: root/client/dbclient_rs.cpp
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2011-02-02 10:47:02 -0500
committerEliot Horowitz <eliot@10gen.com>2011-02-02 10:47:02 -0500
commit1227dfe359d312389a7aaa4302f4be61e05444dc (patch)
treea75548c8ed99d85c15b032ba295fcfa0e597833e /client/dbclient_rs.cpp
parent9297201b7f10690812917a60bc6f283e67972625 (diff)
downloadmongo-1227dfe359d312389a7aaa4302f4be61e05444dc.tar.gz
fix concurrency issues with DBClientReplicaSet SERVER-2466
Diffstat (limited to 'client/dbclient_rs.cpp')
-rw-r--r--client/dbclient_rs.cpp40
1 files changed, 35 insertions, 5 deletions
diff --git a/client/dbclient_rs.cpp b/client/dbclient_rs.cpp
index 07f5d8145b0..748a1f3f52a 100644
--- a/client/dbclient_rs.cpp
+++ b/client/dbclient_rs.cpp
@@ -50,7 +50,7 @@ namespace mongo {
ReplicaSetMonitor::ReplicaSetMonitor( const string& name , const vector<HostAndPort>& servers )
- : _lock( "ReplicaSetMonitor instance" ) , _name( name ) , _master(-1) {
+ : _lock( "ReplicaSetMonitor instance" ) , _checkConnectionLock( "ReplicaSetMonitor check connection lock" ), _name( name ) , _master(-1) {
string errmsg;
@@ -148,7 +148,13 @@ namespace mongo {
HostAndPort ReplicaSetMonitor::getMaster() {
- if ( _master < 0 || !_nodes[_master].ok )
+ bool good = false;
+ {
+ scoped_lock lk( _lock );
+ good = _master >= 0 && _nodes[_master].ok;
+ }
+
+ if ( ! good )
_check();
uassert( 10009 , str::stream() << "ReplicaSetMonitor no master found for set: " << _name , _master >= 0 );
@@ -156,6 +162,23 @@ namespace mongo {
scoped_lock lk( _lock );
return _nodes[_master].addr;
}
+
+ HostAndPort ReplicaSetMonitor::getSlave( const HostAndPort& prev ) {
+ // make sure its valid
+ if ( prev.port() > 0 ) {
+ scoped_lock lk( _lock );
+ for ( unsigned i=0; i<_nodes.size(); i++ ) {
+ if ( prev != _nodes[i].addr )
+ continue;
+
+ if ( _nodes[i].ok )
+ return prev;
+ break;
+ }
+ }
+
+ return getSlave();
+ }
HostAndPort ReplicaSetMonitor::getSlave() {
int x = rand() % _nodes.size();
@@ -235,8 +258,11 @@ namespace mongo {
changed = true;
}
}
+
+
bool ReplicaSetMonitor::_checkConnection( DBClientConnection * c , string& maybePrimary , bool verbose ) {
+ scoped_lock lk( _checkConnectionLock );
bool isMaster = false;
bool changed = false;
try {
@@ -369,20 +395,24 @@ namespace mongo {
_masterHost = _monitor->getMaster();
_master.reset( new DBClientConnection( true ) );
- _master->connect( _masterHost );
+ string errmsg;
+ if ( ! _master->connect( _masterHost , errmsg ) ) {
+ _monitor->notifyFailure( _masterHost );
+ uasserted( 13639 , str::stream() << "can't connect to new replica set master [" << _masterHost.toString() << "] err: " << errmsg );
+ }
_auth( _master.get() );
return _master.get();
}
DBClientConnection * DBClientReplicaSet::checkSlave() {
- HostAndPort h = _monitor->getSlave();
+ HostAndPort h = _monitor->getSlave( _slaveHost );
if ( h == _slaveHost ) {
if ( ! _slave->isFailed() )
return _slave.get();
_monitor->notifySlaveFailure( _slaveHost );
}
-
+
_slaveHost = _monitor->getSlave();
_slave.reset( new DBClientConnection( true ) );
_slave->connect( _slaveHost );