void mongoc_client_pool_push (mongoc_client_pool_t *pool, mongoc_client_t *client) { ENTRY; BSON_ASSERT (pool); BSON_ASSERT (client); mongoc_mutex_lock(&pool->mutex); if (pool->size > pool->min_pool_size) { mongoc_client_t *old_client; old_client = (mongoc_client_t *)_mongoc_queue_pop_head (&pool->queue); if (old_client) { mongoc_client_destroy (old_client); pool->size--; } } mongoc_mutex_unlock(&pool->mutex); mongoc_mutex_lock (&pool->mutex); _mongoc_queue_push_tail (&pool->queue, client); mongoc_cond_signal(&pool->cond); mongoc_mutex_unlock(&pool->mutex); EXIT; }
void mongoc_client_kill_cursor (mongoc_client_t *client, int64_t cursor_id) { mongoc_topology_t *topology; mongoc_server_description_t *selected_server; mongoc_read_prefs_t *read_prefs; uint32_t server_id = 0; topology = client->topology; read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY); mongoc_mutex_lock (&topology->mutex); /* see if there's a known writable server - do no I/O or retries */ selected_server = mongoc_topology_description_select(&topology->description, MONGOC_SS_WRITE, read_prefs, 15); if (selected_server) { server_id = selected_server->id; } mongoc_mutex_unlock (&topology->mutex); if (server_id) { _mongoc_client_kill_cursor (client, selected_server->id, cursor_id); } else { MONGOC_INFO ("No server available for mongoc_client_kill_cursor"); } mongoc_read_prefs_destroy (read_prefs); }
mongoc_client_t * mongoc_client_pool_try_pop (mongoc_client_pool_t *pool) { mongoc_client_t *client; ENTRY; BSON_ASSERT (pool); mongoc_mutex_lock(&pool->mutex); if (!(client = (mongoc_client_t *)_mongoc_queue_pop_head(&pool->queue))) { if (pool->size < pool->max_pool_size) { client = _mongoc_client_new_from_uri(pool->uri, pool->topology); #ifdef MONGOC_ENABLE_SSL if (pool->ssl_opts_set) { mongoc_client_set_ssl_opts (client, &pool->ssl_opts); } #endif pool->size++; } } mongoc_mutex_unlock(&pool->mutex); RETURN(client); }
mongoc_client_t * mongoc_client_pool_pop (mongoc_client_pool_t *pool) { mongoc_client_t *client; ENTRY; BSON_ASSERT (pool); mongoc_mutex_lock(&pool->mutex); again: if (!(client = (mongoc_client_t *)_mongoc_queue_pop_head(&pool->queue))) { if (pool->size < pool->max_pool_size) { client = _mongoc_client_new_from_uri(pool->uri, pool->topology); client->error_api_version = pool->error_api_version; _mongoc_client_set_apm_callbacks_private (client, &pool->apm_callbacks, pool->apm_context); #ifdef MONGOC_ENABLE_SSL if (pool->ssl_opts_set) { mongoc_client_set_ssl_opts (client, &pool->ssl_opts); } #endif pool->size++; } else { mongoc_cond_wait(&pool->cond, &pool->mutex); GOTO(again); } } mongoc_mutex_unlock(&pool->mutex); RETURN(client); }
void mock_server_remove_autoresponder (mock_server_t *server, int id) { size_t i; autoresponder_handle_t *handles; mongoc_mutex_lock (&server->mutex); handles = (autoresponder_handle_t *) server->autoresponders.data; for (i = 0; i < server->autoresponders.len; i++) { if (handles[i].id == id) { /* left-shift everyone after */ server->autoresponders.len--; for (; i < server->autoresponders.len; i++) { handles[i] = handles[i + 1]; } autoresponder_handle_destroy (handles); break; } } mongoc_mutex_unlock (&server->mutex); }
void mock_server_set_verbose (mock_server_t *server, bool verbose) { mongoc_mutex_lock (&server->mutex); server->verbose = verbose; mongoc_mutex_unlock (&server->mutex); }
bool mongoc_client_pool_set_metadata (mongoc_client_pool_t *pool, const char *driver_name, const char *version, const char *platform) { bool ret = false; bson_t* metadata; mongoc_mutex_lock (&pool->mutex); if (pool->metadata_set) { goto done; } if (mongoc_topology_is_scanner_active (pool->topology)) { /* Once the scanner is active we cannot tell it to send different metadata */ goto done; } metadata = &pool->topology->scanner->ismaster_metadata; ret = mongoc_client_metadata_set_data (metadata, driver_name, version, platform); if (ret) { pool->metadata_set = true; } done: mongoc_mutex_unlock (&pool->mutex); return ret; }
bool mongoc_client_pool_set_application (mongoc_client_pool_t *pool, const char *application_name) { bool ret; bson_t* metadata; /* Locking mutex even though this function can only get called once because we don't want to write to the metadata bson_t if someone else is reading from it at the same time */ mongoc_mutex_lock (&pool->mutex); if (mongoc_topology_is_scanner_active (pool->topology)) { /* Once the scanner is active we cannot tell it to send different metadata */ ret = false; goto done; } metadata = &pool->topology->scanner->ismaster_metadata; ret = mongoc_client_metadata_set_application (metadata, application_name); done: mongoc_mutex_unlock (&pool->mutex); return ret; }
void mongoc_log (mongoc_log_level_t log_level, const char *log_domain, const char *format, ...) { va_list args; char *message; static mongoc_once_t once = MONGOC_ONCE_INIT; mongoc_once(&once, &_mongoc_ensure_mutex_once); if (!gLogFunc #ifdef MONGOC_TRACE || (log_level == MONGOC_LOG_LEVEL_TRACE && !gLogTrace) #endif ) { return; } BSON_ASSERT (format); va_start(args, format); message = bson_strdupv_printf(format, args); va_end(args); mongoc_mutex_lock(&gLogMutex); gLogFunc(log_level, log_domain, message, gLogData); mongoc_mutex_unlock(&gLogMutex); bson_free(message); }
void mock_server_set_rand_delay (mock_server_t *server, bool rand_delay) { mongoc_mutex_lock (&server->mutex); server->rand_delay = rand_delay; mongoc_mutex_unlock (&server->mutex); }
void mongoc_log (mongoc_log_level_t log_level, const char *log_domain, const char *format, ...) { va_list args; char *message; int stop_logging; mongoc_once (&once, &_mongoc_ensure_mutex_once); stop_logging = !gLogFunc; #ifdef MONGOC_TRACE stop_logging = stop_logging || (log_level == MONGOC_LOG_LEVEL_TRACE && !gLogTrace); #endif if (stop_logging) { return; } BSON_ASSERT (format); va_start (args, format); message = bson_strdupv_printf (format, args); va_end (args); mongoc_mutex_lock (&gLogMutex); gLogFunc (log_level, log_domain, message, gLogData); mongoc_mutex_unlock (&gLogMutex); bson_free (message); }
static int mongoc_sasl_mutex_lock (void *mutex) { mongoc_mutex_lock ((mongoc_mutex_t *) mutex); return SASL_OK; }
/** run as a child thread by test_mongoc_tls_hangup * * It: * 1. spins up * 2. waits on a condvar until the server is up * 3. connects to the server's port * 4. writes a byte * 5. confirms that the server hangs up promptly * 6. shuts down */ static void * ssl_hangup_client (void *ptr) { ssl_test_data_t *data = (ssl_test_data_t *)ptr; mongoc_stream_t *sock_stream; mongoc_stream_t *ssl_stream; mongoc_socket_t *conn_sock; char buf = 'b'; ssize_t r; mongoc_iovec_t riov; mongoc_iovec_t wiov; struct sockaddr_in server_addr = { 0 }; int64_t start_time; bson_error_t error; conn_sock = mongoc_socket_new (AF_INET, SOCK_STREAM, 0); assert (conn_sock); mongoc_mutex_lock (&data->cond_mutex); while (!data->server_port) { mongoc_cond_wait (&data->cond, &data->cond_mutex); } mongoc_mutex_unlock (&data->cond_mutex); server_addr.sin_family = AF_INET; server_addr.sin_port = htons (data->server_port); server_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); r = mongoc_socket_connect (conn_sock, (struct sockaddr *)&server_addr, sizeof (server_addr), -1); assert (r == 0); sock_stream = mongoc_stream_socket_new (conn_sock); assert (sock_stream); ssl_stream = mongoc_stream_tls_new (sock_stream, data->client, 1); assert (ssl_stream); r = mongoc_stream_tls_handshake_block (ssl_stream, data->host, TIMEOUT, &error); assert (r); wiov.iov_base = (void *)&buf; wiov.iov_len = 1; r = mongoc_stream_writev (ssl_stream, &wiov, 1, TIMEOUT); assert (r == 1); riov.iov_base = (void *)&buf; riov.iov_len = 1; /* we should notice promptly that the server hangs up */ start_time = bson_get_monotonic_time (); r = mongoc_stream_readv (ssl_stream, &riov, 1, 1, TIMEOUT); /* time is in microseconds */ assert (bson_get_monotonic_time () - start_time < 1000 * 1000); assert (r == -1); mongoc_stream_destroy (ssl_stream); data->client_result->result = SSL_TEST_SUCCESS; return NULL; }
void mock_server_set_request_timeout_msec (mock_server_t *server, int64_t request_timeout_msec) { mongoc_mutex_lock (&server->mutex); server->request_timeout_msec = request_timeout_msec; mongoc_mutex_unlock (&server->mutex); }
/*-------------------------------------------------------------------------- * * mock_server_set_ssl_opts -- * * Set server-side SSL options before calling mock_server_run. * * Returns: * None. * * Side effects: * None. * *-------------------------------------------------------------------------- */ void mock_server_set_ssl_opts (mock_server_t *server, mongoc_ssl_opt_t *opts) { mongoc_mutex_lock (&server->mutex); server->ssl = true; memcpy (&server->ssl_opts, opts, sizeof *opts); mongoc_mutex_unlock (&server->mutex); }
void mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data) { mongoc_once (&once, &_mongoc_ensure_mutex_once); mongoc_mutex_lock (&gLogMutex); gLogFunc = log_func; gLogData = user_data; mongoc_mutex_unlock (&gLogMutex); }
double mock_server_get_uptime_sec (mock_server_t *server) { double uptime; mongoc_mutex_lock (&server->mutex); uptime = (bson_get_monotonic_time () - server->start_time) / 1e6; mongoc_mutex_unlock (&server->mutex); return uptime; }
sync_queue_t * mock_server_get_queue (mock_server_t *server) { sync_queue_t *q; mongoc_mutex_lock (&server->mutex); q = server->q; mongoc_mutex_unlock (&server->mutex); return q; }
bool mock_server_get_rand_delay (mock_server_t *server) { bool rand_delay; mongoc_mutex_lock (&server->mutex); rand_delay = server->rand_delay; mongoc_mutex_unlock (&server->mutex); return rand_delay; }
int64_t mock_server_get_request_timeout_msec (mock_server_t *server) { int64_t request_timeout_msec; mongoc_mutex_lock (&server->mutex); request_timeout_msec = server->request_timeout_msec; mongoc_mutex_unlock (&server->mutex); return request_timeout_msec; }
bool mock_server_get_verbose (mock_server_t *server) { bool verbose; mongoc_mutex_lock (&server->mutex); verbose = server->verbose; mongoc_mutex_unlock (&server->mutex); return verbose; }
void future_resolve (future_t *future, future_value_t return_value) { mongoc_mutex_lock (&future->mutex); assert (!future->resolved); assert (future->return_value.type == return_value.type); future->return_value = return_value; future->resolved = true; mongoc_cond_signal (&future->cond); mongoc_mutex_unlock (&future->mutex); }
const mongoc_uri_t * mock_server_get_uri (mock_server_t *server) { mongoc_uri_t *uri; mongoc_mutex_lock (&server->mutex); uri = server->uri; mongoc_mutex_unlock (&server->mutex); return uri; }
static bool _mock_server_stopping (mock_server_t *server) { bool stopped; mongoc_mutex_lock (&server->mutex); stopped = server->stopped; mongoc_mutex_unlock (&server->mutex); return stopped; }
void mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data) { mongoc_once_t once = MONGOC_ONCE_INIT; mongoc_once(&once, &_mongoc_ensure_mutex_once); mongoc_mutex_lock(&gLogMutex); gLogFunc = log_func; mongoc_mutex_unlock(&gLogMutex); }
void mock_server_run_in_thread (mock_server_t *server) { BSON_ASSERT (server); server->using_main_thread = true; mongoc_mutex_lock (&server->mutex); mongoc_thread_create (&server->main_thread, main_thread, server); mongoc_cond_wait (&server->cond, &server->mutex); mongoc_mutex_unlock (&server->mutex); }
static void _mongoc_ssl_thread_locking_callback (int mode, int type, const char *file, int line) { if (mode & CRYPTO_LOCK) { mongoc_mutex_lock (&gMongocSslThreadLocks[type]); } else { mongoc_mutex_unlock (&gMongocSslThreadLocks[type]); } }
void mongoc_client_pool_min_size(mongoc_client_pool_t *pool, uint32_t min_pool_size) { ENTRY; mongoc_mutex_lock (&pool->mutex); pool->min_pool_size = min_pool_size; mongoc_mutex_unlock (&pool->mutex); EXIT; }
/* TODO: merge with mock_server_reply? */ void mock_server_reply_simple (mock_server_t *server, mongoc_stream_t *client, const mongoc_rpc_t *request, mongoc_reply_flags_t flags, const bson_t *doc, int64_t cursor_id) { mongoc_iovec_t *iov; mongoc_array_t ar; mongoc_rpc_t r = {{ 0 }}; size_t expected = 0; ssize_t n_written; int iovcnt; int i; BSON_ASSERT (server); BSON_ASSERT (request); BSON_ASSERT (client); BSON_ASSERT (doc); _mongoc_array_init (&ar, sizeof (mongoc_iovec_t)); mongoc_mutex_lock (&server->mutex); r.reply.request_id = ++server->last_response_id; mongoc_mutex_unlock (&server->mutex); r.reply.msg_len = 0; r.reply.response_to = request->header.request_id; r.reply.opcode = MONGOC_OPCODE_REPLY; r.reply.flags = flags; r.reply.cursor_id = cursor_id; r.reply.start_from = 0; r.reply.n_returned = 1; r.reply.documents = bson_get_data (doc); r.reply.documents_len = doc->len; _mongoc_rpc_gather (&r, &ar); _mongoc_rpc_swab_to_le (&r); iov = (mongoc_iovec_t *)ar.data; iovcnt = (int) ar.len; for (i = 0; i < iovcnt; i++) { expected += iov[i].iov_len; } n_written = mongoc_stream_writev (client, iov, (size_t) iovcnt, -1); assert (n_written == expected); _mongoc_array_destroy (&ar); }
size_t mongoc_client_pool_get_size (mongoc_client_pool_t *pool) { size_t size = 0; ENTRY; mongoc_mutex_lock (&pool->mutex); size = pool->size; mongoc_mutex_unlock (&pool->mutex); RETURN (size); }