MT#55283 use array instead of hash table

Change-Id: Ie510523724d14d8c76bb9647ee184ea3756be06c
pull/1910/head
Richard Fuchs 3 months ago
parent 82093e7f52
commit 267d244cb4

@ -1765,7 +1765,7 @@ static void cli_incoming_list_interfaces(str *instr, struct cli_writer *cw, cons
cw->cw_printf(cw, " Port range: %5u - %5u\n",
lif->spec->port_pool.min,
lif->spec->port_pool.max);
unsigned int f = g_hash_table_size(lif->spec->port_pool.free_ports_ht);
unsigned int f = lif->spec->port_pool.free_ports_q.length;
unsigned int r = lif->spec->port_pool.max - lif->spec->port_pool.min + 1;
cw->cw_printf(cw, " Ports used: %5u / %5u (%5.1f%%)\n",
r - f, r, (double) (r - f) * 100.0 / r);

@ -180,10 +180,10 @@ GString *print_graphite_data(void) {
int num_ports = lif->spec->port_pool.max - lif->spec->port_pool.min + 1;
GPF("ports_free_%s_%s %i", lif->logical->name.s,
sockaddr_print_buf(&lif->spec->local_address.addr),
g_hash_table_size(lif->spec->port_pool.free_ports_ht));
lif->spec->port_pool.free_ports_q.length);
GPF("ports_used_%s_%s %i", lif->logical->name.s,
sockaddr_print_buf(&lif->spec->local_address.addr),
num_ports - g_hash_table_size(lif->spec->port_pool.free_ports_ht));
num_ports - lif->spec->port_pool.free_ports_q.length);
}
mutex_lock(&rtpe_codec_stats_lock);

@ -456,17 +456,17 @@ static int has_free_ports_loc(struct local_intf *loc, unsigned int num_ports) {
return 0;
}
if (num_ports > g_hash_table_size(loc->spec->port_pool.free_ports_ht)) {
if (num_ports > loc->spec->port_pool.free_ports_q.length) {
ilog(LOG_ERR, "Didn't find %d ports available for " STR_FORMAT "/%s",
num_ports, STR_FMT(&loc->logical->name),
sockaddr_print_buf(&loc->spec->local_address.addr));
return 0;
}
__C_DBG("Found %d ports available for " STR_FORMAT "/%s from total of %d free ports",
__C_DBG("Found %d ports available for " STR_FORMAT "/%s from total of %u free ports",
num_ports, STR_FMT(&loc->logical->name),
sockaddr_print_buf(&loc->spec->local_address.addr),
g_hash_table_size(loc->spec->port_pool.free_ports_ht));
loc->spec->port_pool.free_ports_q.length);
return 1;
}
@ -682,39 +682,34 @@ int is_local_endpoint(const struct intf_address *addr, unsigned int port) {
/**
* This function just (globally) reserves a port number, it doesn't provide any binding/unbinding.
*/
static void reserve_port(GQueue * free_ports_q, GHashTable * free_ports_ht,
static void reserve_port(struct port_pool *pp,
GList * value_looked_up, unsigned int port) {
g_queue_delete_link(free_ports_q, value_looked_up);
g_hash_table_remove(free_ports_ht, GUINT_TO_POINTER(port));
g_queue_delete_link(&pp->free_ports_q, value_looked_up);
pp->free_ports[port] = NULL;
}
/**
* This function just releases reserved port number, it doesn't provide any binding/unbinding.
*/
static void release_reserved_port(GQueue * free_ports_q, GHashTable * free_ports_ht,
unsigned int port) {
g_queue_push_tail(free_ports_q, GUINT_TO_POINTER(port));
GList * l = free_ports_q->tail;
g_hash_table_replace(free_ports_ht, GUINT_TO_POINTER(port), l);
static void release_reserved_port(struct port_pool *pp, unsigned int port) {
g_queue_push_tail(&pp->free_ports_q, GUINT_TO_POINTER(port));
GList * l = pp->free_ports_q.tail;
pp->free_ports[port] = l;
}
/* Append a list of free ports within the min-max range */
static void __append_free_ports_to_int(struct intf_spec *spec) {
unsigned int ports_amount, count;
GQueue * free_ports_q = &spec->port_pool.free_ports_q;
GHashTable ** free_ports_ht = &spec->port_pool.free_ports_ht;
if (!*free_ports_ht)
*free_ports_ht = g_hash_table_new(g_direct_hash, g_direct_equal);
struct port_pool *pp = &spec->port_pool;
GQueue * free_ports_q = &pp->free_ports_q;
if (spec->port_pool.max < spec->port_pool.min) {
if (pp->max < pp->min) {
ilog(LOG_WARNING, "Ports range: max value cannot be less than min");
return;
}
/* range of possible ports */
ports_amount = spec->port_pool.max - spec->port_pool.min + 1;
ports_amount = pp->max - pp->min + 1;
count = ports_amount;
if (ports_amount == 0) {
@ -726,7 +721,7 @@ static void __append_free_ports_to_int(struct intf_spec *spec) {
/* create an array to store the initial values within the range */
for (int i = 0; i < ports_amount; i++)
port_values[i] = spec->port_pool.min + i;
port_values[i] = pp->min + i;
/* generate N random numbers within the given range without duplicates,
* using the rolling dice algorithm */
@ -735,14 +730,14 @@ static void __append_free_ports_to_int(struct intf_spec *spec) {
int j = ssl_random() % count;
int value = port_values[j];
mutex_lock(&spec->port_pool.free_list_lock);
mutex_lock(&pp->free_list_lock);
g_queue_push_tail(free_ports_q, GUINT_TO_POINTER(value));
/* store this new GList as value into the hash table */
GList * l = free_ports_q->tail;
/* The value retrieved from the hash table would then point
* into the queue for quick removal */
g_hash_table_replace(*free_ports_ht, GUINT_TO_POINTER(value), l);
mutex_unlock(&spec->port_pool.free_list_lock);
pp->free_ports[value] = l;
mutex_unlock(&pp->free_list_lock);
port_values[j] = port_values[count - 1];
count--;
@ -902,20 +897,16 @@ void interfaces_exclude_port(unsigned int port) {
struct intf_spec *spec;
struct port_pool *pp;
GQueue * free_ports_q;
GHashTable * free_ports_ht;
intf_spec_ht_iter iter;
t_hash_table_iter_init(&iter, __intf_spec_addr_type_hash);
while (t_hash_table_iter_next(&iter, NULL, &spec)) {
pp = &spec->port_pool;
free_ports_q = &pp->free_ports_q;
free_ports_ht = pp->free_ports_ht;
mutex_lock(&pp->free_list_lock);
ll = g_hash_table_lookup(free_ports_ht, GUINT_TO_POINTER(port));
ll = pp->free_ports[port];
if (ll)
reserve_port(free_ports_q, free_ports_ht, ll, port);
reserve_port(pp, ll, port);
mutex_unlock(&pp->free_list_lock);
}
}
@ -996,9 +987,6 @@ static void release_port_now(socket_t *r, struct intf_spec *spec) {
unsigned int port = r->local.port;
struct port_pool *pp = &spec->port_pool;
GQueue * free_ports_q = &pp->free_ports_q;
GHashTable * free_ports_ht = pp->free_ports_ht;
__C_DBG("Trying to release the port '%u'", port);
if (close_socket(r) == 0) {
@ -1008,7 +996,7 @@ static void release_port_now(socket_t *r, struct intf_spec *spec) {
/* first return the engaged port back */
mutex_lock(&pp->free_list_lock);
release_reserved_port(free_ports_q, free_ports_ht, port);
release_reserved_port(pp, port);
mutex_unlock(&pp->free_list_lock);
} else {
ilog(LOG_WARNING, "Unable to close the socket for port '%u'", port);
@ -1066,7 +1054,6 @@ int __get_consecutive_ports(socket_q *out, unsigned int num_ports, unsigned int
struct port_pool * pp = &spec->port_pool; /* port pool for a given local interface */
GQueue * free_ports_q;
GHashTable * free_ports_ht;
if (num_ports == 0) {
ilog(LOG_ERR, "Number of ports to be engaged is '%d', can't handle it like that",
@ -1081,10 +1068,9 @@ int __get_consecutive_ports(socket_q *out, unsigned int num_ports, unsigned int
}
free_ports_q = &pp->free_ports_q;
free_ports_ht = pp->free_ports_ht;
/* a presence of free lists data is critical for us */
if (!(free_ports_q && free_ports_q->head) || !free_ports_ht) {
if (!(free_ports_q && free_ports_q->head)) {
ilog(LOG_ERR, "Failure while trying to get a list of free ports");
goto fail;
}
@ -1093,14 +1079,14 @@ int __get_consecutive_ports(socket_q *out, unsigned int num_ports, unsigned int
if (wanted_start_port > 0) {
ilog(LOG_DEBUG, "A specific port value is requested, wanted_start_port: '%d'", wanted_start_port);
mutex_lock(&pp->free_list_lock);
GList *l = g_hash_table_lookup(free_ports_ht, GUINT_TO_POINTER(wanted_start_port));
GList *l = pp->free_ports[wanted_start_port];
if (!l) {
/* if engaged already, just select any other (so default logic) */
ilog(LOG_WARN, "This requested port has been already engaged, can't take it.");
wanted_start_port = 0; /* take what is proposed by FIFO instead */
} else {
/* we got the port, and we are sure it wasn't engaged */
reserve_port(free_ports_q, free_ports_ht, l, wanted_start_port);
reserve_port(pp, l, wanted_start_port);
port = wanted_start_port;
}
mutex_unlock(&pp->free_list_lock);
@ -1155,14 +1141,14 @@ new_cycle:
ilog(LOG_ERR, "Failure while trying to get a port from the list");
goto fail;
}
g_hash_table_remove(free_ports_ht, GUINT_TO_POINTER(port)); /* RTP */
pp->free_ports[port] = NULL; /* RTP */
mutex_unlock(&pp->free_list_lock);
/* ports for RTP must be even, if there is an additional port for RTCP */
if (num_ports > 1 && (port & 1)) {
/* return port for RTP back and try again */
mutex_lock(&pp->free_list_lock);
release_reserved_port(free_ports_q, free_ports_ht, port);
release_reserved_port(pp, port);
mutex_unlock(&pp->free_list_lock);
goto new_cycle;
}
@ -1174,11 +1160,11 @@ new_cycle:
additional_port++;
mutex_lock(&pp->free_list_lock);
GList *l = g_hash_table_lookup(free_ports_ht, GUINT_TO_POINTER(additional_port));
GList *l = pp->free_ports[additional_port];
if (!l) {
/* return port for RTP back and try again */
release_reserved_port(free_ports_q, free_ports_ht, port);
release_reserved_port(pp, port);
mutex_unlock(&pp->free_list_lock);
/* check if we managed to enagage anything in previous for-cycles */
@ -1186,14 +1172,14 @@ new_cycle:
{
mutex_lock(&pp->free_list_lock);
/* return additional ports back */
release_reserved_port(free_ports_q, free_ports_ht, additional_port);
release_reserved_port(pp, additional_port);
mutex_unlock(&pp->free_list_lock);
}
goto new_cycle;
} else {
/* engage this port right away */
reserve_port(free_ports_q, free_ports_ht, l, additional_port);
reserve_port(pp, l, additional_port);
mutex_unlock(&pp->free_list_lock);
/* track for which additional ports, we have to open sockets */
@ -1221,7 +1207,7 @@ new_cycle:
while ((port = GPOINTER_TO_UINT(g_queue_pop_head(&ports_to_engage))))
{
mutex_lock(&pp->free_list_lock);
release_reserved_port(free_ports_q, free_ports_ht, port);
release_reserved_port(pp, port);
mutex_unlock(&pp->free_list_lock);
}
/* ports which are already bound to a socket, will be freed by `free_port()` */
@ -3244,9 +3230,6 @@ void interfaces_free(void) {
struct intf_spec *spec;
while (t_hash_table_iter_next(&s_iter, NULL, &spec)) {
struct port_pool *pp = &spec->port_pool;
if (pp->free_ports_ht) {
g_hash_table_destroy(pp->free_ports_ht);
}
g_queue_clear(&pp->free_ports_q);
mutex_destroy(&pp->free_list_lock);
g_slice_free1(sizeof(*spec), spec);

@ -670,7 +670,7 @@ stats_metric_q *statistics_gather_metrics(struct interface_sampled_rate_stats *i
METRICs("min", "%u", lif->spec->port_pool.min);
METRICs("max", "%u", lif->spec->port_pool.max);
unsigned int f = g_hash_table_size(lif->spec->port_pool.free_ports_ht);
unsigned int f = lif->spec->port_pool.free_ports_q.length;
unsigned int r = lif->spec->port_pool.max - lif->spec->port_pool.min + 1;
METRICs("used", "%u", r - f);
PROM("ports_used", "gauge");

@ -90,7 +90,7 @@ struct port_pool {
mutex_t free_list_lock;
GQueue free_ports_q; /* for getting the next free port */
GHashTable * free_ports_ht; /* for a lookup, if the port is used */
GList *free_ports[65536]; /* for a lookup if the port is used */
};
struct intf_address {
socktype_t *type;

Loading…
Cancel
Save