* EVENT_HDL_SUB_SERVER_DEL
* EVENT_HDL_SUB_SERVER_UP
* EVENT_HDL_SUB_SERVER_DOWN
+ * EVENT_HDL_SUB_SERVER_STATE
*/
struct {
/* safe data can be safely used from both
} unsafe;
};
+/* check result snapshot provided through some event_hdl server events */
+struct event_hdl_cb_data_server_checkres {
+ uint8_t agent; /* 1 = agent check, 0 = health check */
+ enum chk_result result; /* failed, passed, condpass (CHK_RES_*) */
+ long duration; /* total check duration in ms */
+ struct {
+ short status; /* check status as in check->status */
+ short code; /* provided with some check statuses */
+ } reason;
+ struct {
+ int cur; /* dynamic (= check->health) */
+ int rise, fall; /* config dependant */
+ } health; /* check's health, see check-t.h */
+};
+
+/* data provided to EVENT_HDL_SUB_SERVER_STATE handlers through
+ * event_hdl facility
+ *
+ * Note that this may be casted to regular event_hdl_cb_data_server if
+ * you don't care about state related optional info
+ */
+struct event_hdl_cb_data_server_state {
+ /* provided by:
+ * EVENT_HDL_SUB_SERVER_STATE
+ */
+ struct event_hdl_cb_data_server server; /* must be at the beginning */
+ struct {
+ uint8_t type; /* 0 = operational, 1 = administrative */
+ enum srv_state old_state, new_state; /* updated by both operational and admin changes */
+ uint32_t requeued; /* requeued connections due to server state change */
+ union {
+ /* state change cause:
+ *
+ * look for op_st_chg for operational state change,
+ * and adm_st_chg for administrative state change
+ */
+ struct {
+ enum srv_op_st_chg_cause cause;
+ union {
+ /* check result is provided with
+ * cause == SRV_OP_STCHGC_HEALTH or cause == SRV_OP_STCHGC_AGENT
+ */
+ struct event_hdl_cb_data_server_checkres check;
+ };
+ } op_st_chg;
+ struct {
+ enum srv_adm_st_chg_cause cause;
+ } adm_st_chg;
+ };
+ } safe;
+ /* no unsafe data */
+};
+
/* Storage structure to load server-state lines from a flat file into
* an ebtree, for faster processing
*/
cb_data->unsafe.srv_lock = !thread_isolate;
}
+/* take an event-check snapshot from a live check */
+void _srv_event_hdl_prepare_checkres(struct event_hdl_cb_data_server_checkres *checkres,
+ struct check *check)
+{
+ checkres->agent = !!(check->state & CHK_ST_AGENT);
+ checkres->result = check->result;
+ checkres->duration = check->duration;
+ checkres->reason.status = check->status;
+ checkres->reason.code = check->code;
+ checkres->health.cur = check->health;
+ checkres->health.rise = check->rise;
+ checkres->health.fall = check->fall;
+}
+
+/* Prepare SERVER_STATE event
+ *
+ * This special event will contain extra hints related to the state change
+ *
+ * Must be called with server lock held
+ */
+void _srv_event_hdl_prepare_state(struct event_hdl_cb_data_server_state *cb_data,
+ struct server *srv, int type, int cause,
+ enum srv_state prev_state, int requeued)
+{
+ /* state event provides additional info about the server state change */
+ cb_data->safe.type = type;
+ cb_data->safe.new_state = srv->cur_state;
+ cb_data->safe.old_state = prev_state;
+ cb_data->safe.requeued = requeued;
+ if (type) {
+ /* administrative */
+ cb_data->safe.adm_st_chg.cause = cause;
+ }
+ else {
+ /* operational */
+ cb_data->safe.op_st_chg.cause = cause;
+ if (cause == SRV_OP_STCHGC_HEALTH || cause == SRV_OP_STCHGC_AGENT) {
+ struct check *check = (cause == SRV_OP_STCHGC_HEALTH) ? &srv->check : &srv->agent;
+
+ /* provide additional check-related state change result */
+ _srv_event_hdl_prepare_checkres(&cb_data->safe.op_st_chg.check, check);
+ }
+ }
+}
+
/* server event publishing helper: publish in both global and
* server dedicated subscription list.
*/
{
int prev_srv_count = s->proxy->srv_bck + s->proxy->srv_act;
enum srv_state srv_prev_state = s->cur_state;
+ union {
+ struct event_hdl_cb_data_server_state state;
+ struct event_hdl_cb_data_server common;
+ } cb_data;
+ int requeued;
+
+ /* prepare common server event data */
+ _srv_event_hdl_prepare(&cb_data.common, s, 0);
if (type)
- _srv_update_status_adm(s, cause);
+ requeued = _srv_update_status_adm(s, cause);
else
- _srv_update_status_op(s, cause);
+ requeued = _srv_update_status_op(s, cause);
/* explicitly commit state changes (even if it was already applied implicitly
* by some lb state change function), so we don't miss anything
s->counters.down_trans++;
}
s->last_change = ns_to_sec(now_ns);
+
+ /* publish the state change */
+ _srv_event_hdl_prepare_state(&cb_data.state,
+ s, type, cause, srv_prev_state, requeued);
+ _srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_STATE, cb_data.state, s);
}
/* check if backend stats must be updated due to the server state change */