newsrv->slowstart = (val + 999) / 1000;
cur_arg += 2;
}
+ else if (!strcmp(args[cur_arg], "track")) {
+
+ if (!*args[cur_arg + 1]) {
+ Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
+ file, linenum);
+ return -1;
+ }
+
+ newsrv->trackit = strdup(args[cur_arg + 1]);
+
+ cur_arg += 2;
+ }
else if (!strcmp(args[cur_arg], "check")) {
global.maxsock++;
do_check = 1;
return -1;
}
else {
- Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
+ Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
file, linenum, newsrv->id);
return -1;
}
}
if (do_check) {
+ if (newsrv->trackit) {
+ Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
+ file, linenum);
+ return -1;
+ }
+
if (!newsrv->check_port && newsrv->check_addr.sin_port)
newsrv->check_port = newsrv->check_addr.sin_port;
/*
* If this server supports a maxconn parameter, it needs a dedicated
* tasks to fill the emptied slots when a connection leaves.
+ * Also, resolve deferred tracking dependency if needed.
*/
newsrv = curproxy->srv;
while (newsrv != NULL) {
tv_eternity(&t->expire);
task_queue(t);
}
+
+ if (newsrv->trackit) {
+ struct proxy *px;
+ struct server *srv;
+ char *pname, *sname;
+
+ pname = newsrv->trackit;
+ sname = strrchr(pname, '/');
+
+ if (sname)
+ *sname++ = '\0';
+ else {
+ sname = pname;
+ pname = NULL;
+ }
+
+ if (pname) {
+ px = findproxy(pname, curproxy->mode, PR_CAP_BE);
+ if (!px) {
+ Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
+ file, proxy_type_str(curproxy), curproxy->id,
+ newsrv->id, pname);
+ return -1;
+ }
+ } else
+ px = curproxy;
+
+ srv = findserver(px, sname);
+ if (!srv) {
+ Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
+ file, proxy_type_str(curproxy), curproxy->id,
+ newsrv->id, sname);
+ return -1;
+ }
+
+ if (!(srv->state & SRV_CHECKED)) {
+ Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
+ "tracing as it does not have checks enabled.\n",
+ file, proxy_type_str(curproxy), curproxy->id,
+ newsrv->id, px->id, srv->id);
+ return -1;
+ }
+
+ if (curproxy != px &&
+ (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
+ Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
+ "tracing: disable-on-404 option inconsistency.\n",
+ file, proxy_type_str(curproxy), curproxy->id,
+ newsrv->id, px->id, srv->id);
+ return -1;
+ }
+
+ newsrv->tracked = srv;
+ newsrv->tracknext = srv->tracknext;
+ srv->tracknext = newsrv;
+
+ free(newsrv->trackit);
+ }
+
newsrv = newsrv->next;
}
* Health-checks functions.
*
* Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
+ * Copyright 2007-2008 Krzysztof Piotr Oledzki <ole@ans.pl>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include <types/session.h>
#include <proto/backend.h>
+#include <proto/buffers.h>
#include <proto/fd.h>
#include <proto/log.h>
#include <proto/queue.h>
*/
static void set_server_down(struct server *s)
{
+ struct server *srv;
+ struct chunk msg;
int xferred;
- if (s->health == s->rise) {
+ if (s->health == s->rise || s->tracked) {
int srv_was_paused = s->state & SRV_GOINGDOWN;
s->last_change = now.tv_sec;
* to another server or to the proxy itself.
*/
xferred = redistribute_pending(s);
- sprintf(trash, "%sServer %s/%s is DOWN. %d active and %d backup servers left.%s"
+
+ msg.len = 0;
+ msg.str = trash;
+
+ chunk_printf(&msg, sizeof(trash),
+ "%sServer %s/%s is DOWN", s->state & SRV_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ if (s->tracked)
+ chunk_printf(&msg, sizeof(trash), " via %s/%s",
+ s->tracked->proxy->id, s->tracked->id);
+
+ chunk_printf(&msg, sizeof(trash), ". %d active and %d backup servers left.%s"
" %d sessions active, %d requeued, %d remaining in queue.\n",
- s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id, s->proxy->srv_act, s->proxy->srv_bck,
+ s->proxy->srv_act, s->proxy->srv_bck,
(s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
s->cur_sess, xferred, s->nbpend);
set_backend_down(s->proxy);
s->down_trans++;
+
+ if (s->state && SRV_CHECKED)
+ for(srv = s->tracknext; srv; srv = srv->tracknext)
+ set_server_down(srv);
}
+
s->health = 0; /* failure */
}
+static void set_server_up(struct server *s) {
+
+ struct server *srv;
+ struct chunk msg;
+ int xferred;
+
+ if (s->health == s->rise || s->tracked) {
+ 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;
+ s->proxy->last_change = now.tv_sec;
+ }
+
+ if (s->last_change < now.tv_sec) // ignore negative times
+ s->down_time += now.tv_sec - s->last_change;
+
+ s->last_change = now.tv_sec;
+ s->state |= SRV_RUNNING;
+
+ if (s->slowstart > 0) {
+ s->state |= SRV_WARMINGUP;
+ if (s->proxy->lbprm.algo & BE_LB_PROP_DYN) {
+ /* For dynamic algorithms, start at the first step of the weight,
+ * without multiplying by BE_WEIGHT_SCALE.
+ */
+ s->eweight = s->uweight;
+ if (s->proxy->lbprm.update_server_eweight)
+ s->proxy->lbprm.update_server_eweight(s);
+ }
+ }
+ s->proxy->lbprm.set_server_status_up(s);
+
+ /* check if we can handle some connections queued at the proxy. We
+ * will take as many as we can handle.
+ */
+ xferred = check_for_pending(s);
+
+ msg.len = 0;
+ msg.str = trash;
+
+ chunk_printf(&msg, sizeof(trash),
+ "%sServer %s/%s is UP", s->state & SRV_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ if (s->tracked)
+ chunk_printf(&msg, sizeof(trash), " via %s/%s",
+ s->tracked->proxy->id, s->tracked->id);
+
+ chunk_printf(&msg, sizeof(trash), ". %d active and %d backup servers online.%s"
+ " %d sessions requeued, %d total in queue.\n",
+ s->proxy->srv_act, s->proxy->srv_bck,
+ (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
+ s->cur_sess, xferred, s->nbpend);
+
+ Warning("%s", trash);
+ send_log(s->proxy, LOG_NOTICE, "%s", trash);
+
+ if (s->state && SRV_CHECKED)
+ for(srv = s->tracknext; srv; srv = srv->tracknext)
+ set_server_up(srv);
+ }
+
+ if (s->health >= s->rise)
+ s->health = s->rise + s->fall - 1; /* OK now */
+
+}
+
+static void set_server_disabled(struct server *s) {
+
+ struct server *srv;
+ struct chunk msg;
+ int xferred;
+
+ s->state |= SRV_GOINGDOWN;
+ s->proxy->lbprm.set_server_status_down(s);
+
+ /* we might have sessions queued on this server and waiting for
+ * a connection. Those which are redispatchable will be queued
+ * to another server or to the proxy itself.
+ */
+ xferred = redistribute_pending(s);
+
+ msg.len = 0;
+ msg.str = trash;
+
+ chunk_printf(&msg, sizeof(trash),
+ "Load-balancing on %sServer %s/%s is disabled",
+ s->state & SRV_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ if (s->tracked)
+ chunk_printf(&msg, sizeof(trash), " via %s/%s",
+ s->tracked->proxy->id, s->tracked->id);
+
+
+ chunk_printf(&msg, sizeof(trash),". %d active and %d backup servers online.%s"
+ " %d sessions requeued, %d total in queue.\n",
+ s->proxy->srv_act, s->proxy->srv_bck,
+ (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
+ xferred, s->nbpend);
+
+ Warning("%s", trash);
+
+ send_log(s->proxy, LOG_NOTICE, "%s", trash);
+
+ if (!s->proxy->srv_bck && !s->proxy->srv_act)
+ set_backend_down(s->proxy);
+
+ if (s->state && SRV_CHECKED)
+ for(srv = s->tracknext; srv; srv = srv->tracknext)
+ set_server_disabled(srv);
+}
+
+static void set_server_enabled(struct server *s) {
+
+ struct server *srv;
+ struct chunk msg;
+ int xferred;
+
+ s->state &= ~SRV_GOINGDOWN;
+ s->proxy->lbprm.set_server_status_up(s);
+
+ /* check if we can handle some connections queued at the proxy. We
+ * will take as many as we can handle.
+ */
+ xferred = check_for_pending(s);
+
+ msg.len = 0;
+ msg.str = trash;
+
+ chunk_printf(&msg, sizeof(trash),
+ "Load-balancing on %sServer %s/%s is enabled again",
+ s->state & SRV_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ if (s->tracked)
+ chunk_printf(&msg, sizeof(trash), " via %s/%s",
+ s->tracked->proxy->id, s->tracked->id);
+
+ chunk_printf(&msg, sizeof(trash), ". %d active and %d backup servers online.%s"
+ " %d sessions requeued, %d total in queue.\n",
+ s->proxy->srv_act, s->proxy->srv_bck,
+ (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
+ xferred, s->nbpend);
+
+ Warning("%s", trash);
+ send_log(s->proxy, LOG_NOTICE, "%s", trash);
+
+ if (s->state && SRV_CHECKED)
+ for(srv = s->tracknext; srv; srv = srv->tracknext)
+ set_server_enabled(srv);
+}
/*
* This function is used only for server health-checks. It handles
__label__ new_chk, out;
struct server *s = t->context;
struct sockaddr_in sa;
- int xferred;
int fd;
int rv;
/* we may have to add/remove this server from the LB group */
if ((s->state & SRV_RUNNING) && (s->proxy->options & PR_O_DISABLE404)) {
if ((s->state & SRV_GOINGDOWN) &&
- ((s->result & (SRV_CHK_RUNNING|SRV_CHK_DISABLE)) == SRV_CHK_RUNNING)) {
- /* server enabled again */
- s->state &= ~SRV_GOINGDOWN;
- s->proxy->lbprm.set_server_status_up(s);
-
- /* check if we can handle some connections queued at the proxy. We
- * will take as many as we can handle.
- */
- xferred = check_for_pending(s);
-
- sprintf(trash,
- "Load-balancing on %sServer %s/%s is enabled again. %d active and %d backup servers online.%s"
- " %d sessions requeued, %d total in queue.\n",
- s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id, s->proxy->srv_act, s->proxy->srv_bck,
- (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
- xferred, s->nbpend);
-
- Warning("%s", trash);
- send_log(s->proxy, LOG_NOTICE, "%s", trash);
- }
+ ((s->result & (SRV_CHK_RUNNING|SRV_CHK_DISABLE)) == SRV_CHK_RUNNING))
+ set_server_enabled(s);
else if (!(s->state & SRV_GOINGDOWN) &&
((s->result & (SRV_CHK_RUNNING | SRV_CHK_DISABLE)) ==
- (SRV_CHK_RUNNING | SRV_CHK_DISABLE))) {
- /* server disabled */
- s->state |= SRV_GOINGDOWN;
- s->proxy->lbprm.set_server_status_down(s);
-
- /* we might have sessions queued on this server and waiting for
- * a connection. Those which are redispatchable will be queued
- * to another server or to the proxy itself.
- */
- xferred = redistribute_pending(s);
-
- sprintf(trash,
- "Load-balancing on %sServer %s/%s is disabled. %d active and %d backup servers online.%s"
- " %d sessions requeued, %d total in queue.\n",
- s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id, s->proxy->srv_act, s->proxy->srv_bck,
- (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
- xferred, s->nbpend);
-
- Warning("%s", trash);
-
- send_log(s->proxy, LOG_NOTICE, "%s", trash);
- if (!s->proxy->srv_bck && !s->proxy->srv_act)
- set_backend_down(s->proxy);
- }
+ (SRV_CHK_RUNNING | SRV_CHK_DISABLE)))
+ set_server_disabled(s);
}
if (s->health < s->rise + s->fall - 1) {
s->health++; /* was bad, stays for a while */
- if (s->health == s->rise) {
- 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;
- s->proxy->last_change = now.tv_sec;
- }
-
- if (s->last_change < now.tv_sec) // ignore negative times
- s->down_time += now.tv_sec - s->last_change;
-
- s->last_change = now.tv_sec;
- s->state |= SRV_RUNNING;
- if (s->slowstart > 0) {
- s->state |= SRV_WARMINGUP;
- if (s->proxy->lbprm.algo & BE_LB_PROP_DYN) {
- /* For dynamic algorithms, start at the first step of the weight,
- * without multiplying by BE_WEIGHT_SCALE.
- */
- s->eweight = s->uweight;
- if (s->proxy->lbprm.update_server_eweight)
- s->proxy->lbprm.update_server_eweight(s);
- }
- }
- s->proxy->lbprm.set_server_status_up(s);
-
- /* check if we can handle some connections queued at the proxy. We
- * will take as many as we can handle.
- */
- xferred = check_for_pending(s);
-
- sprintf(trash,
- "%sServer %s/%s is UP. %d active and %d backup servers online.%s"
- " %d sessions requeued, %d total in queue.\n",
- s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id, s->proxy->srv_act, s->proxy->srv_bck,
- (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
- xferred, s->nbpend);
-
- Warning("%s", trash);
- send_log(s->proxy, LOG_NOTICE, "%s", trash);
- }
-
- if (s->health >= s->rise)
- s->health = s->rise + s->fall - 1; /* OK now */
+ set_server_up(s);
}
s->curfd = -1; /* no check running anymore */
fd_delete(fd);
"wretr,wredis,"
"status,weight,act,bck,"
"chkfail,chkdown,lastchg,downtime,qlimit,"
- "pid,iid,sid,throttle,lbtot,"
+ "pid,iid,sid,throttle,lbtot,tracked,"
"\n");
}
int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri, int flags)
{
struct buffer *rep = s->rep;
- struct server *sv;
+ struct server *sv, *svs; /* server and server-state, server-state=server or server->tracked */
struct chunk msg;
msg.len = 0;
"%s,"
/* rest of server: nothing */
",,,,,,,,"
- /* pid, iid, sid, throttle, lbtot, */
- "%d,%d,0,,,"
+ /* pid, iid, sid, throttle, lbtot, tracked*/
+ "%d,%d,0,,,,"
"\n",
px->id,
px->feconn, px->feconn_max, px->maxconn, px->cum_feconn,
sv = s->data_ctx.stats.sv;
+ if (sv->tracked)
+ svs = sv->tracked;
+ else
+ svs = sv;
+
/* FIXME: produce some small strings for "UP/DOWN x/y &#xxxx;" */
- if (!(sv->state & SRV_CHECKED))
+ if (!(svs->state & SRV_CHECKED))
sv_state = 6;
- else if (sv->state & SRV_RUNNING) {
- if (sv->health == sv->rise + sv->fall - 1)
+ else if (svs->state & SRV_RUNNING) {
+ if (svs->health == svs->rise + svs->fall - 1)
sv_state = 3; /* UP */
else
sv_state = 2; /* going down */
- if (sv->state & SRV_GOINGDOWN)
+ if (svs->state & SRV_GOINGDOWN)
sv_state += 2;
}
else
- if (sv->health)
+ if (svs->health)
sv_state = 1; /* going up */
else
sv_state = 0; /* DOWN */
chunk_printf(&msg, sizeof(trash),
srv_hlt_st[sv_state],
- (sv->state & SRV_RUNNING) ? (sv->health - sv->rise + 1) : (sv->health),
- (sv->state & SRV_RUNNING) ? (sv->fall) : (sv->rise));
+ (svs->state & SRV_RUNNING) ? (svs->health - svs->rise + 1) : (svs->health),
+ (svs->state & SRV_RUNNING) ? (svs->fall) : (svs->rise));
chunk_printf(&msg, sizeof(trash),
/* weight */
"<td align=right>%d</td><td align=right>%d</td>"
"<td nowrap align=right>%s</td>"
"",
- sv->failed_checks, sv->down_trans,
+ svs->failed_checks, svs->down_trans,
human_time(srv_downtime(sv), 1));
+ else if (sv != svs)
+ chunk_printf(&msg, sizeof(trash),
+ "<td nowrap colspan=3>via %s/%s</td>", svs->proxy->id, svs->id );
else
chunk_printf(&msg, sizeof(trash),
"<td colspan=3></td>");
/* sessions: lbtot */
chunk_printf(&msg, sizeof(trash), ",%d", sv->cum_lbconn);
+
+ /* tracked */
+ if (sv->tracked)
+ chunk_printf(&msg, sizeof(trash), ",%s/%s",
+ sv->tracked->proxy->id, sv->tracked->id);
+ else
+ chunk_printf(&msg, sizeof(trash), ",");
+
/* ',' then EOL */
chunk_printf(&msg, sizeof(trash), ",\n");
}
"%d,%d,%d,"
/* rest of backend: nothing, down transitions, last change, total downtime */
",%d,%d,%d,,"
- /* pid, iid, sid, throttle, lbtot, */
- "%d,%d,0,,%d,"
+ /* pid, iid, sid, throttle, lbtot, tracked,*/
+ "%d,%d,0,,%d,,"
"\n",
px->id,
px->nbpend /* or px->totpend ? */, px->nbpend_max,