[master] 18be02e Add a new director method "->resolve" which returns another backend to use.

Poul-Henning Kamp phk at FreeBSD.org
Tue Sep 23 14:30:30 CEST 2014


commit 18be02e3419c665b9d5b0a455abb56b66a1cfd10
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Sep 23 12:28:27 2014 +0000

    Add a new director method "->resolve" which returns another backend to use.
    
    This is called recursively until we get to the bottom of the pile.
    
    Doing it this way means that "pick one" directors dont need to know
    about other methods on directors and can concentrate on just picking.
    
    It also prevents us from eating up a lot of stack.

diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c
index fe25fbe..ccd4cf4 100644
--- a/bin/varnishd/cache/cache_backend.c
+++ b/bin/varnishd/cache/cache_backend.c
@@ -441,11 +441,16 @@ VDI_GetHdr(struct worker *wrk, struct busyobj *bo)
 	}
 
 	CHECK_OBJ_NOTNULL(bo->director, DIRECTOR_MAGIC);
+	while (bo->director != NULL && bo->director->resolve != NULL)
+		bo->director = bo->director->resolve(bo->director, wrk, bo);
 
-	if (bo->director->gethdrs != NULL)
-		return (bo->director->gethdrs(bo->director, wrk, bo));
-	else
-		return (vdi_simple_gethdrs(bo->director, wrk, bo));
+	if (bo->director == NULL) {
+		VSLb(bo->vsl, SLT_FetchError, "Backend selection failed");
+		return (-1);
+	}
+
+	AN(bo->director->gethdrs);
+	return (bo->director->gethdrs(bo->director, wrk, bo));
 }
 
 /*--------------------------------------------------------------------*/
diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h
index fe4bb15..5fa79bd 100644
--- a/bin/varnishd/cache/cache_backend.h
+++ b/bin/varnishd/cache/cache_backend.h
@@ -77,6 +77,8 @@ struct vrt_backend_probe;
 
 typedef struct vbc *vdi_getfd_f(const struct director *, struct busyobj *);
 typedef unsigned vdi_healthy_f(const struct director *, double *changed);
+typedef struct director *vdi_resolve_f(const struct director *,
+    struct worker *, struct busyobj *);
 typedef int vdi_gethdrs_f(const struct director *, struct worker *,
     struct busyobj *);
 
@@ -87,6 +89,7 @@ struct director {
 	char			*vcl_name;
 	vdi_getfd_f		*getfd;
 	vdi_healthy_f		*healthy;
+	vdi_resolve_f		*resolve;
 	vdi_gethdrs_f		*gethdrs;
 	void			*priv;
 };
diff --git a/lib/libvmod_directors/fall_back.c b/lib/libvmod_directors/fall_back.c
index edec2af..272864e 100644
--- a/lib/libvmod_directors/fall_back.c
+++ b/lib/libvmod_directors/fall_back.c
@@ -45,7 +45,7 @@ struct vmod_directors_fallback {
 };
 
 static unsigned __match_proto__(vdi_healthy)
-vmod_rr_healthy(const struct director *dir, double *changed)
+vmod_fallback_healthy(const struct director *dir, double *changed)
 {
 	struct vmod_directors_fallback *rr;
 
@@ -53,13 +53,17 @@ vmod_rr_healthy(const struct director *dir, double *changed)
 	return (vdir_any_healthy(rr->vd, changed));
 }
 
-static struct vbc * __match_proto__(vdi_getfd_f)
-vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
+static struct director * __match_proto__(vdi_resolve_f)
+vmod_fallback_resolve(const struct director *dir, struct worker *wrk,
+    struct busyobj *bo)
 {
 	struct vmod_directors_fallback *rr;
 	unsigned u;
 	VCL_BACKEND be = NULL;
 
+	CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
 	CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_FALLBACK_MAGIC);
 	vdir_lock(rr->vd);
 	for (u = 0; u < rr->vd->n_backend; u++) {
@@ -69,9 +73,9 @@ vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
 			break;
 	}
 	vdir_unlock(rr->vd);
-	if (u == rr->vd->n_backend || be == NULL)
-		return (NULL);
-	return (be->getfd(be, bo));
+	if (u == rr->vd->n_backend)
+		be = NULL;
+	return (be);
 }
 
 VCL_VOID __match_proto__()
@@ -86,7 +90,8 @@ vmod_fallback__init(const struct vrt_ctx *ctx,
 	ALLOC_OBJ(rr, VMOD_DIRECTORS_FALLBACK_MAGIC);
 	AN(rr);
 	*rrp = rr;
-	vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr);
+	vdir_new(&rr->vd, vcl_name, vmod_fallback_healthy,
+	    vmod_fallback_resolve, rr);
 }
 
 VCL_VOID __match_proto__()
