MINOR: server/event_hdl: add support for SERVER_ADD and SERVER_DEL events
Basic support for ADD and DEL server events are added through this commit:
SERVER_ADD is published on dynamic server addition through cli.
SERVER_DEL is published on dynamic server deletion through cli.
This work depends on:
"MINOR: event_hdl: add event handler base api"
"MINOR: server: add srv->rid (revision id) value"
diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h
index dd42807..dd1a3af 100644
--- a/include/haproxy/server-t.h
+++ b/include/haproxy/server-t.h
@@ -40,6 +40,7 @@
#include <haproxy/stats-t.h>
#include <haproxy/task-t.h>
#include <haproxy/thread-t.h>
+#include <haproxy/event_hdl-t.h>
/* server states. Only SRV_ST_STOPPED indicates a down server. */
@@ -403,6 +404,8 @@
} op_st_chg; /* operational status change's reason */
char adm_st_chg_cause[48]; /* administrative status change's cause */
+ event_hdl_sub_list e_subs; /* event_hdl: server's subscribers list (atomically updated) */
+
/* warning, these structs are huge, keep them at the bottom */
struct conn_src conn_src; /* connection source settings */
struct sockaddr_storage addr; /* the address to connect to, doesn't include the port */
@@ -411,6 +414,35 @@
EXTRA_COUNTERS(extra_counters);
};
+/* data provided to EVENT_HDL_SUB_SERVER handlers through event_hdl facility */
+struct event_hdl_cb_data_server {
+ /* provided by:
+ * EVENT_HDL_SUB_SERVER_ADD
+ * EVENT_HDL_SUB_SERVER_DOWN
+ */
+ struct {
+ /* safe data can be safely used from both
+ * sync and async handlers
+ * data consistency is guaranteed
+ */
+ char name[64]; /* server name/id */
+ char proxy_name[64]; /* id of proxy the server belongs to */
+ int puid; /* proxy-unique server ID */
+ int rid; /* server id revision */
+ unsigned int flags; /* server flags */
+ } safe;
+ struct {
+ /* unsafe data may only be used from sync handlers:
+ * in async mode, data consistency cannot be guaranteed
+ * and unsafe data may already be stale, thus using
+ * it is highly discouraged because it
+ * could lead to undefined behavior (UAF, null dereference...)
+ */
+ struct server *ptr; /* server live ptr */
+ /* lock hints */
+ uint8_t thread_isolate; /* 1 = thread_isolate is on, no locking required */
+ } unsafe;
+};
/* Storage structure to load server-state lines from a flat file into
* an ebtree, for faster processing
diff --git a/src/server.c b/src/server.c
index bc8d0cb..eddaf91 100644
--- a/src/server.c
+++ b/src/server.c
@@ -47,6 +47,7 @@
#include <haproxy/time.h>
#include <haproxy/tools.h>
#include <haproxy/xxhash.h>
+#include <haproxy/event_hdl.h>
static void srv_update_status(struct server *s);
@@ -133,6 +134,33 @@
}
/*
+ * Use this to publish EVENT_HDL_SUB_SERVER family type event
+ * from srv facility
+ * Event will be published in both global subscription list and
+ * server dedicated subscription list
+ * server ptr must be valid
+ */
+static inline void srv_event_hdl_publish(struct event_hdl_sub_type event, struct server *srv, uint8_t thread_isolate)
+{
+ struct event_hdl_cb_data_server cb_data;
+
+ /* safe data assignments */
+ cb_data.safe.puid = srv->puid;
+ cb_data.safe.rid = srv->rid;
+ cb_data.safe.flags = srv->flags;
+ snprintf(cb_data.safe.name, sizeof(cb_data.safe.name), "%s", srv->id);
+ if (srv->proxy)
+ snprintf(cb_data.safe.proxy_name, sizeof(cb_data.safe.proxy_name), "%s", srv->proxy->id);
+ /* unsafe data assignments */
+ cb_data.unsafe.ptr = srv;
+ cb_data.unsafe.thread_isolate = thread_isolate;
+ /* publish in server dedicated sub list */
+ event_hdl_publish(&srv->e_subs, event, EVENT_HDL_CB_DATA(&cb_data));
+ /* publish in global subscription list */
+ event_hdl_publish(NULL, event, EVENT_HDL_CB_DATA(&cb_data));
+}
+
+/*
* Check that we did not get a hash collision.
* Unlikely, but it can happen. The server's proxy must be at least
* read-locked.
@@ -2337,6 +2365,7 @@
LIST_APPEND(&servers_list, &srv->global_list);
LIST_INIT(&srv->srv_rec_item);
LIST_INIT(&srv->ip_rec_item);
+ event_hdl_sub_list_init(&srv->e_subs);
srv->next_state = SRV_ST_RUNNING; /* early server setup */
srv->last_change = now.tv_sec;
@@ -2419,6 +2448,7 @@
HA_SPIN_DESTROY(&srv->lock);
LIST_DELETE(&srv->global_list);
+ event_hdl_sub_list_destroy(&srv->e_subs);
EXTRA_COUNTERS_FREE(srv->extra_counters);
@@ -4893,6 +4923,11 @@
*/
srv->rid = (srv_id_reuse_cnt) ? (srv_id_reuse_cnt / 2) : 0;
+ /* adding server cannot fail when we reach this:
+ * publishing EVENT_HDL_SUB_SERVER_ADD
+ */
+ srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_ADD, srv, 1);
+
thread_release();
/* Start the check task. The server must be fully initialized.
@@ -5020,6 +5055,11 @@
goto out;
}
+ /* removing cannot fail anymore when we reach this:
+ * publishing EVENT_HDL_SUB_SERVER_DEL
+ */
+ srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_DEL, srv, 1);
+
/* remove srv from tracking list */
if (srv->track)
release_server_track(srv);