nodelist: Stop recursing in router_choose_random_node()

Instead, call out to a helper function, repeating the call if needed.

Avoids duplicating exclusions for:
  * the current relay's family, and
  * any exclusions specified by the caller.

Part of 34200.
This commit is contained in:
teor 2020-05-11 17:58:28 +10:00
parent 2ea1692c20
commit 3f7f976d48

View File

@ -930,47 +930,25 @@ nodelist_subtract(smartlist_t *sl, const smartlist_t *excluded)
bitarray_free(excluded_idx); bitarray_free(excluded_idx);
} }
/** Return a random running node from the nodelist. Never pick a node that is /* Node selection helper for router_choose_random_node().
* in <b>excludedsmartlist</b>, or which matches <b>excludedset</b>, even if
* they are the only nodes available.
* *
* <b>flags</b> is a set of CRN_* flags, see * Populates a node list based on <b>flags</b>, ignoring nodes in
* router_add_running_nodes_to_smartlist() for details. * <b>excludednodes</b> and <b>excludedset</b>. Chooses the node based on
*/ * <b>rule</b>. */
const node_t * static const node_t *
router_choose_random_node(smartlist_t *excludedsmartlist, router_choose_random_node_helper(smartlist_t *excludednodes,
routerset_t *excludedset, routerset_t *excludedset,
router_crn_flags_t flags) router_crn_flags_t flags,
bandwidth_weight_rule_t rule)
{ {
/* A limited set of flags, used for weighting and fallback node selection. smartlist_t *sl=smartlist_new();
*/
const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
const int need_guard = (flags & CRN_NEED_GUARD) != 0;
const int pref_addr = (flags & CRN_PREF_ADDR) != 0;
smartlist_t *sl=smartlist_new(),
*excludednodes=smartlist_new();
const node_t *choice = NULL; const node_t *choice = NULL;
const routerinfo_t *r;
bandwidth_weight_rule_t rule;
rule = (need_guard ? WEIGHT_FOR_GUARD : WEIGHT_FOR_MID);
/* If the node_t is not found we won't be to exclude ourself but we
* won't be able to pick ourself in router_choose_random_node() so
* this is fine to at least try with our routerinfo_t object. */
if ((r = router_get_my_routerinfo()))
routerlist_add_node_and_family(excludednodes, r);
router_add_running_nodes_to_smartlist(sl, flags); router_add_running_nodes_to_smartlist(sl, flags);
log_debug(LD_CIRC, log_debug(LD_CIRC,
"We found %d running nodes.", "We found %d running nodes.",
smartlist_len(sl)); smartlist_len(sl));
if (excludedsmartlist) {
smartlist_add_all(excludednodes, excludedsmartlist);
}
nodelist_subtract(sl, excludednodes); nodelist_subtract(sl, excludednodes);
if (excludedset) { if (excludedset) {
@ -984,8 +962,53 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
choice = node_sl_choose_by_bandwidth(sl, rule); choice = node_sl_choose_by_bandwidth(sl, rule);
smartlist_free(sl); smartlist_free(sl);
return choice;
}
/** Return a random running node from the nodelist. Never pick a node that is
* in <b>excludedsmartlist</b>, or which matches <b>excludedset</b>, even if
* they are the only nodes available.
*
* <b>flags</b> is a set of CRN_* flags, see
* router_add_running_nodes_to_smartlist() for details.
*/
const node_t *
router_choose_random_node(smartlist_t *excludedsmartlist,
routerset_t *excludedset,
router_crn_flags_t flags)
{
/* A limited set of flags, used for fallback node selection.
*/
const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
const int need_guard = (flags & CRN_NEED_GUARD) != 0;
const int pref_addr = (flags & CRN_PREF_ADDR) != 0;
smartlist_t *excludednodes=smartlist_new();
const node_t *choice = NULL;
const routerinfo_t *r;
bandwidth_weight_rule_t rule;
rule = (need_guard ? WEIGHT_FOR_GUARD : WEIGHT_FOR_MID);
/* If the node_t is not found we won't be to exclude ourself but we
* won't be able to pick ourself in router_choose_random_node() so
* this is fine to at least try with our routerinfo_t object. */
if ((r = router_get_my_routerinfo()))
routerlist_add_node_and_family(excludednodes, r);
if (excludedsmartlist) {
smartlist_add_all(excludednodes, excludedsmartlist);
}
choice = router_choose_random_node_helper(excludednodes,
excludedset,
flags,
rule);
if (!choice && (need_uptime || need_capacity || need_guard || pref_addr)) { if (!choice && (need_uptime || need_capacity || need_guard || pref_addr)) {
/* try once more -- recurse but with fewer restrictions. */ /* try once more, with fewer restrictions. */
log_info(LD_CIRC, log_info(LD_CIRC,
"We couldn't find any live%s%s%s%s routers; falling back " "We couldn't find any live%s%s%s%s routers; falling back "
"to list of all routers.", "to list of all routers.",
@ -995,8 +1018,10 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
pref_addr?", preferred address":""); pref_addr?", preferred address":"");
flags &= ~ (CRN_NEED_UPTIME|CRN_NEED_CAPACITY|CRN_NEED_GUARD| flags &= ~ (CRN_NEED_UPTIME|CRN_NEED_CAPACITY|CRN_NEED_GUARD|
CRN_PREF_ADDR); CRN_PREF_ADDR);
choice = router_choose_random_node( choice = router_choose_random_node_helper(excludednodes,
excludedsmartlist, excludedset, flags); excludedset,
flags,
rule);
} }
smartlist_free(excludednodes); smartlist_free(excludednodes);
if (!choice) { if (!choice) {