[MEDIUM] Implement "track [<backend>/]<server>"
This patch implements ability to set the current state of one server
by tracking another one. It:
- adds two variables: *tracknext, *tracked to struct server
- implements findserver(), similar to findproxy()
- adds "track" keyword accepting both "proxy/server" and "server" (assuming current proxy)
- verifies if both checks and tracking is not enabled at the same time
- changes set_server_down() to notify tracking server
- creates set_server_up(), set_server_disabled(), set_server_enabled() by
moving the code from process_chk() and adding notifications
- changes stats to show a name of tracked server instead of Chk/Dwn/Dwntime(html)
or by adding new variable (csv)
Changes from the previuos version:
- it is possibile to track independently of the declaration order
- one extra comma bug is fixed
- new condition to check if there is no disable-on-404 inconsistency
diff --git a/TODO b/TODO
index ae120a1..74b3cce 100644
--- a/TODO
+++ b/TODO
@@ -174,9 +174,6 @@
filters and backend, on which every entity could rely.
- implement 'on uri <uri> <proxy>', 'on host <host> <proxy>'
- remove the first now useless hop in hdr_idx
- - implement "track XXX.YYY" for each server as an alternative to
- health checks. This will automatically set the server state to
- the same as server YYY of proxy XXX.
- balance on URI hash (specify length or depth)
- balance on any header hash (eg: host)
- balance with redirections to real servers
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 900b9a7..504f8a9 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -3893,6 +3893,13 @@
as the backend "source" keyword, except that it only applies to the server
referencing it. Please consult the "source" keyword for details.
+track [<proxy>/]<server>
+ This option enables ability to set the current state of the server by
+ tracking another one. Only a server with checks enabled can be tracked
+ so it is not possible for example to track a server that tracks another
+ one. If <proxy> is omitted the current one is used. If disable-on-404 is
+ used, it has to be enabled on both proxies.
+
weight <weight>
The "weight" parameter is used to adjust the server's weight relative to
other servers. All servers will receive a load proportional to their weight
diff --git a/include/proto/proxy.h b/include/proto/proxy.h
index 55f9aab..7268bfa 100644
--- a/include/proto/proxy.h
+++ b/include/proto/proxy.h
@@ -36,6 +36,7 @@
const char *proxy_cap_str(int cap);
const char *proxy_mode_str(int mode);
struct proxy *findproxy(const char *name, int mode, int cap);
+struct server *findserver(const struct proxy *px, const char *name);
int proxy_parse_timeout(const char **args, struct proxy *proxy,
struct proxy *defpx, char *err, int errlen);
diff --git a/include/types/server.h b/include/types/server.h
index c93236c..0e2183e 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -91,6 +91,8 @@
struct sockaddr_in tproxy_addr; /* non-local address we want to bind to for connect() */
#endif
+ struct server *tracknext, *tracked; /* next server in a tracking list, tracked server */
+ char *trackit; /* temporary variable to make assignment deferrable */
struct sockaddr_in check_addr; /* the address to check, if different from <addr> */
short check_port; /* the port to use for the health checks */
int health; /* 0->rise-1 = bad; rise->rise+fall-1 = good */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 13b0e36..25d954a 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1625,6 +1625,18 @@
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;
@@ -1684,13 +1696,19 @@
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;
@@ -2913,6 +2931,7 @@
/*
* 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) {
@@ -2950,6 +2969,65 @@
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;
}
diff --git a/src/checks.c b/src/checks.c
index 1a5bf71..53b7e54 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -2,6 +2,7 @@
* 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
@@ -34,6 +35,7 @@
#include <types/session.h>
#include <proto/backend.h>
+#include <proto/buffers.h>
#include <proto/fd.h>
#include <proto/log.h>
#include <proto/queue.h>
@@ -120,9 +122,11 @@
*/
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;
@@ -134,10 +138,21 @@
* 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);
@@ -153,10 +168,167 @@
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
@@ -364,7 +536,6 @@
__label__ new_chk, out;
struct server *s = t->context;
struct sockaddr_in sa;
- int xferred;
int fd;
int rv;
@@ -575,103 +746,18 @@
/* 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);
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 59ee93b..71e382a 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -171,7 +171,7 @@
"wretr,wredis,"
"status,weight,act,bck,"
"chkfail,chkdown,lastchg,downtime,qlimit,"
- "pid,iid,sid,throttle,lbtot,"
+ "pid,iid,sid,throttle,lbtot,tracked,"
"\n");
}
@@ -587,7 +587,7 @@
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;
@@ -706,8 +706,8 @@
"%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,
@@ -734,20 +734,25 @@
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 */
@@ -800,8 +805,8 @@
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 */
@@ -819,8 +824,11 @@
"<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>");
@@ -908,6 +916,14 @@
/* 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");
}
@@ -991,8 +1007,8 @@
"%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,
diff --git a/src/proxy.c b/src/proxy.c
index 281ee8e..402fc88 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -176,7 +176,7 @@
struct proxy *findproxy(const char *name, int mode, int cap) {
- struct proxy *curproxy, *target=NULL;
+ struct proxy *curproxy, *target = NULL;
for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
if ((curproxy->cap & cap)!=cap || strcmp(curproxy->id, name))
@@ -204,6 +204,37 @@
}
/*
+ * This function finds a server with matching name within selected proxy.
+ * It also checks if there are more matching servers with
+ * requested name as this often leads into unexpected situations.
+ */
+
+struct server *findserver(const struct proxy *px, const char *name) {
+
+ struct server *cursrv, *target = NULL;
+
+ if (!px)
+ return NULL;
+
+ for (cursrv = px->srv; cursrv; cursrv = cursrv->next) {
+ if (strcmp(cursrv->id, name))
+ continue;
+
+ if (!target) {
+ target = cursrv;
+ continue;
+ }
+
+ Alert("Refusing to use duplicated server '%s' fould in proxy: %s!\n",
+ name, px->id);
+
+ return NULL;
+ }
+
+ return target;
+}
+
+/*
* This function creates all proxy sockets. It should be done very early,
* typically before privileges are dropped. The sockets will be registered
* but not added to any fd_set, in order not to loose them across the fork().