static mcon_collection *mongo_filter_candidates_by_replicaset_name(mongo_con_manager *manager, mcon_collection *candidates, mongo_servers *servers) { int i; mcon_collection *filtered; char *candidate_hash; char *candidate_replsetname; mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "limiting to servers with same replicaset name"); filtered = mcon_init_collection(sizeof(mongo_connection*)); for (i = 0; i < candidates->count; i++) { candidate_hash = ((mongo_connection *) candidates->data[i])->hash; mongo_server_split_hash(candidate_hash, NULL, NULL, (char**) &candidate_replsetname, NULL, NULL, NULL, NULL); /* Filter out all servers that don't have the replicaset name the same * as what we have in the server definition struct. But only when the * repl_set_name in the server definition struct is actually *set*. If * not, we allow all connections. This make sure we can sort of handle * [ replicaset => true ], although it would not support one PHP worker * process connecting to multiple replicasets correctly. */ if (candidate_replsetname) { if (!servers->repl_set_name || strcmp(candidate_replsetname, servers->repl_set_name) == 0) { mongo_print_connection_info(manager, (mongo_connection *) candidates->data[i], MLOG_FINE); mcon_collection_add(filtered, (mongo_connection *) candidates->data[i]); } free(candidate_replsetname); } } mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "limiting to servers with same replicaset name: done"); return filtered; }
/* 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; int current_pid, connection_pid; current_pid = getpid(); col = mcon_init_collection(sizeof(mongo_connection*)); mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "filter_connections: adding connections:"); while (ptr) { connection_pid = mongo_server_hash_to_pid(ptr->connection->hash); if (connection_pid != current_pid) { mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "filter_connections: skipping %s as it doesn't match the current pid (%d)", ptr->connection->hash, current_pid); } else 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; }
static mcon_collection* mongo_filter_candidates_by_tagset(mongo_con_manager *manager, mcon_collection *candidates, mongo_read_preference_tagset *tagset) { int i; mcon_collection *tmp; tmp = mcon_init_collection(sizeof(mongo_connection*)); for (i = 0; i < candidates->count; i++) { if (candidate_matches_tags(manager, (mongo_connection *) candidates->data[i], tagset)) { mcon_collection_add(tmp, candidates->data[i]); } } return tmp; }
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; }
static mcon_collection* mongo_filter_candidates_by_tagset(mongo_con_manager *manager, mcon_collection *candidates, mongo_read_preference_tagset *tagset, int rp_type) { int i; mcon_collection *tmp; tmp = mcon_init_collection(sizeof(mongo_connection*)); for (i = 0; i < candidates->count; i++) { if (rp_type == MONGO_RP_PRIMARY_PREFERRED && (((mongo_connection *) candidates->data[i])->connection_type == MONGO_NODE_PRIMARY)) { mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "candidate_matches_tags: added primary regardless of tags: %s", ((mongo_connection *) candidates->data[i])->hash); mcon_collection_add(tmp, candidates->data[i]); } else if (candidate_matches_tags(manager, (mongo_connection *) candidates->data[i], tagset)) { mcon_collection_add(tmp, candidates->data[i]); } } return tmp; }
/* 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; }
mcon_collection *mongo_select_nearest_servers(mongo_con_manager *manager, mcon_collection *col, mongo_read_preference *rp) { mcon_collection *filtered; int i, nearest_ping; filtered = mcon_init_collection(sizeof(mongo_connection*)); mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "selecting near servers"); switch (rp->type) { case MONGO_RP_PRIMARY: case MONGO_RP_PRIMARY_PREFERRED: case MONGO_RP_SECONDARY: case MONGO_RP_SECONDARY_PREFERRED: case MONGO_RP_NEAREST: /* The nearest ping time is in the first element */ nearest_ping = ((mongo_connection*)col->data[0])->ping_ms; mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "selecting near servers: nearest is %dms", nearest_ping); /* FIXME: Change to iterator later */ for (i = 0; i < col->count; i++) { if (((mongo_connection*)col->data[i])->ping_ms <= nearest_ping + MONGO_RP_CUTOFF) { mcon_collection_add(filtered, col->data[i]); } } break; default: return NULL; } /* Clean up the old collection that we no longer need */ mcon_collection_free(col); mcon_collection_iterate(manager, filtered, mongo_print_connection_iterate_wrapper); mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "selecting near server: done"); return filtered; }
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; }