[master] a49d550 Always take the number of healthy backends into account when selecting a backend by weight.
Martin Blix Grydeland
martin at varnish-software.com
Mon Jan 12 16:38:20 CET 2015
commit a49d5507fdd2abc5cbd6245ae93e768722e96733
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date: Mon Jan 12 16:13:43 2015 +0100
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
diff --git a/lib/libvmod_directors/hash.c b/lib/libvmod_directors/hash.c
index e7b63a0..698e48d 100644
--- a/lib/libvmod_directors/hash.c
+++ b/lib/libvmod_directors/hash.c
@@ -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);
}
diff --git a/lib/libvmod_directors/random.c b/lib/libvmod_directors/random.c
index 4c1b462..415a8ad 100644
--- a/lib/libvmod_directors/random.c
+++ b/lib/libvmod_directors/random.c
@@ -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__()
diff --git a/lib/libvmod_directors/vdir.c b/lib/libvmod_directors/vdir.c
index 0ed64ec..8ebefa4 100644
--- a/lib/libvmod_directors/vdir.c
+++ b/lib/libvmod_directors/vdir.c
@@ -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);
diff --git a/lib/libvmod_directors/vdir.h b/lib/libvmod_directors/vdir.h
index 0d21e2f..e8107ab 100644
--- a/lib/libvmod_directors/vdir.h
+++ b/lib/libvmod_directors/vdir.h
@@ -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);
More information about the varnish-commit
mailing list