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.cpp41
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 );