bool DBClientCursor::peekError(BSONObj* error){ if( ! wasError ) return false; vector<BSONObj> v; peek(v, 1); verify( v.size() == 1 ); verify( hasErrField( v[0] ) ); if( error ) *error = v[0].getOwned(); return true; }
void DBClientReplicaSet::checkResponse( const char* data, int nReturned, bool* retry, string* targetHost ){ // For now, do exactly as we did before, so as not to break things. In general though, we // should fix this so checkResponse has a more consistent contract. if( ! retry ){ if( _lazyState._lastClient ) return _lazyState._lastClient->checkResponse( data, nReturned ); else return checkMaster()->checkResponse( data, nReturned ); } *retry = false; if( targetHost && _lazyState._lastClient ) *targetHost = _lazyState._lastClient->getServerAddress(); else *targetHost = ""; if( ! _lazyState._lastClient ) return; if( nReturned != 1 && nReturned != -1 ) return; BSONObj dataObj; if( nReturned == 1 ) dataObj = BSONObj( data ); // Check if we should retry here if( _lazyState._lastOp == dbQuery && _lazyState._slaveOk ){ // Check the error code for a slave not secondary error if( nReturned == -1 || ( hasErrField( dataObj ) && ! dataObj["code"].eoo() && dataObj["code"].Int() == 13436 ) ){ bool wasMaster = false; if( _lazyState._lastClient == _slave.get() ){ isntSecondary(); } else if( _lazyState._lastClient == _master.get() ){ wasMaster = true; isntMaster(); } else warning() << "passed " << dataObj << " but last rs client " << _lazyState._lastClient->toString() << " is not master or secondary" << endl; if( _lazyState._retries < 3 ){ _lazyState._retries++; *retry = true; } else{ // assert( wasMaster ); // printStackTrace(); log() << "too many retries (" << _lazyState._retries << "), could not get data from replica set" << endl; } } } }
bool DBClientCursor::peekError(BSONObj* error) { if (!wasError) return false; vector<BSONObj> v; peek(v, 1); verify(v.size() == 1); // We check both the legacy error format, and the new error format. hasErrField checks for // $err, and getStatusFromCommandResult checks for modern errors of the form '{ok: 0.0, code: // <...>, errmsg: ...}'. verify(hasErrField(v[0]) || !getStatusFromCommandResult(v[0]).isOK()); if (error) *error = v[0].getOwned(); return true; }
void DBClientReplicaSet::checkResponse( const char* data, int nReturned, bool* retry, string* targetHost ){ // For now, do exactly as we did before, so as not to break things. In general though, we // should fix this so checkResponse has a more consistent contract. if( ! retry ){ if( _lazyState._lastClient ) return _lazyState._lastClient->checkResponse( data, nReturned ); else return checkMaster()->checkResponse( data, nReturned ); } *retry = false; if( targetHost && _lazyState._lastClient ) *targetHost = _lazyState._lastClient->getServerAddress(); else if (targetHost) *targetHost = ""; if( ! _lazyState._lastClient ) return; // nReturned == 1 means that we got one result back, which might be an error // nReturned == -1 is a sentinel value for "no data returned" aka (usually) network problem // If neither, this must be a query result so our response is ok wrt the replica set if( nReturned != 1 && nReturned != -1 ) return; BSONObj dataObj; if( nReturned == 1 ) dataObj = BSONObj( data ); // Check if we should retry here if( _lazyState._lastOp == dbQuery && _lazyState._secondaryQueryOk ){ // query could potentially go to a secondary, so see if this is an error (or empty) and // retry if we're not past our retry limit. if( nReturned == -1 /* no result, maybe network problem */ || ( hasErrField( dataObj ) && ! dataObj["code"].eoo() && dataObj["code"].Int() == NotMasterOrSecondaryCode ) ){ if( _lazyState._lastClient == _lastSlaveOkConn.get() ){ isntSecondary(); } else if( _lazyState._lastClient == _master.get() ){ isntMaster(); } else { warning() << "passed " << dataObj << " but last rs client " << _lazyState._lastClient->toString() << " is not master or secondary" << endl; } if ( _lazyState._retries < static_cast<int>( MAX_RETRY ) ) { _lazyState._retries++; *retry = true; } else{ log() << "too many retries (" << _lazyState._retries << "), could not get data from replica set" << endl; } } } else if( _lazyState._lastOp == dbQuery ){ // if query could not potentially go to a secondary, just mark the master as bad if( nReturned == -1 /* no result, maybe network problem */ || ( hasErrField( dataObj ) && ! dataObj["code"].eoo() && dataObj["code"].Int() == NotMasterNoSlaveOkCode ) ) { if( _lazyState._lastClient == _master.get() ){ isntMaster(); } } } }