static bson_bool_t _mongoc_cursor_query (mongoc_cursor_t *cursor) { bson_uint32_t hint; bson_uint32_t request_id; mongoc_rpc_t rpc; ENTRY; bson_return_val_if_fail(cursor, FALSE); if (!_mongoc_client_warm_up (cursor->client, &cursor->error)) { cursor->failed = TRUE; RETURN (FALSE); } rpc.query.msg_len = 0; rpc.query.request_id = 0; rpc.query.response_to = 0; rpc.query.opcode = MONGOC_OPCODE_QUERY; rpc.query.flags = cursor->flags; rpc.query.collection = cursor->ns; rpc.query.skip = cursor->skip; if ((cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR)) { rpc.query.n_return = 0; } else { rpc.query.n_return = _mongoc_n_return(cursor); } rpc.query.query = bson_get_data(&cursor->query); rpc.query.fields = bson_get_data(&cursor->fields); if (!(hint = _mongoc_client_sendv (cursor->client, &rpc, 1, 0, NULL, cursor->read_prefs, &cursor->error))) { goto failure; } cursor->hint = hint; request_id = BSON_UINT32_FROM_LE(rpc.header.request_id); _mongoc_buffer_clear(&cursor->buffer, FALSE); if (!_mongoc_client_recv(cursor->client, &cursor->rpc, &cursor->buffer, hint, &cursor->error)) { goto failure; } if ((cursor->rpc.header.opcode != MONGOC_OPCODE_REPLY) || (cursor->rpc.header.response_to != request_id)) { bson_set_error(&cursor->error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "A reply to an invalid request id was received."); goto failure; } if (_mongoc_cursor_unwrap_failure(cursor)) { if ((cursor->error.domain == MONGOC_ERROR_QUERY) && (cursor->error.code == MONGOC_ERROR_QUERY_NOT_TAILABLE)) { cursor->failed = TRUE; } goto failure; } if (cursor->reader) { bson_reader_destroy(cursor->reader); } cursor->reader = bson_reader_new_from_data(cursor->rpc.reply.documents, cursor->rpc.reply.documents_len); if (cursor->flags & MONGOC_QUERY_EXHAUST) { cursor->in_exhaust = TRUE; cursor->client->in_exhaust = TRUE; } cursor->done = FALSE; cursor->end_of_event = FALSE; cursor->sent = TRUE; RETURN(TRUE); failure: cursor->failed = TRUE; cursor->done = TRUE; RETURN(FALSE); }
static bson_bool_t _mongoc_cursor_get_more (mongoc_cursor_t *cursor) { bson_uint64_t cursor_id; bson_uint32_t request_id; mongoc_rpc_t rpc; ENTRY; BSON_ASSERT(cursor); if (! cursor->in_exhaust) { if (!_mongoc_client_warm_up (cursor->client, &cursor->error)) { cursor->failed = TRUE; RETURN (FALSE); } if (!(cursor_id = cursor->rpc.reply.cursor_id)) { bson_set_error(&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "No valid cursor was provided."); goto failure; } rpc.get_more.msg_len = 0; rpc.get_more.request_id = 0; rpc.get_more.response_to = 0; rpc.get_more.opcode = MONGOC_OPCODE_GET_MORE; rpc.get_more.zero = 0; rpc.get_more.collection = cursor->ns; if ((cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR)) { rpc.get_more.n_return = 0; } else { rpc.get_more.n_return = _mongoc_n_return(cursor); } rpc.get_more.cursor_id = cursor_id; /* * TODO: Stamp protections for disconnections. */ if (!_mongoc_client_sendv(cursor->client, &rpc, 1, cursor->hint, NULL, cursor->read_prefs, &cursor->error)) { cursor->done = TRUE; cursor->failed = TRUE; RETURN(FALSE); } request_id = BSON_UINT32_FROM_LE(rpc.header.request_id); } else { request_id = BSON_UINT32_FROM_LE(cursor->rpc.header.request_id); } _mongoc_buffer_clear(&cursor->buffer, FALSE); if (!_mongoc_client_recv(cursor->client, &cursor->rpc, &cursor->buffer, cursor->hint, &cursor->error)) { goto failure; } if ((cursor->rpc.header.opcode != MONGOC_OPCODE_REPLY) || (cursor->rpc.header.response_to != request_id)) { bson_set_error(&cursor->error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "A reply to an invalid request id was received."); goto failure; } if (_mongoc_cursor_unwrap_failure(cursor)) { goto failure; } if (cursor->reader) { bson_reader_destroy(cursor->reader); } cursor->reader = bson_reader_new_from_data(cursor->rpc.reply.documents, cursor->rpc.reply.documents_len); cursor->end_of_event = FALSE; RETURN(TRUE); failure: cursor->done = TRUE; cursor->failed = TRUE; RETURN(FALSE); }
static bool _mongoc_cursor_query (mongoc_cursor_t *cursor) { mongoc_rpc_t rpc; uint32_t hint; uint32_t request_id; ENTRY; bson_return_val_if_fail (cursor, false); if (!_mongoc_client_warm_up (cursor->client, &cursor->error)) { cursor->failed = true; RETURN (false); } rpc.query.msg_len = 0; rpc.query.request_id = 0; rpc.query.response_to = 0; rpc.query.opcode = MONGOC_OPCODE_QUERY; rpc.query.flags = cursor->flags; rpc.query.collection = cursor->ns; rpc.query.skip = cursor->skip; if ((cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR)) { rpc.query.n_return = 0; } else { rpc.query.n_return = _mongoc_n_return(cursor); } rpc.query.query = bson_get_data(&cursor->query); if (cursor->has_fields) { rpc.query.fields = bson_get_data (&cursor->fields); } else { rpc.query.fields = NULL; } if (!(hint = _mongoc_client_sendv (cursor->client, &rpc, 1, cursor->hint, NULL, cursor->read_prefs, &cursor->error))) { GOTO (failure); } cursor->hint = hint; request_id = BSON_UINT32_FROM_LE(rpc.header.request_id); _mongoc_buffer_clear(&cursor->buffer, false); if (!_mongoc_client_recv(cursor->client, &cursor->rpc, &cursor->buffer, hint, &cursor->error)) { GOTO (failure); } if (cursor->rpc.header.opcode != MONGOC_OPCODE_REPLY) { bson_set_error (&cursor->error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "Invalid opcode. Expected %d, got %d.", MONGOC_OPCODE_REPLY, cursor->rpc.header.opcode); GOTO (failure); } if (cursor->rpc.header.response_to != request_id) { bson_set_error (&cursor->error, MONGOC_ERROR_PROTOCOL, MONGOC_ERROR_PROTOCOL_INVALID_REPLY, "Invalid response_to. Expected %d, got %d.", request_id, cursor->rpc.header.response_to); GOTO (failure); } if (_mongoc_cursor_unwrap_failure(cursor)) { if ((cursor->error.domain == MONGOC_ERROR_QUERY) && (cursor->error.code == MONGOC_ERROR_QUERY_NOT_TAILABLE)) { cursor->failed = true; } GOTO (failure); } if (cursor->reader) { bson_reader_destroy(cursor->reader); } cursor->reader = bson_reader_new_from_data(cursor->rpc.reply.documents, cursor->rpc.reply.documents_len); if ((cursor->flags & MONGOC_QUERY_EXHAUST)) { cursor->in_exhaust = true; cursor->client->in_exhaust = true; } cursor->done = false; cursor->end_of_event = false; cursor->sent = true; RETURN (true); failure: cursor->failed = true; cursor->done = true; RETURN (false); }