From: phk Date: Tue, 26 Aug 2008 19:26:46 +0000 (+0000) Subject: Make the random and round-robin directors avoid backends which are X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=390ebf1a1aacbab052072e13d7c8b2eb1fd74dfd;p=varnish 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. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3134 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/cache_dir_random.c b/varnish-cache/bin/varnishd/cache_dir_random.c index b4dd545c..dcb09ce8 100644 --- a/varnish-cache/bin/varnishd/cache_dir_random.c +++ b/varnish-cache/bin/varnishd/cache_dir_random.c @@ -50,7 +50,7 @@ struct vdi_random_host { struct backend *backend; - unsigned weight; + double weight; }; struct vdi_random { @@ -61,25 +61,60 @@ struct vdi_random { 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 @@ VRT_init_dir_random(struct cli *cli, struct director **bp, const struct vrt_dir_ 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 @@ VRT_init_dir_random(struct cli *cli, struct director **bp, const struct vrt_dir_ 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; } diff --git a/varnish-cache/bin/varnishd/cache_dir_round_robin.c b/varnish-cache/bin/varnishd/cache_dir_round_robin.c index 5304360e..6b468827 100644 --- a/varnish-cache/bin/varnishd/cache_dir_round_robin.c +++ b/varnish-cache/bin/varnishd/cache_dir_round_robin.c @@ -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; - - return (VBE_GetVbe(sp, backend)); + 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 (NULL); } /*lint -e{818} not const-able */