From f0d9a01bccdaeb466c12c92057914bbfef59526c Mon Sep 17 00:00:00 2001 From: Antonin Kral Date: Thu, 15 Dec 2011 09:35:47 +0100 Subject: Imported Upstream version 2.0.2 --- client/dbclient_rs.cpp | 66 +++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 27 deletions(-) (limited to 'client/dbclient_rs.cpp') diff --git a/client/dbclient_rs.cpp b/client/dbclient_rs.cpp index 2cab1f7..c57a52d 100644 --- a/client/dbclient_rs.cpp +++ b/client/dbclient_rs.cpp @@ -247,38 +247,27 @@ namespace mongo { } HostAndPort ReplicaSetMonitor::getSlave() { + LOG(2) << "dbclient_rs getSlave " << getServerAddress() << endl; - LOG(2) << "selecting new slave from replica set " << getServerAddress() << endl; - - // Logic is to retry three times for any secondary node, if we can't find any secondary, we'll take - // any "ok" node - // TODO: Could this query hidden nodes? - const int MAX = 3; - for ( int xxx=0; xxx= MAX ) ) - return _nodes[ _nextSlave ].addr; - - LOG(2) << "not selecting " << _nodes[_nextSlave] << " as it is not ok to use" << endl; - } - + for ( unsigned ii = 0; ii < _nodes.size(); ii++ ) { + _nextSlave = ( _nextSlave + 1 ) % _nodes.size(); + if ( _nextSlave != _master ) { + if ( _nodes[ _nextSlave ].okForSecondaryQueries() ) + return _nodes[ _nextSlave ].addr; + LOG(2) << "dbclient_rs getSlave not selecting " << _nodes[_nextSlave] << ", not currently okForSecondaryQueries" << endl; } + } - check(false); + if( _master >= 0 ) { + assert( static_cast(_master) < _nodes.size() ); + LOG(2) << "dbclient_rs getSlave no member in secondary state found, returning primary " << _nodes[ _master ] << endl; + return _nodes[_master].addr; } - LOG(2) << "no suitable slave nodes found, returning default node " << _nodes[ 0 ] << endl; - + LOG(2) << "dbclient_rs getSlave no suitable member found, returning first node " << _nodes[ 0 ] << endl; + assert( _nodes.size() > 0 ); return _nodes[0].addr; } @@ -820,10 +809,14 @@ namespace mongo { bool DBClientReplicaSet::call( Message &toSend, Message &response, bool assertOk , string * actualServer ) { + const char * ns = 0; + if ( toSend.operation() == dbQuery ) { // TODO: might be possible to do this faster by changing api DbMessage dm( toSend ); QueryMessage qm( dm ); + ns = qm.ns; + if ( qm.queryOptions & QueryOption_SlaveOk ) { for ( int i=0; i<3; i++ ) { try { @@ -844,7 +837,26 @@ namespace mongo { DBClientConnection* m = checkMaster(); if ( actualServer ) *actualServer = m->getServerAddress(); - return m->call( toSend , response , assertOk ); + + if ( ! m->call( toSend , response , assertOk ) ) + return false; + + if ( ns ) { + QueryResult * res = (QueryResult*)response.singleData(); + if ( res->nReturned == 1 ) { + BSONObj x(res->data() ); + if ( str::contains( ns , "$cmd" ) ) { + if ( isNotMasterErrorString( x["errmsg"] ) ) + isntMaster(); + } + else { + if ( isNotMasterErrorString( getErrField( x ) ) ) + isntMaster(); + } + } + } + + return true; } } -- cgit v1.2.3