MAJOR: listeners: use dual-linked lists to chain listeners with frontends
Navigating through listeners was very inconvenient and error-prone. Not to
mention that listeners were linked in reverse order and reverted afterwards.
In order to definitely get rid of these issues, we now do the following :
- frontends have a dual-linked list of bind_conf
- frontends have a dual-linked list of listeners
- bind_conf have a dual-linked list of listeners
- listeners have a pointer to their bind_conf
This way we can now navigate from anywhere to anywhere and always find the
proper bind_conf for a given listener, as well as find the list of listeners
for a current bind_conf.
diff --git a/src/dumpstats.c b/src/dumpstats.c
index ab4c416..5cd903b 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -181,6 +181,8 @@
struct proxy *defpx, const char *file, int line,
char **err)
{
+ struct bind_conf *bind_conf;
+
if (!strcmp(args[1], "socket")) {
struct sockaddr_un *su;
int cur_arg;
@@ -209,6 +211,8 @@
}
}
+ bind_conf = bind_conf_alloc(&global.stats_fe->conf.bind, file, line, args[2]);
+
global.stats_sock.state = LI_INIT;
global.stats_sock.options = LI_O_UNLIMITED;
global.stats_sock.accept = session_accept;
@@ -220,9 +224,9 @@
global.stats_sock.perm.ux.level = ACCESS_LVL_OPER; /* default access level */
global.stats_sock.maxconn = global.stats_fe->maxconn;
global.stats_sock.timeout = &global.stats_fe->timeout.client;
-
- global.stats_sock.next = global.stats_fe->listen;
- global.stats_fe->listen = &global.stats_sock;
+ global.stats_sock.bind_conf = bind_conf;
+ LIST_ADDQ(&global.stats_fe->conf.listeners, &global.stats_sock.by_fe);
+ LIST_ADDQ(&bind_conf->listeners, &global.stats_sock.by_bind);
cur_arg = 3;
while (*args[cur_arg]) {
@@ -969,7 +973,7 @@
sv->counters.sps_max = 0;
}
- for (li = px->listen; li; li = li->next)
+ list_for_each_entry(li, &px->conf.listeners, by_bind)
if (li->counters) {
if (clrall)
memset(li->counters, 0, sizeof(*li->counters));
@@ -1149,7 +1153,7 @@
* its listeners. The blocked ones will be dequeued.
*/
px->maxconn = v;
- for (l = px->listen; l != NULL; l = l->next) {
+ list_for_each_entry(l, &px->conf.listeners, by_bind) {
l->maxconn = v;
if (l->state == LI_FULL)
resume_listener(l);
@@ -2508,17 +2512,17 @@
return 0;
}
- si->applet.ctx.stats.l = px->listen; /* may be NULL */
+ si->applet.ctx.stats.l = px->conf.listeners.n;
si->applet.ctx.stats.px_st = STAT_PX_ST_LI;
/* fall through */
case STAT_PX_ST_LI:
/* stats.l has been initialized above */
- for (; si->applet.ctx.stats.l != NULL; si->applet.ctx.stats.l = l->next) {
+ for (; si->applet.ctx.stats.l != &px->conf.listeners; si->applet.ctx.stats.l = l->by_fe.n) {
if (buffer_almost_full(&rep->buf))
return 0;
- l = si->applet.ctx.stats.l;
+ l = LIST_ELEM(si->applet.ctx.stats.l, struct listener *, by_fe);
if (!l->counters)
continue;