From 57e4033e70ca3ca47a6cb090deedce2b6dc090bc Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Tue, 9 Sep 2025 14:24:05 -0400 Subject: [PATCH 01/10] Delete legacy op cursor code --- src/libmongoc/CMakeLists.txt | 1 - src/libmongoc/src/mongoc/mongoc-cursor-cmd.c | 19 +- .../src/mongoc/mongoc-cursor-find-opquery.c | 115 ----- src/libmongoc/src/mongoc/mongoc-cursor-find.c | 10 +- .../src/mongoc/mongoc-cursor-legacy.c | 402 ------------------ .../src/mongoc/mongoc-cursor-private.h | 8 - src/libmongoc/src/mongoc/mongoc-cursor.c | 61 --- src/libmongoc/tests/test-mongoc-cursor.c | 33 +- 8 files changed, 11 insertions(+), 638 deletions(-) delete mode 100644 src/libmongoc/src/mongoc/mongoc-cursor-find-opquery.c diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 2fa771cf945..8386bc93059 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -569,7 +569,6 @@ set (MONGOC_SOURCES ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-cmd-deprecated.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-find.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-find-cmd.c - ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-find-opquery.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-legacy.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-array.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-database.c diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c b/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c index c9f402c0b48..5cd4239a95e 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c @@ -19,8 +19,8 @@ #include -typedef enum { NONE, CMD_RESPONSE, OP_GETMORE_RESPONSE } reading_from_t; -typedef enum { UNKNOWN, GETMORE_CMD, OP_GETMORE } getmore_type_t; +typedef enum { NONE, CMD_RESPONSE } reading_from_t; +typedef enum { UNKNOWN, GETMORE_CMD } getmore_type_t; typedef struct _data_cmd_t { /* Two paths: * - Mongo 3.2+, sent "getMore" cmd, we're reading reply's "nextBatch" array @@ -53,13 +53,7 @@ _getmore_type(mongoc_cursor_t *cursor) wire_version = server_stream->sd->max_wire_version; mongoc_server_stream_cleanup(server_stream); - // CDRIVER-4722: always GETMORE_CMD once WIRE_VERSION_MIN >= - // WIRE_VERSION_4_2. - if (_mongoc_cursor_use_op_msg(cursor, wire_version)) { - data->getmore_type = GETMORE_CMD; - } else { - data->getmore_type = OP_GETMORE; - } + data->getmore_type = GETMORE_CMD; return data->getmore_type; } @@ -94,9 +88,6 @@ _pop_from_batch(mongoc_cursor_t *cursor) case CMD_RESPONSE: _mongoc_cursor_response_read(cursor, &data->response, &cursor->current); break; - case OP_GETMORE_RESPONSE: - cursor->current = bson_reader_read(data->response_legacy.reader, NULL); - break; case NONE: default: fprintf(stderr, "trying to pop from an uninitialized cursor reader.\n"); @@ -124,10 +115,6 @@ _get_next_batch(mongoc_cursor_t *cursor) bson_destroy(&getmore_cmd); data->reading_from = CMD_RESPONSE; return IN_BATCH; - case OP_GETMORE: - _mongoc_cursor_op_getmore(cursor, &data->response_legacy); - data->reading_from = OP_GETMORE_RESPONSE; - return IN_BATCH; case UNKNOWN: default: return DONE; diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-find-opquery.c b/src/libmongoc/src/mongoc/mongoc-cursor-find-opquery.c deleted file mode 100644 index 087fb10fa03..00000000000 --- a/src/libmongoc/src/mongoc/mongoc-cursor-find-opquery.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2009-present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include - -#include - -typedef struct _data_find_opquery_t { - mongoc_cursor_response_legacy_t response_legacy; - bson_t filter; -} data_find_opquery_t; - - -static bool -_hit_limit(mongoc_cursor_t *cursor) -{ - int64_t limit, limit_abs; - limit = mongoc_cursor_get_limit(cursor); - /* don't use llabs, that is a C99 function. */ - limit_abs = limit > 0 ? limit : -limit; - /* mark as done if we've hit the limit. */ - if (limit && cursor->count >= limit_abs) { - return true; - } - return false; -} - - -static mongoc_cursor_state_t -_prime(mongoc_cursor_t *cursor) -{ - data_find_opquery_t *data = (data_find_opquery_t *)cursor->impl.data; - if (_hit_limit(cursor)) { - return DONE; - } - - _mongoc_cursor_op_query_find(cursor, &data->filter, &data->response_legacy); - return IN_BATCH; -} - - -static mongoc_cursor_state_t -_pop_from_batch(mongoc_cursor_t *cursor) -{ - data_find_opquery_t *data = (data_find_opquery_t *)cursor->impl.data; - - if (_hit_limit(cursor)) { - return DONE; - } - - cursor->current = bson_reader_read(data->response_legacy.reader, NULL); - if (cursor->current) { - return IN_BATCH; - } else { - return cursor->cursor_id ? END_OF_BATCH : DONE; - } -} - - -static mongoc_cursor_state_t -_get_next_batch(mongoc_cursor_t *cursor) -{ - data_find_opquery_t *data = (data_find_opquery_t *)cursor->impl.data; - _mongoc_cursor_op_getmore(cursor, &data->response_legacy); - return IN_BATCH; -} - - -static void -_destroy(mongoc_cursor_impl_t *impl) -{ - data_find_opquery_t *data = (data_find_opquery_t *)impl->data; - _mongoc_cursor_response_legacy_destroy(&data->response_legacy); - bson_destroy(&data->filter); - bson_free(data); -} - - -static void -_clone(mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src) -{ - data_find_opquery_t *data_dst = bson_malloc0(sizeof(data_find_opquery_t)); - data_find_opquery_t *data_src = (data_find_opquery_t *)src->data; - _mongoc_cursor_response_legacy_init(&data_dst->response_legacy); - bson_copy_to(&data_src->filter, &data_dst->filter); - dst->data = data_dst; -} - - -void -_mongoc_cursor_impl_find_opquery_init(mongoc_cursor_t *cursor, bson_t *filter) -{ - data_find_opquery_t *data = BSON_ALIGNED_ALLOC0(data_find_opquery_t); - _mongoc_cursor_response_legacy_init(&data->response_legacy); - BSON_ASSERT(bson_steal(&data->filter, filter)); - cursor->impl.prime = _prime; - cursor->impl.pop_from_batch = _pop_from_batch; - cursor->impl.get_next_batch = _get_next_batch; - cursor->impl.destroy = _destroy; - cursor->impl.clone = _clone; - cursor->impl.data = data; -} diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-find.c b/src/libmongoc/src/mongoc/mongoc-cursor-find.c index 2772145e0a2..55e0eeb9c82 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-find.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-find.c @@ -26,8 +26,6 @@ typedef struct _data_find_t { extern void _mongoc_cursor_impl_find_cmd_init(mongoc_cursor_t *cursor, bson_t *filter); -extern void -_mongoc_cursor_impl_find_opquery_init(mongoc_cursor_t *cursor, bson_t *filter); static mongoc_cursor_state_t @@ -48,12 +46,8 @@ _prime(mongoc_cursor_t *cursor) mongoc_server_stream_cleanup(server_stream); /* set all mongoc_impl_t function pointers. */ - /* CDRIVER-4722: always find_cmd when server >= 4.2 */ - if (_mongoc_cursor_use_op_msg(cursor, wire_version)) { - _mongoc_cursor_impl_find_cmd_init(cursor, &data->filter /* stolen */); - } else { - _mongoc_cursor_impl_find_opquery_init(cursor, &data->filter /* stolen */); - } + _mongoc_cursor_impl_find_cmd_init(cursor, &data->filter /* stolen */); + /* destroy this impl data since impl functions have been replaced. */ bson_free(data); /* prime with the new implementation. */ diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c b/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c index 9b2dd7fa08c..edd9f5b6bca 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c @@ -160,104 +160,6 @@ _mongoc_cursor_op_getmore_send(mongoc_cursor_t *cursor, return true; } -void -_mongoc_cursor_op_getmore(mongoc_cursor_t *cursor, mongoc_cursor_response_legacy_t *response) -{ - BSON_ASSERT_PARAM(cursor); - BSON_ASSERT_PARAM(response); - - ENTRY; - - const int64_t started = bson_get_monotonic_time(); - - const mongoc_ss_log_context_t ss_log_context = { - .operation = "getMore", .has_operation_id = true, .operation_id = cursor->operation_id}; - mongoc_server_stream_t *const server_stream = _mongoc_cursor_fetch_stream(cursor, &ss_log_context); - - if (!server_stream) { - GOTO(done); - } - - int32_t flags; - if (!_mongoc_cursor_opts_to_flags(cursor, server_stream, &flags)) { - GOTO(fail); - } - mongoc_cluster_t *const cluster = &cursor->client->cluster; - - const int32_t request_id = cursor->in_exhaust ? mcd_rpc_header_get_request_id(response->rpc) : ++cluster->request_id; - - if (!cursor->in_exhaust && - !_mongoc_cursor_op_getmore_send(cursor, server_stream, request_id, flags, response->rpc)) { - GOTO(fail); - } - - mcd_rpc_message_reset(response->rpc); - _mongoc_buffer_clear(&response->buffer, false); - cursor->cursor_id = 0; - - if (!_mongoc_client_recv(cursor->client, response->rpc, &response->buffer, server_stream, &cursor->error)) { - GOTO(fail); - } - - const int32_t op_code = mcd_rpc_header_get_op_code(response->rpc); - if (op_code != MONGOC_OP_CODE_REPLY) { - _mongoc_set_error(&cursor->error, - MONGOC_ERROR_PROTOCOL, - MONGOC_ERROR_PROTOCOL_INVALID_REPLY, - "invalid opcode for OP_GET_MORE: expected %" PRId32 ", got %" PRId32, - MONGOC_OP_CODE_REPLY, - op_code); - GOTO(fail); - } - - const int32_t response_to = mcd_rpc_header_get_response_to(response->rpc); - if (response_to != request_id) { - _mongoc_set_error(&cursor->error, - MONGOC_ERROR_PROTOCOL, - MONGOC_ERROR_PROTOCOL_INVALID_REPLY, - "invalid response_to for OP_GET_MORE: expected %" PRId32 ", got %" PRId32, - request_id, - response_to); - GOTO(fail); - } - - if (!mcd_rpc_message_check_ok( - response->rpc, cursor->client->error_api_version, &cursor->error, &cursor->error_doc)) { - GOTO(fail); - } - - if (response->reader) { - bson_reader_destroy(response->reader); - } - - cursor->cursor_id = mcd_rpc_op_reply_get_cursor_id(response->rpc); - - const void *documents = mcd_rpc_op_reply_get_documents(response->rpc); - if (documents == NULL) { - // Use a non-NULL pointer to satisfy precondition of - // `bson_reader_new_from_data`: - documents = ""; - } - - response->reader = bson_reader_new_from_data(documents, mcd_rpc_op_reply_get_documents_len(response->rpc)); - - _mongoc_cursor_monitor_succeeded(cursor, - response, - bson_get_monotonic_time() - started, - false, /* not first batch */ - server_stream, - "getMore"); - - GOTO(done); - -fail: - _mongoc_cursor_monitor_failed(cursor, bson_get_monotonic_time() - started, server_stream, "getMore"); - -done: - mongoc_server_stream_cleanup(server_stream); -} - - #define OPT_CHECK(_type) \ do { \ if (!BSON_ITER_HOLDS_##_type(&iter)) { \ @@ -327,316 +229,12 @@ _mongoc_cursor_op_getmore(mongoc_cursor_t *cursor, mongoc_cursor_response_legacy BSON_APPEND_DOCUMENT(query, "$" #_legacy_name, &subdocument); \ } while (false) -static bson_t * -_mongoc_cursor_parse_opts_for_op_query(mongoc_cursor_t *cursor, - mongoc_server_stream_t *stream, - bson_t *filter, - bson_t *query /* OUT */, - bson_t *fields /* OUT */, - int32_t *flags /* OUT */, - int32_t *skip /* OUT */) -{ - bool pushed_dollar_query; - bson_iter_t iter; - uint32_t len; - const uint8_t *data; - bson_t subdocument; - const char *key; - char *dollar_modifier; - - *flags = MONGOC_OP_QUERY_FLAG_NONE; - *skip = 0; - - /* assume we'll send filter straight to server, like "{a: 1}". if we find an - * opt we must add, like "sort", we push the query like "$query: {a: 1}", - * then add a query modifier for the option, in this example "$orderby". - */ - pushed_dollar_query = false; - - if (!bson_iter_init(&iter, &cursor->opts)) { - OPT_BSON_ERR("Invalid 'opts' parameter."); - } - - while (bson_iter_next(&iter)) { - key = bson_iter_key(&iter); - - /* most common options first */ - if (!strcmp(key, MONGOC_CURSOR_PROJECTION)) { - OPT_CHECK(DOCUMENT); - bson_iter_document(&iter, &len, &data); - if (!bson_init_static(&subdocument, data, (size_t)len)) { - OPT_BSON_ERR("Invalid 'projection' subdocument in 'opts'."); - } - bson_destroy(fields); - bson_copy_to(&subdocument, fields); - } else if (!strcmp(key, MONGOC_CURSOR_SORT)) { - PUSH_DOLLAR_QUERY(); - OPT_SUBDOCUMENT(sort, orderby); - } else if (!strcmp(key, MONGOC_CURSOR_SKIP)) { - OPT_CHECK_INT(); - *skip = (int32_t)bson_iter_as_int64(&iter); - } - /* the rest of the options, alphabetically */ - else if (!strcmp(key, MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS)) { - OPT_FLAG(MONGOC_OP_QUERY_FLAG_PARTIAL); - } else if (!strcmp(key, MONGOC_CURSOR_AWAIT_DATA)) { - OPT_FLAG(MONGOC_OP_QUERY_FLAG_AWAIT_DATA); - } else if (!strcmp(key, MONGOC_CURSOR_COMMENT)) { - OPT_CHECK(UTF8); - PUSH_DOLLAR_QUERY(); - BSON_APPEND_UTF8(query, "$comment", bson_iter_utf8(&iter, NULL)); - } else if (!strcmp(key, MONGOC_CURSOR_HINT)) { - if (BSON_ITER_HOLDS_UTF8(&iter)) { - PUSH_DOLLAR_QUERY(); - BSON_APPEND_UTF8(query, "$hint", bson_iter_utf8(&iter, NULL)); - } else if (BSON_ITER_HOLDS_DOCUMENT(&iter)) { - PUSH_DOLLAR_QUERY(); - OPT_SUBDOCUMENT(hint, hint); - } else { - OPT_ERR("Wrong type for 'hint' field in 'opts'."); - } - } else if (!strcmp(key, MONGOC_CURSOR_MAX)) { - PUSH_DOLLAR_QUERY(); - OPT_SUBDOCUMENT(max, max); - } else if (!strcmp(key, MONGOC_CURSOR_MAX_SCAN)) { - OPT_CHECK_INT(); - PUSH_DOLLAR_QUERY(); - BSON_APPEND_INT64(query, "$maxScan", bson_iter_as_int64(&iter)); - } else if (!strcmp(key, MONGOC_CURSOR_MAX_TIME_MS)) { - OPT_CHECK_INT(); - PUSH_DOLLAR_QUERY(); - BSON_APPEND_INT64(query, "$maxTimeMS", bson_iter_as_int64(&iter)); - } else if (!strcmp(key, MONGOC_CURSOR_MIN)) { - PUSH_DOLLAR_QUERY(); - OPT_SUBDOCUMENT(min, min); - } else if (!strcmp(key, MONGOC_CURSOR_READ_CONCERN)) { - OPT_ERR("Set readConcern on client, database, or collection," - " not in a query."); - } else if (!strcmp(key, MONGOC_CURSOR_RETURN_KEY)) { - OPT_CHECK(BOOL); - PUSH_DOLLAR_QUERY(); - BSON_APPEND_BOOL(query, "$returnKey", bson_iter_as_bool(&iter)); - } else if (!strcmp(key, MONGOC_CURSOR_SHOW_RECORD_ID)) { - OPT_CHECK(BOOL); - PUSH_DOLLAR_QUERY(); - BSON_APPEND_BOOL(query, "$showDiskLoc", bson_iter_as_bool(&iter)); - } else if (!strcmp(key, MONGOC_CURSOR_SNAPSHOT)) { - OPT_CHECK(BOOL); - PUSH_DOLLAR_QUERY(); - BSON_APPEND_BOOL(query, "$snapshot", bson_iter_as_bool(&iter)); - } else if (!strcmp(key, MONGOC_CURSOR_COLLATION)) { - _mongoc_set_error(&cursor->error, - MONGOC_ERROR_COMMAND, - MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION, - "The selected server does not support collation"); - return NULL; - } - /* singleBatch limit and batchSize are handled in _mongoc_n_return, - * exhaust noCursorTimeout oplogReplay tailable in _mongoc_cursor_flags - * maxAwaitTimeMS is handled in _mongoc_cursor_prepare_getmore_command - * sessionId is used to retrieve the mongoc_client_session_t - */ - else if (strcmp(key, MONGOC_CURSOR_SINGLE_BATCH) && strcmp(key, MONGOC_CURSOR_LIMIT) && - strcmp(key, MONGOC_CURSOR_BATCH_SIZE) && strcmp(key, MONGOC_CURSOR_EXHAUST) && - strcmp(key, MONGOC_CURSOR_NO_CURSOR_TIMEOUT) && strcmp(key, MONGOC_CURSOR_OPLOG_REPLAY) && - strcmp(key, MONGOC_CURSOR_TAILABLE) && strcmp(key, MONGOC_CURSOR_MAX_AWAIT_TIME_MS)) { - /* pass unrecognized options to server, prefixed with $ */ - PUSH_DOLLAR_QUERY(); - dollar_modifier = bson_strdup_printf("$%s", key); - if (!bson_append_iter(query, dollar_modifier, -1, &iter)) { - _mongoc_set_error(&cursor->error, - MONGOC_ERROR_BSON, - MONGOC_ERROR_BSON_INVALID, - "Error adding \"%s\" to query", - dollar_modifier); - bson_free(dollar_modifier); - return NULL; - } - bson_free(dollar_modifier); - } - } - - if (!_mongoc_cursor_opts_to_flags(cursor, stream, flags)) { - /* cursor->error is set */ - return NULL; - } - - return pushed_dollar_query ? query : filter; -} - #undef OPT_CHECK #undef OPT_ERR #undef OPT_BSON_ERR #undef OPT_FLAG #undef OPT_SUBDOCUMENT - -static bool -_mongoc_cursor_op_query_find_send(mongoc_cursor_t *cursor, - mongoc_server_stream_t *server_stream, - int32_t request_id, - bson_t *filter, - mcd_rpc_message *rpc) -{ - bool ret = false; - - cursor->operation_id = ++cursor->client->cluster.operation_id; - - mongoc_assemble_query_result_t result = ASSEMBLE_QUERY_RESULT_INIT; - bson_t query = BSON_INITIALIZER; - bson_t fields = BSON_INITIALIZER; - int32_t skip; - int32_t flags; - const bson_t *const query_ptr = - _mongoc_cursor_parse_opts_for_op_query(cursor, server_stream, filter, &query, &fields, &flags, &skip); - - if (!query_ptr) { - GOTO(done); - } - - assemble_query(cursor->read_prefs, server_stream, query_ptr, flags, &result); - - { - int32_t message_length = 0; - - message_length += mcd_rpc_header_set_message_length(rpc, 0); - message_length += mcd_rpc_header_set_request_id(rpc, request_id); - message_length += mcd_rpc_header_set_response_to(rpc, 0); - message_length += mcd_rpc_header_set_op_code(rpc, MONGOC_OP_CODE_QUERY); - - message_length += mcd_rpc_op_query_set_flags(rpc, result.flags); - message_length += mcd_rpc_op_query_set_full_collection_name(rpc, cursor->ns); - message_length += mcd_rpc_op_query_set_number_to_skip(rpc, skip); - message_length += mcd_rpc_op_query_set_number_to_return(rpc, _mongoc_n_return(cursor)); - message_length += mcd_rpc_op_query_set_query(rpc, bson_get_data(result.assembled_query)); - - if (!bson_empty(&fields)) { - message_length += mcd_rpc_op_query_set_return_fields_selector(rpc, bson_get_data(&fields)); - } - - mcd_rpc_message_set_length(rpc, message_length); - } - - if (!_mongoc_cursor_monitor_legacy_query(cursor, filter, server_stream)) { - GOTO(done); - } - - if (!mongoc_cluster_legacy_rpc_sendv_to_server(&cursor->client->cluster, rpc, server_stream, &cursor->error)) { - GOTO(done); - } - - ret = true; - -done: - assemble_query_result_cleanup(&result); - bson_destroy(&fields); - bson_destroy(&query); - - return ret; -} - -bool -_mongoc_cursor_op_query_find(mongoc_cursor_t *cursor, bson_t *filter, mongoc_cursor_response_legacy_t *response) -{ - BSON_ASSERT_PARAM(cursor); - BSON_ASSERT_PARAM(filter); - BSON_ASSERT_PARAM(response); - - ENTRY; - - bool ret = false; - - const mongoc_ss_log_context_t ss_log_context = { - .operation = "find", .has_operation_id = true, .operation_id = cursor->operation_id}; - mongoc_server_stream_t *const server_stream = _mongoc_cursor_fetch_stream(cursor, &ss_log_context); - - if (!server_stream) { - RETURN(false); - } - - const int64_t started = bson_get_monotonic_time(); - const int32_t request_id = ++cursor->client->cluster.request_id; - mcd_rpc_message *const rpc = mcd_rpc_message_new(); - - if (!_mongoc_cursor_op_query_find_send(cursor, server_stream, request_id, filter, rpc)) { - GOTO(done); - } - - mcd_rpc_message_reset(rpc); - _mongoc_buffer_clear(&response->buffer, false); - - if (!_mongoc_client_recv(cursor->client, response->rpc, &response->buffer, server_stream, &cursor->error)) { - GOTO(done); - } - - const int32_t op_code = mcd_rpc_header_get_op_code(response->rpc); - if (op_code != MONGOC_OP_CODE_REPLY) { - _mongoc_set_error(&cursor->error, - MONGOC_ERROR_PROTOCOL, - MONGOC_ERROR_PROTOCOL_INVALID_REPLY, - "invalid opcode for OP_QUERY: expected %" PRId32 ", got %" PRId32, - MONGOC_OP_CODE_REPLY, - op_code); - GOTO(done); - } - - const int32_t response_to = mcd_rpc_header_get_response_to(response->rpc); - if (response_to != request_id) { - _mongoc_set_error(&cursor->error, - MONGOC_ERROR_PROTOCOL, - MONGOC_ERROR_PROTOCOL_INVALID_REPLY, - "invalid response_to for OP_QUERY: expected %" PRId32 ", got %" PRId32, - request_id, - response_to); - GOTO(done); - } - - if (!mcd_rpc_message_check_ok( - response->rpc, cursor->client->error_api_version, &cursor->error, &cursor->error_doc)) { - GOTO(done); - } - - if (response->reader) { - bson_reader_destroy(response->reader); - } - - cursor->cursor_id = mcd_rpc_op_reply_get_cursor_id(response->rpc); - - const void *documents = mcd_rpc_op_reply_get_documents(response->rpc); - if (documents == NULL) { - // Use a non-NULL pointer to satisfy precondition of - // `bson_reader_new_from_data`: - documents = ""; - } - - response->reader = bson_reader_new_from_data(documents, mcd_rpc_op_reply_get_documents_len(response->rpc)); - - if (_mongoc_cursor_get_opt_bool(cursor, MONGOC_CURSOR_EXHAUST)) { - cursor->in_exhaust = true; - cursor->client->in_exhaust = true; - } - - _mongoc_cursor_monitor_succeeded(cursor, - response, - bson_get_monotonic_time() - started, - true, /* first_batch */ - server_stream, - "find"); - - ret = true; - -done: - if (!ret) { - _mongoc_cursor_monitor_failed(cursor, bson_get_monotonic_time() - started, server_stream, "find"); - } - - mcd_rpc_message_destroy(rpc); - mongoc_server_stream_cleanup(server_stream); - - return ret; -} - - void _mongoc_cursor_response_legacy_init(mongoc_cursor_response_legacy_t *response) { diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-private.h b/src/libmongoc/src/mongoc/mongoc-cursor-private.h index 839a8de4d77..8c6d518aab6 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-private.h +++ b/src/libmongoc/src/mongoc/mongoc-cursor-private.h @@ -200,10 +200,6 @@ const bson_t * _mongoc_cursor_initial_query(mongoc_cursor_t *cursor); const bson_t * _mongoc_cursor_get_more(mongoc_cursor_t *cursor); -bool -_mongoc_cursor_opts_to_flags(mongoc_cursor_t *cursor, mongoc_server_stream_t *stream, int32_t *flags /* OUT */); -bool -_mongoc_cursor_use_op_msg(const mongoc_cursor_t *cursor, int32_t wire_version); void _mongoc_cursor_monitor_succeeded(mongoc_cursor_t *cursor, mongoc_cursor_response_legacy_t *response, @@ -234,10 +230,6 @@ _mongoc_cursor_prime(mongoc_cursor_t *cursor); /* legacy functions defined in mongoc-cursor-legacy.c */ bool _mongoc_cursor_next(mongoc_cursor_t *cursor, const bson_t **bson); -bool -_mongoc_cursor_op_query_find(mongoc_cursor_t *cursor, bson_t *filter, mongoc_cursor_response_legacy_t *response); -void -_mongoc_cursor_op_getmore(mongoc_cursor_t *cursor, mongoc_cursor_response_legacy_t *response); mongoc_cursor_t * _mongoc_cursor_new_with_opts(mongoc_client_t *client, const char *db_and_collection, diff --git a/src/libmongoc/src/mongoc/mongoc-cursor.c b/src/libmongoc/src/mongoc/mongoc-cursor.c index 2dbf8785324..551886879eb 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor.c @@ -894,58 +894,6 @@ _mongoc_cursor_monitor_failed(mongoc_cursor_t *cursor, } \ } while (false) -bool -_mongoc_cursor_opts_to_flags(mongoc_cursor_t *cursor, mongoc_server_stream_t *stream, int32_t *flags /* OUT */) -{ - /* CDRIVER-4722: these flags are only used in legacy OP_QUERY */ - bson_iter_t iter; - const char *key; - - *flags = MONGOC_OP_QUERY_FLAG_NONE; - - if (!bson_iter_init(&iter, &cursor->opts)) { - _mongoc_set_error(&cursor->error, MONGOC_ERROR_BSON, MONGOC_ERROR_BSON_INVALID, "Invalid 'opts' parameter."); - return false; - } - - while (bson_iter_next(&iter)) { - key = bson_iter_key(&iter); - - if (!strcmp(key, MONGOC_CURSOR_ALLOW_PARTIAL_RESULTS)) { - ADD_FLAG(flags, MONGOC_OP_QUERY_FLAG_PARTIAL); - } else if (!strcmp(key, MONGOC_CURSOR_AWAIT_DATA)) { - ADD_FLAG(flags, MONGOC_OP_QUERY_FLAG_AWAIT_DATA); - } else if (!strcmp(key, MONGOC_CURSOR_EXHAUST)) { - ADD_FLAG(flags, MONGOC_OP_QUERY_FLAG_EXHAUST); - } else if (!strcmp(key, MONGOC_CURSOR_NO_CURSOR_TIMEOUT)) { - ADD_FLAG(flags, MONGOC_OP_QUERY_FLAG_NO_CURSOR_TIMEOUT); - } else if (!strcmp(key, MONGOC_CURSOR_OPLOG_REPLAY)) { - ADD_FLAG(flags, MONGOC_OP_QUERY_FLAG_OPLOG_REPLAY); - } else if (!strcmp(key, MONGOC_CURSOR_TAILABLE)) { - ADD_FLAG(flags, MONGOC_OP_QUERY_FLAG_TAILABLE_CURSOR); - } - } - - if (cursor->secondary_ok) { - *flags |= MONGOC_OP_QUERY_FLAG_SECONDARY_OK; - } else if (cursor->server_id && - (stream->topology_type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY || - stream->topology_type == MONGOC_TOPOLOGY_RS_NO_PRIMARY) && - stream->sd->type != MONGOC_SERVER_RS_PRIMARY) { - *flags |= MONGOC_OP_QUERY_FLAG_SECONDARY_OK; - } - - return true; -} - -bool -_mongoc_cursor_use_op_msg(const mongoc_cursor_t *cursor, int32_t wire_version) -{ - /* CDRIVER-4722: always true once 4.2 is the minimum supported - No check needed for 3.6 as it's the current minimum */ - return !_mongoc_cursor_get_opt_bool(cursor, MONGOC_CURSOR_EXHAUST) || wire_version >= WIRE_VERSION_4_2; -} - bool _mongoc_cursor_run_command( mongoc_cursor_t *cursor, const bson_t *command, const bson_t *opts, bson_t *reply, bool retry_prohibited) @@ -1021,15 +969,6 @@ _mongoc_cursor_run_command( db = bson_strndup(cursor->ns, cursor->dblen); parts.assembled.db_name = db; - { - int32_t flags; - if (!_mongoc_cursor_opts_to_flags(cursor, server_stream, &flags)) { - _mongoc_bson_init_if_set(reply); - GOTO(done); - } - parts.user_query_flags = (mongoc_query_flags_t)flags; - } - if (_mongoc_cursor_get_opt_bool(cursor, MONGOC_CURSOR_EXHAUST)) { const bool sharded = _mongoc_topology_get_type(cursor->client->topology) == MONGOC_TOPOLOGY_SHARDED; const int32_t wire_version = server_stream->sd->max_wire_version; diff --git a/src/libmongoc/tests/test-mongoc-cursor.c b/src/libmongoc/tests/test-mongoc-cursor.c index 1c32e1db77c..016caf26418 100644 --- a/src/libmongoc/tests/test-mongoc-cursor.c +++ b/src/libmongoc/tests/test-mongoc-cursor.c @@ -593,9 +593,6 @@ killcursors_succeeded(const mongoc_apm_command_succeeded_t *event) ASSERT_CMPINT64(ctx->cursor_id, ==, bson_iter_int64(&array)); } -extern void -_mongoc_cursor_impl_find_opquery_init(mongoc_cursor_t *cursor, bson_t *filter); - /* Tests killing a cursor with mongo_cursor_destroy and a real server. * Asserts that the cursor ID is no longer valid by attempting to get another * batch of results with the previously killed cursor ID. Uses OP_GET_MORE (on @@ -646,31 +643,13 @@ test_kill_cursor_live(void) ASSERT_CMPINT(ctx.succeeded_count, ==, 1); - if (test_framework_supports_legacy_opcodes()) { - b = bson_new(); - cursor = _mongoc_cursor_find_new(client, collection->ns, b, NULL, NULL, NULL, NULL); - /* override the typical priming, and immediately transition to an OPQUERY - * find cursor. */ - cursor->impl.destroy(&cursor->impl); - _mongoc_cursor_impl_find_opquery_init(cursor, b); - - cursor->cursor_id = ctx.cursor_id; - cursor->state = END_OF_BATCH; /* meaning, "finished reading first batch" */ - r = mongoc_cursor_next(cursor, &doc); - ASSERT(!r); - ASSERT(mongoc_cursor_error(cursor, &error)); - ASSERT_ERROR_CONTAINS(error, MONGOC_ERROR_CURSOR, 16, "cursor is invalid"); - - mongoc_cursor_destroy(cursor); - } else { - bson_t *cmd; + bson_t *cmd; - cmd = BCON_NEW("getMore", BCON_INT64(ctx.cursor_id), "collection", mongoc_collection_get_name(collection)); - r = mongoc_client_command_simple(client, "test", cmd, NULL /* read prefs */, NULL /* reply */, &error); - ASSERT(!r); - ASSERT_ERROR_CONTAINS(error, MONGOC_ERROR_QUERY, MONGOC_SERVER_ERR_CURSOR_NOT_FOUND, "not found"); - bson_destroy(cmd); - } + cmd = BCON_NEW("getMore", BCON_INT64(ctx.cursor_id), "collection", mongoc_collection_get_name(collection)); + r = mongoc_client_command_simple(client, "test", cmd, NULL /* read prefs */, NULL /* reply */, &error); + ASSERT(!r); + ASSERT_ERROR_CONTAINS(error, MONGOC_ERROR_QUERY, MONGOC_SERVER_ERR_CURSOR_NOT_FOUND, "not found"); + bson_destroy(cmd); mongoc_bulk_operation_destroy(bulk); mongoc_collection_destroy(collection); From 1ddad9e1b945814b530f42991cb602921ed39d90 Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Tue, 9 Sep 2025 15:20:02 -0400 Subject: [PATCH 02/10] Remove dead code --- src/libmongoc/src/mongoc/mongoc-cursor-cmd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c b/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c index 5cd4239a95e..ec9bbf5483a 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c @@ -39,7 +39,6 @@ static getmore_type_t _getmore_type(mongoc_cursor_t *cursor) { mongoc_server_stream_t *server_stream; - int32_t wire_version; data_cmd_t *data = (data_cmd_t *)cursor->impl.data; if (data->getmore_type != UNKNOWN) { return data->getmore_type; @@ -50,7 +49,6 @@ _getmore_type(mongoc_cursor_t *cursor) if (!server_stream) { return UNKNOWN; } - wire_version = server_stream->sd->max_wire_version; mongoc_server_stream_cleanup(server_stream); data->getmore_type = GETMORE_CMD; From 41071e8bf254b8b7b0e54ed94d02ebe8410d9f1f Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Tue, 9 Sep 2025 15:35:14 -0400 Subject: [PATCH 03/10] Remove even more dead code --- src/libmongoc/src/mongoc/mongoc-cursor-find.c | 2 - .../src/mongoc/mongoc-cursor-legacy.c | 199 ------------------ 2 files changed, 201 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-find.c b/src/libmongoc/src/mongoc/mongoc-cursor-find.c index 55e0eeb9c82..fc1d9a8775d 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-find.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-find.c @@ -31,7 +31,6 @@ _mongoc_cursor_impl_find_cmd_init(mongoc_cursor_t *cursor, bson_t *filter); static mongoc_cursor_state_t _prime(mongoc_cursor_t *cursor) { - int32_t wire_version; mongoc_server_stream_t *server_stream; data_find_t *data = (data_find_t *)cursor->impl.data; @@ -42,7 +41,6 @@ _prime(mongoc_cursor_t *cursor) if (!server_stream) { return DONE; } - wire_version = server_stream->sd->max_wire_version; mongoc_server_stream_cleanup(server_stream); /* set all mongoc_impl_t function pointers. */ diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c b/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c index edd9f5b6bca..69acf8362f7 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c @@ -36,205 +36,6 @@ #include #include -static bool -_mongoc_cursor_monitor_legacy_get_more(mongoc_cursor_t *cursor, mongoc_server_stream_t *server_stream) -{ - bson_t doc; - char *db; - mongoc_client_t *client; - mongoc_apm_command_started_t event; - - ENTRY; - - client = cursor->client; - _mongoc_cursor_prepare_getmore_command(cursor, &doc); - - const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; - - mongoc_structured_log( - log_and_monitor->structured_log, - MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, - MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, - "Command started", - int32("requestId", client->cluster.request_id), - server_description(server_stream->sd, SERVER_HOST, SERVER_PORT, SERVER_CONNECTION_ID, SERVICE_ID), - utf8_n("databaseName", cursor->ns, cursor->dblen), - utf8("commandName", "getMore"), - int64("operationId", cursor->operation_id), - bson_as_json("command", &doc)); - - if (!log_and_monitor->apm_callbacks.started) { - /* successful */ - bson_destroy(&doc); - RETURN(true); - } - - db = bson_strndup(cursor->ns, cursor->dblen); - mongoc_apm_command_started_init(&event, - &doc, - db, - "getMore", - client->cluster.request_id, - cursor->operation_id, - &server_stream->sd->host, - server_stream->sd->id, - &server_stream->sd->service_id, - server_stream->sd->server_connection_id, - NULL, - log_and_monitor->apm_context); - - log_and_monitor->apm_callbacks.started(&event); - mongoc_apm_command_started_cleanup(&event); - bson_destroy(&doc); - bson_free(db); - - RETURN(true); -} - - -static bool -_mongoc_cursor_monitor_legacy_query(mongoc_cursor_t *cursor, - const bson_t *filter, - mongoc_server_stream_t *server_stream) -{ - bson_t doc; - char *db; - bool r; - - ENTRY; - - bson_init(&doc); - db = bson_strndup(cursor->ns, cursor->dblen); - - /* simulate a MongoDB 3.2+ "find" command */ - _mongoc_cursor_prepare_find_command(cursor, filter, &doc); - - bsonBuildAppend(cursor->opts, insert(doc, not(key("serverId", "maxAwaitTimeMS", "sessionId")))); - - r = _mongoc_cursor_monitor_command(cursor, server_stream, &doc, "find"); - - bson_destroy(&doc); - bson_free(db); - - RETURN(r); -} - - -static bool -_mongoc_cursor_op_getmore_send(mongoc_cursor_t *cursor, - mongoc_server_stream_t *server_stream, - int32_t request_id, - int32_t flags, - mcd_rpc_message *rpc) -{ - BSON_ASSERT_PARAM(cursor); - BSON_ASSERT_PARAM(server_stream); - BSON_ASSERT_PARAM(rpc); - - const int32_t n_return = (flags & MONGOC_OP_QUERY_FLAG_TAILABLE_CURSOR) != 0 ? 0 : _mongoc_n_return(cursor); - - { - int32_t message_length = 0; - - message_length += mcd_rpc_header_set_message_length(rpc, 0); - message_length += mcd_rpc_header_set_request_id(rpc, request_id); - message_length += mcd_rpc_header_set_response_to(rpc, 0); - message_length += mcd_rpc_header_set_op_code(rpc, MONGOC_OP_CODE_GET_MORE); - - message_length += sizeof(int32_t); // ZERO - message_length += mcd_rpc_op_get_more_set_full_collection_name(rpc, cursor->ns); - message_length += mcd_rpc_op_get_more_set_number_to_return(rpc, n_return); - message_length += mcd_rpc_op_get_more_set_cursor_id(rpc, cursor->cursor_id); - - mcd_rpc_message_set_length(rpc, message_length); - } - - if (!_mongoc_cursor_monitor_legacy_get_more(cursor, server_stream)) { - return false; - } - - if (!mongoc_cluster_legacy_rpc_sendv_to_server(&cursor->client->cluster, rpc, server_stream, &cursor->error)) { - return false; - } - - return true; -} - -#define OPT_CHECK(_type) \ - do { \ - if (!BSON_ITER_HOLDS_##_type(&iter)) { \ - _mongoc_set_error(&cursor->error, \ - MONGOC_ERROR_COMMAND, \ - MONGOC_ERROR_COMMAND_INVALID_ARG, \ - "invalid option %s, should be type %s", \ - key, \ - #_type); \ - return NULL; \ - } \ - } while (false) - - -#define OPT_CHECK_INT() \ - do { \ - if (!BSON_ITER_HOLDS_INT(&iter)) { \ - _mongoc_set_error(&cursor->error, \ - MONGOC_ERROR_COMMAND, \ - MONGOC_ERROR_COMMAND_INVALID_ARG, \ - "invalid option %s, should be integer", \ - key); \ - return NULL; \ - } \ - } while (false) - - -#define OPT_ERR(_msg) \ - do { \ - _mongoc_set_error(&cursor->error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, _msg); \ - return NULL; \ - } while (false) - - -#define OPT_BSON_ERR(_msg) \ - do { \ - _mongoc_set_error(&cursor->error, MONGOC_ERROR_BSON, MONGOC_ERROR_BSON_INVALID, _msg); \ - return NULL; \ - } while (false) - - -#define OPT_FLAG(_flag) \ - do { \ - OPT_CHECK(BOOL); \ - if (bson_iter_as_bool(&iter)) { \ - *flags |= _flag; \ - } \ - } while (false) - - -#define PUSH_DOLLAR_QUERY() \ - do { \ - if (!pushed_dollar_query) { \ - pushed_dollar_query = true; \ - bson_append_document(query, "$query", 6, filter); \ - } \ - } while (false) - - -#define OPT_SUBDOCUMENT(_opt_name, _legacy_name) \ - do { \ - OPT_CHECK(DOCUMENT); \ - bson_iter_document(&iter, &len, &data); \ - if (!bson_init_static(&subdocument, data, (size_t)len)) { \ - OPT_BSON_ERR("Invalid '" #_opt_name "' subdocument in 'opts'."); \ - } \ - BSON_APPEND_DOCUMENT(query, "$" #_legacy_name, &subdocument); \ - } while (false) - -#undef OPT_CHECK -#undef OPT_ERR -#undef OPT_BSON_ERR -#undef OPT_FLAG -#undef OPT_SUBDOCUMENT - void _mongoc_cursor_response_legacy_init(mongoc_cursor_response_legacy_t *response) { From f84ef1ee16dcd2d70341a00fa3f6766c943c33aa Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Thu, 11 Sep 2025 11:02:22 -0400 Subject: [PATCH 04/10] Add Kevin's read pref fix --- src/libmongoc/src/mongoc/mongoc-cursor.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libmongoc/src/mongoc/mongoc-cursor.c b/src/libmongoc/src/mongoc/mongoc-cursor.c index 551886879eb..da2e8d8c139 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor.c @@ -894,6 +894,21 @@ _mongoc_cursor_monitor_failed(mongoc_cursor_t *cursor, } \ } while (false) +bool +_mongoc_cursor_secondary_ok(mongoc_cursor_t *cursor, mongoc_server_stream_t *stream) +{ + if (cursor->secondary_ok) { + return true; + } else if (cursor->server_id && + (stream->topology_type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY || + stream->topology_type == MONGOC_TOPOLOGY_RS_NO_PRIMARY) && + stream->sd->type != MONGOC_SERVER_RS_PRIMARY) { + return true; + } + + return false; +} + bool _mongoc_cursor_run_command( mongoc_cursor_t *cursor, const bson_t *command, const bson_t *opts, bson_t *reply, bool retry_prohibited) @@ -995,7 +1010,7 @@ _mongoc_cursor_run_command( */ is_primary = !cursor->read_prefs || cursor->read_prefs->mode == MONGOC_READ_PRIMARY; - if (strcmp(cmd_name, "getMore") != 0 && is_primary && parts.user_query_flags & MONGOC_QUERY_SECONDARY_OK) { + if (strcmp(cmd_name, "getMore") != 0 && is_primary && _mongoc_cursor_secondary_ok(cursor, server_stream)) { parts.read_prefs = prefs = mongoc_read_prefs_new(MONGOC_READ_PRIMARY_PREFERRED); } else { parts.read_prefs = cursor->read_prefs; From 7f3df1a33e84a856e1c0b8cb8b6443c67c26f015 Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Thu, 11 Sep 2025 11:30:06 -0400 Subject: [PATCH 05/10] Remove mongoc_cursor_response_legacy_t --- src/libmongoc/CMakeLists.txt | 1 - src/libmongoc/src/mongoc/mongoc-cursor-cmd.c | 4 - .../src/mongoc/mongoc-cursor-legacy.c | 56 ----------- .../src/mongoc/mongoc-cursor-private.h | 19 ---- src/libmongoc/src/mongoc/mongoc-cursor.c | 94 ------------------- 5 files changed, 174 deletions(-) delete mode 100644 src/libmongoc/src/mongoc/mongoc-cursor-legacy.c diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 8386bc93059..9c8a05dbb5c 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -569,7 +569,6 @@ set (MONGOC_SOURCES ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-cmd-deprecated.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-find.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-find-cmd.c - ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-legacy.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-array.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-database.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-error.c diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c b/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c index ec9bbf5483a..68a48a5bef3 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c @@ -28,7 +28,6 @@ typedef struct _data_cmd_t { * we're reading the raw reply from a stream */ mongoc_cursor_response_t response; - mongoc_cursor_response_legacy_t response_legacy; reading_from_t reading_from; getmore_type_t getmore_type; /* cache after first getmore. */ bson_t cmd; @@ -126,7 +125,6 @@ _destroy(mongoc_cursor_impl_t *impl) data_cmd_t *data = (data_cmd_t *)impl->data; bson_destroy(&data->response.reply); bson_destroy(&data->cmd); - _mongoc_cursor_response_legacy_destroy(&data->response_legacy); bson_free(data); } @@ -137,7 +135,6 @@ _clone(mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src) data_cmd_t *data_src = (data_cmd_t *)src->data; data_cmd_t *data_dst = BSON_ALIGNED_ALLOC0(data_cmd_t); bson_init(&data_dst->response.reply); - _mongoc_cursor_response_legacy_init(&data_dst->response_legacy); bson_copy_to(&data_src->cmd, &data_dst->cmd); dst->data = data_dst; } @@ -158,7 +155,6 @@ _mongoc_cursor_cmd_new(mongoc_client_t *client, data_cmd_t *data = BSON_ALIGNED_ALLOC0(data_cmd_t); cursor = _mongoc_cursor_new_with_opts(client, db_and_coll, opts, user_prefs, default_prefs, read_concern); - _mongoc_cursor_response_legacy_init(&data->response_legacy); _mongoc_cursor_check_and_copy_to(cursor, "command", cmd, &data->cmd); bson_init(&data->response.reply); cursor->impl.prime = _prime; diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c b/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c deleted file mode 100644 index 69acf8362f7..00000000000 --- a/src/libmongoc/src/mongoc/mongoc-cursor-legacy.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2009-present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* cursor functions for pre-3.2 MongoDB, including: - * - OP_QUERY find (superseded by the find command) - * - OP_GETMORE (superseded by the getMore command) - * - receiving OP_REPLY documents in a stream (instead of batch) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -void -_mongoc_cursor_response_legacy_init(mongoc_cursor_response_legacy_t *response) -{ - response->rpc = mcd_rpc_message_new(); - _mongoc_buffer_init(&response->buffer, NULL, 0, NULL, NULL); -} - - -void -_mongoc_cursor_response_legacy_destroy(mongoc_cursor_response_legacy_t *response) -{ - if (response->reader) { - bson_reader_destroy(response->reader); - response->reader = NULL; - } - _mongoc_buffer_destroy(&response->buffer); - mcd_rpc_message_destroy(response->rpc); -} diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-private.h b/src/libmongoc/src/mongoc/mongoc-cursor-private.h index 8c6d518aab6..1f8539db473 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-private.h +++ b/src/libmongoc/src/mongoc/mongoc-cursor-private.h @@ -102,13 +102,6 @@ struct _mongoc_cursor_impl_t { void *data; }; -/* pre-3.2 and exhaust cursor responses -- read documents from stream. */ -typedef struct _mongoc_cursor_response_legacy { - mcd_rpc_message *rpc; - mongoc_buffer_t buffer; - bson_reader_t *reader; -} mongoc_cursor_response_legacy_t; - /* 3.2+ responses -- read batch docs like {cursor:{id: 123, firstBatch: []}} */ typedef struct _mongoc_cursor_response_t { bson_t reply; /* the entire command reply */ @@ -200,13 +193,6 @@ const bson_t * _mongoc_cursor_initial_query(mongoc_cursor_t *cursor); const bson_t * _mongoc_cursor_get_more(mongoc_cursor_t *cursor); -void -_mongoc_cursor_monitor_succeeded(mongoc_cursor_t *cursor, - mongoc_cursor_response_legacy_t *response, - int64_t duration, - bool first_batch, - mongoc_server_stream_t *stream, - const char *cmd_name); /* start iterating a reply like * {cursor: {id: 1234, ns: "db.collection", firstBatch: [...]}} or * {cursor: {id: 1234, ns: "db.collection", nextBatch: [...]}} */ @@ -227,7 +213,6 @@ bool _mongoc_cursor_check_and_copy_to(mongoc_cursor_t *cursor, const char *err_prefix, const bson_t *src, bson_t *dst); void _mongoc_cursor_prime(mongoc_cursor_t *cursor); -/* legacy functions defined in mongoc-cursor-legacy.c */ bool _mongoc_cursor_next(mongoc_cursor_t *cursor, const bson_t **bson); mongoc_cursor_t * @@ -237,10 +222,6 @@ _mongoc_cursor_new_with_opts(mongoc_client_t *client, const mongoc_read_prefs_t *user_prefs, const mongoc_read_prefs_t *default_prefs, const mongoc_read_concern_t *read_concern); -void -_mongoc_cursor_response_legacy_init(mongoc_cursor_response_legacy_t *response); -void -_mongoc_cursor_response_legacy_destroy(mongoc_cursor_response_legacy_t *response); /* cursor constructors. */ mongoc_cursor_t * _mongoc_cursor_find_new(mongoc_client_t *client, diff --git a/src/libmongoc/src/mongoc/mongoc-cursor.c b/src/libmongoc/src/mongoc/mongoc-cursor.c index da2e8d8c139..0db10edbe02 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor.c @@ -726,100 +726,6 @@ _mongoc_cursor_monitor_command(mongoc_cursor_t *cursor, RETURN(true); } - -/* append array of docs from current cursor batch */ -static void -_mongoc_cursor_append_docs_array(mongoc_cursor_t *cursor, bson_t *docs, mongoc_cursor_response_legacy_t *response) -{ - bool eof = false; - char str[16]; - const char *key; - uint32_t i = 0; - size_t keylen; - const bson_t *doc; - - BSON_UNUSED(cursor); - - while ((doc = bson_reader_read(response->reader, &eof))) { - keylen = bson_uint32_to_string(i, &key, str, sizeof str); - bson_append_document(docs, key, (int)keylen, doc); - } - - bson_reader_reset(response->reader); -} - - -void -_mongoc_cursor_monitor_succeeded(mongoc_cursor_t *cursor, - mongoc_cursor_response_legacy_t *response, - int64_t duration, - bool first_batch, - mongoc_server_stream_t *stream, - const char *cmd_name) -{ - bson_t docs_array; - mongoc_apm_command_succeeded_t event; - - ENTRY; - - mongoc_client_t *client = cursor->client; - const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; - - /* we sent OP_QUERY/OP_GETMORE, fake a reply to find/getMore command: - * {ok: 1, cursor: {id: 17, ns: "...", first/nextBatch: [ ... docs ... ]}} - */ - bson_init(&docs_array); - _mongoc_cursor_append_docs_array(cursor, &docs_array, response); - - bsonBuildDecl(reply, - kv("ok", int32(1)), - kv("cursor", - doc(kv("id", int64(mongoc_cursor_get_id(cursor))), - kv("ns", utf8_w_len(cursor->ns, cursor->nslen)), - kv(first_batch ? "firstBatch" : "nextBatch", bsonArray(docs_array))))); - char *db = bson_strndup(cursor->ns, cursor->dblen); - - bson_destroy(&docs_array); - - mongoc_structured_log(log_and_monitor->structured_log, - MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, - MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, - "Command succeeded", - int32("requestId", client->cluster.request_id), - server_description(stream->sd, SERVER_HOST, SERVER_PORT, SERVER_CONNECTION_ID, SERVICE_ID), - utf8("databaseName", db), - utf8("commandName", cmd_name), - int64("operationId", cursor->operation_id), - monotonic_time_duration(duration), - cmd_name_reply(cmd_name, &reply)); - - if (log_and_monitor->apm_callbacks.succeeded) { - mongoc_apm_command_succeeded_init(&event, - duration, - &reply, - cmd_name, - db, - client->cluster.request_id, - cursor->operation_id, - &stream->sd->host, - stream->sd->id, - &stream->sd->service_id, - stream->sd->server_connection_id, - false, - log_and_monitor->apm_context); - - log_and_monitor->apm_callbacks.succeeded(&event); - - mongoc_apm_command_succeeded_cleanup(&event); - } - - bson_destroy(&reply); - bson_free(db); - - EXIT; -} - - void _mongoc_cursor_monitor_failed(mongoc_cursor_t *cursor, int64_t duration, From 6983c27d0e75b6944b7d13563cd14ece71983033 Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Thu, 11 Sep 2025 11:51:55 -0400 Subject: [PATCH 06/10] Simplify bool expression --- src/libmongoc/src/mongoc/mongoc-cursor.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-cursor.c b/src/libmongoc/src/mongoc/mongoc-cursor.c index 0db10edbe02..d791d68e73a 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor.c @@ -803,16 +803,10 @@ _mongoc_cursor_monitor_failed(mongoc_cursor_t *cursor, bool _mongoc_cursor_secondary_ok(mongoc_cursor_t *cursor, mongoc_server_stream_t *stream) { - if (cursor->secondary_ok) { - return true; - } else if (cursor->server_id && - (stream->topology_type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY || - stream->topology_type == MONGOC_TOPOLOGY_RS_NO_PRIMARY) && - stream->sd->type != MONGOC_SERVER_RS_PRIMARY) { - return true; - } - - return false; + return cursor->secondary_ok || (cursor->server_id != 0 && + (stream->topology_type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY || + stream->topology_type == MONGOC_TOPOLOGY_RS_NO_PRIMARY) && + stream->sd->type != MONGOC_SERVER_RS_PRIMARY); } bool From 6757eb65ba9fae447531c6c4310af5d1a35e6b57 Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Thu, 11 Sep 2025 13:15:34 -0400 Subject: [PATCH 07/10] Remove 2-code-path logic --- src/libmongoc/src/mongoc/mongoc-cursor-cmd.c | 63 +++----------------- 1 file changed, 8 insertions(+), 55 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c b/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c index 68a48a5bef3..2001ca1acfa 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-cmd.c @@ -19,43 +19,12 @@ #include -typedef enum { NONE, CMD_RESPONSE } reading_from_t; -typedef enum { UNKNOWN, GETMORE_CMD } getmore_type_t; typedef struct _data_cmd_t { - /* Two paths: - * - Mongo 3.2+, sent "getMore" cmd, we're reading reply's "nextBatch" array - * - Mongo 2.6 to 3, after "aggregate" or similar command we sent OP_GETMORE, - * we're reading the raw reply from a stream - */ mongoc_cursor_response_t response; - reading_from_t reading_from; - getmore_type_t getmore_type; /* cache after first getmore. */ bson_t cmd; } data_cmd_t; -static getmore_type_t -_getmore_type(mongoc_cursor_t *cursor) -{ - mongoc_server_stream_t *server_stream; - data_cmd_t *data = (data_cmd_t *)cursor->impl.data; - if (data->getmore_type != UNKNOWN) { - return data->getmore_type; - } - const mongoc_ss_log_context_t ss_log_context = { - .operation = "getMore", .has_operation_id = true, .operation_id = cursor->operation_id}; - server_stream = _mongoc_cursor_fetch_stream(cursor, &ss_log_context); - if (!server_stream) { - return UNKNOWN; - } - mongoc_server_stream_cleanup(server_stream); - - data->getmore_type = GETMORE_CMD; - - return data->getmore_type; -} - - static mongoc_cursor_state_t _prime(mongoc_cursor_t *cursor) { @@ -70,7 +39,6 @@ _prime(mongoc_cursor_t *cursor) /* server replies to aggregate/listIndexes/listCollections with: * {cursor: {id: N, firstBatch: []}} */ _mongoc_cursor_response_refresh(cursor, &data->cmd, &copied_opts, &data->response); - data->reading_from = CMD_RESPONSE; bson_destroy(&copied_opts); return IN_BATCH; } @@ -81,15 +49,8 @@ _pop_from_batch(mongoc_cursor_t *cursor) { data_cmd_t *data = (data_cmd_t *)cursor->impl.data; - switch (data->reading_from) { - case CMD_RESPONSE: - _mongoc_cursor_response_read(cursor, &data->response, &cursor->current); - break; - case NONE: - default: - fprintf(stderr, "trying to pop from an uninitialized cursor reader.\n"); - BSON_ASSERT(false); - } + _mongoc_cursor_response_read(cursor, &data->response, &cursor->current); + if (cursor->current) { return IN_BATCH; } else { @@ -103,19 +64,12 @@ _get_next_batch(mongoc_cursor_t *cursor) { data_cmd_t *data = (data_cmd_t *)cursor->impl.data; bson_t getmore_cmd; - getmore_type_t getmore_type = _getmore_type(cursor); - - switch (getmore_type) { - case GETMORE_CMD: - _mongoc_cursor_prepare_getmore_command(cursor, &getmore_cmd); - _mongoc_cursor_response_refresh(cursor, &getmore_cmd, NULL /* opts */, &data->response); - bson_destroy(&getmore_cmd); - data->reading_from = CMD_RESPONSE; - return IN_BATCH; - case UNKNOWN: - default: - return DONE; - } + + _mongoc_cursor_prepare_getmore_command(cursor, &getmore_cmd); + _mongoc_cursor_response_refresh(cursor, &getmore_cmd, NULL /* opts */, &data->response); + bson_destroy(&getmore_cmd); + + return IN_BATCH; } @@ -175,7 +129,6 @@ _mongoc_cursor_cmd_new_from_reply(mongoc_client_t *client, const bson_t *cmd, co mongoc_cursor_t *cursor = _mongoc_cursor_cmd_new(client, NULL, cmd, opts, NULL, NULL, NULL); data_cmd_t *data = (data_cmd_t *)cursor->impl.data; - data->reading_from = CMD_RESPONSE; cursor->state = IN_BATCH; bson_destroy(&data->response.reply); From 6c56921de2a4e2f8c319c85d383e4f2c3bd6d622 Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Thu, 11 Sep 2025 14:02:48 -0400 Subject: [PATCH 08/10] Remove even more mentions of legacy op codes --- .../src/mongoc/mongoc-cursor-private.h | 10 -- src/libmongoc/src/mongoc/mongoc-cursor.c | 117 +----------------- src/libmongoc/tests/test-mongoc-cursor.c | 9 +- 3 files changed, 5 insertions(+), 131 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-private.h b/src/libmongoc/src/mongoc/mongoc-cursor-private.h index 1f8539db473..5d9ea2fd8b7 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-private.h +++ b/src/libmongoc/src/mongoc/mongoc-cursor-private.h @@ -178,16 +178,6 @@ _mongoc_cursor_more(mongoc_cursor_t *cursor); bool _mongoc_cursor_set_opt_int64(mongoc_cursor_t *cursor, const char *option, int64_t value); void -_mongoc_cursor_monitor_failed(mongoc_cursor_t *cursor, - int64_t duration, - mongoc_server_stream_t *stream, - const char *cmd_name); -bool -_mongoc_cursor_monitor_command(mongoc_cursor_t *cursor, - mongoc_server_stream_t *server_stream, - const bson_t *cmd, - const char *cmd_name); -void _mongoc_cursor_prepare_find_command(mongoc_cursor_t *cursor, const bson_t *filter, bson_t *command); const bson_t * _mongoc_cursor_initial_query(mongoc_cursor_t *cursor); diff --git a/src/libmongoc/src/mongoc/mongoc-cursor.c b/src/libmongoc/src/mongoc/mongoc-cursor.c index d791d68e73a..29ca1c06581 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor.c @@ -672,119 +672,6 @@ _mongoc_cursor_fetch_stream(mongoc_cursor_t *cursor, const mongoc_ss_log_context RETURN(server_stream); } - -bool -_mongoc_cursor_monitor_command(mongoc_cursor_t *cursor, - mongoc_server_stream_t *server_stream, - const bson_t *cmd, - const char *cmd_name) -{ - mongoc_apm_command_started_t event; - char *db; - - ENTRY; - - mongoc_client_t *client = cursor->client; - const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; - - mongoc_structured_log( - log_and_monitor->structured_log, - MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, - MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, - "Command started", - int32("requestId", client->cluster.request_id), - server_description(server_stream->sd, SERVER_HOST, SERVER_PORT, SERVER_CONNECTION_ID, SERVICE_ID), - utf8_n("databaseName", cursor->ns, cursor->dblen), - utf8("commandName", cmd_name), - int64("operationId", cursor->operation_id), - bson_as_json("command", cmd)); - - if (!log_and_monitor->apm_callbacks.started) { - /* successful */ - RETURN(true); - } - - db = bson_strndup(cursor->ns, cursor->dblen); - - mongoc_apm_command_started_init(&event, - cmd, - db, - cmd_name, - client->cluster.request_id, - cursor->operation_id, - &server_stream->sd->host, - server_stream->sd->id, - &server_stream->sd->service_id, - server_stream->sd->server_connection_id, - NULL, - log_and_monitor->apm_context); - - log_and_monitor->apm_callbacks.started(&event); - mongoc_apm_command_started_cleanup(&event); - bson_free(db); - - RETURN(true); -} - -void -_mongoc_cursor_monitor_failed(mongoc_cursor_t *cursor, - int64_t duration, - mongoc_server_stream_t *stream, - const char *cmd_name) -{ - mongoc_apm_command_failed_t event; - - ENTRY; - - mongoc_client_t *client = cursor->client; - const mongoc_log_and_monitor_instance_t *log_and_monitor = &client->topology->log_and_monitor; - - /* we sent OP_QUERY/OP_GETMORE, fake a reply to find/getMore command: - * {ok: 0} - */ - bsonBuildDecl(reply, kv("ok", int32(0))); - char *db = bson_strndup(cursor->ns, cursor->dblen); - - mongoc_structured_log(log_and_monitor->structured_log, - MONGOC_STRUCTURED_LOG_LEVEL_DEBUG, - MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND, - "Command failed", - int32("requestId", client->cluster.request_id), - server_description(stream->sd, SERVER_HOST, SERVER_PORT, SERVER_CONNECTION_ID, SERVICE_ID), - utf8("databaseName", db), - utf8("commandName", cmd_name), - int64("operationId", cursor->operation_id), - monotonic_time_duration(duration), - bson_as_json("failure", &reply)); - - if (log_and_monitor->apm_callbacks.failed) { - mongoc_apm_command_failed_init(&event, - duration, - cmd_name, - db, - &cursor->error, - &reply, - client->cluster.request_id, - cursor->operation_id, - &stream->sd->host, - stream->sd->id, - &stream->sd->service_id, - stream->sd->server_connection_id, - false, - log_and_monitor->apm_context); - - log_and_monitor->apm_callbacks.failed(&event); - - mongoc_apm_command_failed_cleanup(&event); - } - - bson_destroy(&reply); - bson_free(db); - - EXIT; -} - - #define ADD_FLAG(_flags, _value) \ do { \ if (!BSON_ITER_HOLDS_BOOL(&iter)) { \ @@ -904,9 +791,7 @@ _mongoc_cursor_run_command( /* we might use mongoc_cursor_set_hint to target a secondary but have no * read preference, so the secondary rejects the read. same if we have a - * direct connection to a secondary (topology type "single"). with - * OP_QUERY we handle this by setting secondaryOk. here we use - * $readPreference. + * direct connection to a secondary (topology type "single"). */ is_primary = !cursor->read_prefs || cursor->read_prefs->mode == MONGOC_READ_PRIMARY; diff --git a/src/libmongoc/tests/test-mongoc-cursor.c b/src/libmongoc/tests/test-mongoc-cursor.c index 016caf26418..076470e4a04 100644 --- a/src/libmongoc/tests/test-mongoc-cursor.c +++ b/src/libmongoc/tests/test-mongoc-cursor.c @@ -595,9 +595,8 @@ killcursors_succeeded(const mongoc_apm_command_succeeded_t *event) /* Tests killing a cursor with mongo_cursor_destroy and a real server. * Asserts that the cursor ID is no longer valid by attempting to get another - * batch of results with the previously killed cursor ID. Uses OP_GET_MORE (on - * servers older than 3.2) or a getMore command (servers 3.2+) to iterate the - * cursor ID. + * batch of results with the previously killed cursor ID. Uses getMore command + * to iterate the cursor ID. */ static void test_kill_cursor_live(void) @@ -638,7 +637,7 @@ test_kill_cursor_live(void) ctx.cursor_id = mongoc_cursor_get_id(cursor); ASSERT(ctx.cursor_id); - /* sends OP_KILLCURSORS or killCursors command to server */ + /* sends killCursors command to server */ mongoc_cursor_destroy(cursor); ASSERT_CMPINT(ctx.succeeded_count, ==, 1); @@ -737,7 +736,7 @@ _test_kill_cursors(bool pooled) reply_to_request_simple(request, "{'ok': 1}"); - /* OP_KILLCURSORS was sent to the right secondary */ + /* killCursors command was sent to the right secondary */ ASSERT_CMPINT(request_get_server_port(kill_cursors), ==, request_get_server_port(request)); BSON_ASSERT(future_wait(future)); From 630848ee4699c4915df638251f9a4670ca2fc7de Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Fri, 12 Sep 2025 12:14:35 -0400 Subject: [PATCH 09/10] Remove unnecessary server stream check --- src/libmongoc/src/mongoc/mongoc-cursor-find.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-find.c b/src/libmongoc/src/mongoc/mongoc-cursor-find.c index fc1d9a8775d..b6b9b6e2912 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-find.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-find.c @@ -31,18 +31,8 @@ _mongoc_cursor_impl_find_cmd_init(mongoc_cursor_t *cursor, bson_t *filter); static mongoc_cursor_state_t _prime(mongoc_cursor_t *cursor) { - mongoc_server_stream_t *server_stream; data_find_t *data = (data_find_t *)cursor->impl.data; - /* determine if this should be a command or op_query cursor. */ - const mongoc_ss_log_context_t ss_log_context = { - .operation = "find", .has_operation_id = true, .operation_id = cursor->operation_id}; - server_stream = _mongoc_cursor_fetch_stream(cursor, &ss_log_context); - if (!server_stream) { - return DONE; - } - mongoc_server_stream_cleanup(server_stream); - /* set all mongoc_impl_t function pointers. */ _mongoc_cursor_impl_find_cmd_init(cursor, &data->filter /* stolen */); From f0ee949807c0a71b2637491deb9549daa847e1fe Mon Sep 17 00:00:00 2001 From: Connor MacDonald Date: Fri, 12 Sep 2025 12:35:23 -0400 Subject: [PATCH 10/10] Combine ...find.c with ...find-cmd.c --- src/libmongoc/CMakeLists.txt | 1 - .../src/mongoc/mongoc-cursor-find-cmd.c | 106 ------------------ src/libmongoc/src/mongoc/mongoc-cursor-find.c | 71 ++++++++---- 3 files changed, 52 insertions(+), 126 deletions(-) delete mode 100644 src/libmongoc/src/mongoc/mongoc-cursor-find-cmd.c diff --git a/src/libmongoc/CMakeLists.txt b/src/libmongoc/CMakeLists.txt index 9c8a05dbb5c..5fce0c2c11e 100644 --- a/src/libmongoc/CMakeLists.txt +++ b/src/libmongoc/CMakeLists.txt @@ -568,7 +568,6 @@ set (MONGOC_SOURCES ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-change-stream.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-cmd-deprecated.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-find.c - ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-find-cmd.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-array.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-database.c ${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-error.c diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-find-cmd.c b/src/libmongoc/src/mongoc/mongoc-cursor-find-cmd.c deleted file mode 100644 index d562e3a258f..00000000000 --- a/src/libmongoc/src/mongoc/mongoc-cursor-find-cmd.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2009-present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include - -#include - -typedef struct _data_find_cmd_t { - mongoc_cursor_response_t response; - bson_t filter; -} data_find_cmd_t; - - -static mongoc_cursor_state_t -_prime(mongoc_cursor_t *cursor) -{ - data_find_cmd_t *data = (data_find_cmd_t *)cursor->impl.data; - bson_t find_cmd; - - bson_init(&find_cmd); - cursor->operation_id = ++cursor->client->cluster.operation_id; - /* construct { find: "", filter: {} } */ - _mongoc_cursor_prepare_find_command(cursor, &data->filter, &find_cmd); - _mongoc_cursor_response_refresh(cursor, &find_cmd, &cursor->opts, &data->response); - bson_destroy(&find_cmd); - return IN_BATCH; -} - - -static mongoc_cursor_state_t -_pop_from_batch(mongoc_cursor_t *cursor) -{ - data_find_cmd_t *data = (data_find_cmd_t *)cursor->impl.data; - _mongoc_cursor_response_read(cursor, &data->response, &cursor->current); - if (cursor->current) { - return IN_BATCH; - } else { - return cursor->cursor_id ? END_OF_BATCH : DONE; - } -} - - -static mongoc_cursor_state_t -_get_next_batch(mongoc_cursor_t *cursor) -{ - data_find_cmd_t *data = (data_find_cmd_t *)cursor->impl.data; - bson_t getmore_cmd; - - if (!cursor->cursor_id) { - return DONE; - } - _mongoc_cursor_prepare_getmore_command(cursor, &getmore_cmd); - _mongoc_cursor_response_refresh(cursor, &getmore_cmd, NULL /* opts */, &data->response); - bson_destroy(&getmore_cmd); - return IN_BATCH; -} - - -static void -_destroy(mongoc_cursor_impl_t *impl) -{ - data_find_cmd_t *data = (data_find_cmd_t *)impl->data; - bson_destroy(&data->filter); - bson_destroy(&data->response.reply); - bson_free(data); -} - - -static void -_clone(mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src) -{ - data_find_cmd_t *data_src = (data_find_cmd_t *)src->data; - data_find_cmd_t *data_dst = BSON_ALIGNED_ALLOC0(data_find_cmd_t); - bson_init(&data_dst->response.reply); - bson_copy_to(&data_src->filter, &data_dst->filter); - dst->data = data_dst; -} - - -/* transition a find cursor to use the find command. */ -void -_mongoc_cursor_impl_find_cmd_init(mongoc_cursor_t *cursor, bson_t *filter) -{ - data_find_cmd_t *data = BSON_ALIGNED_ALLOC0(data_find_cmd_t); - BSON_ASSERT(bson_steal(&data->filter, filter)); - bson_init(&data->response.reply); - cursor->impl.prime = _prime; - cursor->impl.pop_from_batch = _pop_from_batch; - cursor->impl.get_next_batch = _get_next_batch; - cursor->impl.destroy = _destroy; - cursor->impl.clone = _clone; - cursor->impl.data = (void *)data; -} diff --git a/src/libmongoc/src/mongoc/mongoc-cursor-find.c b/src/libmongoc/src/mongoc/mongoc-cursor-find.c index b6b9b6e2912..0dc8a516e7c 100644 --- a/src/libmongoc/src/mongoc/mongoc-cursor-find.c +++ b/src/libmongoc/src/mongoc/mongoc-cursor-find.c @@ -20,36 +20,52 @@ #include typedef struct _data_find_t { + mongoc_cursor_response_t response; bson_t filter; } data_find_t; - -extern void -_mongoc_cursor_impl_find_cmd_init(mongoc_cursor_t *cursor, bson_t *filter); - - static mongoc_cursor_state_t _prime(mongoc_cursor_t *cursor) { data_find_t *data = (data_find_t *)cursor->impl.data; + bson_t find_cmd; + + bson_init(&find_cmd); + cursor->operation_id = ++cursor->client->cluster.operation_id; + /* construct { find: "", filter: {} } */ + _mongoc_cursor_prepare_find_command(cursor, &data->filter, &find_cmd); + _mongoc_cursor_response_refresh(cursor, &find_cmd, &cursor->opts, &data->response); + bson_destroy(&find_cmd); + return IN_BATCH; +} - /* set all mongoc_impl_t function pointers. */ - _mongoc_cursor_impl_find_cmd_init(cursor, &data->filter /* stolen */); - /* destroy this impl data since impl functions have been replaced. */ - bson_free(data); - /* prime with the new implementation. */ - return cursor->impl.prime(cursor); +static mongoc_cursor_state_t +_pop_from_batch(mongoc_cursor_t *cursor) +{ + data_find_t *data = (data_find_t *)cursor->impl.data; + _mongoc_cursor_response_read(cursor, &data->response, &cursor->current); + if (cursor->current) { + return IN_BATCH; + } else { + return cursor->cursor_id ? END_OF_BATCH : DONE; + } } -static void -_clone(mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src) +static mongoc_cursor_state_t +_get_next_batch(mongoc_cursor_t *cursor) { - data_find_t *data_dst = BSON_ALIGNED_ALLOC0(data_find_t); - data_find_t *data_src = (data_find_t *)src->data; - bson_copy_to(&data_src->filter, &data_dst->filter); - dst->data = data_dst; + data_find_t *data = (data_find_t *)cursor->impl.data; + bson_t getmore_cmd; + + if (!cursor->cursor_id) { + return DONE; + } + _mongoc_cursor_prepare_getmore_command(cursor, &getmore_cmd); + _mongoc_cursor_response_refresh(cursor, &getmore_cmd, NULL /* opts */, &data->response); + bson_destroy(&getmore_cmd); + return IN_BATCH; } @@ -58,10 +74,21 @@ _destroy(mongoc_cursor_impl_t *impl) { data_find_t *data = (data_find_t *)impl->data; bson_destroy(&data->filter); + bson_destroy(&data->response.reply); bson_free(data); } +static void +_clone(mongoc_cursor_impl_t *dst, const mongoc_cursor_impl_t *src) +{ + data_find_t *data_src = (data_find_t *)src->data; + data_find_t *data_dst = BSON_ALIGNED_ALLOC0(data_find_t); + bson_init(&data_dst->response.reply); + bson_copy_to(&data_src->filter, &data_dst->filter); + dst->data = data_dst; +} + mongoc_cursor_t * _mongoc_cursor_find_new(mongoc_client_t *client, const char *db_and_coll, @@ -74,12 +101,18 @@ _mongoc_cursor_find_new(mongoc_client_t *client, BSON_ASSERT_PARAM(client); mongoc_cursor_t *cursor; + data_find_t *data = BSON_ALIGNED_ALLOC0(data_find_t); + bson_init(&data->response.reply); + cursor = _mongoc_cursor_new_with_opts(client, db_and_coll, opts, user_prefs, default_prefs, read_concern); _mongoc_cursor_check_and_copy_to(cursor, "filter", filter, &data->filter); cursor->impl.prime = _prime; - cursor->impl.clone = _clone; + cursor->impl.pop_from_batch = _pop_from_batch; + cursor->impl.get_next_batch = _get_next_batch; cursor->impl.destroy = _destroy; - cursor->impl.data = data; + cursor->impl.clone = _clone; + cursor->impl.data = (void *)data; + return cursor; }