r3134 - trunk/varnish-cache/bin/varnishd

phk at projects.linpro.no phk at projects.linpro.no
Tue Aug 26 21:26:47 CEST 2008


Author: phk
Date: 2008-08-26 21:26:46 +0200 (Tue, 26 Aug 2008)
New Revision: 3134

Modified:
   trunk/varnish-cache/bin/varnishd/cache_dir_random.c
   trunk/varnish-cache/bin/varnishd/cache_dir_round_robin.c
Log:
Make the random and round-robin directors avoid backends which are
polled as unhealty.

This technically makes Varnish 2.0 "feature complete", but some further
polishing is to be expected.



Modified: trunk/varnish-cache/bin/varnishd/cache_dir_random.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_dir_random.c	2008-08-26 13:09:27 UTC (rev 3133)
+++ trunk/varnish-cache/bin/varnishd/cache_dir_random.c	2008-08-26 19:26:46 UTC (rev 3134)
@@ -50,7 +50,7 @@
 
 struct vdi_random_host {
 	struct backend		*backend;
-	unsigned		weight;
+	double			weight;
 };
 
 struct vdi_random {
@@ -61,25 +61,60 @@
 	unsigned		nhosts;
 };
 
-
 static struct vbe_conn *
 vdi_random_getfd(struct sess *sp)
 {
-	int i;
+	int i, j, k;
 	struct vdi_random *vs;
-	uint32_t r;
-	struct vdi_random_host *vh;
+	double r, s1, s2;
+	struct vbe_conn *vbe;
 
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 	CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
 	CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_RANDOM_MAGIC);
-	r = random();
-	r &= 0x7fffffff;
 
-	for (i = 0, vh = vs->hosts; i < vs->nhosts; vh++) 
-		if (r < vh->weight)
-			return (VBE_GetVbe(sp, vh->backend));
-	assert(0 == __LINE__);
+	k = 0;
+	for (k = 0; k < 4; ) {	/* XXX: 4 is arbitrary */
+
+		r = random() / 2147483648.0;	/* 2^31 */
+		assert(r >= 0.0 && r < 1.0);
+
+		s1 = 0.0;
+		j = 0;
+		for (i = 0; i < vs->nhosts; i++) {
+			if (!vs->hosts[i].backend->healthy)
+				continue;
+			s1 += vs->hosts[i].weight;
+			j++;
+		}	
+
+		if (j == 0)		/* No healthy hosts */
+			return (NULL);
+
+		r *= s1;
+
+		s2 = 0;
+		j = 0;
+		for (i = 0; i < vs->nhosts; i++)  {
+			if (!vs->hosts[i].backend->healthy)
+				continue;
+			s2 += vs->hosts[i].weight;
+			if (r > s2)
+				j = i + 1;
+		}
+		if (s2 != s1) {
+			/*
+			 * Health bit changed in an unusable way while we
+			 * worked the problem.  Usable changes are any that
+			 * result in the same sum we prepared for.
+			 */
+			continue;
+		}
+		vbe = VBE_GetVbe(sp, vs->hosts[j].backend);
+		if (vbe != NULL)
+			return (vbe);
+		k++;
+	} 
 	return (NULL);
 }
 
@@ -108,8 +143,7 @@
 	struct vdi_random *vs;
 	const struct vrt_dir_random_entry *te;
 	struct vdi_random_host *vh;
-	double s, a, b;
-	unsigned v;
+	double s;
 	int i;
 	
 	(void)cli;
@@ -130,24 +164,9 @@
 	te = t->members;
 	for (i = 0; i < t->nmember; i++, vh++, te++) {
 		assert(te->weight > 0.0);
-		s += te->weight;
+		vh->weight = te->weight;
 		vh->backend = VBE_AddBackend(cli, te->host);
 	}
 	vs->nhosts = t->nmember;
-
-	/* Normalize weights */
-	i = 0;
-	a = 0.0;
-	assert(s > 0.0);
-	for (te = t->members; i < t->nmember; te++, i++) {
-		/* First normalize the specified weight in FP */
-		b = te->weight / s;	/*lint !e795 not zero division */
-		/* Then accumulate to eliminate rounding errors */
-		a += b;
-		/* Convert to unsigned in random() range */
-		v = (unsigned)((1U<<31) * a);
-		vs->hosts[i].weight = v;
-	}
-	assert(vs->hosts[t->nmember - 1].weight > 0x7fffffff);
 	*bp = &vs->dir;
 }

Modified: trunk/varnish-cache/bin/varnishd/cache_dir_round_robin.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_dir_round_robin.c	2008-08-26 13:09:27 UTC (rev 3133)
+++ trunk/varnish-cache/bin/varnishd/cache_dir_round_robin.c	2008-08-26 19:26:46 UTC (rev 3134)
@@ -47,32 +47,41 @@
 /*--------------------------------------------------------------------*/
 
 struct vdi_round_robin_host {
-	struct backend		*backend;
+	struct backend			*backend;
 };
 
 struct vdi_round_robin {
-	unsigned		magic;
-#define VDI_ROUND_ROBIN_MAGIC	0x2114a178
-	struct director		dir;
+	unsigned			magic;
+#define VDI_ROUND_ROBIN_MAGIC		0x2114a178
+	struct director			dir;
 	struct vdi_round_robin_host	*hosts;
-	unsigned		nhosts;
-	unsigned		next_host;
+	unsigned			nhosts;
+	unsigned			next_host;
 };
 
 static struct vbe_conn *
 vdi_round_robin_getfd(struct sess *sp)
 {
+	int i;
 	struct vdi_round_robin *vs;
 	struct backend *backend;
+	struct vbe_conn *vbe;
 
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 	CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
 	CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_ROUND_ROBIN_MAGIC);
 
-	backend = vs->hosts[ vs->next_host ].backend;
-	vs->next_host = (vs->next_host + 1) % vs->nhosts;
+	for (i = 0; i < vs->nhosts; i++) {
+		backend = vs->hosts[vs->next_host].backend;
+		vs->next_host = (vs->next_host + 1) % vs->nhosts;
+		if (!backend->healthy)
+			continue;
+		vbe = VBE_GetVbe(sp, backend);
+		if (vbe != NULL)
+			return (vbe);
+	}
 
-	return (VBE_GetVbe(sp, backend));
+	return (NULL);
 }
 
 /*lint -e{818} not const-able */




More information about the varnish-commit mailing list