[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