bson_bool_t _mongoc_cursor_next (mongoc_cursor_t *cursor, const bson_t **bson) { const bson_t *b; bson_bool_t eof; ENTRY; BSON_ASSERT(cursor); if (cursor->client->in_exhaust && ! cursor->in_exhaust) { bson_set_error(&cursor->error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_IN_EXHAUST, "Another cursor derived from this client is in exhaust."); cursor->failed = TRUE; RETURN(FALSE); } if (bson) { *bson = NULL; } if (cursor->limit && cursor->count >= cursor->limit) { return FALSE; } /* * Short circuit if we are finished already. */ if (BSON_UNLIKELY(cursor->done)) { RETURN(FALSE); } /* * Check to see if we need to send a GET_MORE for more results. */ if (!cursor->sent) { if (!_mongoc_cursor_query(cursor)) { RETURN(FALSE); } } else if (BSON_UNLIKELY(cursor->end_of_event)) { if (!_mongoc_cursor_get_more(cursor)) { RETURN(FALSE); } } /* * Read the next BSON document from the event. */ eof = FALSE; b = bson_reader_read(cursor->reader, &eof); cursor->end_of_event = eof; cursor->done = cursor->end_of_event && ( (cursor->in_exhaust && !cursor->rpc.reply.cursor_id) || (!b && !(cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR)) ); /* * Do a supplimental check to see if we had a corrupted reply in the * document stream. */ if (!b && !eof) { cursor->failed = TRUE; bson_set_error(&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "The reply was corrupt."); RETURN(FALSE); } if (bson) { *bson = b; } RETURN(!!b); }
bool _mongoc_cursor_next (mongoc_cursor_t *cursor, const bson_t **bson) { const bson_t *b; bool eof; ENTRY; BSON_ASSERT (cursor); if (bson) { *bson = NULL; } if (cursor->done || cursor->failed) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "Cannot advance a completed or failed cursor."); RETURN (false); } /* * We cannot proceed if another cursor is receiving results in exhaust mode. */ if (cursor->client->in_exhaust && !cursor->in_exhaust) { bson_set_error (&cursor->error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_IN_EXHAUST, "Another cursor derived from this client is in exhaust."); cursor->failed = true; RETURN (false); } /* * If we reached our limit, make sure we mark this as done and do not try to * make further progress. */ if (cursor->limit && cursor->count >= cursor->limit) { cursor->done = true; RETURN (false); } /* * Try to read the next document from the reader if it exists, we might * get NULL back and EOF, in which case we need to submit a getmore. */ if (cursor->reader) { eof = false; b = bson_reader_read (cursor->reader, &eof); cursor->end_of_event = eof; if (b) { GOTO (complete); } } /* * Check to see if we need to send a GET_MORE for more results. */ if (!cursor->sent) { if (!_mongoc_cursor_query (cursor)) { RETURN (false); } } else if (BSON_UNLIKELY (cursor->end_of_event) && cursor->rpc.reply.cursor_id) { if (!_mongoc_cursor_get_more (cursor)) { RETURN (false); } } eof = false; b = bson_reader_read (cursor->reader, &eof); cursor->end_of_event = eof; complete: cursor->done = (cursor->end_of_event && ((cursor->in_exhaust && !cursor->rpc.reply.cursor_id) || (!b && !(cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR)))); /* * Do a supplimental check to see if we had a corrupted reply in the * document stream. */ if (!b && !eof) { cursor->failed = true; bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "The reply was corrupt."); RETURN (false); } if (bson) { *bson = b; } RETURN (!!b); }