diff options
Diffstat (limited to 'client/dbclient_rs.cpp')
-rw-r--r-- | client/dbclient_rs.cpp | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/client/dbclient_rs.cpp b/client/dbclient_rs.cpp index b6ce776..ae01da3 100644 --- a/client/dbclient_rs.cpp +++ b/client/dbclient_rs.cpp @@ -74,7 +74,7 @@ namespace mongo { ReplicaSetMonitor::ReplicaSetMonitor( const string& name , const vector<HostAndPort>& servers ) - : _lock( "ReplicaSetMonitor instance" ) , _checkConnectionLock( "ReplicaSetMonitor check connection lock" ), _name( name ) , _master(-1) { + : _lock( "ReplicaSetMonitor instance" ) , _checkConnectionLock( "ReplicaSetMonitor check connection lock" ), _name( name ) , _master(-1), _nextSlave(0) { uassert( 13642 , "need at least 1 node for a replica set" , servers.size() > 0 ); @@ -85,6 +85,12 @@ namespace mongo { string errmsg; for ( unsigned i=0; i<servers.size(); i++ ) { + + bool haveAlready = false; + for ( unsigned n = 0; n < _nodes.size() && ! haveAlready; n++ ) + haveAlready = ( _nodes[n].addr == servers[i] ); + if( haveAlready ) continue; + auto_ptr<DBClientConnection> conn( new DBClientConnection( true , 0, 5.0 ) ); if (!conn->connect( servers[i] , errmsg ) ) { log(1) << "error connecting to seed " << servers[i] << ": " << errmsg << endl; @@ -221,19 +227,17 @@ namespace mongo { } HostAndPort ReplicaSetMonitor::getSlave() { - int x = rand() % _nodes.size(); - { - scoped_lock lk( _lock ); - for ( unsigned i=0; i<_nodes.size(); i++ ) { - int p = ( i + x ) % _nodes.size(); - if ( p == _master ) - continue; - if ( _nodes[p].ok ) - return _nodes[p].addr; - } + + scoped_lock lk( _lock ); + for ( unsigned i=0; i<_nodes.size(); i++ ) { + _nextSlave = ( _nextSlave + 1 ) % _nodes.size(); + if ( _nextSlave == _master ) + continue; + if ( _nodes[ _nextSlave ].ok ) + return _nodes[ _nextSlave ].addr; } - return _nodes[0].addr; + return _nodes[ 0 ].addr; } /** @@ -292,6 +296,10 @@ namespace mongo { newConn->connect( h , temp ); { scoped_lock lk( _lock ); + if ( _find_inlock( toCheck ) >= 0 ) { + // we need this check inside the lock so there isn't thread contention on adding to vector + continue; + } _nodes.push_back( Node( h , newConn ) ); } log() << "updated set (" << _name << ") to: " << getServerAddress() << endl; @@ -309,10 +317,9 @@ namespace mongo { BSONObj o; c->isMaster(isMaster, &o); - log( ! verbose ) << "ReplicaSetMonitor::_checkConnection: " << c->toString() << ' ' << o << '\n'; + log( ! verbose ) << "ReplicaSetMonitor::_checkConnection: " << c->toString() << ' ' << o << endl; // add other nodes - string maybePrimary; if ( o["hosts"].type() == Array ) { if ( o["primary"].type() == String ) maybePrimary = o["primary"].String(); @@ -394,12 +401,17 @@ namespace mongo { int ReplicaSetMonitor::_find( const string& server ) const { scoped_lock lk( _lock ); + return _find_inlock( server ); + } + + int ReplicaSetMonitor::_find_inlock( const string& server ) const { for ( unsigned i=0; i<_nodes.size(); i++ ) if ( _nodes[i].addr == server ) return i; return -1; } + int ReplicaSetMonitor::_find( const HostAndPort& server ) const { scoped_lock lk( _lock ); for ( unsigned i=0; i<_nodes.size(); i++ ) @@ -426,7 +438,7 @@ namespace mongo { DBClientConnection * DBClientReplicaSet::checkMaster() { HostAndPort h = _monitor->getMaster(); - if ( h == _masterHost ) { + if ( h == _masterHost && _master ) { // a master is selected. let's just make sure connection didn't die if ( ! _master->isFailed() ) return _master.get(); @@ -447,7 +459,7 @@ namespace mongo { DBClientConnection * DBClientReplicaSet::checkSlave() { HostAndPort h = _monitor->getSlave( _slaveHost ); - if ( h == _slaveHost ) { + if ( h == _slaveHost && _slave ) { if ( ! _slave->isFailed() ) return _slave.get(); _monitor->notifySlaveFailure( _slaveHost ); @@ -534,8 +546,8 @@ namespace mongo { try { return checkSlave()->query(ns,query,nToReturn,nToSkip,fieldsToReturn,queryOptions,batchSize); } - catch ( DBException & ) { - LOG(1) << "can't query replica set slave: " << _slaveHost << endl; + catch ( DBException &e ) { + log() << "can't query replica set slave " << i << " : " << _slaveHost << e.what() << endl; } } } @@ -552,8 +564,8 @@ namespace mongo { try { return checkSlave()->findOne(ns,query,fieldsToReturn,queryOptions); } - catch ( DBException & ) { - LOG(1) << "can't query replica set slave: " << _slaveHost << endl; + catch ( DBException &e ) { + LOG(1) << "can't findone replica set slave " << i << " : " << _slaveHost << e.what() << endl; } } } @@ -588,8 +600,8 @@ namespace mongo { *actualServer = s->getServerAddress(); return s->call( toSend , response , assertOk ); } - catch ( DBException & ) { - log(1) << "can't query replica set slave: " << _slaveHost << endl; + catch ( DBException &e ) { + LOG(1) << "can't call replica set slave " << i << " : " << _slaveHost << e.what() << endl; if ( actualServer ) *actualServer = ""; } |