diff --git a/include/proto/backend.h b/include/proto/backend.h index 7414edeb6..8fa8c834f 100644 --- a/include/proto/backend.h +++ b/include/proto/backend.h @@ -42,6 +42,7 @@ int backend_parse_balance(const char **args, char *err, void recount_servers(struct proxy *px); void recalc_server_map(struct proxy *px); int be_downtime(struct proxy *px); +void init_server_map(struct proxy *p); /* * This function tries to find a running server with free connection slots for diff --git a/include/types/proxy.h b/include/types/proxy.h index 03f9601ba..53de5132f 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -86,6 +86,7 @@ struct proxy { int tot_weight; /* total effective weight of servers participating to LB */ int tot_used; /* total number of servers used for LB */ int wmult; /* ratio between user weight and effective weight */ + int wdiv; /* ratio between effective weight and user weight */ struct { struct server **srv; /* the server map used to apply weights */ int rr_idx; /* next server to be elected in round robin mode */ diff --git a/src/backend.c b/src/backend.c index 96de0ba37..46078ceb1 100644 --- a/src/backend.c +++ b/src/backend.c @@ -161,6 +161,59 @@ void recalc_server_map(struct proxy *px) px->lbprm.map.state &= ~PR_MAP_RECALC; } +/* This function is responsible of building the server MAP for map-based LB + * algorithms, allocating the map, and setting p->lbprm.wmult to the GCD of the + * weights if applicable. It should be called only once per proxy, at config + * time. + */ +void init_server_map(struct proxy *p) +{ + struct server *srv; + int pgcd; + int act, bck; + + if (!p->srv) + return; + + /* We will factor the weights to reduce the table, + * using Euclide's largest common divisor algorithm + */ + pgcd = p->srv->uweight; + for (srv = p->srv->next; srv && pgcd > 1; srv = srv->next) { + int w = srv->uweight; + while (w) { + int t = pgcd % w; + pgcd = w; + w = t; + } + } + + /* It is sometimes useful to know what factor to apply + * to the backend's effective weight to know its real + * weight. + */ + p->lbprm.wmult = pgcd; + + act = bck = 0; + for (srv = p->srv; srv; srv = srv->next) { + srv->eweight = srv->uweight / pgcd; + if (srv->state & SRV_BACKUP) + bck += srv->eweight; + else + act += srv->eweight; + } + + /* this is the largest map we will ever need for this servers list */ + if (act < bck) + act = bck; + + p->lbprm.map.srv = (struct server **)calloc(act, sizeof(struct server *)); + /* recounts servers and their weights */ + p->lbprm.map.state = PR_MAP_RECALC; + recount_servers(p); + recalc_server_map(p); +} + /* * This function tries to find a running server for the proxy following * the URL parameter hash method. It looks for a specific parameter in the diff --git a/src/cfgparse.c b/src/cfgparse.c index 05864d82e..9ca0509a8 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -2653,53 +2653,9 @@ int readcfgfile(const char *file) } curproxy->lbprm.wmult = 1; /* default weight multiplier */ + curproxy->lbprm.wdiv = 1; /* default weight divider */ - /* now, newsrv == curproxy->srv */ - if (newsrv) { - struct server *srv; - int pgcd; - int act, bck; - - /* We will factor the weights to reduce the table, - * using Euclide's largest common divisor algorithm - */ - pgcd = newsrv->uweight; - for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) { - int t, w; - - w = srv->uweight; - while (w) { - t = pgcd % w; - pgcd = w; - w = t; - } - } - - /* It is sometimes useful to know what factor to apply - * to the backend's effective weight to know its real - * weight. - */ - curproxy->lbprm.wmult = pgcd; - - act = bck = 0; - for (srv = newsrv; srv; srv = srv->next) { - srv->eweight = srv->uweight / pgcd; - if (srv->state & SRV_BACKUP) - bck += srv->eweight; - else - act += srv->eweight; - } - - /* this is the largest map we will ever need for this servers list */ - if (act < bck) - act = bck; - - curproxy->lbprm.map.srv = (struct server **)calloc(act, sizeof(struct server *)); - /* recounts servers and their weights */ - curproxy->lbprm.map.state = PR_MAP_RECALC; - recount_servers(curproxy); - recalc_server_map(curproxy); - } + init_server_map(curproxy); if (curproxy->options & PR_O_LOGASAP) curproxy->to_log &= ~LW_BYTES; diff --git a/src/dumpstats.c b/src/dumpstats.c index 2c91b4391..cac57cfa1 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -756,7 +756,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri, /* act, bck */ "%s%s" "", - sv->uweight, + sv->eweight * px->lbprm.wmult / px->lbprm.wdiv, (sv->state & SRV_BACKUP) ? "-" : "Y", (sv->state & SRV_BACKUP) ? "Y" : "-"); @@ -808,7 +808,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri, /* weight, active, backup */ "%d,%d,%d," "", - sv->uweight, + sv->eweight * px->lbprm.wmult / px->lbprm.wdiv, (sv->state & SRV_BACKUP) ? 0 : 1, (sv->state & SRV_BACKUP) ? 1 : 0); @@ -872,7 +872,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri, px->retries, px->redispatches, human_time(now.tv_sec - px->last_change, 1), (px->lbprm.tot_weight > 0 || !px->srv) ? "UP" : "DOWN", - px->lbprm.tot_weight * px->lbprm.wmult, + px->lbprm.tot_weight * px->lbprm.wmult / px->lbprm.wdiv, px->srv_act, px->srv_bck); chunk_printf(&msg, sizeof(trash), @@ -918,7 +918,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri, px->failed_conns, px->failed_resp, px->retries, px->redispatches, (px->lbprm.tot_weight > 0 || !px->srv) ? "UP" : "DOWN", - px->lbprm.tot_weight * px->lbprm.wmult, + px->lbprm.tot_weight * px->lbprm.wmult / px->lbprm.wdiv, px->srv_act, px->srv_bck, px->down_trans, now.tv_sec - px->last_change, px->srv?be_downtime(px):0,