diff --git a/include/haproxy/event_hdl-t.h b/include/haproxy/event_hdl-t.h index 504f6cf67..3cd19624d 100644 --- a/include/haproxy/event_hdl-t.h +++ b/include/haproxy/event_hdl-t.h @@ -239,6 +239,8 @@ struct event_hdl_sub { #define EVENT_HDL_SUB_SERVER EVENT_HDL_SUB_FAMILY(1) #define EVENT_HDL_SUB_SERVER_ADD EVENT_HDL_SUB_TYPE(1,1) #define EVENT_HDL_SUB_SERVER_DEL EVENT_HDL_SUB_TYPE(1,2) +#define EVENT_HDL_SUB_SERVER_UP EVENT_HDL_SUB_TYPE(1,3) +#define EVENT_HDL_SUB_SERVER_DOWN EVENT_HDL_SUB_TYPE(1,4) /* --------------------------------------- */ diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index dd1a3afa0..f3f5a02f4 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -441,6 +441,7 @@ struct event_hdl_cb_data_server { struct server *ptr; /* server live ptr */ /* lock hints */ uint8_t thread_isolate; /* 1 = thread_isolate is on, no locking required */ + uint8_t srv_lock; /* 1 = srv lock is held */ } unsafe; }; diff --git a/src/event_hdl.c b/src/event_hdl.c index 06f4ae478..6444386f9 100644 --- a/src/event_hdl.c +++ b/src/event_hdl.c @@ -26,6 +26,8 @@ static struct event_hdl_sub_type_map event_hdl_sub_type_map[] = { {"SERVER", EVENT_HDL_SUB_SERVER}, {"SERVER_ADD", EVENT_HDL_SUB_SERVER_ADD}, {"SERVER_DEL", EVENT_HDL_SUB_SERVER_DEL}, + {"SERVER_UP", EVENT_HDL_SUB_SERVER_UP}, + {"SERVER_DOWN", EVENT_HDL_SUB_SERVER_DOWN}, }; /* internal types (only used in this file) */ diff --git a/src/server.c b/src/server.c index eddaf9107..ed06687d5 100644 --- a/src/server.c +++ b/src/server.c @@ -139,6 +139,7 @@ int srv_getinter(const struct check *check) * Event will be published in both global subscription list and * server dedicated subscription list * server ptr must be valid + * must be called with srv lock or under thread_isolate */ static inline void srv_event_hdl_publish(struct event_hdl_sub_type event, struct server *srv, uint8_t thread_isolate) { @@ -154,6 +155,7 @@ static inline void srv_event_hdl_publish(struct event_hdl_sub_type event, struct /* unsafe data assignments */ cb_data.unsafe.ptr = srv; cb_data.unsafe.thread_isolate = thread_isolate; + cb_data.unsafe.srv_lock = !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 */ @@ -5259,6 +5261,9 @@ static void srv_update_status(struct server *s) s->next_admin = s->cur_admin; if ((s->cur_state != SRV_ST_STOPPED) && (s->next_state == SRV_ST_STOPPED)) { + /* no maintenance + server DOWN: publish event SERVER DOWN */ + srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_DOWN, s, 0); + s->last_change = now.tv_sec; if (s->proxy->lbprm.set_server_status_down) s->proxy->lbprm.set_server_status_down(s); @@ -5326,6 +5331,9 @@ static void srv_update_status(struct server *s) } else if (((s->cur_state != SRV_ST_RUNNING) && (s->next_state == SRV_ST_RUNNING)) || ((s->cur_state != SRV_ST_STARTING) && (s->next_state == SRV_ST_STARTING))) { + /* no maintenance + server going UP: publish event SERVER UP */ + srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_UP, s, 0); + if (s->proxy->srv_bck == 0 && s->proxy->srv_act == 0) { if (s->proxy->last_change < now.tv_sec) // ignore negative times s->proxy->down_time += now.tv_sec - s->proxy->last_change; @@ -5452,6 +5460,9 @@ static void srv_update_status(struct server *s) if (s->onmarkeddown & HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS) srv_shutdown_streams(s, SF_ERR_DOWN); + /* maintenance on previously running server: publish event SERVER DOWN */ + srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_DOWN, s, 0); + /* force connection cleanup on the given server */ srv_cleanup_connections(s); /* we might have streams queued on this server and waiting for @@ -5525,6 +5536,12 @@ static void srv_update_status(struct server *s) } + /* ignore if server stays down when leaving maintenance mode */ + if (s->next_state != SRV_ST_STOPPED) { + /* leaving maintenance + server UP: publish event SERVER UP */ + srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_UP, s, 0); + } + tmptrash = alloc_trash_chunk(); if (tmptrash) { if (!(s->next_admin & SRV_ADMF_FMAINT) && (s->cur_admin & SRV_ADMF_FMAINT)) {