void mongoc_client_set_read_prefs (mongoc_client_t *client, const mongoc_read_prefs_t *read_prefs) { BSON_ASSERT (client); if (read_prefs != client->read_prefs) { if (client->read_prefs) { mongoc_read_prefs_destroy(client->read_prefs); } client->read_prefs = read_prefs ? mongoc_read_prefs_copy(read_prefs) : mongoc_read_prefs_new(MONGOC_READ_PRIMARY); } }
void mongoc_database_set_read_prefs (mongoc_database_t *database, const mongoc_read_prefs_t *read_prefs) { BSON_ASSERT (database); if (database->read_prefs) { mongoc_read_prefs_destroy(database->read_prefs); database->read_prefs = NULL; } if (read_prefs) { database->read_prefs = mongoc_read_prefs_copy(read_prefs); } }
void mongoc_database_set_read_prefs (mongoc_database_t *database, const mongoc_read_prefs_t *read_prefs) { bson_return_if_fail(database); if (database->read_prefs) { mongoc_read_prefs_destroy(database->read_prefs); database->read_prefs = NULL; } if (read_prefs) { database->read_prefs = mongoc_read_prefs_copy(read_prefs); } }
void mongoc_client_set_read_prefs (mongoc_client_t *client, const mongoc_read_prefs_t *read_prefs) { bson_return_if_fail (client); if (read_prefs != client->read_prefs) { if (client->read_prefs) { mongoc_read_prefs_destroy(client->read_prefs); } client->read_prefs = read_prefs ? mongoc_read_prefs_copy(read_prefs) : mongoc_read_prefs_new(MONGOC_READ_PRIMARY); } }
mongoc_client_t * _mongoc_client_new_from_uri (const mongoc_uri_t *uri, mongoc_topology_t *topology) { mongoc_client_t *client; const mongoc_read_prefs_t *read_prefs; const mongoc_read_concern_t *read_concern; const mongoc_write_concern_t *write_concern; BSON_ASSERT (uri); #ifndef MONGOC_ENABLE_SSL if (mongoc_uri_get_ssl (uri)) { MONGOC_ERROR ("Can't create SSL client, SSL not enabled in this build."); return NULL; } #endif client = (mongoc_client_t *)bson_malloc0(sizeof *client); client->uri = mongoc_uri_copy (uri); client->request_id = rand (); client->initiator = mongoc_client_default_stream_initiator; client->initiator_data = client; client->topology = topology; write_concern = mongoc_uri_get_write_concern (client->uri); client->write_concern = mongoc_write_concern_copy (write_concern); read_concern = mongoc_uri_get_read_concern (client->uri); client->read_concern = mongoc_read_concern_copy (read_concern); read_prefs = mongoc_uri_get_read_prefs_t (client->uri); client->read_prefs = mongoc_read_prefs_copy (read_prefs); mongoc_cluster_init (&client->cluster, client->uri, client); #ifdef MONGOC_ENABLE_SSL client->use_ssl = false; if (mongoc_uri_get_ssl (client->uri)) { /* sets use_ssl = true */ mongoc_client_set_ssl_opts (client, mongoc_ssl_opt_get_default ()); } #endif mongoc_counter_clients_active_inc (); return client; }
mongoc_change_stream_t * _mongoc_change_stream_new_from_client (mongoc_client_t *client, const bson_t *pipeline, const bson_t *opts) { mongoc_change_stream_t *stream; BSON_ASSERT (client); stream = (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t)); bson_strncpy (stream->db, "admin", sizeof (stream->db)); stream->coll[0] = '\0'; stream->read_prefs = mongoc_read_prefs_copy (client->read_prefs); stream->read_concern = mongoc_read_concern_copy (client->read_concern); stream->client = client; stream->change_stream_type = MONGOC_CHANGE_STREAM_CLIENT; _change_stream_init (stream, pipeline, opts); return stream; }
mongoc_change_stream_t * _mongoc_change_stream_new_from_database (const mongoc_database_t *db, const bson_t *pipeline, const bson_t *opts) { mongoc_change_stream_t *stream; BSON_ASSERT (db); stream = (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t)); bson_strncpy (stream->db, db->name, sizeof (stream->db)); stream->coll[0] = '\0'; stream->read_prefs = mongoc_read_prefs_copy (db->read_prefs); stream->read_concern = mongoc_read_concern_copy (db->read_concern); stream->client = db->client; stream->change_stream_type = MONGOC_CHANGE_STREAM_DATABASE; _change_stream_init (stream, pipeline, opts); return stream; }
mongoc_change_stream_t * _mongoc_change_stream_new_from_collection (const mongoc_collection_t *coll, const bson_t *pipeline, const bson_t *opts) { mongoc_change_stream_t *stream; BSON_ASSERT (coll); stream = (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t)); bson_strncpy (stream->db, coll->db, sizeof (stream->db)); bson_strncpy (stream->coll, coll->collection, sizeof (stream->coll)); stream->read_prefs = mongoc_read_prefs_copy (coll->read_prefs); stream->read_concern = mongoc_read_concern_copy (coll->read_concern); stream->client = coll->client; stream->change_stream_type = MONGOC_CHANGE_STREAM_COLLECTION; _change_stream_init (stream, pipeline, opts); return stream; }
mongoc_client_t * _mongoc_client_new_from_uri (const mongoc_uri_t *uri, mongoc_topology_t *topology) { mongoc_client_t *client; const mongoc_read_prefs_t *read_prefs; const mongoc_write_concern_t *write_concern; #ifdef MONGOC_ENABLE_SSL const bson_t *options; bson_iter_t iter; #endif BSON_ASSERT (uri); client = (mongoc_client_t *)bson_malloc0(sizeof *client); client->uri = mongoc_uri_copy (uri); client->request_id = rand (); client->initiator = mongoc_client_default_stream_initiator; client->initiator_data = client; client->topology = topology; write_concern = mongoc_uri_get_write_concern (client->uri); client->write_concern = mongoc_write_concern_copy (write_concern); read_prefs = mongoc_uri_get_read_prefs_t (client->uri); client->read_prefs = mongoc_read_prefs_copy (read_prefs); mongoc_cluster_init (&client->cluster, client->uri, client); #ifdef MONGOC_ENABLE_SSL options = mongoc_uri_get_options (client->uri); if (bson_iter_init_find (&iter, options, "ssl") && BSON_ITER_HOLDS_BOOL (&iter) && bson_iter_bool (&iter)) { mongoc_client_set_ssl_opts (client, mongoc_ssl_opt_get_default ()); } #endif mongoc_counter_clients_active_inc (); return client; }
static void set_func_opt (bson_t *opts, mongoc_read_prefs_t **prefs_ptr, opt_type_t opt_type) { SET_OPT_PREAMBLE (function); switch (opt_type) { case OPT_READ_CONCERN: BSON_ASSERT (mongoc_read_concern_append (rc, opts)); break; case OPT_WRITE_CONCERN: BSON_ASSERT (mongoc_write_concern_append (wc, opts)); break; case OPT_READ_PREFS: *prefs_ptr = mongoc_read_prefs_copy (prefs); break; default: abort (); } SET_OPT_CLEANUP; }
mongoc_cursor_t * _mongoc_cursor_new (mongoc_client_t *client, const char *db_and_collection, mongoc_query_flags_t flags, bson_uint32_t skip, bson_uint32_t limit, bson_uint32_t batch_size, bson_bool_t is_command, const bson_t *query, const bson_t *fields, const mongoc_read_prefs_t *read_prefs) { mongoc_read_mode_t mode; mongoc_cursor_t *cursor; const bson_t *tags; const char *mode_str; bson_t child; ENTRY; BSON_ASSERT(client); BSON_ASSERT(db_and_collection); BSON_ASSERT(query); /* we can't have exhaust queries with limits */ BSON_ASSERT (!((flags & MONGOC_QUERY_EXHAUST) && limit)); /* we can't have exhaust queries with sharded clusters */ BSON_ASSERT (!((flags & MONGOC_QUERY_EXHAUST) && client->cluster.isdbgrid)); /* * Cursors execute their query lazily. This sadly means that we must copy * some extra data around between the bson_t structures. This should be * small in most cases, so it reduces to a pure memcpy. The benefit to this * design is simplified error handling by API consumers. */ cursor = bson_malloc0(sizeof *cursor); cursor->client = client; strncpy(cursor->ns, db_and_collection, sizeof cursor->ns - 1); cursor->nslen = strlen(cursor->ns); cursor->flags = flags; cursor->skip = skip; cursor->limit = limit; cursor->batch_size = cursor->batch_size; cursor->is_command = is_command; if (!bson_has_field (query, "$query")) { bson_init (&cursor->query); bson_append_document (&cursor->query, "$query", 6, query); } else { bson_copy_to (query, &cursor->query); } if (read_prefs) { cursor->read_prefs = mongoc_read_prefs_copy (read_prefs); mode = mongoc_read_prefs_get_mode (read_prefs); tags = mongoc_read_prefs_get_tags (read_prefs); if (mode != MONGOC_READ_PRIMARY) { flags |= MONGOC_QUERY_SLAVE_OK; if ((mode != MONGOC_READ_SECONDARY_PREFERRED) || tags) { bson_append_document_begin (&cursor->query, "$readPreference", 15, &child); mode_str = _mongoc_cursor_get_read_mode_string (mode); bson_append_utf8 (&child, "mode", 4, mode_str, -1); if (tags) { bson_append_array (&child, "tags", 4, tags); } bson_append_document_end (&cursor->query, &child); } } } if (fields) { bson_copy_to(fields, &cursor->fields); } else { bson_init(&cursor->fields); } _mongoc_buffer_init(&cursor->buffer, NULL, 0, NULL); mongoc_counter_cursors_active_inc(); RETURN(cursor); }
mongoc_cursor_t * _mongoc_cursor_new (mongoc_client_t *client, const char *db_and_collection, mongoc_query_flags_t flags, uint32_t skip, uint32_t limit, uint32_t batch_size, bool is_command, const bson_t *query, const bson_t *fields, const mongoc_read_prefs_t *read_prefs) { mongoc_read_prefs_t *local_read_prefs = NULL; mongoc_read_mode_t mode; mongoc_cursor_t *cursor; const bson_t *tags; bson_iter_t iter; const char *key; const char *mode_str; bson_t child; bool found = false; int i; ENTRY; BSON_ASSERT (client); BSON_ASSERT (db_and_collection); BSON_ASSERT (query); if (!read_prefs) { read_prefs = client->read_prefs; } cursor = bson_malloc0 (sizeof *cursor); /* * CDRIVER-244: * * If this is a command, we need to verify we can send it to the location * specified by the read preferences. Otherwise, log a warning that we * are rerouting to the primary instance. */ if (is_command && read_prefs && (mongoc_read_prefs_get_mode (read_prefs) != MONGOC_READ_PRIMARY) && bson_iter_init (&iter, query) && bson_iter_next (&iter) && (key = bson_iter_key (&iter))) { for (i = 0; gSecondaryOkCommands [i]; i++) { if (0 == strcasecmp (key, gSecondaryOkCommands [i])) { found = true; break; } } if (!found) { cursor->redir_primary = true; local_read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY); read_prefs = local_read_prefs; MONGOC_INFO ("Database command \"%s\" rerouted to primary node", key); } } /* * Cursors execute their query lazily. This sadly means that we must copy * some extra data around between the bson_t structures. This should be * small in most cases, so it reduces to a pure memcpy. The benefit to this * design is simplified error handling by API consumers. */ cursor->client = client; bson_strncpy (cursor->ns, db_and_collection, sizeof cursor->ns); cursor->nslen = (uint32_t)strlen(cursor->ns); cursor->flags = flags; cursor->skip = skip; cursor->limit = limit; cursor->batch_size = batch_size; cursor->is_command = is_command; #define MARK_FAILED(c) \ do { \ (c)->failed = true; \ (c)->done = true; \ (c)->end_of_event = true; \ (c)->sent = true; \ } while (0) /* we can't have exhaust queries with limits */ if ((flags & MONGOC_QUERY_EXHAUST) && limit) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "Cannot specify MONGOC_QUERY_EXHAUST and set a limit."); MARK_FAILED (cursor); GOTO (finish); } /* we can't have exhaust queries with sharded clusters */ if ((flags & MONGOC_QUERY_EXHAUST) && (client->cluster.mode == MONGOC_CLUSTER_SHARDED_CLUSTER)) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "Cannot specify MONGOC_QUERY_EXHAUST with sharded cluster."); MARK_FAILED (cursor); GOTO (finish); } /* * Check types of various optional parameters. */ if (!is_command) { if (bson_iter_init_find (&iter, query, "$explain") && !(BSON_ITER_HOLDS_BOOL (&iter) || BSON_ITER_HOLDS_INT32 (&iter))) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "$explain must be a boolean."); MARK_FAILED (cursor); GOTO (finish); } if (bson_iter_init_find (&iter, query, "$snapshot") && !BSON_ITER_HOLDS_BOOL (&iter) && !BSON_ITER_HOLDS_INT32 (&iter)) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "$snapshot must be a boolean."); MARK_FAILED (cursor); GOTO (finish); } } if (!cursor->is_command && !bson_has_field (query, "$query")) { bson_init (&cursor->query); bson_append_document (&cursor->query, "$query", 6, query); } else { bson_copy_to (query, &cursor->query); } if (read_prefs) { cursor->read_prefs = mongoc_read_prefs_copy (read_prefs); mode = mongoc_read_prefs_get_mode (read_prefs); tags = mongoc_read_prefs_get_tags (read_prefs); if (mode != MONGOC_READ_PRIMARY) { flags |= MONGOC_QUERY_SLAVE_OK; if ((mode != MONGOC_READ_SECONDARY_PREFERRED) || tags) { bson_append_document_begin (&cursor->query, "$readPreference", 15, &child); mode_str = _mongoc_cursor_get_read_mode_string (mode); bson_append_utf8 (&child, "mode", 4, mode_str, -1); if (tags) { bson_append_array (&child, "tags", 4, tags); } bson_append_document_end (&cursor->query, &child); } } } if (fields) { bson_copy_to(fields, &cursor->fields); } else { bson_init(&cursor->fields); } _mongoc_buffer_init(&cursor->buffer, NULL, 0, NULL); finish: mongoc_counter_cursors_active_inc(); if (local_read_prefs) { mongoc_read_prefs_destroy (local_read_prefs); } RETURN (cursor); }
static bool hippo_mongo_driver_manager_apply_rp(mongoc_uri_t *uri, const Array options) { mongoc_read_prefs_t *new_rp; const mongoc_read_prefs_t *old_rp; const char *rp_str = NULL; bson_t *b_tags; if (!(old_rp = mongoc_uri_get_read_prefs_t(uri))) { throw MongoDriver::Utils::throwRunTimeException("mongoc_uri_t does not have a read preference"); return false; } if (options.size() == 0) { return true; } if ( !options.exists(s_MongoDBDriverManager_slaveok) && !options.exists(s_MongoDBDriverManager_readpreference) && !options.exists(s_MongoDBDriverManager_readpreferencetags) && !options.exists(s_MongoDBDriverManager_readPreference) && !options.exists(s_MongoDBDriverManager_readPreferenceTags) ) { return true; } new_rp = mongoc_read_prefs_copy(old_rp); if (options.exists(s_MongoDBDriverManager_slaveok) && options[s_MongoDBDriverManager_slaveok].isBoolean()) { mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_SECONDARY_PREFERRED); } if (options.exists(s_MongoDBDriverManager_readpreference) && options[s_MongoDBDriverManager_readpreference].isString()) { rp_str = options[s_MongoDBDriverManager_readpreference].toString().c_str(); } if (options.exists(s_MongoDBDriverManager_readPreference) && options[s_MongoDBDriverManager_readPreference].isString()) { rp_str = options[s_MongoDBDriverManager_readPreference].toString().c_str(); } if (rp_str) { if (0 == strcasecmp("primary", rp_str)) { mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_PRIMARY); } else if (0 == strcasecmp("primarypreferred", rp_str)) { mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_PRIMARY_PREFERRED); } else if (0 == strcasecmp("secondary", rp_str)) { mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_SECONDARY); } else if (0 == strcasecmp("secondarypreferred", rp_str)) { mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_SECONDARY_PREFERRED); } else if (0 == strcasecmp("nearest", rp_str)) { mongoc_read_prefs_set_mode(new_rp, MONGOC_READ_NEAREST); } else { throw MongoDriver::Utils::throwInvalidArgumentException("Unsupported readPreference value: '" + Variant(rp_str).toString() + "'"); mongoc_read_prefs_destroy(new_rp); return false; } } if (options.exists(s_MongoDBDriverManager_readpreferencetags) && options[s_MongoDBDriverManager_readpreferencetags].isArray()) { VariantToBsonConverter converter(options[s_MongoDBDriverManager_readpreferencetags].toArray(), HIPPO_BSON_NO_FLAGS); b_tags = bson_new(); converter.convert(b_tags); mongoc_read_prefs_set_tags(new_rp, b_tags); } else if (options.exists(s_MongoDBDriverManager_readPreferenceTags) && options[s_MongoDBDriverManager_readPreferenceTags].isArray()) { VariantToBsonConverter converter(options[s_MongoDBDriverManager_readPreferenceTags].toArray(), HIPPO_BSON_NO_FLAGS); b_tags = bson_new(); converter.convert(b_tags); mongoc_read_prefs_set_tags(new_rp, b_tags); } if ( mongoc_read_prefs_get_mode(new_rp) == MONGOC_READ_PRIMARY && !bson_empty(mongoc_read_prefs_get_tags(new_rp)) ) { throw MongoDriver::Utils::throwInvalidArgumentException("Primary read preference mode conflicts with tags"); mongoc_read_prefs_destroy(new_rp); return false; } /* This may be redundant in light of the last check (primary with tags), * but we'll check anyway in case additional validation is implemented. */ if (!mongoc_read_prefs_is_valid(new_rp)) { throw MongoDriver::Utils::throwInvalidArgumentException("Read preference is not valid"); mongoc_read_prefs_destroy(new_rp); return false; } mongoc_uri_set_read_prefs_t(uri, new_rp); mongoc_read_prefs_destroy(new_rp); return true; }
ReadPrefs :: ReadPrefs (mongoc_read_prefs_t const * readPrefs, QObject * parent) : QObject (parent) , readPrefs (mongoc_read_prefs_copy (readPrefs), readPrefsDeleter) {}