void DBClientCursor::dataReceived() { QueryResult *qr = (QueryResult *) m->singleData(); resultFlags = qr->resultFlags(); if ( qr->resultFlags() & QueryResult::ResultFlag_CursorNotFound ) { // cursor id no longer valid at the server. assert( qr->cursorId == 0 ); cursorId = 0; // 0 indicates no longer valid (dead) if ( ! ( opts & QueryOption_CursorTailable ) ) throw UserException( 13127 , "getMore: cursor didn't exist on server, possible restart or timeout?" ); } if ( cursorId == 0 || ! ( opts & QueryOption_CursorTailable ) ) { // only set initially: we don't want to kill it on end of data // if it's a tailable cursor cursorId = qr->cursorId; } nReturned = qr->nReturned; pos = 0; data = qr->data(); connector->checkResponse( data, nReturned ); /* this assert would fire the way we currently work: assert( nReturned || cursorId == 0 ); */ }
// THROWS static void recvAsCmd( DBClientBase* conn, Message* toRecv, BSONObj* result ) { conn->recv( *toRecv ); // A query result is returned from commands QueryResult* recvdQuery = reinterpret_cast<QueryResult*>( toRecv->singleData() ); *result = BSONObj( recvdQuery->data() ); }
// THROWS static void recvAsCmd( DBClientBase* conn, Message* toRecv, BSONObj* result ) { if ( !conn->recv( *toRecv ) ) { // Confusingly, socket exceptions here are written to the log, not thrown. uasserted( 17255, "error receiving write command response, " "possible socket exception - see logs" ); } // A query result is returned from commands QueryResult* recvdQuery = reinterpret_cast<QueryResult*>( toRecv->singleData() ); *result = BSONObj( recvdQuery->data() ); }
void DBClientCursor::dataReceived() { QueryResult *qr = (QueryResult *) m->data; if ( qr->resultFlags() & QueryResult::ResultFlag_CursorNotFound ) { // cursor id no longer valid at the server. assert( qr->cursorId == 0 ); cursorId = 0; // 0 indicates no longer valid (dead) } if ( cursorId == 0 || ! ( opts & Option_CursorTailable ) ) { // only set initially: we don't want to kill it on end of data // if it's a tailable cursor cursorId = qr->cursorId; } nReturned = qr->nReturned; pos = 0; data = qr->data(); connector->checkResponse( data, nReturned ); /* this assert would fire the way we currently work: assert( nReturned || cursorId == 0 ); */ }
void DBClientCursor::dataReceived( bool& retry, string& host ) { QueryResult *qr = (QueryResult *) b.m->singleData(); resultFlags = qr->resultFlags(); if ( qr->resultFlags() & ResultFlag_ErrSet ) { wasError = true; } if ( qr->resultFlags() & ResultFlag_CursorNotFound ) { // cursor id no longer valid at the server. assert( qr->cursorId == 0 ); cursorId = 0; // 0 indicates no longer valid (dead) if ( ! ( opts & QueryOption_CursorTailable ) ) throw UserException( 13127 , "getMore: cursor didn't exist on server, possible restart or timeout?" ); } if ( cursorId == 0 || ! ( opts & QueryOption_CursorTailable ) ) { // only set initially: we don't want to kill it on end of data // if it's a tailable cursor cursorId = qr->cursorId; } b.nReturned = qr->nReturned; b.pos = 0; b.data = qr->data(); _client->checkResponse( b.data, b.nReturned, &retry, &host ); // watches for "not master" if( qr->resultFlags() & ResultFlag_ShardConfigStale ) { BSONObj error; assert( peekError( &error ) ); throw RecvStaleConfigException( error["ns"].String(), (string)"stale config on lazy receive" + causedBy( getErrField( error ) ) ); } /* this assert would fire the way we currently work: assert( nReturned || cursorId == 0 ); */ }
Status DBClientMultiCommand::recvAny( ConnectionString* endpoint, BSONSerializable* response ) { scoped_ptr<PendingCommand> command( _pendingCommands.front() ); _pendingCommands.pop_front(); *endpoint = command->endpoint; if ( !command->status.isOK() ) return command->status; dassert( NULL != command->conn ); try { Message toRecv; command->conn->recv( toRecv ); // RPC was sent as a command, so a query result is what we get back QueryResult* recvdQuery = reinterpret_cast<QueryResult*>( toRecv.singleData() ); BSONObj result( recvdQuery->data() ); shardConnectionPool.release( command->endpoint.toString(), command->conn ); command->conn = NULL; string errMsg; if ( !response->parseBSON( result, &errMsg ) || !response->isValid( &errMsg ) ) { return Status( ErrorCodes::FailedToParse, errMsg ); } } catch ( const DBException& ex ) { delete command->conn; command->conn = NULL; return ex.toStatus(); } return Status::OK(); }
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; shared_ptr<ReadPreferenceSetting> readPref( _extractReadPref( qm.query, qm.queryOptions ) ); if ( _isSecondaryQuery( ns, qm.query, *readPref ) ) { LOG( 3 ) << "dbclient_rs call using secondary or tagged node selection in " << _getMonitor()->getName() << ", read pref is " << readPref->toBSON() << " (primary : " << ( _master.get() != NULL ? _master->getServerAddress() : "[not cached]" ) << ", lastTagged : " << ( _lastSlaveOkConn.get() != NULL ? _lastSlaveOkConn->getServerAddress() : "[not cached]" ) << ")" << endl; for (size_t retry = 0; retry < MAX_RETRY; retry++) { try { DBClientConnection* conn = selectNodeUsingTags(readPref); if (conn == NULL) { return false; } if (actualServer != NULL) { *actualServer = conn->getServerAddress(); } return conn->call(toSend, response, assertOk); } catch ( const DBException& dbExcep ) { LOG(1) << "can't call replica set node " << _lastSlaveOkHost << ": " << causedBy( dbExcep ) << endl; if ( actualServer ) *actualServer = ""; invalidateLastSlaveOkCache(); } } // Was not able to successfully send after max retries return false; } } LOG( 3 ) << "dbclient_rs call to primary node in " << _getMonitor()->getName() << endl; DBClientConnection* m = checkMaster(); if ( actualServer ) *actualServer = m->getServerAddress(); 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; }