void mongoc_bulk_operation_insert (mongoc_bulk_operation_t *bulk, const bson_t *document) { mongoc_write_command_t command = { 0 }; mongoc_write_command_t *last; ENTRY; BSON_ASSERT (bulk); BSON_ASSERT (document); if (bulk->commands.len) { last = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, bulk->commands.len - 1); if (last->type == MONGOC_WRITE_COMMAND_INSERT) { _mongoc_write_command_insert_append (last, document); EXIT; } } _mongoc_write_command_init_insert ( &command, document, bulk->flags, bulk->operation_id, !mongoc_write_concern_is_acknowledged (bulk->write_concern)); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
void mongoc_bulk_operation_destroy (mongoc_bulk_operation_t *bulk) /* IN */ { mongoc_write_command_t *command; int i; if (bulk) { for (i = 0; i < bulk->commands.len; i++) { command = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, i); _mongoc_write_command_destroy (command); } bson_free (bulk->database); bson_free (bulk->collection); mongoc_write_concern_destroy (bulk->write_concern); _mongoc_array_destroy (&bulk->commands); if (bulk->executed) { _mongoc_write_result_destroy (&bulk->result); } bson_free (bulk); } }
void mongoc_bulk_operation_insert (mongoc_bulk_operation_t *bulk, const bson_t *document) { mongoc_write_command_t command = { 0 }; mongoc_write_command_t *last; ENTRY; bson_return_if_fail (bulk); bson_return_if_fail (document); if (bulk->commands.len) { last = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, bulk->commands.len - 1); if (last->type == MONGOC_WRITE_COMMAND_INSERT) { _mongoc_write_command_insert_append (last, &document, 1); EXIT; } } _mongoc_write_command_init_insert (&command, &document, 1, bulk->ordered, !_mongoc_write_concern_needs_gle (bulk->write_concern)); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
void mongoc_bulk_operation_remove_one (mongoc_bulk_operation_t *bulk, /* IN */ const bson_t *selector) /* IN */ { mongoc_write_command_t command = { 0 }; mongoc_write_command_t *last; ENTRY; BSON_ASSERT (bulk); BSON_ASSERT (selector); if (bulk->commands.len) { last = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, bulk->commands.len - 1); if ((last->type == MONGOC_WRITE_COMMAND_DELETE) && !last->u.delete_.multi) { _mongoc_write_command_delete_append (last, selector); EXIT; } } _mongoc_write_command_init_delete (&command, selector, false, bulk->flags, bulk->operation_id); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
bool mongoc_bulk_operation_insert_with_opts (mongoc_bulk_operation_t *bulk, const bson_t *document, const bson_t *opts, bson_error_t *error) { mongoc_bulk_insert_opts_t insert_opts; mongoc_write_command_t command = {0}; mongoc_write_command_t *last; bool ret = false; ENTRY; BSON_ASSERT (bulk); BSON_ASSERT (document); BULK_RETURN_IF_PRIOR_ERROR; if (!_mongoc_bulk_insert_opts_parse ( bulk->client, opts, &insert_opts, error)) { GOTO (done); } if (!_mongoc_validate_new_document (document, insert_opts.validate, error)) { GOTO (done); } if (bulk->commands.len) { last = &_mongoc_array_index ( &bulk->commands, mongoc_write_command_t, bulk->commands.len - 1); if (last->type == MONGOC_WRITE_COMMAND_INSERT) { _mongoc_write_command_insert_append (last, document); ret = true; GOTO (done); } } _mongoc_write_command_init_insert ( &command, document, opts, bulk->flags, bulk->operation_id, !mongoc_write_concern_is_acknowledged (bulk->write_concern)); _mongoc_array_append_val (&bulk->commands, command); ret = true; done: _mongoc_bulk_insert_opts_cleanup (&insert_opts); RETURN (ret); }
static void _mongoc_bulk_operation_update_append ( mongoc_bulk_operation_t *bulk, const bson_t *selector, const bson_t *document, const mongoc_bulk_update_opts_t *update_opts, const bson_t *extra_opts) { mongoc_write_command_t command = {0}; mongoc_write_command_t *last; bson_t opts; bool has_collation; bson_init (&opts); bson_append_bool (&opts, "upsert", 6, update_opts->upsert); bson_append_bool (&opts, "multi", 5, update_opts->multi); has_collation = !bson_empty (&update_opts->collation); if (has_collation) { bson_append_document (&opts, "collation", 9, &update_opts->collation); } if (extra_opts) { bson_concat (&opts, extra_opts); } if (bulk->commands.len) { last = &_mongoc_array_index ( &bulk->commands, mongoc_write_command_t, bulk->commands.len - 1); if (last->type == MONGOC_WRITE_COMMAND_UPDATE) { last->flags.has_collation |= has_collation; last->flags.has_multi_write |= update_opts->multi; _mongoc_write_command_update_append (last, selector, document, &opts); bson_destroy (&opts); return; } } _mongoc_write_command_init_update ( &command, selector, document, &opts, bulk->flags, bulk->operation_id); command.flags.has_collation = has_collation; command.flags.has_multi_write = update_opts->multi; _mongoc_array_append_val (&bulk->commands, command); bson_destroy (&opts); }
void mongoc_bulk_operation_update (mongoc_bulk_operation_t *bulk, const bson_t *selector, const bson_t *document, bool upsert) { bool multi = true; mongoc_write_command_t command = { 0 }; bson_iter_t iter; mongoc_write_command_t *last; BSON_ASSERT (bulk); BSON_ASSERT (selector); BSON_ASSERT (document); ENTRY; if (bson_iter_init (&iter, document)) { while (bson_iter_next (&iter)) { if (!strchr (bson_iter_key (&iter), '$')) { MONGOC_WARNING ("%s(): update only works with $ operators.", BSON_FUNC); EXIT; } } } if (bulk->commands.len) { last = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, bulk->commands.len - 1); if (last->type == MONGOC_WRITE_COMMAND_UPDATE) { _mongoc_write_command_update_append (last, selector, document, upsert, multi); EXIT; } } _mongoc_write_command_init_update (&command, selector, document, upsert, multi, bulk->flags, bulk->operation_id); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
void mongoc_bulk_operation_replace_one (mongoc_bulk_operation_t *bulk, const bson_t *selector, const bson_t *document, bool upsert) { mongoc_write_command_t command = { 0 }; size_t err_off; mongoc_write_command_t *last; int flags = BSON_VALIDATE_DOT_KEYS|BSON_VALIDATE_DOLLAR_KEYS; BSON_ASSERT (bulk); BSON_ASSERT (selector); BSON_ASSERT (document); ENTRY; if (!bson_validate (document, (bson_validate_flags_t)flags, &err_off)) { MONGOC_WARNING ("%s(): replacement document may not contain " "$ or . in keys. Ignoring document.", BSON_FUNC); EXIT; } if (bulk->commands.len) { last = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, bulk->commands.len - 1); if (last->type == MONGOC_WRITE_COMMAND_UPDATE) { _mongoc_write_command_update_append (last, selector, document, upsert, false); EXIT; } } _mongoc_write_command_init_update (&command, selector, document, upsert, false, bulk->flags, bulk->operation_id); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
/* TODO: factor */ static void * worker_thread (void *data) { worker_closure_t *closure = (worker_closure_t *) data; mock_server_t *server = closure->server; mongoc_stream_t *client_stream = closure->client_stream; mongoc_buffer_t buffer; mongoc_rpc_t *rpc = NULL; bool handled; bson_error_t error; int32_t msg_len; bool stopped; sync_queue_t *q; request_t *request; mongoc_array_t autoresponders; ssize_t i; autoresponder_handle_t handle; #ifdef MONGOC_ENABLE_SSL bool ssl; #endif ENTRY; BSON_ASSERT(closure); #ifdef MONGOC_ENABLE_SSL mongoc_mutex_lock (&server->mutex); ssl = server->ssl; mongoc_mutex_unlock (&server->mutex); if (ssl) { if (!mongoc_stream_tls_handshake_block (client_stream, "localhost", TIMEOUT, &error)) { MONGOC_ERROR("Blocking TLS handshake failed"); mongoc_stream_close (client_stream); mongoc_stream_destroy (client_stream); RETURN (NULL); } } #endif _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL); _mongoc_array_init (&autoresponders, sizeof (autoresponder_handle_t)); again: bson_free (rpc); rpc = NULL; handled = false; mongoc_mutex_lock (&server->mutex); stopped = server->stopped; mongoc_mutex_unlock (&server->mutex); if (stopped) { GOTO(failure); } if (_mongoc_buffer_fill (&buffer, client_stream, 4, TIMEOUT, &error) == -1) { GOTO (again); } assert (buffer.len >= 4); memcpy (&msg_len, buffer.data + buffer.off, 4); msg_len = BSON_UINT32_FROM_LE (msg_len); if (msg_len < 16) { MONGOC_WARNING ("No data"); GOTO (failure); } if (_mongoc_buffer_fill (&buffer, client_stream, (size_t) msg_len, -1, &error) == -1) { MONGOC_WARNING ("%s():%d: %s", BSON_FUNC, __LINE__, error.message); GOTO (failure); } assert (buffer.len >= (unsigned) msg_len); /* copies message from buffer */ request = request_new (&buffer, msg_len, server, client_stream, closure->port); mongoc_mutex_lock (&server->mutex); _mongoc_array_copy (&autoresponders, &server->autoresponders); mongoc_mutex_unlock (&server->mutex); if (mock_server_get_verbose (server)) { printf ("%5.2f %hu -> %hu %s\n", mock_server_get_uptime_sec (server), closure->port, server->port, request->as_str); fflush (stdout); } /* run responders most-recently-added-first */ for (i = server->autoresponders.len - 1; i >= 0; i--) { handle = _mongoc_array_index (&server->autoresponders, autoresponder_handle_t, i); if (handle.responder (request, handle.data)) { handled = true; /* responder should destroy the request */ request = NULL; break; } } if (!handled) { q = mock_server_get_queue (server); q_put (q, (void *) request); request = NULL; } memmove (buffer.data, buffer.data + buffer.off + msg_len, buffer.len - msg_len); buffer.off = 0; buffer.len -= msg_len; GOTO (again); failure: _mongoc_array_destroy (&autoresponders); _mongoc_buffer_destroy (&buffer); mongoc_stream_close (client_stream); mongoc_stream_destroy (client_stream); bson_free (rpc); bson_free (closure); _mongoc_buffer_destroy (&buffer); RETURN (NULL); }
static void * main_thread (void *data) { mock_server_t *server = (mock_server_t *)data; mongoc_socket_t *client_sock; bool stopped; uint16_t port; mongoc_stream_t *client_stream; worker_closure_t *closure; mongoc_thread_t thread; mongoc_array_t worker_threads; size_t i; mongoc_mutex_lock (&server->mutex); server->running = true; mongoc_cond_signal (&server->cond); mongoc_mutex_unlock (&server->mutex); for (; ;) { client_sock = mongoc_socket_accept_ex ( server->sock, bson_get_monotonic_time () + TIMEOUT, &port); mongoc_mutex_lock (&server->mutex); stopped = server->stopped; mongoc_mutex_unlock (&server->mutex); if (stopped) { break; } if (client_sock) { if (mock_server_get_verbose (server)) { printf ("%5.2f %hu -> server port %hu (connected)\n", mock_server_get_uptime_sec (server), port, server->port); fflush (stdout); } client_stream = mongoc_stream_socket_new (client_sock); #ifdef MONGOC_ENABLE_SSL mongoc_mutex_lock (&server->mutex); if (server->ssl) { server->ssl_opts.weak_cert_validation = 1; client_stream = mongoc_stream_tls_new (client_stream, &server->ssl_opts, 0); if (!client_stream) { mongoc_mutex_unlock (&server->mutex); perror ("Failed to attach tls stream"); break; } } mongoc_mutex_unlock (&server->mutex); #endif closure = (worker_closure_t *)bson_malloc (sizeof *closure); closure->server = server; closure->client_stream = client_stream; closure->port = port; mongoc_thread_create (&thread, worker_thread, closure); mongoc_mutex_lock (&server->mutex); _mongoc_array_append_val (&server->worker_threads, thread); mongoc_mutex_unlock (&server->mutex); } } /* copy list of worker threads and join them all */ _mongoc_array_init (&worker_threads, sizeof (mongoc_thread_t)); mongoc_mutex_lock (&server->mutex); _mongoc_array_copy (&worker_threads, &server->worker_threads); mongoc_mutex_unlock (&server->mutex); for (i = 0; i < worker_threads.len; i++) { mongoc_thread_join ( _mongoc_array_index (&worker_threads, mongoc_thread_t, i)); } _mongoc_array_destroy (&worker_threads); mongoc_mutex_lock (&server->mutex); server->running = false; mongoc_mutex_unlock (&server->mutex); return NULL; }
void mock_server_destroy (mock_server_t *server) { size_t i; autoresponder_handle_t *handle; int64_t deadline = bson_get_monotonic_time () + 10 * 1000 * 1000; request_t *request; mongoc_mutex_lock (&server->mutex); if (server->running) { server->stopped = true; } mongoc_mutex_unlock (&server->mutex); while (bson_get_monotonic_time () <= deadline) { /* wait 10 seconds */ mongoc_mutex_lock (&server->mutex); if (!server->running) { mongoc_mutex_unlock (&server->mutex); break; } mongoc_mutex_unlock (&server->mutex); _mongoc_usleep (1000); } mongoc_mutex_lock (&server->mutex); if (server->running) { fprintf (stderr, "server still running after timeout\n"); fflush (stderr); abort (); } mongoc_mutex_unlock (&server->mutex); mongoc_thread_join (server->main_thread); _mongoc_array_destroy (&server->worker_threads); for (i = 0; i < server->autoresponders.len; i++) { handle = &_mongoc_array_index (&server->autoresponders, autoresponder_handle_t, i); autoresponder_handle_destroy (handle); } _mongoc_array_destroy (&server->autoresponders); mongoc_cond_destroy (&server->cond); mongoc_mutex_unlock (&server->mutex); mongoc_mutex_destroy (&server->mutex); mongoc_socket_destroy (server->sock); bson_free (server->uri_str); mongoc_uri_destroy (server->uri); while ((request = (request_t *) q_get_nowait (server->q))) { request_destroy (request); } q_destroy (server->q); bson_free (server); }
uint32_t mongoc_bulk_operation_execute (mongoc_bulk_operation_t *bulk, /* IN */ bson_t *reply, /* OUT */ bson_error_t *error) /* OUT */ { mongoc_cluster_t *cluster; mongoc_write_command_t *command; mongoc_server_stream_t *server_stream; bool ret; uint32_t offset = 0; int i; ENTRY; BSON_ASSERT (bulk); if (reply) { bson_init (reply); } if (!bulk->client) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "mongoc_bulk_operation_execute() requires a client " "and one has not been set."); RETURN (false); } cluster = &bulk->client->cluster; if (bulk->executed) { _mongoc_write_result_destroy (&bulk->result); _mongoc_write_result_init (&bulk->result); } bulk->executed = true; if (!bulk->database) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "mongoc_bulk_operation_execute() requires a database " "and one has not been set."); RETURN (false); } else if (!bulk->collection) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "mongoc_bulk_operation_execute() requires a collection " "and one has not been set."); RETURN (false); } /* error stored by functions like mongoc_bulk_operation_insert that * can't report errors immediately */ if (bulk->result.error.domain) { if (error) { memcpy (error, &bulk->result.error, sizeof (bson_error_t)); } RETURN (false); } if (!bulk->commands.len) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "Cannot do an empty bulk write"); RETURN (false); } for (i = 0; i < bulk->commands.len; i++) { if (bulk->server_id) { server_stream = mongoc_cluster_stream_for_server ( cluster, bulk->server_id, true /* reconnect_ok */, error); } else { server_stream = mongoc_cluster_stream_for_writes (cluster, error); } if (!server_stream) { RETURN (false); } command = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, i); _mongoc_write_command_execute (command, bulk->client, server_stream, bulk->database, bulk->collection, bulk->write_concern, offset, bulk->session, &bulk->result); bulk->server_id = server_stream->sd->id; if (bulk->result.failed && (bulk->flags.ordered || bulk->result.must_stop)) { mongoc_server_stream_cleanup (server_stream); GOTO (cleanup); } offset += command->n_documents; mongoc_server_stream_cleanup (server_stream); } cleanup: ret = MONGOC_WRITE_RESULT_COMPLETE (&bulk->result, bulk->client->error_api_version, bulk->write_concern, MONGOC_ERROR_COMMAND /* err domain */, reply, error); RETURN (ret ? bulk->server_id : 0); }
bool _mongoc_bulk_operation_remove_with_opts ( mongoc_bulk_operation_t *bulk, const bson_t *selector, const mongoc_bulk_remove_opts_t *remove_opts, int32_t limit, bson_error_t *error) /* OUT */ { mongoc_write_command_t command = {0}; mongoc_write_command_t *last; bson_t opts; bool has_collation; bool ret = false; ENTRY; BSON_ASSERT (bulk); BSON_ASSERT (selector); bson_init (&opts); /* allow "limit" in opts, but it must be the correct limit */ if (remove_opts->limit != limit) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "Invalid \"limit\" in opts: %" PRId32 "." " The value must be %" PRId32 ", or omitted.", remove_opts->limit, limit); GOTO (done); } bson_append_int32 (&opts, "limit", 5, limit); has_collation = !bson_empty (&remove_opts->collation); if (has_collation) { bson_append_document (&opts, "collation", 9, &remove_opts->collation); } if (bulk->commands.len) { last = &_mongoc_array_index ( &bulk->commands, mongoc_write_command_t, bulk->commands.len - 1); if (last->type == MONGOC_WRITE_COMMAND_DELETE) { last->flags.has_collation |= has_collation; last->flags.has_multi_write |= (remove_opts->limit == 0); _mongoc_write_command_delete_append (last, selector, &opts); ret = true; GOTO (done); } } _mongoc_write_command_init_delete ( &command, selector, NULL, &opts, bulk->flags, bulk->operation_id); command.flags.has_collation = has_collation; command.flags.has_multi_write = (remove_opts->limit == 0); _mongoc_array_append_val (&bulk->commands, command); ret = true; done: bson_destroy (&opts); RETURN (ret); }
uint32_t mongoc_bulk_operation_execute (mongoc_bulk_operation_t *bulk, /* IN */ bson_t *reply, /* OUT */ bson_error_t *error) /* OUT */ { mongoc_write_command_t *command; uint32_t hint = 0; bool ret; int i; ENTRY; bson_return_val_if_fail (bulk, false); if (bulk->executed) { _mongoc_write_result_destroy (&bulk->result); } _mongoc_write_result_init (&bulk->result); bulk->executed = true; if (!bulk->client) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "mongoc_bulk_operation_execute() requires a client " "and one has not been set."); RETURN (false); } else if (!bulk->database) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "mongoc_bulk_operation_execute() requires a database " "and one has not been set."); RETURN (false); } else if (!bulk->collection) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "mongoc_bulk_operation_execute() requires a collection " "and one has not been set."); RETURN (false); } if (reply) { bson_init (reply); } if (!bulk->commands.len) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "Cannot do an empty bulk write"); RETURN (false); } for (i = 0; i < bulk->commands.len; i++) { command = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, i); _mongoc_write_command_execute (command, bulk->client, hint, bulk->database, bulk->collection, bulk->write_concern, &bulk->result); hint = command->hint; if (bulk->result.failed && bulk->ordered) { GOTO (cleanup); } } cleanup: ret = _mongoc_write_result_complete (&bulk->result, reply, error); RETURN (ret ? hint : 0); }
static void * worker_thread (void *data) { worker_closure_t *closure = (worker_closure_t *) data; mock_server_t *server = closure->server; mongoc_stream_t *client_stream = closure->client_stream; mongoc_buffer_t buffer; mongoc_rpc_t *rpc = NULL; bool handled; bson_error_t error; int32_t msg_len; sync_queue_t *requests; sync_queue_t *replies; request_t *request; mongoc_array_t autoresponders; ssize_t i; autoresponder_handle_t handle; reply_t *reply; #ifdef MONGOC_ENABLE_SSL bool ssl; #endif ENTRY; /* queue of client replies sent over this worker's connection */ replies = q_new (); #ifdef MONGOC_ENABLE_SSL mongoc_mutex_lock (&server->mutex); ssl = server->ssl; mongoc_mutex_unlock (&server->mutex); if (ssl) { if (!mongoc_stream_tls_handshake_block (client_stream, "localhost", TIMEOUT, &error)) { mongoc_stream_close (client_stream); mongoc_stream_destroy (client_stream); RETURN (NULL); } } #endif _mongoc_buffer_init (&buffer, NULL, 0, NULL, NULL); _mongoc_array_init (&autoresponders, sizeof (autoresponder_handle_t)); again: /* loop, checking for requests to receive or replies to send */ bson_free (rpc); rpc = NULL; if (_mongoc_buffer_fill (&buffer, client_stream, 4, 10, &error) > 0) { assert (buffer.len >= 4); memcpy (&msg_len, buffer.data + buffer.off, 4); msg_len = BSON_UINT32_FROM_LE (msg_len); if (msg_len < 16) { MONGOC_WARNING ("No data"); GOTO (failure); } if (_mongoc_buffer_fill (&buffer, client_stream, (size_t) msg_len, -1, &error) == -1) { MONGOC_WARNING ("%s():%d: %s", BSON_FUNC, __LINE__, error.message); GOTO (failure); } assert (buffer.len >= (unsigned) msg_len); /* copies message from buffer */ request = request_new (&buffer, msg_len, server, client_stream, closure->port, replies); memmove (buffer.data, buffer.data + buffer.off + msg_len, buffer.len - msg_len); buffer.off = 0; buffer.len -= msg_len; mongoc_mutex_lock (&server->mutex); _mongoc_array_copy (&autoresponders, &server->autoresponders); mongoc_mutex_unlock (&server->mutex); test_suite_mock_server_log ("%5.2f %hu -> %hu %s", mock_server_get_uptime_sec (server), closure->port, server->port, request->as_str); /* run responders most-recently-added-first */ handled = false; for (i = server->autoresponders.len - 1; i >= 0; i--) { handle = _mongoc_array_index (&server->autoresponders, autoresponder_handle_t, i); if (handle.responder (request, handle.data)) { /* responder destroyed request and enqueued a reply in "replies" */ handled = true; request = NULL; break; } } if (!handled) { /* pass to the main thread via the queue */ requests = mock_server_get_queue (server); q_put (requests, (void *) request); } } if (_mock_server_stopping (server)) { GOTO (failure); } reply = q_get (replies, 10); if (reply) { _mock_server_reply_with_stream (server, reply, client_stream); _reply_destroy (reply); } if (_mock_server_stopping (server)) { GOTO (failure); } GOTO (again); failure: _mongoc_array_destroy (&autoresponders); _mongoc_buffer_destroy (&buffer); mongoc_stream_close (client_stream); mongoc_stream_destroy (client_stream); bson_free (rpc); bson_free (closure); _mongoc_buffer_destroy (&buffer); while ((reply = q_get_nowait (replies))) { _reply_destroy (reply); } q_destroy (replies); RETURN (NULL); }
uint32_t mongoc_bulk_operation_execute (mongoc_bulk_operation_t *bulk, /* IN */ bson_t *reply, /* OUT */ bson_error_t *error) /* OUT */ { mongoc_cluster_t *cluster; mongoc_write_command_t *command; mongoc_server_stream_t *server_stream; bool ret; uint32_t offset = 0; int i; ENTRY; BSON_ASSERT (bulk); cluster = &bulk->client->cluster; if (bulk->executed) { _mongoc_write_result_destroy (&bulk->result); } _mongoc_write_result_init (&bulk->result); bulk->executed = true; if (!bulk->client) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "mongoc_bulk_operation_execute() requires a client " "and one has not been set."); RETURN (false); } else if (!bulk->database) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "mongoc_bulk_operation_execute() requires a database " "and one has not been set."); RETURN (false); } else if (!bulk->collection) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "mongoc_bulk_operation_execute() requires a collection " "and one has not been set."); RETURN (false); } if (reply) { bson_init (reply); } if (!bulk->commands.len) { bson_set_error (error, MONGOC_ERROR_COMMAND, MONGOC_ERROR_COMMAND_INVALID_ARG, "Cannot do an empty bulk write"); RETURN (false); } if (bulk->server_id) { server_stream = mongoc_cluster_stream_for_server (cluster, bulk->server_id, true /* reconnect_ok */, error); } else { server_stream = mongoc_cluster_stream_for_writes (cluster, error); } if (!server_stream) { RETURN (false); } for (i = 0; i < bulk->commands.len; i++) { command = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, i); _mongoc_write_command_execute (command, bulk->client, server_stream, bulk->database, bulk->collection, bulk->write_concern, offset, &bulk->result); bulk->server_id = command->server_id; if (bulk->result.failed && bulk->flags.ordered) { GOTO (cleanup); } offset += command->n_documents; } cleanup: ret = _mongoc_write_result_complete (&bulk->result, reply, error); mongoc_server_stream_cleanup (server_stream); RETURN (ret ? bulk->server_id : 0); }