void mongoc_bulk_operation_update_one (mongoc_bulk_operation_t *bulk, const bson_t *selector, const bson_t *document, bool upsert) { mongoc_write_command_t command = { 0 }; bson_iter_t iter; bson_return_if_fail (bulk); bson_return_if_fail (selector); bson_return_if_fail (document); ENTRY; if (bson_iter_init (&iter, document)) { while (bson_iter_next (&iter)) { if (!strchr (bson_iter_key (&iter), '$')) { MONGOC_WARNING ("%s(): update_one only works with $ operators.", __FUNCTION__); EXIT; } } } _mongoc_write_command_init_update (&command, selector, document, upsert, false, bulk->ordered); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
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_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; bson_return_if_fail (bulk); bson_return_if_fail (selector); bson_return_if_fail (document); ENTRY; if (!bson_validate (document, (BSON_VALIDATE_DOT_KEYS | BSON_VALIDATE_DOLLAR_KEYS), &err_off)) { MONGOC_WARNING ("%s(): replacement document may not contain " "$ or . in keys. Ingoring document.", __FUNCTION__); EXIT; } _mongoc_write_command_init_update (&command, selector, document, upsert, false, bulk->ordered); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
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_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); }
void mongoc_bulk_operation_remove_one (mongoc_bulk_operation_t *bulk, /* IN */ const bson_t *selector) /* IN */ { mongoc_write_command_t command = { 0 }; bson_return_if_fail (bulk); bson_return_if_fail (selector); ENTRY; _mongoc_write_command_init_delete (&command, selector, false, bulk->ordered); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
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); }
int mock_server_autoresponds (mock_server_t *server, autoresponder_t responder, void *data, destructor_t destructor) { autoresponder_handle_t handle = { responder, data, destructor }; int id; mongoc_mutex_lock (&server->mutex); id = handle.id = server->last_autoresponder_id++; /* TODO: peek and see if a matching request is enqueued */ _mongoc_array_append_val (&server->autoresponders, handle); mongoc_mutex_unlock (&server->mutex); return id; }
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; }
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; }
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); }
void mongoc_topology_description_suitable_servers ( mongoc_array_t *set, /* OUT */ mongoc_ss_optype_t optype, mongoc_topology_description_t *topology, const mongoc_read_prefs_t *read_pref, size_t local_threshold_ms) { mongoc_suitable_data_t data; mongoc_server_description_t **candidates; mongoc_server_description_t *server; int64_t nearest = -1; int i; mongoc_read_mode_t read_mode = mongoc_read_prefs_get_mode(read_pref); candidates = (mongoc_server_description_t **)bson_malloc0(sizeof(*candidates) * topology->servers->items_len); data.read_mode = read_mode; data.topology_type = topology->type; data.primary = NULL; data.candidates = candidates; data.candidates_len = 0; data.has_secondary = false; /* Single server -- * Either it is suitable or it isn't */ if (topology->type == MONGOC_TOPOLOGY_SINGLE) { server = (mongoc_server_description_t *)mongoc_set_get_item (topology->servers, 0); if (_mongoc_topology_description_server_is_candidate (server->type, read_mode, topology->type)) { _mongoc_array_append_val (set, server); } goto DONE; } /* Replica sets -- * Find suitable servers based on read mode */ if (topology->type == MONGOC_TOPOLOGY_RS_NO_PRIMARY || topology->type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY) { if (optype == MONGOC_SS_READ) { mongoc_set_for_each(topology->servers, _mongoc_replica_set_read_suitable_cb, &data); /* if we have a primary, it's a candidate, for some read modes we are done */ if (read_mode == MONGOC_READ_PRIMARY || read_mode == MONGOC_READ_PRIMARY_PREFERRED) { if (data.primary) { _mongoc_array_append_val (set, data.primary); goto DONE; } } if (! mongoc_server_description_filter_eligible (data.candidates, data.candidates_len, read_pref)) { if (read_mode == MONGOC_READ_NEAREST) { goto DONE; } else { data.has_secondary = false; } } if (data.has_secondary && (read_mode == MONGOC_READ_SECONDARY || read_mode == MONGOC_READ_SECONDARY_PREFERRED)) { /* secondary or secondary preferred and we have one. */ for (i = 0; i < data.candidates_len; i++) { if (candidates[i] && candidates[i]->type == MONGOC_SERVER_RS_PRIMARY) { candidates[i] = NULL; } } } else if (read_mode == MONGOC_READ_SECONDARY_PREFERRED && data.primary) { /* secondary preferred, but only the one primary is a candidate */ _mongoc_array_append_val (set, data.primary); goto DONE; } } else if (topology->type == MONGOC_TOPOLOGY_RS_WITH_PRIMARY) { /* includes optype == MONGOC_SS_WRITE as the exclusion of the above if */ mongoc_set_for_each(topology->servers, _mongoc_topology_description_has_primary_cb, &data.primary); if (data.primary) { _mongoc_array_append_val (set, data.primary); goto DONE; } } } /* Sharded clusters -- * All candidates in the latency window are suitable */ if (topology->type == MONGOC_TOPOLOGY_SHARDED) { mongoc_set_for_each (topology->servers, _mongoc_find_suitable_mongos_cb, &data); } /* Ways to get here: * - secondary read * - secondary preferred read * - primary_preferred and no primary read * - sharded anything * Find the nearest, then select within the window */ for (i = 0; i < data.candidates_len; i++) { if (candidates[i] && (nearest == -1 || nearest > candidates[i]->round_trip_time)) { nearest = candidates[i]->round_trip_time; } } for (i = 0; i < data.candidates_len; i++) { if (candidates[i] && (candidates[i]->round_trip_time <= nearest + local_threshold_ms)) { _mongoc_array_append_val (set, candidates[i]); } } DONE: bson_free (candidates); return; }