[master] 90b058b Add a random director to VMOD.directors

Poul-Henning Kamp phk at varnish-cache.org
Tue Mar 12 15:22:06 CET 2013


commit 90b058b859833e740627b57998bf3b3511a8ab9b
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Mar 12 14:21:31 2013 +0000

    Add a random director to VMOD.directors

diff --git a/bin/varnishtest/tests/b00016.vtc b/bin/varnishtest/tests/b00016.vtc
index 17e38f4..93be72b 100644
--- a/bin/varnishtest/tests/b00016.vtc
+++ b/bin/varnishtest/tests/b00016.vtc
@@ -21,21 +21,23 @@ client c1 {
 } -run
 
 varnish v1 -vcl { 
-	director bar random {
-		{
-		.backend = {
-		 	.host = "${bad_ip}"; .port = "9080";
-		}
-		.weight = 1;
-		}
+	import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
+
+	backend b1 {
+		.host = "${bad_ip}"; .port = "9080";
+	}
+	sub vcl_init {
+		new bar = directors.random();
+		bar.add_backend(b1, 1);
 	}
 
 	sub vcl_recv {
-	    error 200 "ok";
+		set req.backend = bar.backend();
+		error 200 "ok";
 	}
 
 	sub vcl_error {
-	    set obj.http.X-Backend-Name = req.backend;
+		set obj.http.X-Backend-Name = req.backend;
 	}
 }
 
diff --git a/bin/varnishtest/tests/r00263.vtc b/bin/varnishtest/tests/r00263.vtc
index 79df874..8ae4bd7 100644
--- a/bin/varnishtest/tests/r00263.vtc
+++ b/bin/varnishtest/tests/r00263.vtc
@@ -1,18 +1,23 @@
 varnishtest "Test refcounting backends from director"
 
+# XXX: This test is probably not relevant with VMOD.directors
+
 varnish v1  -vcl {
+	import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
+
 	backend node1 { .host = "10.0.0.1"; .port = "80"; }
 	backend node2 { .host = "10.0.0.2"; .port = "80"; }
 	backend node3 { .host = "10.0.0.3"; .port = "80"; }
 
-	director cluster random {
-		{ .backend = node1; .weight = 1; }
-		{ .backend = node2; .weight = 1; }
-		{ .backend = node3; .weight = 1; }
+	sub vcl_init {
+		new cluster = directors.random();
+		cluster.add_backend(node1, 1);
+		cluster.add_backend(node2, 1);
+		cluster.add_backend(node3, 1);
 	}
 
 	sub vcl_recv {
-		set req.backend = cluster;
+		set req.backend = cluster.backend();
 	}
 } -start 
 
diff --git a/bin/varnishtest/tests/r00306.vtc b/bin/varnishtest/tests/r00306.vtc
index 079e994..c00badb 100644
--- a/bin/varnishtest/tests/r00306.vtc
+++ b/bin/varnishtest/tests/r00306.vtc
@@ -18,19 +18,23 @@ server s2 {
 } -start
 
 varnish v1 -vcl {
+
+	import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
+
 	backend s1 {
 		.host = "${s1_addr}"; .port = "${s1_port}";
 	}
 	backend s2 {
 		.host = "${s2_addr}"; .port = "${s2_port}";
 	}
-	director foo random {
-		{ .backend = s2; .weight = 1; }
-		{ .backend = s1; .weight = 1; }
+	sub vcl_init {
+		new foo = directors.random();
+		foo.add_backend(s1, 1);
+		foo.add_backend(s2, 1);
 	}
 
 	sub vcl_recv {
-		set req.backend = foo;
+		set req.backend = foo.backend();
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/r00722.vtc b/bin/varnishtest/tests/r00722.vtc
index 8d7dc24..2e41814 100644
--- a/bin/varnishtest/tests/r00722.vtc
+++ b/bin/varnishtest/tests/r00722.vtc
@@ -6,18 +6,33 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-	director foo random {
-		{ .backend = s1; .weight = 1; }
-		{ .backend = { .host = "${s1_addr}"; .port = "${s1_port}";} .weight =1; }
-		{ .backend = { .host = "${s1_addr}"; .port = "${s1_port}";} .weight =1; }
+	import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
+
+	backend b2 {
+		.host = "${s1_addr}"; .port = "${s1_port}";
+	}
+
+	backend b3 {
+		.host = "${s1_addr}"; .port = "${s1_port}";
+	}
+
+	sub vcl_init {
+		new foo = directors.random();
+		foo.add_backend(s1, 1);
+		foo.add_backend(b2, 1);
+		foo.add_backend(b3, 1);
 	}
 	sub vcl_recv {
-		set req.backend = foo;
+		set req.backend = foo.backend();
 	}
 } -start
 
+varnish v1 -cliok "vcl.list"
+varnish v1 -cliok "backend.list"
 
 varnish v1 -vcl+backend { }
+varnish v1 -cliok "vcl.list"
+varnish v1 -cliok "backend.list"
 
 varnish v1 -cliok "vcl.list"
 varnish v1 -cliok "vcl.discard vcl1"
diff --git a/bin/varnishtest/tests/v00007.vtc b/bin/varnishtest/tests/v00007.vtc
index 5768c02..d0c37f8 100644
--- a/bin/varnishtest/tests/v00007.vtc
+++ b/bin/varnishtest/tests/v00007.vtc
@@ -8,13 +8,16 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-	director foo random {
-		{ .backend = s1; .weight = 1; }
-		{ .weight = 1; .backend = s1; }
+	import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so";
+
+	sub vcl_init {
+		new foo = directors.random();
+		foo.add_backend(s1, 1);
+		foo.add_backend(s1, 1);
 	}
 
 	sub vcl_recv {
-		set req.backend = foo;
+		set req.backend = foo.backend();
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/v00022.vtc b/bin/varnishtest/tests/v00022.vtc
index 15b9a90..5bfb1fe 100644
--- a/bin/varnishtest/tests/v00022.vtc
+++ b/bin/varnishtest/tests/v00022.vtc
@@ -32,15 +32,18 @@ server s4 {
 } -start
 
 varnish v1 -vcl+backend {
-	director foo random {
-		{ .backend = s1; .weight = 1; }
-		{ .backend = s2; .weight = 1; }
-		{ .backend = s3; .weight = 1; }
-		{ .backend = s4; .weight = 1; }
+	import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
+
+	sub vcl_init {
+		new foo = directors.random();
+		foo.add_backend(s1, 1);
+		foo.add_backend(s2, 1);
+		foo.add_backend(s3, 1);
+		foo.add_backend(s4, 1);
 	}
 
 	sub vcl_recv {
-		set req.backend = foo;
+		set req.backend = foo.backend();
 		return(pass);
 	}
 } -start
diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am
index 2c879c8..b222026 100644
--- a/lib/libvmod_directors/Makefile.am
+++ b/lib/libvmod_directors/Makefile.am
@@ -17,6 +17,7 @@ libvmod_directors_la_SOURCES = \
 	vdir.c \
 	vdir.h \
 	fall_back.c \
+	random.c \
 	round_robin.c
 
 nodist_libvmod_directors_la_SOURCES = \
diff --git a/lib/libvmod_directors/random.c b/lib/libvmod_directors/random.c
new file mode 100644
index 0000000..32f829a
--- /dev/null
+++ b/lib/libvmod_directors/random.c
@@ -0,0 +1,148 @@
+/*-
+ * Copyright (c) 2013 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "cache/cache.h"
+#include "cache/cache_backend.h"
+
+#include "vrt.h"
+#include "vbm.h"
+
+#include "vdir.h"
+
+#include "vcc_if.h"
+
+struct vmod_directors_random {
+	unsigned				magic;
+#define VMOD_DIRECTORS_RANDOM_MAGIC		0x4732d092
+	struct vdir				*vd;
+	unsigned				nloops;
+	struct vbitmap				*vbm;
+};
+
+static unsigned __match_proto__(vdi_healthy)
+vmod_rr_healthy(const struct director *dir, const struct req *req)
+{
+	struct vmod_directors_random *rr;
+
+	CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC);
+	return (vdir_any_healthy(rr->vd, req));
+}
+
+static struct vbc * __match_proto__(vdi_getfd_f)
+vmod_rr_getfd(const struct director *dir, struct req *req)
+{
+	struct vmod_directors_random *rr;
+	struct vbitmap *vbm = NULL;
+	unsigned u, v, l;
+	VCL_BACKEND be = NULL;
+	double tw;
+	int nbe;
+	double r;
+
+	CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC);
+	tw = rr->vd->total_weight;
+	nbe = rr->vd->n_backend;
+	r = scalbn(random(), -31);
+	assert(r >= 0.0 && r <= 1.0);
+	vdir_lock(rr->vd);
+	for (l = 0; nbe > 0 && tw > 0.0 && l < rr->nloops; l++) {
+		u = vdir_pick_by_weight(rr->vd, r * tw, vbm);
+		be = rr->vd->backend[u];
+		CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
+		if (be->healthy(be, req))
+			break;
+		if (l == 0) {
+			vbm = rr->vbm;
+			for (v = 0; v < nbe; v++)
+				vbit_clr(vbm, v);
+		}
+		vbit_set(vbm, u);
+		nbe--;
+		tw -= rr->vd->weight[u];
+		be = NULL;
+	}
+	vdir_unlock(rr->vd);
+	if (be == NULL)
+		return (NULL);
+	return (be->getfd(be, req));
+}
+
+VCL_VOID __match_proto__()
+vmod_random__init(struct req *req, struct vmod_directors_random **rrp,
+    const char *vcl_name)
+{
+	struct vmod_directors_random *rr;
+
+	AZ(req);
+	AN(rrp);
+	AZ(*rrp);
+	ALLOC_OBJ(rr, VMOD_DIRECTORS_RANDOM_MAGIC);
+	AN(rr);
+	rr->vbm = vbit_init(8);
+	AN(rr->vbm);
+	rr->nloops = 3; //
+	*rrp = rr;
+	vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr);
+}
+
+VCL_VOID __match_proto__()
+vmod_random__fini(struct req *req, struct vmod_directors_random **rrp)
+{
+	struct vmod_directors_random *rr;
+
+	AZ(req);
+	rr = *rrp;
+	*rrp = NULL;
+	CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC);
+	vdir_delete(&rr->vd);
+	vbit_destroy(rr->vbm);
+	FREE_OBJ(rr);
+}
+
+VCL_VOID __match_proto__()
+vmod_random_add_backend(struct req *req,
+    struct vmod_directors_random *rr, VCL_BACKEND be, double w)
+{
+
+	(void)req;
+	CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC);
+	(void)vdir_add_backend(rr->vd, be, w);
+}
+
+VCL_BACKEND __match_proto__()
+vmod_random_backend(struct req *req, struct vmod_directors_random *rr)
+{
+	(void)req;
+	CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC);
+	return (rr->vd->dir);
+}
diff --git a/lib/libvmod_directors/vdir.c b/lib/libvmod_directors/vdir.c
index be8f340..c8d6fe5 100644
--- a/lib/libvmod_directors/vdir.c
+++ b/lib/libvmod_directors/vdir.c
@@ -34,6 +34,7 @@
 #include "cache/cache_backend.h"
 
 #include "vrt.h"
+#include "vbm.h"
 
 #include "vdir.h"
 
@@ -118,6 +119,7 @@ vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight)
 	u = vd->n_backend++;
 	vd->backend[u] = be;
 	vd->weight[u] = weight;
+	vd->total_weight += weight;
 	vdir_unlock(vd);
 	return (u);
 }
@@ -142,3 +144,24 @@ vdir_any_healthy(struct vdir *vd, const struct req *req)
 	vdir_unlock(vd);
 	return (retval);
 }
+
+unsigned
+vdir_pick_by_weight(const struct vdir *vd, double w,
+    const struct vbitmap *blacklist)
+{
+	double a = 0.0;
+	VCL_BACKEND be = NULL;
+	unsigned u;
+
+	for (u = 0; u < vd->n_backend; u++) {
+		be = vd->backend[u];
+		CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
+		if (blacklist != NULL && vbit_test(blacklist, u))
+			continue;
+		a += vd->weight[u];
+		if (w < a)
+			return (u);
+	}
+	WRONG("");
+}
+
diff --git a/lib/libvmod_directors/vdir.h b/lib/libvmod_directors/vdir.h
index 1b588b4..7f42e70 100644
--- a/lib/libvmod_directors/vdir.h
+++ b/lib/libvmod_directors/vdir.h
@@ -26,6 +26,8 @@
  * SUCH DAMAGE.
  */
 
+struct vbitmap;
+
 struct vdir {
 	unsigned				magic;
 #define VDIR_MAGIC				0x99f4b726
@@ -34,6 +36,7 @@ struct vdir {
 	unsigned				l_backend;
 	VCL_BACKEND				*backend;
 	double					*weight;
+	double					total_weight;
 	struct director				*dir;
 };
 
@@ -44,3 +47,5 @@ void vdir_lock(struct vdir *vd);
 void vdir_unlock(struct vdir *vd);
 unsigned vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight);
 unsigned vdir_any_healthy(struct vdir *vd, const struct req *);
+unsigned vdir_pick_by_weight(const struct vdir *vd, double w,
+    const struct vbitmap *blacklist);
diff --git a/lib/libvmod_directors/vmod.vcc b/lib/libvmod_directors/vmod.vcc
index 2945559..b74057d 100644
--- a/lib/libvmod_directors/vmod.vcc
+++ b/lib/libvmod_directors/vmod.vcc
@@ -36,3 +36,8 @@ Object fallback() {
 	Method VOID .add_backend(BACKEND)
 	Method BACKEND .backend()
 }
+
+Object random() {
+	Method VOID .add_backend(BACKEND, REAL)
+	Method BACKEND .backend()
+}



More information about the varnish-commit mailing list