diff --git a/lib/libvmod_directors/random.c b/lib/libvmod_directors/random.c
index 8ae36a7..a7e26d8 100644
--- a/lib/libvmod_directors/random.c
+++ b/lib/libvmod_directors/random.c
@@ -50,7 +50,7 @@ struct vmod_directors_random {
 };
 
 static unsigned __match_proto__(vdi_healthy)
-vmod_rr_healthy(const struct director *dir, double *changed)
+vmod_random_healthy(const struct director *dir, double *changed)
 {
 	struct vmod_directors_random *rr;
 
@@ -58,20 +58,22 @@ vmod_rr_healthy(const struct director *dir, double *changed)
 	return (vdir_any_healthy(rr->vd, changed));
 }
 
-static struct vbc * __match_proto__(vdi_getfd_f)
-vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
+static struct director * __match_proto__(vdi_resolve_f)
+vmod_random_resolve(const struct director *dir, struct worker *wrk,
+    struct busyobj *bo)
 {
 	struct vmod_directors_random *rr;
 	VCL_BACKEND be;
 	double r;
 
+	CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
 	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);
-	if (be == NULL)
-		return (NULL);
-	return (be->getfd(be, bo));
+	return (be);
 }
 
 VCL_VOID __match_proto__()
@@ -88,7 +90,8 @@ vmod_random__init(const struct vrt_ctx *ctx, struct vmod_directors_random **rrp,
 	rr->vbm = vbit_init(8);
 	AN(rr->vbm);
 	*rrp = rr;
-	vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr);
+	vdir_new(&rr->vd, vcl_name, vmod_random_healthy, vmod_random_resolve,
+	    rr);
 }
 
 VCL_VOID __match_proto__()
diff --git a/lib/libvmod_directors/round_robin.c b/lib/libvmod_directors/round_robin.c
index 629bbbf..581eef3 100644
--- a/lib/libvmod_directors/round_robin.c
+++ b/lib/libvmod_directors/round_robin.c
@@ -54,13 +54,17 @@ vmod_rr_healthy(const struct director *dir, double *changed)
 	return (vdir_any_healthy(rr->vd, changed));
 }
 
-static struct vbc * __match_proto__(vdi_getfd_f)
-vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
+static struct director * __match_proto__(vdi_resolve_f)
+vmod_rr_resolve(const struct director *dir, struct worker *wrk,
+    struct busyobj *bo)
 {
 	struct vmod_directors_round_robin *rr;
 	unsigned u;
 	VCL_BACKEND be = NULL;
 
+	CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
 	CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
 	vdir_lock(rr->vd);
 	for (u = 0; u < rr->vd->n_backend; u++) {
@@ -72,9 +76,9 @@ vmod_rr_getfd(const struct director *dir, struct busyobj *bo)
 			break;
 	}
 	vdir_unlock(rr->vd);
-	if (u == rr->vd->n_backend || be == NULL)
-		return (NULL);
-	return (be->getfd(be, bo));
+	if (u == rr->vd->n_backend)
+		be = NULL;
+	return (be);
 }
 
 VCL_VOID __match_proto__()
@@ -89,7 +93,7 @@ vmod_round_robin__init(const struct vrt_ctx *ctx,
 	ALLOC_OBJ(rr, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC);
 	AN(rr);
 	*rrp = rr;
-	vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr);
+	vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_resolve, rr);
 }
 
 VCL_VOID __match_proto__()
diff --git a/lib/libvmod_directors/vdir.c b/lib/libvmod_directors/vdir.c
index 75ea080..52cf4c4 100644
--- a/lib/libvmod_directors/vdir.c
+++ b/lib/libvmod_directors/vdir.c
@@ -52,7 +52,7 @@ vdir_expand(struct vdir *vd, unsigned n)
 
 void
 vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy_f *healthy,
-    vdi_getfd_f *getfd, void *priv)
+    vdi_resolve_f *resolve, void *priv)
 {
 	struct vdir *vd;
 
@@ -69,7 +69,7 @@ vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy_f *healthy,
 	REPLACE(vd->dir->vcl_name, vcl_name);
 	vd->dir->priv = priv;
 	vd->dir->healthy = healthy;
-	vd->dir->getfd = getfd;
+	vd->dir->resolve = resolve;
 	vd->vbm = vbit_init(8);
 	AN(vd->vbm);
 }
diff --git a/lib/libvmod_directors/vdir.h b/lib/libvmod_directors/vdir.h
index 583d6e1..5afb754 100644
--- a/lib/libvmod_directors/vdir.h
+++ b/lib/libvmod_directors/vdir.h
@@ -42,7 +42,7 @@ struct vdir {
 };
 
 void vdir_new(struct vdir **vdp, const char *vcl_name, vdi_healthy_f *healthy,
-    vdi_getfd_f *getfd, void *priv);
+    vdi_resolve_f *resolve, void *priv);
 void vdir_delete(struct vdir **vdp);
 void vdir_lock(struct vdir *vd);
 void vdir_unlock(struct vdir *vd);



More information about the varnish-commit mailing list