Commit a49d5507 authored by Martin Blix Grydeland's avatar Martin Blix Grydeland

Always take the number of healthy backends into account when selecting

a backend by weight.

This removes the bias problems the current code exhibits when there is
a sick backend in the set.

Spotted by: xcir

Fixes: #1658
parent 363fde20
......@@ -47,7 +47,6 @@ struct vmod_directors_hash {
unsigned magic;
#define VMOD_DIRECTORS_HASH_MAGIC 0xc08dd611
struct vdir *vd;
unsigned n_backend;
struct vbitmap *vbm;
};
......@@ -89,7 +88,6 @@ vmod_hash_add_backend(VRT_CTX,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_HASH_MAGIC);
(void)vdir_add_backend(rr->vd, be, w);
rr->n_backend++;
}
VCL_BACKEND __match_proto__()
......@@ -120,6 +118,6 @@ vmod_hash_backend(VRT_CTX, struct vmod_directors_hash *rr,
r = vbe32dec(sha256);
r = scalbn(r, -32);
assert(r >= 0 && r <= 1.0);
be = vdir_pick_be(rr->vd, r, rr->n_backend);
be = vdir_pick_be(rr->vd, r);
return (be);
}
......@@ -45,7 +45,6 @@ struct vmod_directors_random {
unsigned magic;
#define VMOD_DIRECTORS_RANDOM_MAGIC 0x4732d092
struct vdir *vd;
unsigned n_backend;
};
static unsigned __match_proto__(vdi_healthy)
......@@ -72,7 +71,7 @@ vmod_random_resolve(const struct director *dir, struct worker *wrk,
CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC);
r = scalbn(random(), -31);
assert(r >= 0 && r < 1.0);
be = vdir_pick_be(rr->vd, r, rr->n_backend);
be = vdir_pick_be(rr->vd, r);
return (be);
}
......@@ -112,7 +111,6 @@ vmod_random_add_backend(VRT_CTX,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC);
(void)vdir_add_backend(rr->vd, be, w);
rr->n_backend++;
}
VCL_BACKEND __match_proto__()
......
......@@ -175,33 +175,25 @@ vdir_pick_by_weight(const struct vdir *vd, double w,
}
VCL_BACKEND
vdir_pick_be(struct vdir *vd, double w, unsigned nloops)
vdir_pick_be(struct vdir *vd, double w)
{
struct vbitmap *vbm = NULL;
unsigned u, v, l;
unsigned u;
double tw = 0.0;
VCL_BACKEND be = NULL;
double tw;
int nbe;
tw = vd->total_weight;
nbe = vd->n_backend;
assert(w >= 0.0 && w < 1.0);
vdir_lock(vd);
for (l = 0; nbe > 0 && tw > 0.0 && l < nloops; l++) {
u = vdir_pick_by_weight(vd, w * tw, vbm);
for (u = 0; u < vd->n_backend; u++) {
if (vd->backend[u]->healthy(vd->backend[u], NULL, NULL)) {
vbit_clr(vd->vbm, u);
tw += vd->weight[u];
} else
vbit_set(vd->vbm, u);
}
if (tw > 0.0) {
u = vdir_pick_by_weight(vd, w * tw, vd->vbm);
assert(u < vd->n_backend);
be = vd->backend[u];
CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
if (be->healthy(be, NULL, NULL))
break;
if (l == 0) {
vbm = vd->vbm;
for (v = 0; v < nbe; v++)
vbit_clr(vbm, v);
}
vbit_set(vbm, u);
nbe--;
tw -= vd->weight[u];
be = NULL;
}
vdir_unlock(vd);
return (be);
......
......@@ -49,4 +49,4 @@ void vdir_unlock(struct vdir *vd);
unsigned vdir_add_backend(struct vdir *, VCL_BACKEND be, double weight);
unsigned vdir_any_healthy(struct vdir *, const struct busyobj *,
double *changed);
VCL_BACKEND vdir_pick_be(struct vdir *, double w, unsigned nloops);
VCL_BACKEND vdir_pick_be(struct vdir *, double w);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment