summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilly Tarreau <w@1wt.eu>2020-09-24 07:27:06 +0200
committerWilly Tarreau <w@1wt.eu>2020-10-07 18:44:08 +0200
commit7cf76b8423df6d3ad1019b82412085f5b0924108 (patch)
tree2822ca349d25b713f14f678fe7bf400e1b8ce6d5
parentb6a486166da3347dffc83d8d7ecada88a73348ec (diff)
downloadhaproxy-7cf76b8423df6d3ad1019b82412085f5b0924108.tar.gz
MINOR: proxy: maintain per-state counters of listeners
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.
-rw-r--r--include/haproxy/proxy-t.h4
-rw-r--r--src/listener.c48
2 files changed, 51 insertions, 1 deletions
diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h
index 2680fbffa..16fee4a2e 100644
--- a/include/haproxy/proxy-t.h
+++ b/include/haproxy/proxy-t.h
@@ -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 */
diff --git a/src/listener.c b/src/listener.c
index 1ad017db8..c4ee3c319 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -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;
}