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); }
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 void test_mongoc_client_read_prefs (void) { mongoc_collection_t *collection; mongoc_read_prefs_t *read_prefs; mongoc_cursor_t *cursor; mongoc_client_t *client; mock_server_t *server; uint16_t port; const bson_t *doc; bson_error_t error; bool success = false; bson_t b = BSON_INITIALIZER; bson_t q = BSON_INITIALIZER; char *uristr; port = 20000 + (rand () % 1000); server = mock_server_new ("127.0.0.1", port, read_prefs_handler, &success); mock_server_run_in_thread (server); usleep (5000); uristr = bson_strdup_printf ("mongodb://127.0.0.1:%hu/", port); client = mongoc_client_new (uristr); if (!_mongoc_client_warm_up (client, &error)) { assert (false); } collection = mongoc_client_get_collection (client, "test", "test"); bson_append_utf8 (&b, "dc", 2, "ny", 2); read_prefs = mongoc_read_prefs_new (MONGOC_READ_SECONDARY_PREFERRED); mongoc_read_prefs_add_tag (read_prefs, &b); mongoc_read_prefs_add_tag (read_prefs, NULL); mongoc_collection_set_read_prefs (collection, read_prefs); cursor = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 1, 0, &q, NULL, read_prefs); mongoc_cursor_next (cursor, &doc); usleep (50000); assert (success); mongoc_read_prefs_destroy (read_prefs); mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mock_server_quit (server, 0); bson_destroy (&b); bson_free (uristr); }