diff options
Diffstat (limited to 'client/dbclient_rs.cpp')
-rw-r--r-- | client/dbclient_rs.cpp | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/client/dbclient_rs.cpp b/client/dbclient_rs.cpp index ae01da3..37f6225 100644 --- a/client/dbclient_rs.cpp +++ b/client/dbclient_rs.cpp @@ -463,9 +463,12 @@ namespace mongo { if ( ! _slave->isFailed() ) return _slave.get(); _monitor->notifySlaveFailure( _slaveHost ); + _slaveHost = _monitor->getSlave(); } - - _slaveHost = _monitor->getSlave(); + else { + _slaveHost = h; + } + _slave.reset( new DBClientConnection( true , this ) ); _slave->connect( _slaveHost ); _auth( _slave.get() ); @@ -544,7 +547,7 @@ namespace mongo { // checkSlave will try a different slave automatically after a failure for ( int i=0; i<2; i++ ) { try { - return checkSlave()->query(ns,query,nToReturn,nToSkip,fieldsToReturn,queryOptions,batchSize); + return checkSlaveQueryResult( checkSlave()->query(ns,query,nToReturn,nToSkip,fieldsToReturn,queryOptions,batchSize) ); } catch ( DBException &e ) { log() << "can't query replica set slave " << i << " : " << _slaveHost << e.what() << endl; @@ -581,6 +584,38 @@ namespace mongo { assert(0); } + auto_ptr<DBClientCursor> DBClientReplicaSet::checkSlaveQueryResult( auto_ptr<DBClientCursor> result ){ + + bool isError = result->hasResultFlag( ResultFlag_ErrSet ); + if( ! isError ) return result; + + BSONObj error = result->peekOne(); + + BSONElement code = error["code"]; + if( code.eoo() || ! code.isNumber() ){ + warning() << "no code for error from secondary host " << _slaveHost << ", error was " << error << endl; + return result; + } + + // We only check for "not master or secondary" errors here + + // If the error code here ever changes, we need to change this code also + if( code.Int() == 13436 /* not master or secondary */ ){ + isntSecondary(); + throw DBException( str::stream() << "slave " << _slaveHost.toString() << " is no longer secondary", 14812 ); + } + + return result; + } + + void DBClientReplicaSet::isntSecondary() { + log() << "slave no longer has secondary status: " << _slaveHost << endl; + // Failover to next slave + _monitor->notifySlaveFailure( _slaveHost ); + _slave.reset(); + } + + void DBClientReplicaSet::isntMaster() { log() << "got not master for: " << _masterHost << endl; _monitor->notifyFailure( _masterHost ); |