MAJOR: server: use states instead of flags to store the server state
Servers used to have 3 flags to store a state, now they have 4 states
instead. This avoids lots of confusion for the 4 remaining undefined
states.
The encoding from the previous to the new states can be represented
this way :
SRV_STF_RUNNING
| SRV_STF_GOINGDOWN
| | SRV_STF_WARMINGUP
| | |
0 x x SRV_ST_STOPPED
1 0 0 SRV_ST_RUNNING
1 0 1 SRV_ST_STARTING
1 1 x SRV_ST_STOPPING
Note that the case where all bits were set used to exist and was randomly
dealt with. For example, the task was not stopped, the throttle value was
still updated and reported in the stats and in the http_server_state header.
It was the same if the server was stopped by the agent or for maintenance.
It's worth noting that the internal function names are still quite confusing.
diff --git a/include/proto/backend.h b/include/proto/backend.h
index 601a61a..31c191e 100644
--- a/include/proto/backend.h
+++ b/include/proto/backend.h
@@ -63,11 +63,15 @@
return 0;
if (srv->admin & SRV_ADMF_MAINT)
return 0;
- if (state & SRV_STF_GOINGDOWN)
+ switch (state) {
+ case SRV_ST_STARTING:
+ case SRV_ST_RUNNING:
+ return 1;
+ case SRV_ST_STOPPING:
+ case SRV_ST_STOPPED:
return 0;
- if (!(state & SRV_STF_RUNNING))
- return 0;
- return 1;
+ }
+ return 0;
}
/* This function returns non-zero if the designated server was usable for LB
@@ -81,11 +85,15 @@
return 0;
if (srv->prev_admin & SRV_ADMF_MAINT)
return 0;
- if (state & SRV_STF_GOINGDOWN)
- return 0;
- if (!(state & SRV_STF_RUNNING))
+ switch (state) {
+ case SRV_ST_STARTING:
+ case SRV_ST_RUNNING:
+ return 1;
+ case SRV_ST_STOPPING:
+ case SRV_ST_STOPPED:
return 0;
- return 1;
+ }
+ return 0;
}
/* This function commits the current server state and weight onto the previous
diff --git a/include/types/server.h b/include/types/server.h
index ba0a1a5..377ea06 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -43,11 +43,12 @@
#include <types/checks.h>
-/* server states, still used as cumulative flags */
+/* server states. Only SRV_ST_DOWN indicates a down server. */
enum srv_state {
- 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_ST_STOPPED = 0, /* the server is down. Please keep set to zero. */
+ SRV_ST_STARTING, /* the server is warming up (up but throttled) */
+ SRV_ST_RUNNING, /* the server is fully up */
+ SRV_ST_STOPPING, /* the server is up but soft-stopping (eg: 404) */
};
/* Maintenance mode : each server may be in maintenance by itself or may inherit
@@ -113,7 +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_state state, prev_state; /* server state among SRV_ST_* */
enum srv_admin admin, prev_admin; /* server maintenance status : SRV_ADMF_* */
unsigned char flags; /* server flags (SRV_F_*) */
struct server *next;
diff --git a/src/backend.c b/src/backend.c
index 0b4ff4d..e5c2ad1 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1242,7 +1242,7 @@
while (srv) {
if (srv->addr.ss_family == AF_INET &&
memcmp(&addr, &(srv->addr), sizeof(addr)) == 0) {
- if ((srv->state & SRV_STF_RUNNING) || (px->options & PR_O_PERSIST)) {
+ if ((srv->state != SRV_ST_STOPPED) || (px->options & PR_O_PERSIST)) {
/* we found the server and it is usable */
s->flags |= SN_DIRECT | SN_ASSIGNED;
s->target = &srv->obj_type;
@@ -1490,7 +1490,7 @@
smp->flags = SMP_F_VOL_TEST;
smp->type = SMP_T_BOOL;
if (!(srv->admin & SRV_ADMF_MAINT) &&
- (!(srv->check.state & CHK_ST_CONFIGURED) || (srv->state & SRV_STF_RUNNING)))
+ (!(srv->check.state & CHK_ST_CONFIGURED) || (srv->state != SRV_ST_STOPPED)))
smp->data.uint = 1;
else
smp->data.uint = 0;
@@ -1512,7 +1512,7 @@
smp->data.uint = 0;
for (iterator = args->data.prx->srv; iterator; iterator = iterator->next) {
- if ((iterator->state & SRV_STF_RUNNING) == 0)
+ if (iterator->state == SRV_ST_STOPPED)
continue;
if (iterator->maxconn == 0 || iterator->maxqueue == 0) {
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 037eaa9..5384f4f 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -6618,7 +6618,7 @@
/* if the other server is forced disabled, we have to do the same here */
if (srv->admin & SRV_ADMF_MAINT) {
- newsrv->state &= ~SRV_STF_RUNNING;
+ newsrv->state = SRV_ST_STOPPED;
newsrv->check.health = 0;
newsrv->agent.health = 0;
}
diff --git a/src/checks.c b/src/checks.c
index f4bfd54..62c8779 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -182,7 +182,7 @@
}
if (xferred >= 0) {
- if (!(s->state & SRV_STF_RUNNING))
+ if (s->state == SRV_ST_STOPPED)
chunk_appendf(msg, ". %d active and %d backup servers left.%s"
" %d sessions active, %d requeued, %d remaining in queue",
s->proxy->srv_act, s->proxy->srv_bck,
@@ -264,7 +264,7 @@
health--; /* still good */
} else {
if (health == rise)
- state &= ~(SRV_STF_RUNNING | SRV_STF_GOINGDOWN);
+ state = SRV_ST_STOPPED;
health = 0;
}
@@ -276,7 +276,7 @@
health++; /* was bad, stays for a while */
if (health == rise)
- state |= SRV_STF_RUNNING;
+ state = SRV_ST_RUNNING;
if (health >= rise)
health = rise + fall - 1; /* OK now */
@@ -300,9 +300,9 @@
server_status_printf(&trash, s, check, -1);
chunk_appendf(&trash, ", status: %d/%d %s",
- (state & SRV_STF_RUNNING) ? (health - rise + 1) : (health),
- (state & SRV_STF_RUNNING) ? (fall) : (rise),
- (state & SRV_STF_RUNNING) ? (s->uweight?"UP":"DRAIN"):"DOWN");
+ (state != SRV_ST_STOPPED) ? (health - rise + 1) : (health),
+ (state != SRV_ST_STOPPED) ? (fall) : (rise),
+ (state != SRV_ST_STOPPED) ? (s->uweight?"UP":"DRAIN"):"DOWN");
Warning("%s.\n", trash.str);
send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
@@ -416,12 +416,12 @@
check->health = check->rise;
}
- if ((s->state & SRV_STF_RUNNING && check->health == check->rise) || s->track) {
- int srv_was_paused = s->state & SRV_STF_GOINGDOWN;
+ if ((s->state != SRV_ST_STOPPED && check->health == check->rise) || s->track) {
+ int srv_was_stopping = (s->state == SRV_ST_STOPPING);
int prev_srv_count = s->proxy->srv_bck + s->proxy->srv_act;
s->last_change = now.tv_sec;
- s->state &= ~(SRV_STF_RUNNING | SRV_STF_GOINGDOWN);
+ s->state = SRV_ST_STOPPED;
if (s->proxy->lbprm.set_server_status_down)
s->proxy->lbprm.set_server_status_down(s);
@@ -452,7 +452,7 @@
Warning("%s.\n", trash.str);
/* we don't send an alert if the server was previously paused */
- if (srv_was_paused)
+ if (srv_was_stopping)
send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
else
send_log(s->proxy, LOG_ALERT, "%s.\n", trash.str);
@@ -498,14 +498,14 @@
s->down_time += now.tv_sec - s->last_change;
s->last_change = now.tv_sec;
- s->state |= SRV_STF_RUNNING;
s->admin &= ~SRV_ADMF_FMAINT;
s->check.state &= ~CHK_ST_PAUSED;
- if (s->slowstart > 0) {
- s->state |= SRV_STF_WARMINGUP;
+ s->state = SRV_ST_STARTING;
+ if (s->slowstart > 0)
task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20))));
- }
+ else
+ s->state = SRV_ST_RUNNING;
server_recalc_eweight(s);
@@ -559,7 +559,7 @@
struct server *srv;
int xferred;
- s->state |= SRV_STF_GOINGDOWN;
+ s->state = SRV_ST_STOPPING;
if (s->proxy->lbprm.set_server_status_down)
s->proxy->lbprm.set_server_status_down(s);
@@ -596,7 +596,11 @@
struct server *srv;
int xferred;
- s->state &= ~SRV_STF_GOINGDOWN;
+ if (s->slowstart)
+ s->state = SRV_ST_STARTING;
+ else
+ s->state = SRV_ST_RUNNING;
+
if (s->proxy->lbprm.set_server_status_up)
s->proxy->lbprm.set_server_status_up(s);
@@ -745,13 +749,13 @@
if (!(s->check.state & CHK_ST_ENABLED))
sv_state = 6;
- else if (s->state & SRV_STF_RUNNING) {
+ else if (s->state != SRV_ST_STOPPED) {
if (s->check.health == s->check.rise + s->check.fall - 1)
sv_state = 3; /* UP */
else
sv_state = 2; /* going down */
- if (s->state & SRV_STF_GOINGDOWN)
+ if (s->state == SRV_ST_STOPPING)
sv_state += 2;
} else {
if (s->check.health)
@@ -762,8 +766,8 @@
hlen += snprintf(buffer + hlen, size - hlen,
srv_hlt_st[sv_state],
- (s->state & SRV_STF_RUNNING) ? (s->check.health - s->check.rise + 1) : (s->check.health),
- (s->state & SRV_STF_RUNNING) ? (s->check.fall) : (s->check.rise));
+ (s->state != SRV_ST_STOPPED) ? (s->check.health - s->check.rise + 1) : (s->check.health),
+ (s->state != SRV_ST_STOPPED) ? (s->check.fall) : (s->check.rise));
hlen += snprintf(buffer + hlen, size - hlen, "; name=%s/%s; node=%s; weight=%d/%d; scur=%d/%d; qcur=%d",
s->proxy->id, s->id,
@@ -773,7 +777,7 @@
s->cur_sess, s->proxy->beconn - s->proxy->nbpend,
s->nbpend);
- if ((s->state & SRV_STF_WARMINGUP) &&
+ if ((s->state == SRV_ST_STARTING) &&
now.tv_sec < s->last_change + s->slowstart &&
now.tv_sec >= s->last_change) {
ratio = MAX(1, 100 * (now.tv_sec - s->last_change) / s->slowstart);
@@ -1084,7 +1088,7 @@
desc = ltrim(check->bi->data + 12, ' ');
if ((s->proxy->options & PR_O_DISABLE404) &&
- (s->state & SRV_STF_RUNNING) && (check->code == 404)) {
+ (s->state != SRV_ST_STOPPED) && (check->code == 404)) {
/* 404 may be accepted as "stopping" only if the server was up */
cut_crlf(desc);
set_server_check_status(check, HCHK_STATUS_L7OKCD, desc);
@@ -1481,9 +1485,10 @@
/* by default, plan on stopping the task */
t->expire = TICK_ETERNITY;
if ((s->admin & SRV_ADMF_MAINT) ||
- (s->state & (SRV_STF_RUNNING|SRV_STF_WARMINGUP)) != (SRV_STF_RUNNING|SRV_STF_WARMINGUP))
+ (s->state != SRV_ST_STARTING))
return t;
+ /* recalculate the weights and update the state */
server_recalc_eweight(s);
/* probably that we can refill this server with a bit more connections */
@@ -1492,7 +1497,7 @@
/* get back there in 1 second or 1/20th of the slowstart interval,
* whichever is greater, resulting in small 5% steps.
*/
- if (s->state & SRV_STF_WARMINGUP)
+ if (s->state == SRV_ST_STARTING)
t->expire = tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20)));
return t;
}
@@ -1701,10 +1706,10 @@
check_failed(check);
else { /* check was OK */
/* we may have to add/remove this server from the LB group */
- if ((s->state & SRV_STF_RUNNING) && (s->proxy->options & PR_O_DISABLE404)) {
- if ((s->state & SRV_STF_GOINGDOWN) && (check->result != CHK_RES_CONDPASS))
+ if ((s->state != SRV_ST_STOPPED) && (s->proxy->options & PR_O_DISABLE404)) {
+ if ((s->state == SRV_ST_STOPPING) && (check->result != CHK_RES_CONDPASS))
set_server_enabled(check);
- else if (!(s->state & SRV_STF_GOINGDOWN) && (check->result == CHK_RES_CONDPASS))
+ else if ((s->state != SRV_ST_STOPPING) && (check->result == CHK_RES_CONDPASS))
set_server_disabled(check);
}
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 1de4199..fbe1d2a 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -1716,7 +1716,7 @@
/* If this server tracks the status of another one,
* we must restore the good status.
*/
- if (sv->track->state & SRV_STF_RUNNING) {
+ if (sv->track->state != SRV_ST_STOPPED) {
set_server_up(&sv->check);
sv->check.health = sv->check.rise; /* up, but will fall down at first failure */
} else {
@@ -2923,8 +2923,8 @@
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - ref->last_change, 1));
chunk_appendf(&trash,
srv_hlt_st[state],
- (ref->state & SRV_STF_RUNNING) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
- (ref->state & SRV_STF_RUNNING) ? (ref->check.fall) : (ref->check.rise));
+ (ref->state != SRV_ST_STOPPED) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
+ (ref->state != SRV_ST_STOPPED) ? (ref->check.fall) : (ref->check.rise));
}
if (sv->check.state & CHK_ST_ENABLED) {
@@ -2987,7 +2987,7 @@
chunk_appendf(&trash, "<td colspan=3></td>");
/* throttle */
- if ((sv->state & SRV_STF_WARMINGUP) && !server_is_draining(sv))
+ if (sv->state == SRV_ST_STARTING && !server_is_draining(sv))
chunk_appendf(&trash, "<td class=ac>%d %%</td></tr>\n", server_throttle_rate(sv));
else
chunk_appendf(&trash, "<td class=ac>-</td></tr>\n");
@@ -3037,8 +3037,8 @@
else
chunk_appendf(&trash,
srv_hlt_st[state],
- (ref->state & SRV_STF_RUNNING) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
- (ref->state & SRV_STF_RUNNING) ? (ref->check.fall) : (ref->check.rise));
+ (ref->state != SRV_ST_STOPPED) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
+ (ref->state != SRV_ST_STOPPED) ? (ref->check.fall) : (ref->check.rise));
chunk_appendf(&trash,
/* weight, active, backup */
@@ -3065,7 +3065,7 @@
relative_pid, px->uuid, sv->puid);
/* throttle */
- if ((sv->state & SRV_STF_WARMINGUP) && !server_is_draining(sv))
+ if (sv->state == SRV_ST_STARTING && !server_is_draining(sv))
chunk_appendf(&trash, "%d", server_throttle_rate(sv));
/* sessions: lbtot */
@@ -3621,7 +3621,7 @@
/* FIXME: produce some small strings for "UP/DOWN x/y &#xxxx;" */
if (!(svs->check.state & CHK_ST_ENABLED))
sv_state = 8;
- else if (svs->state & SRV_STF_RUNNING) {
+ else if (svs->state != SRV_ST_STOPPED) {
if (svs->check.health == svs->check.rise + svs->check.fall - 1)
sv_state = 3; /* UP */
else
@@ -3629,7 +3629,7 @@
if (server_is_draining(sv))
sv_state += 4;
- else if (svs->state & SRV_STF_GOINGDOWN)
+ else if (svs->state == SRV_ST_STOPPING)
sv_state += 2;
}
else
@@ -4264,7 +4264,7 @@
* If this server tracks the status of another one,
* we must restore the good status.
*/
- if (!sv->track || (sv->track->state & SRV_STF_RUNNING)) {
+ if (!sv->track || (sv->track->state != SRV_ST_STOPPED)) {
set_server_up(&sv->check);
sv->check.health = sv->check.rise; /* up, but will fall down at first failure */
}
diff --git a/src/haproxy.c b/src/haproxy.c
index ca74e4e..d8d8c61 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -449,7 +449,7 @@
chunk_printf(&trash,
"SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
p->id, s->id,
- (s->state & SRV_STF_RUNNING) ? "UP" : "DOWN",
+ (s->state != SRV_ST_STOPPED) ? "UP" : "DOWN",
s->cur_sess, s->nbpend, s->counters.cum_sess);
Warning("%s\n", trash.str);
send_log(p, LOG_NOTICE, "%s\n", trash.str);
diff --git a/src/lb_map.c b/src/lb_map.c
index 24ae4ec..df7af7f 100644
--- a/src/lb_map.c
+++ b/src/lb_map.c
@@ -101,7 +101,7 @@
for (cur = px->srv; cur; cur = cur->next) {
if (cur->eweight &&
(cur->flags & SRV_F_BACKUP) == flag &&
- (cur->state & (SRV_STF_RUNNING | SRV_STF_GOINGDOWN)) == SRV_STF_RUNNING) {
+ (cur->state == SRV_ST_STARTING || cur->state == SRV_ST_RUNNING)) {
int v;
/* If we are forced to return only one server, we don't want to
diff --git a/src/proto_http.c b/src/proto_http.c
index 4892b8b..bd6d024 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -7069,12 +7069,12 @@
while (srv) {
if (strcmp(srv->id, asession->serverid) == 0) {
- if ((srv->state & SRV_STF_RUNNING) ||
+ if ((srv->state != SRV_ST_STOPPED) ||
(s->be->options & PR_O_PERSIST) ||
(s->flags & SN_FORCE_PRST)) {
/* we found the server and it's usable */
txn->flags &= ~TX_CK_MASK;
- txn->flags |= (srv->state & SRV_STF_RUNNING) ? TX_CK_VALID : TX_CK_DOWN;
+ txn->flags |= (srv->state != SRV_ST_STOPPED) ? TX_CK_VALID : TX_CK_DOWN;
s->flags |= SN_DIRECT | SN_ASSIGNED;
s->target = &srv->obj_type;
@@ -7479,12 +7479,12 @@
while (srv) {
if (srv->cookie && (srv->cklen == delim - val_beg) &&
!memcmp(val_beg, srv->cookie, delim - val_beg)) {
- if ((srv->state & SRV_STF_RUNNING) ||
+ if ((srv->state != SRV_ST_STOPPED) ||
(s->be->options & PR_O_PERSIST) ||
(s->flags & SN_FORCE_PRST)) {
/* we found the server and we can use it */
txn->flags &= ~TX_CK_MASK;
- txn->flags |= (srv->state & SRV_STF_RUNNING) ? TX_CK_VALID : TX_CK_DOWN;
+ txn->flags |= (srv->state != SRV_ST_STOPPED) ? TX_CK_VALID : TX_CK_DOWN;
s->flags |= SN_DIRECT | SN_ASSIGNED;
s->target = &srv->obj_type;
break;
diff --git a/src/queue.c b/src/queue.c
index 8fd1f08..21a48d6 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -50,7 +50,7 @@
else max = MAX(s->minconn,
s->proxy->beconn * s->maxconn / s->proxy->fullconn);
- if ((s->state & SRV_STF_WARMINGUP) &&
+ if ((s->state == SRV_ST_STARTING) &&
now.tv_sec < s->last_change + s->slowstart &&
now.tv_sec >= s->last_change) {
unsigned int ratio;
diff --git a/src/server.c b/src/server.c
index 7309f42..0351411 100644
--- a/src/server.c
+++ b/src/server.c
@@ -32,7 +32,7 @@
int srv_downtime(const struct server *s)
{
- if ((s->state & SRV_STF_RUNNING) && s->last_change < now.tv_sec) // ignore negative time
+ if ((s->state != SRV_ST_STOPPED) && s->last_change < now.tv_sec) // ignore negative time
return s->down_time;
return now.tv_sec - s->last_change + s->down_time;
@@ -53,7 +53,7 @@
if ((check->state & CHK_ST_CONFIGURED) && (check->health == check->rise + check->fall - 1))
return check->inter;
- if (!(s->state & SRV_STF_RUNNING) && check->health == 0)
+ if ((s->state == SRV_ST_STOPPED) && check->health == 0)
return (check->downinter)?(check->downinter):(check->inter);
return (check->fastinter)?(check->fastinter):(check->inter);
@@ -185,13 +185,14 @@
if (now.tv_sec < sv->last_change || now.tv_sec >= sv->last_change + sv->slowstart) {
/* go to full throttle if the slowstart interval is reached */
- sv->state &= ~SRV_STF_WARMINGUP;
+ if (sv->state == SRV_ST_STARTING)
+ sv->state = SRV_ST_RUNNING;
}
/* We must take care of not pushing the server to full throttle during slow starts.
* It must also start immediately, at least at the minimal step when leaving maintenance.
*/
- if ((sv->state & SRV_STF_WARMINGUP) && (px->lbprm.algo & BE_LB_PROP_DYN))
+ if ((sv->state == SRV_ST_STARTING) && (px->lbprm.algo & BE_LB_PROP_DYN))
w = (px->lbprm.wdiv * (now.tv_sec - sv->last_change) + sv->slowstart) / sv->slowstart;
else
w = px->lbprm.wdiv;
@@ -347,7 +348,7 @@
do_agent = 0;
newsrv->flags = 0;
newsrv->admin = 0;
- newsrv->state = SRV_STF_RUNNING; /* early server setup */
+ newsrv->state = SRV_ST_RUNNING; /* early server setup */
newsrv->last_change = now.tv_sec;
newsrv->id = strdup(args[1]);
@@ -682,7 +683,7 @@
}
else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
newsrv->admin |= SRV_ADMF_FMAINT;
- newsrv->state &= ~SRV_STF_RUNNING;
+ newsrv->state = SRV_ST_STOPPED;
newsrv->check.state |= CHK_ST_PAUSED;
newsrv->check.health = 0;
newsrv->agent.health = 0;
diff --git a/src/session.c b/src/session.c
index 336274c..cfb45c8 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1375,7 +1375,7 @@
if (ret) {
struct server *srv = rule->srv.ptr;
- if ((srv->state & SRV_STF_RUNNING) ||
+ if ((srv->state != SRV_ST_STOPPED) ||
(px->options & PR_O_PERSIST) ||
(s->flags & SN_FORCE_PRST)) {
s->flags |= SN_DIRECT | SN_ASSIGNED;
@@ -1460,7 +1460,7 @@
struct server *srv;
srv = container_of(node, struct server, conf.id);
- if ((srv->state & SRV_STF_RUNNING) ||
+ if ((srv->state != SRV_ST_STOPPED) ||
(px->options & PR_O_PERSIST) ||
(s->flags & SN_FORCE_PRST)) {
s->flags |= SN_DIRECT | SN_ASSIGNED;