summaryrefslogtreecommitdiff
path: root/client/dbclient_rs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'client/dbclient_rs.cpp')
-rw-r--r--client/dbclient_rs.cpp56
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 = "";
}