static void fwrr_set_server_status_down(struct server *srv)
{
struct proxy *p = srv->proxy;
- struct fwrr_group *grp;
if (!srv_lb_status_changed(srv))
return;
/* server was already down */
goto out_update_backend;
- grp = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
- grp->next_weight -= srv->cur_eweight;
if (srv->flags & SRV_F_BACKUP) {
- p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
+ p->lbprm.fwrr.next_weight_bck -= srv->cur_eweight;
+ p->lbprm.tot_wbck = p->lbprm.fwrr.next_weight_bck;
p->srv_bck--;
if (srv == p->lbprm.fbck) {
p->lbprm.fbck = srv2;
}
} else {
- p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
+ p->lbprm.fwrr.next_weight_act -= srv->cur_eweight;
+ p->lbprm.tot_wact = p->lbprm.fwrr.next_weight_act;
p->srv_act--;
}
{
struct proxy *p = srv->proxy;
struct fwrr_group *grp;
+ int next_weight;
if (!srv_lb_status_changed(srv))
return;
goto out_update_backend;
grp = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
- grp->next_weight += srv->next_eweight;
if (srv->flags & SRV_F_BACKUP) {
- p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
+ p->lbprm.fwrr.next_weight_bck += srv->next_eweight;
+ next_weight = p->lbprm.tot_wbck = p->lbprm.fwrr.next_weight_bck;
p->srv_bck++;
if (!(p->options & PR_O_USE_ALL_BK)) {
}
}
} else {
- p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
+ p->lbprm.fwrr.next_weight_act += srv->next_eweight;
+ next_weight = p->lbprm.tot_wact = p->lbprm.fwrr.next_weight_act;
p->srv_act++;
}
/* note that eweight cannot be 0 here */
fwrr_get_srv(srv);
- srv->npos = grp->curr_pos + (grp->next_weight + grp->curr_weight - grp->curr_pos) / srv->next_eweight;
+ srv->npos = grp->curr_pos + (next_weight + grp->curr_weight - grp->curr_pos) / srv->next_eweight;
fwrr_queue_srv(srv);
out_update_backend:
int old_state, new_state;
struct proxy *p = srv->proxy;
struct fwrr_group *grp;
+ int next_weight;
if (!srv_lb_status_changed(srv))
return;
HA_RWLOCK_WRLOCK(LBPRM_LOCK, &p->lbprm.lock);
- grp = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
- grp->next_weight = grp->next_weight - srv->cur_eweight + srv->next_eweight;
-
- p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
- p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
+ if (srv->flags & SRV_F_BACKUP) {
+ p->lbprm.fwrr.next_weight_bck = p->lbprm.fwrr.next_weight_bck - srv->cur_eweight + srv->next_eweight;
+ next_weight = p->lbprm.tot_wbck = p->lbprm.fwrr.next_weight_bck;
+ grp = &p->lbprm.fwrr.bck;
+ } else {
+ p->lbprm.fwrr.next_weight_act = p->lbprm.fwrr.next_weight_act - srv->cur_eweight + srv->next_eweight;
+ next_weight = p->lbprm.tot_wact = p->lbprm.fwrr.next_weight_act;
+ grp = &p->lbprm.fwrr.act;
+ }
if (srv->lb_tree == grp->init) {
fwrr_dequeue_srv(srv);
*/
fwrr_dequeue_srv(srv);
fwrr_get_srv(srv);
- srv->npos = grp->curr_pos + (grp->next_weight + grp->curr_weight - grp->curr_pos) / srv->next_eweight;
+ srv->npos = grp->curr_pos + (next_weight + grp->curr_weight - grp->curr_pos) / srv->next_eweight;
fwrr_queue_srv(srv);
} else {
/* The server is either active or in the next queue. If it's
if (srv->next_eweight > 0) {
int prev_next = srv->npos;
- int step = grp->next_weight / srv->next_eweight;
+ int step = next_weight / srv->next_eweight;
srv->npos = srv->lpos + step;
srv->rweight = 0;
/* prepare the active servers group */
p->lbprm.fwrr.act.curr_pos = p->lbprm.fwrr.act.curr_weight =
- p->lbprm.fwrr.act.next_weight = p->lbprm.tot_wact;
+ p->lbprm.fwrr.next_weight_act = p->lbprm.tot_wact;
p->lbprm.fwrr.act.curr = p->lbprm.fwrr.act.t0 =
p->lbprm.fwrr.act.t1 = init_head;
p->lbprm.fwrr.act.init = &p->lbprm.fwrr.act.t0;
/* prepare the backup servers group */
p->lbprm.fwrr.bck.curr_pos = p->lbprm.fwrr.bck.curr_weight =
- p->lbprm.fwrr.bck.next_weight = p->lbprm.tot_wbck;
+ p->lbprm.fwrr.next_weight_bck = p->lbprm.tot_wbck;
p->lbprm.fwrr.bck.curr = p->lbprm.fwrr.bck.t0 =
p->lbprm.fwrr.bck.t1 = init_head;
p->lbprm.fwrr.bck.init = &p->lbprm.fwrr.bck.t0;
{
struct proxy *p = s->proxy;
struct fwrr_group *grp;
+ int next_weight;
grp = (s->flags & SRV_F_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
+ if (s->flags & SRV_F_BACKUP) {
+ next_weight = p->lbprm.fwrr.next_weight_bck;
+ } else {
+ next_weight = p->lbprm.fwrr.next_weight_act;
+ }
/* Delay everything which does not fit into the window and everything
* which does not fit into the theoretical new window.
}
else if (s->next_eweight <= 0 ||
s->npos >= 2 * grp->curr_weight ||
- s->npos >= grp->curr_weight + grp->next_weight) {
+ s->npos >= grp->curr_weight + next_weight) {
/* put into next tree, and readjust npos in case we could
* finally take this back to current. */
s->npos -= grp->curr_weight;
*
* The lbprm's lock must be held. The server's lock is not used.
*/
-static inline void fwrr_switch_trees(struct fwrr_group *grp)
+static inline void fwrr_switch_trees(struct fwrr_group *grp, int next_weight)
{
struct eb_root *swap;
swap = grp->init;
grp->init = grp->next;
grp->next = swap;
- grp->curr_weight = grp->next_weight;
+ grp->curr_weight = next_weight;
grp->curr_pos = grp->curr_weight;
}
*
* The lbprm's lock must be held to protect lpos/npos/rweight.
*/
-static inline void fwrr_update_position(struct fwrr_group *grp, struct server *s)
+static inline void fwrr_update_position(struct fwrr_group *grp, struct server *s, int next_weight)
{
unsigned int eweight = *(volatile unsigned int *)&s->cur_eweight;
}
s->lpos = s->npos;
- s->npos += grp->next_weight / eweight;
- s->rweight += grp->next_weight % eweight;
+ s->lpos += next_weight / eweight;
+ s->rweight += next_weight % eweight;
if (s->rweight >= eweight) {
s->rweight -= eweight;
struct server *srv, *full, *avoided;
struct fwrr_group *grp;
int switched;
+ int next_weight;
HA_RWLOCK_WRLOCK(LBPRM_LOCK, &p->lbprm.lock);
- if (p->srv_act)
+ if (p->srv_act) {
grp = &p->lbprm.fwrr.act;
- else if (p->lbprm.fbck) {
+ next_weight = p->lbprm.fwrr.next_weight_act;
+ } else if (p->lbprm.fbck) {
srv = p->lbprm.fbck;
goto out;
}
- else if (p->srv_bck)
+ else if (p->srv_bck) {
+ next_weight = p->lbprm.fwrr.next_weight_bck;
grp = &p->lbprm.fwrr.bck;
- else {
+ } else {
srv = NULL;
goto out;
}
* which might have recently changed.
*/
if (!grp->curr_weight)
- grp->curr_pos = grp->curr_weight = grp->next_weight;
+ grp->curr_pos = grp->curr_weight = next_weight;
/* get first server from the "current" tree. When the end of
* the tree is reached, we may have to switch, but only once.
goto requeue_servers;
}
switched = 1;
- fwrr_switch_trees(grp);
+ fwrr_switch_trees(grp, next_weight);
}
/* OK, we have a server. However, it may be saturated, in which
* its position and dequeue it anyway, so that we can move it
* to a better place afterwards.
*/
- fwrr_update_position(grp, srv);
+ fwrr_update_position(grp, srv, next_weight);
fwrr_dequeue_srv(srv);
grp->curr_pos++;
if (!srv->maxconn || (!srv->queueslength && srv->served < srv_dynamic_maxconn(srv))) {