/* * Main balancing routine. This does not try to keep the same proxy for * the call if some proxies were disabled or enabled; proxy death considered * too rare. Otherwise we should implement "mature" HA clustering, which is * too expensive here. */ struct rtpp_node * select_rtpp_node(str callid, int do_test) { unsigned sum, weight_sum; struct rtpp_node* node; int was_forced, sumcut, found, constant_weight_sum; LM_INFO("entering select_rtpp_node\n"); /* check last list version */ if (my_version != *list_version && update_rtpp_proxies() < 0) { LM_ERR("cannot update rtpp proxies list\n"); return 0; } if(!selected_rtpp_set){ LM_ERR("script error -no valid set selected\n"); return NULL; } /* Most popular case: 1 proxy, nothing to calculate */ if (selected_rtpp_set->rtpp_node_count == 1) { LM_INFO("rtpproxy node count = 1\n"); node = selected_rtpp_set->rn_first; if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()) node->rn_disabled = rtpp_test(node, 1, 0); LM_INFO("result rtpp_test = %d\n", node->rn_disabled); return node->rn_disabled ? NULL : node; } /* XXX Use quick-and-dirty hashing algo */ for(sum = 0; callid.len > 0; callid.len--) sum += callid.s[callid.len - 1]; sum &= 0xff; was_forced = 0; retry: LM_INFO("retrying to find rtpproxy\n"); weight_sum = 0; constant_weight_sum = 0; found = 0; for (node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) { if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()){ /* Try to enable if it's time to try. */ node->rn_disabled = rtpp_test(node, 1, 0); } constant_weight_sum += node->rn_weight; if (!node->rn_disabled) { weight_sum += node->rn_weight; found = 1; } } if (found == 0) { /* No proxies? Force all to be redetected, if not yet */ if (was_forced) return NULL; was_forced = 1; for(node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) { node->rn_disabled = rtpp_test(node, 1, 1); } goto retry; } sumcut = weight_sum ? sum % constant_weight_sum : -1; /* * sumcut here lays from 0 to constant_weight_sum-1. * Scan proxy list and decrease until appropriate proxy is found. */ was_forced = 0; for (node=selected_rtpp_set->rn_first; node!=NULL;) { if (sumcut < (int)node->rn_weight) { if (node->rn_disabled) { if (was_forced == 0) { /* appropriate proxy is disabled : redistribute on enabled ones */ sumcut = weight_sum ? sum % weight_sum : -1; node = selected_rtpp_set->rn_first; was_forced = 1; } continue; } else { goto found; } } sumcut -= node->rn_weight; node = node->rn_next; } /* No node list */ return NULL; found: LM_INFO("rtpproxy found\n"); if (do_test) { LM_INFO("do_test enabled\n"); node->rn_disabled = rtpp_test(node, node->rn_disabled, 0); if (node->rn_disabled) LM_INFO("going to retry\n"); goto retry; } return node; }