Пример #1
0
/* The algorithm works as follows: In case we have a read preference of
 * primary, secondary or nearest the set will always contain a set of all nodes
 * that should always be considered to be returned. With primary, there is only
 * going to be one node, with primary the set contains only secondaries and
 * with nearest we do not prefer a secondary over a primary or v.v.
 *
 * In case we have a read preference of primaryPreferred or
 * secondaryPreferred, we need to do a bit more logic for selecting the node
 * that we use. */
mongo_connection *mongo_pick_server_from_set(mongo_con_manager *manager, mcon_collection *col, mongo_read_preference *rp)
{
	mongo_connection *con = NULL;
	int entry;

	/* If we prefer the primary, we check whether the first node is a primary
	 * (which it should be if it's available and sorted according to primary >
	 * secondary). If the first node in the list is no primary, we fall back
	 * to picking a random node from the set. */
	if (rp->type == MONGO_RP_PRIMARY_PREFERRED) {
		if (((mongo_connection*)col->data[0])->connection_type == MONGO_NODE_PRIMARY) {
			mongo_manager_log(manager, MLOG_RS, MLOG_INFO, "pick server: the primary");
			con = (mongo_connection*)col->data[0];
			mongo_print_connection_info(manager, con, MLOG_INFO);
			return con;
		}
	}

	/* If we prefer a secondary, then we need to ignore the last item from the
	 * list, as this is the primary node - but only if there is more than one
	 * node in the list AND the last node in the list is a primary. */
	if (rp->type == MONGO_RP_SECONDARY_PREFERRED) {
		if (
			(col->count > 1) &&
			(((mongo_connection*)col->data[col->count - 1])->connection_type == MONGO_NODE_PRIMARY)
		) {
			entry = rand() % (col->count - 1);
			mongo_manager_log(manager, MLOG_RS, MLOG_INFO, "pick server: random element %d while ignoring the primary", entry);
			con = (mongo_connection*)col->data[entry];
			mongo_print_connection_info(manager, con, MLOG_INFO);
			return con;
		}
	}

	/* For now, we just pick a random server from the set */
	entry = rand() % col->count;
	mongo_manager_log(manager, MLOG_RS, MLOG_INFO, "pick server: random element %d", entry);
	con = (mongo_connection*)col->data[entry];
	mongo_print_connection_info(manager, con, MLOG_INFO);
	return con;
}
Пример #2
0
static mcon_collection *mongo_filter_candidates_by_credentials(mongo_con_manager *manager, mcon_collection *candidates, mongo_servers *servers)
{
	int              i;
	char            *db, *username, *auth_hash, *hashed = NULL;
	mcon_collection *filtered;

	mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "limiting by credentials");
	filtered = mcon_init_collection(sizeof(mongo_connection*));

	for (i = 0; i < candidates->count; i++) {
		db = username = auth_hash = hashed = NULL;
		mongo_server_split_hash(((mongo_connection *) candidates->data[i])->hash, NULL, NULL, NULL, &db, &username, &auth_hash, NULL);
		if (servers->server[0]->username && servers->server[0]->password && servers->server[0]->db) {
			if (strcmp(db, servers->server[0]->db) != 0) {
				mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "- skipping '%s', database didn't match ('%s' vs '%s')", ((mongo_connection *) candidates->data[i])->hash, db, servers->server[0]->db);
				goto skip;
			}
			if (strcmp(username, servers->server[0]->username) != 0) {
				mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "- skipping '%s', username didn't match ('%s' vs '%s')", ((mongo_connection *) candidates->data[i])->hash, username, servers->server[0]->username);
				goto skip;
			}
			hashed = mongo_server_create_hashed_password(username, servers->server[0]->password);
			if (strcmp(auth_hash, hashed) != 0) {
				mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "- skipping '%s', authentication hash didn't match ('%s' vs '%s')", ((mongo_connection *) candidates->data[i])->hash, auth_hash, hashed);
				goto skip;
			}
		}

		mcon_collection_add(filtered, (mongo_connection *) candidates->data[i]);
		mongo_print_connection_info(manager, (mongo_connection *) candidates->data[i], MLOG_FINE);
skip:
		if (db) {
			free(db);
		}
		if (username) {
			free(username);
		}
		if (auth_hash) {
			free(auth_hash);
		}
		if (hashed) {
			free(hashed);
		}
	}
	mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "limiting by credentials: done");

	return filtered;
}
Пример #3
0
/* Collecting the correct servers */
static mcon_collection *filter_connections(mongo_con_manager *manager, int types, mongo_read_preference *rp)
{
	mcon_collection *col;
	mongo_con_manager_item *ptr = manager->connections;
	col = mcon_init_collection(sizeof(mongo_connection*));

	mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "filter_connections: adding connections:");
	while (ptr) {
		if (ptr->connection->connection_type & types) {
			mongo_print_connection_info(manager, ptr->connection, MLOG_FINE);
			mcon_collection_add(col, ptr->connection);
		}
		ptr = ptr->next;
	}
	mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "filter_connections: done");

	return col;
}
Пример #4
0
static mcon_collection *mongo_filter_candidates_by_seed(mongo_con_manager *manager, mcon_collection *candidates, mongo_servers *servers)
{
	int              i, j;
	mcon_collection *filtered;
	char            *server_hash;

	mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "limiting by seeded/discovered servers");
	filtered = mcon_init_collection(sizeof(mongo_connection*));

	for (j = 0; j < servers->count; j++) {
		server_hash = mongo_server_create_hash(servers->server[j]);
		for (i = 0; i < candidates->count; i++) {
			if (strcmp(((mongo_connection *) candidates->data[i])->hash, server_hash) == 0) {
				mongo_print_connection_info(manager, (mongo_connection *) candidates->data[i], MLOG_FINE);
				mcon_collection_add(filtered, (mongo_connection *) candidates->data[i]);
			}
		}
		free(server_hash);
	}

	mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "limiting by seeded/discovered servers: done");

	return filtered;
}
Пример #5
0
void mongo_print_connection_iterate_wrapper(mongo_con_manager *manager, void *elem)
{
	mongo_connection *con = (mongo_connection*) elem;

	mongo_print_connection_info(manager, con, MLOG_FINE);
}