static void _mongoc_client_killcursors_command (mongoc_cluster_t *cluster, mongoc_server_stream_t *server_stream, int64_t cursor_id, const char *db, const char *collection) { bson_t command = BSON_INITIALIZER; bson_t child; bson_append_utf8 (&command, "killCursors", 11, collection, -1); bson_append_array_begin (&command, "cursors", 7, &child); bson_append_int64 (&child, "0", 1, cursor_id); bson_append_array_end (&command, &child); /* Find, getMore And killCursors Commands Spec: "The result from the * killCursors command MAY be safely ignored." */ mongoc_cluster_run_command (cluster, server_stream->stream, server_stream->sd->id, MONGOC_QUERY_SLAVE_OK, db, &command, NULL, NULL); bson_destroy (&command); }
/** * mongoc_client_command_simple: * @client: A mongoc_client_t. * @db_name: The namespace, such as "admin". * @command: The command to execute. * @read_prefs: The read preferences or NULL. * @reply: A location for the reply document or NULL. * @error: A location for the error, or NULL. * * This wrapper around mongoc_client_command() aims to make it simpler to * run a command and check the output result. * * false is returned if the command failed to be delivered or if the execution * of the command failed. For example, a command that returns {'ok': 0} will * result in this function returning false. * * To allow the caller to disambiguate between command execution failure and * failure to send the command, reply will always be set if non-NULL. The * caller should release this with bson_destroy(). * * Returns: true if the command executed and resulted in success. Otherwise * false and @error is set. @reply is always set, either to the resulting * document or an empty bson document upon failure. */ bool mongoc_client_command_simple (mongoc_client_t *client, const char *db_name, const bson_t *command, const mongoc_read_prefs_t *read_prefs, bson_t *reply, bson_error_t *error) { mongoc_cluster_t *cluster; mongoc_server_stream_t *server_stream; mongoc_apply_read_prefs_result_t result = READ_PREFS_RESULT_INIT; bool ret = false; ENTRY; BSON_ASSERT (client); BSON_ASSERT (db_name); BSON_ASSERT (command); cluster = &client->cluster; server_stream = mongoc_cluster_stream_for_reads (cluster, read_prefs, error); if (!server_stream) { if (reply) { bson_init (reply); } GOTO (done); } apply_read_preferences (read_prefs, server_stream, command, MONGOC_QUERY_NONE, &result); ret = mongoc_cluster_run_command (cluster, server_stream->stream, server_stream->sd->id, result.flags, db_name, result.query_with_read_prefs, reply, error); done: mongoc_server_stream_cleanup (server_stream); apply_read_prefs_result_cleanup (&result); RETURN (ret); }
static void _mongoc_write_command(mongoc_write_command_t *command, mongoc_client_t *client, mongoc_server_stream_t *server_stream, const char *database, const char *collection, const mongoc_write_concern_t *write_concern, uint32_t offset, mongoc_write_result_t *result, bson_error_t *error) { const uint8_t *data; bson_iter_t iter; const char *key; uint32_t len = 0; bson_t tmp; bson_t ar; bson_t cmd; bson_t reply; char str [16]; bool has_more; bool ret = false; uint32_t i; int32_t max_bson_obj_size; int32_t max_write_batch_size; int32_t min_wire_version; uint32_t key_len; ENTRY; BSON_ASSERT (command); BSON_ASSERT (client); BSON_ASSERT (database); BSON_ASSERT (server_stream); BSON_ASSERT (collection); max_bson_obj_size = mongoc_server_stream_max_bson_obj_size (server_stream); max_write_batch_size = mongoc_server_stream_max_write_batch_size (server_stream); /* * If we have an unacknowledged write and the server supports the legacy * opcodes, then submit the legacy opcode so we don't need to wait for * a response from the server. */ min_wire_version = server_stream->sd->min_wire_version; if ((min_wire_version == 0) && !_mongoc_write_concern_needs_gle (write_concern)) { if (command->flags.bypass_document_validation != MONGOC_BYPASS_DOCUMENT_VALIDATION_DEFAULT) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "Cannot set bypassDocumentValidation for unacknowledged writes"); EXIT; } gLegacyWriteOps[command->type] (command, client, server_stream, database, collection, write_concern, offset, result, error); EXIT; } if (!command->n_documents || !bson_iter_init (&iter, command->documents) || !bson_iter_next (&iter)) { _empty_error (command, error); result->failed = true; EXIT; } again: bson_init (&cmd); has_more = false; i = 0; BSON_APPEND_UTF8 (&cmd, gCommandNames[command->type], collection); BSON_APPEND_DOCUMENT (&cmd, "writeConcern", WRITE_CONCERN_DOC (write_concern)); BSON_APPEND_BOOL (&cmd, "ordered", command->flags.ordered); if (command->flags.bypass_document_validation != MONGOC_BYPASS_DOCUMENT_VALIDATION_DEFAULT) { BSON_APPEND_BOOL (&cmd, "bypassDocumentValidation", !!command->flags.bypass_document_validation); } if (!_mongoc_write_command_will_overflow (0, command->documents->len, command->n_documents, max_bson_obj_size, max_write_batch_size)) { /* copy the whole documents buffer as e.g. "updates": [...] */ BSON_APPEND_ARRAY (&cmd, gCommandFields[command->type], command->documents); i = command->n_documents; } else { bson_append_array_begin (&cmd, gCommandFields[command->type], -1, &ar); do { if (!BSON_ITER_HOLDS_DOCUMENT (&iter)) { BSON_ASSERT (false); } bson_iter_document (&iter, &len, &data); key_len = (uint32_t) bson_uint32_to_string (i, &key, str, sizeof str); if (_mongoc_write_command_will_overflow (ar.len, key_len + len + 2, i, max_bson_obj_size, max_write_batch_size)) { has_more = true; break; } if (!bson_init_static (&tmp, data, len)) { BSON_ASSERT (false); } BSON_APPEND_DOCUMENT (&ar, key, &tmp); bson_destroy (&tmp); i++; } while (bson_iter_next (&iter)); bson_append_array_end (&cmd, &ar); } if (!i) { too_large_error (error, i, len, max_bson_obj_size, NULL); result->failed = true; ret = false; } else { ret = mongoc_cluster_run_command (&client->cluster, server_stream->stream, MONGOC_QUERY_NONE, database, &cmd, &reply, error); if (!ret) { result->failed = true; } _mongoc_write_result_merge (result, command, &reply, offset); offset += i; bson_destroy (&reply); } bson_destroy (&cmd); if (has_more && (ret || !command->flags.ordered)) { GOTO (again); } EXIT; }