]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: proxy: maintain per-state counters of listeners
authorWilly Tarreau <w@1wt.eu>
Thu, 24 Sep 2020 05:27:06 +0000 (07:27 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 9 Oct 2020 09:27:30 +0000 (11:27 +0200)
The proxy state tries to be synthetic but that doesn't work well with
many listeners, especially for transition phases or after a failed
pause/resume.

In order to address this, we'll instead rely on counters of listeners in
a given state for the 3 major states (ready, paused, listen) and a total
counter. We'll now be able to determine a proxy's state by comparing these
counters only.

include/haproxy/proxy-t.h
src/listener.c

index 2680fbffacf3ea5d75369936c95ccadb91ba875d..16fee4a2ea2957dee891c95f6e8dc900566399d6 100644 (file)
@@ -395,6 +395,10 @@ struct proxy {
        int uuid;                               /* universally unique proxy ID, used for SNMP */
        unsigned int backlog;                   /* force the frontend's listen backlog */
        unsigned long bind_proc;                /* bitmask of processes using this proxy */
+       unsigned int li_all;                    /* total number of listeners attached to this proxy */
+       unsigned int li_paused;                 /* total number of listeners paused (LI_PAUSED) */
+       unsigned int li_bound;                  /* total number of listeners ready (LI_LISTEN)  */
+       unsigned int li_ready;                  /* total number of listeners ready (>=LI_READY) */
 
        /* warning: these structs are huge, keep them at the bottom */
        struct sockaddr_storage dispatch_addr;  /* the default address to connect to */
index 1ad017db8c1dc40357f0291ec898b7fbdeb641fa..c4ee3c31907999b6f1a21f6775302f9249a7c08b 100644 (file)
@@ -218,9 +218,55 @@ REGISTER_CONFIG_POSTPARSER("multi-threaded accept queue", accept_queue_init);
 
 #endif // USE_THREAD
 
-/* adjust the listener's state */
+/* adjust the listener's state and its proxy's listener counters if needed.
+ * It must be called under the listener's lock, but uses atomic ops to change
+ * the proxy's counters so that the proxy lock is not needed.
+ */
 void listener_set_state(struct listener *l, enum li_state st)
 {
+       struct proxy *px = l->bind_conf->frontend;
+
+       if (px) {
+               /* from state */
+               switch (l->state) {
+               case LI_NEW: /* first call */
+                       _HA_ATOMIC_ADD(&px->li_all, 1);
+                       break;
+               case LI_INIT:
+               case LI_ASSIGNED:
+                       break;
+               case LI_PAUSED:
+                       _HA_ATOMIC_SUB(&px->li_paused, 1);
+                       break;
+               case LI_LISTEN:
+                       _HA_ATOMIC_SUB(&px->li_bound, 1);
+                       break;
+               case LI_READY:
+               case LI_FULL:
+               case LI_LIMITED:
+                       _HA_ATOMIC_SUB(&px->li_ready, 1);
+                       break;
+               }
+
+               /* to state */
+               switch (st) {
+               case LI_NEW:
+               case LI_INIT:
+               case LI_ASSIGNED:
+                       break;
+               case LI_PAUSED:
+                       _HA_ATOMIC_ADD(&px->li_paused, 1);
+                       break;
+               case LI_LISTEN:
+                       _HA_ATOMIC_ADD(&px->li_bound, 1);
+                       break;
+               case LI_READY:
+               case LI_FULL:
+               case LI_LIMITED:
+                       _HA_ATOMIC_ADD(&px->li_ready, 1);
+                       break;
+               }
+       }
        l->state = st;
 }