REORG/MEDIUM: server: move the maintenance bits out of the server state
Now we introduce srv->admin and srv->prev_admin which are bitfields
containing one bit per source of administrative status (maintenance only
for now). For the sake of backwards compatibility we implement a single
source (ADMF_FMAINT) but the code already checks any source (ADMF_MAINT)
where the STF_MAINTAIN bit was previously checked. This will later allow
us to add ADMF_IMAINT for maintenance mode inherited from tracked servers.
Along doing these changes, it appeared that some places will need to be
revisited when implementing the inherited bit, this concerns all those
modifying the ADMF_FMAINT bit (enable/disable actions on the CLI or stats
page), and the checks to report "via" on the stats page. But currently
the code is harmless.
diff --git a/include/proto/backend.h b/include/proto/backend.h
index 8043613..601a61a 100644
--- a/include/proto/backend.h
+++ b/include/proto/backend.h
@@ -61,7 +61,9 @@
if (!srv->eweight)
return 0;
- if (state & (SRV_STF_GOINGDOWN | SRV_STF_MAINTAIN))
+ if (srv->admin & SRV_ADMF_MAINT)
+ return 0;
+ if (state & SRV_STF_GOINGDOWN)
return 0;
if (!(state & SRV_STF_RUNNING))
return 0;
@@ -77,7 +79,9 @@
if (!srv->prev_eweight)
return 0;
- if (state & (SRV_STF_GOINGDOWN | SRV_STF_MAINTAIN))
+ if (srv->prev_admin & SRV_ADMF_MAINT)
+ return 0;
+ if (state & SRV_STF_GOINGDOWN)
return 0;
if (!(state & SRV_STF_RUNNING))
return 0;
@@ -90,6 +94,7 @@
static inline void srv_lb_commit_status(struct server *srv)
{
srv->prev_state = srv->state;
+ srv->prev_admin = srv->admin;
srv->prev_eweight = srv->eweight;
}
@@ -99,6 +104,7 @@
static inline int srv_lb_status_changed(const struct server *srv)
{
return (srv->state != srv->prev_state ||
+ srv->admin != srv->prev_admin ||
srv->eweight != srv->prev_eweight);
}
diff --git a/include/types/server.h b/include/types/server.h
index 6b77b15..ba0a1a5 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -48,9 +48,18 @@
SRV_STF_RUNNING = 0x1, /* the server is UP */
SRV_STF_GOINGDOWN = 0x2, /* the server is going down (eg: 404) */
SRV_STF_WARMINGUP = 0x4, /* the server is warming up after a failure */
- SRV_STF_MAINTAIN = 0x8, /* the server is in maintenance mode */
};
+/* Maintenance mode : each server may be in maintenance by itself or may inherit
+ * this status from another server it tracks. Let's store these origins here as
+ * flags. If no maintenance origin is specified, the server is not in maintenance.
+ */
+enum srv_admin {
+ SRV_ADMF_FMAINT = 0x1, /* the server was explicitly forced into maintenance */
+ SRV_ADMF_IMAINT = 0x2, /* the server has inherited the maintenance status from a tracked server */
+ SRV_ADMF_MAINT = 0x3, /* mask to check if any maintenance flag is present */
+};
+
/* server flags */
#define SRV_F_BACKUP 0x0001 /* this server is a backup server */
#define SRV_F_MAPPORTS 0x0002 /* this server uses mapped ports */
@@ -105,6 +114,7 @@
struct server {
enum obj_type obj_type; /* object type == OBJ_TYPE_SERVER */
enum srv_state state, prev_state; /* server state among SRV_STF_* */
+ enum srv_admin admin, prev_admin; /* server maintenance status : SRV_ADMF_* */
unsigned char flags; /* server flags (SRV_F_*) */
struct server *next;
int cklen; /* the len of the cookie, to speed up checks */
diff --git a/src/backend.c b/src/backend.c
index 3ce7415..0b4ff4d 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1489,7 +1489,7 @@
smp->flags = SMP_F_VOL_TEST;
smp->type = SMP_T_BOOL;
- if (!(srv->state & SRV_STF_MAINTAIN) &&
+ if (!(srv->admin & SRV_ADMF_MAINT) &&
(!(srv->check.state & CHK_ST_CONFIGURED) || (srv->state & SRV_STF_RUNNING)))
smp->data.uint = 1;
else
diff --git a/src/cfgparse.c b/src/cfgparse.c
index a002cb2..037eaa9 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -6617,7 +6617,7 @@
}
/* if the other server is forced disabled, we have to do the same here */
- if (srv->state & SRV_STF_MAINTAIN) {
+ if (srv->admin & SRV_ADMF_MAINT) {
newsrv->state &= ~SRV_STF_RUNNING;
newsrv->check.health = 0;
newsrv->agent.health = 0;
diff --git a/src/checks.c b/src/checks.c
index 9228c89..f4bfd54 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -412,7 +412,7 @@
struct server *srv;
int xferred;
- if (s->state & SRV_STF_MAINTAIN) {
+ if (s->admin & SRV_ADMF_MAINT) {
check->health = check->rise;
}
@@ -436,7 +436,7 @@
chunk_reset(&trash);
- if (s->state & SRV_STF_MAINTAIN) {
+ if (s->admin & SRV_ADMF_MAINT) {
chunk_appendf(&trash,
"%sServer %s/%s is DOWN for maintenance", s->flags & SRV_F_BACKUP ? "Backup " : "",
s->proxy->id, s->id);
@@ -463,7 +463,7 @@
s->counters.down_trans++;
for (srv = s->trackers; srv; srv = srv->tracknext)
- if (!(srv->state & SRV_STF_MAINTAIN))
+ if (!(srv->admin & SRV_ADMF_MAINT))
/* Only notify tracking servers that are not already in maintenance. */
set_server_down(&srv->check);
}
@@ -476,9 +476,9 @@
struct server *s = check->server;
struct server *srv;
int xferred;
- enum srv_state old_state = s->state;
+ enum srv_admin old_admin = s->admin;
- if (s->state & SRV_STF_MAINTAIN) {
+ if (s->admin & SRV_ADMF_MAINT) {
check->health = check->rise;
}
@@ -499,7 +499,7 @@
s->last_change = now.tv_sec;
s->state |= SRV_STF_RUNNING;
- s->state &= ~SRV_STF_MAINTAIN;
+ s->admin &= ~SRV_ADMF_FMAINT;
s->check.state &= ~CHK_ST_PAUSED;
if (s->slowstart > 0) {
@@ -525,7 +525,7 @@
chunk_reset(&trash);
- if (old_state & SRV_STF_MAINTAIN) {
+ if (old_admin) {
chunk_appendf(&trash,
"%sServer %s/%s is UP (leaving maintenance)", s->flags & SRV_F_BACKUP ? "Backup " : "",
s->proxy->id, s->id);
@@ -543,7 +543,7 @@
send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
for (srv = s->trackers; srv; srv = srv->tracknext)
- if (!(srv->state & SRV_STF_MAINTAIN))
+ if (!(srv->admin & SRV_ADMF_MAINT))
/* Only notify tracking servers if they're not in maintenance. */
set_server_up(&srv->check);
}
@@ -1480,7 +1480,8 @@
/* by default, plan on stopping the task */
t->expire = TICK_ETERNITY;
- if ((s->state & (SRV_STF_RUNNING|SRV_STF_WARMINGUP|SRV_STF_MAINTAIN)) != (SRV_STF_RUNNING|SRV_STF_WARMINGUP))
+ if ((s->admin & SRV_ADMF_MAINT) ||
+ (s->state & (SRV_STF_RUNNING|SRV_STF_WARMINGUP)) != (SRV_STF_RUNNING|SRV_STF_WARMINGUP))
return t;
server_recalc_eweight(s);
@@ -1707,7 +1708,7 @@
set_server_disabled(check);
}
- if (!(s->state & SRV_STF_MAINTAIN) &&
+ if (!(s->admin & SRV_ADMF_MAINT) &&
check->health < check->rise + check->fall - 1) {
check->health++; /* was bad, stays for a while */
set_server_up(check);
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 47328ce..1de4199 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -1710,7 +1710,7 @@
if (!sv)
return 1;
- if (sv->state & SRV_STF_MAINTAIN) {
+ if (sv->admin & SRV_ADMF_MAINT) {
/* The server is really in maintenance, we can change the server state */
if (sv->track) {
/* If this server tracks the status of another one,
@@ -1720,7 +1720,7 @@
set_server_up(&sv->check);
sv->check.health = sv->check.rise; /* up, but will fall down at first failure */
} else {
- sv->state &= ~SRV_STF_MAINTAIN;
+ sv->admin &= ~SRV_ADMF_FMAINT;
sv->check.state &= ~CHK_ST_PAUSED;
set_server_down(&sv->check);
}
@@ -1782,9 +1782,9 @@
if (!sv)
return 1;
- if (! (sv->state & SRV_STF_MAINTAIN)) {
+ if (!(sv->admin & SRV_ADMF_MAINT)) {
/* Not already in maintenance, we can change the server state */
- sv->state |= SRV_STF_MAINTAIN;
+ sv->admin |= SRV_ADMF_FMAINT;
sv->check.state |= CHK_ST_PAUSED;
set_server_down(&sv->check);
}
@@ -2780,7 +2780,7 @@
"<i>no check</i>"
};
- if ((sv->state & SRV_STF_MAINTAIN) || (ref->state & SRV_STF_MAINTAIN))
+ if ((sv->admin | ref->admin) & SRV_ADMF_MAINT)
chunk_appendf(&trash, "<tr class=\"maintain\">");
else
chunk_appendf(&trash,
@@ -2911,11 +2911,11 @@
/* status, lest check */
chunk_appendf(&trash, "<td class=ac>");
- if (sv->state & SRV_STF_MAINTAIN) {
+ if (sv->admin & SRV_ADMF_MAINT) {
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - sv->last_change, 1));
chunk_appendf(&trash, "MAINT");
}
- else if (ref != sv && ref->state & SRV_STF_MAINTAIN) {
+ else if (ref != sv && (ref->admin & SRV_ADMF_MAINT)) {
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - ref->last_change, 1));
chunk_appendf(&trash, "MAINT(via)");
}
@@ -2976,7 +2976,7 @@
ref->counters.down_trans, human_time(srv_downtime(sv), 1));
}
else if (sv != ref) {
- if (sv->state & SRV_STF_MAINTAIN)
+ if (sv->admin & SRV_ADMF_MAINT)
chunk_appendf(&trash, "<td class=ac colspan=3></td>");
else
chunk_appendf(&trash,
@@ -3030,9 +3030,9 @@
sv->counters.retries, sv->counters.redispatches);
/* status */
- if (sv->state & SRV_STF_MAINTAIN)
+ if (sv->admin & SRV_ADMF_MAINT)
chunk_appendf(&trash, "MAINT,");
- else if (ref != sv && ref->state & SRV_STF_MAINTAIN)
+ else if (ref != sv && (ref->admin & SRV_ADMF_MAINT))
chunk_appendf(&trash, "MAINT(via),");
else
chunk_appendf(&trash,
@@ -3638,7 +3638,7 @@
else
sv_state = 0; /* DOWN */
- if (((sv_state == 0) || (sv->state & SRV_STF_MAINTAIN)) && (appctx->ctx.stats.flags & STAT_HIDE_DOWN)) {
+ if (((sv_state == 0) || (sv->admin & SRV_ADMF_MAINT)) && (appctx->ctx.stats.flags & STAT_HIDE_DOWN)) {
/* do not report servers which are DOWN */
appctx->ctx.stats.sv = sv->next;
continue;
@@ -4249,9 +4249,9 @@
else if ((sv = findserver(px, value)) != NULL) {
switch (action) {
case ST_ADM_ACTION_DISABLE:
- if ((px->state != PR_STSTOPPED) && !(sv->state & SRV_STF_MAINTAIN)) {
+ if ((px->state != PR_STSTOPPED) && !(sv->admin & SRV_ADMF_MAINT)) {
/* Not already in maintenance, we can change the server state */
- sv->state |= SRV_STF_MAINTAIN;
+ sv->admin |= SRV_ADMF_FMAINT;
sv->check.state |= CHK_ST_PAUSED;
set_server_down(&sv->check);
altered_servers++;
@@ -4259,7 +4259,7 @@
}
break;
case ST_ADM_ACTION_ENABLE:
- if ((px->state != PR_STSTOPPED) && (sv->state & SRV_STF_MAINTAIN)) {
+ if ((px->state != PR_STSTOPPED) && (sv->admin & SRV_ADMF_MAINT)) {
/* Already in maintenance, we can change the server state.
* If this server tracks the status of another one,
* we must restore the good status.
@@ -4269,7 +4269,7 @@
sv->check.health = sv->check.rise; /* up, but will fall down at first failure */
}
else {
- sv->state &= ~SRV_STF_MAINTAIN;
+ sv->admin &= ~SRV_ADMF_FMAINT;
sv->check.state &= ~CHK_ST_PAUSED;
set_server_down(&sv->check);
}
diff --git a/src/server.c b/src/server.c
index dc0883e..7309f42 100644
--- a/src/server.c
+++ b/src/server.c
@@ -346,6 +346,7 @@
do_check = 0;
do_agent = 0;
newsrv->flags = 0;
+ newsrv->admin = 0;
newsrv->state = SRV_STF_RUNNING; /* early server setup */
newsrv->last_change = now.tv_sec;
newsrv->id = strdup(args[1]);
@@ -680,7 +681,7 @@
cur_arg += 1;
}
else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
- newsrv->state |= SRV_STF_MAINTAIN;
+ newsrv->admin |= SRV_ADMF_FMAINT;
newsrv->state &= ~SRV_STF_RUNNING;
newsrv->check.state |= CHK_ST_PAUSED;
newsrv->check.health = 0;