r2437 - in trunk/varnish-cache: bin/varnishd include lib/libvcl

phk at projects.linpro.no phk at projects.linpro.no
Wed Feb 6 16:19:49 CET 2008


Author: phk
Date: 2008-02-06 16:19:49 +0100 (Wed, 06 Feb 2008)
New Revision: 2437

Added:
   trunk/varnish-cache/bin/varnishd/cache_dir_simple.c
Modified:
   trunk/varnish-cache/bin/varnishd/Makefile.am
   trunk/varnish-cache/bin/varnishd/cache.h
   trunk/varnish-cache/bin/varnishd/cache_backend.c
   trunk/varnish-cache/bin/varnishd/cache_backend_random.c
   trunk/varnish-cache/bin/varnishd/cache_backend_simple.c
   trunk/varnish-cache/bin/varnishd/cache_center.c
   trunk/varnish-cache/bin/varnishd/cache_fetch.c
   trunk/varnish-cache/bin/varnishd/cache_http.c
   trunk/varnish-cache/bin/varnishd/cache_main.c
   trunk/varnish-cache/bin/varnishd/cache_panic.c
   trunk/varnish-cache/bin/varnishd/cache_vcl.c
   trunk/varnish-cache/bin/varnishd/cache_vrt.c
   trunk/varnish-cache/include/vcl.h
   trunk/varnish-cache/include/vrt.h
   trunk/varnish-cache/include/vrt_obj.h
   trunk/varnish-cache/lib/libvcl/vcc_backend.c
   trunk/varnish-cache/lib/libvcl/vcc_compile.c
   trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c
   trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl
   trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl
Log:
First part of major backend overhaul.

*** Please do not use -trunk in production until I say so again ***

I have not entirely decided in the precise terminology, so the following
may sound a lot more complicated than it really is:

In VCL we can now have "backends" and "directors" both of which we
treat as a "backend".

When we define backends and directors in VCL, they refer to "backend
hosts" which is just another way to say "hostname+portname" but later
these will grow other parameters (max connections etc).

A director is a piece of code that selects a "backend host" somehow,
"random" and "round-robin" are the first algorithms.  A backend
can still be specified directly of course, that's the "simple director"
that always return the same "backend host".

This is probably where an example is in order:


	/* A backend as we know it */
	backend b1 {
		.host = "fs";
		.port = "80";
	}

	/* A director */
	director b2 random {
		{
			/* We can refer to named backends */
			.backend        = b1;
			.weight         = 7;
		}
		{
			/* Or define them inline */
			.backend        = {
				.host = "fs2";
			}
			.weight         = 3;
		}
	}

	sub vcl_recv {
		if (req.url ~ "\[[a-z]]") {
			set req.backend = b2;
		} else {
			set req.backend = b1;
		}
	}

This results in quite a lot of changes in the C code, VRT API and
VCL compiler, the major thrust being:

Directors like "simple" and "random" will not have to think about
the actual connections to the backends, but just concentrate on
selecting which backend should be used.

When a new VCL is loaded, it will instantiate all directors, but
try to reuse any preexisting "backend hosts" (which we still
call "backend" in the C code).

This is simple for a backend like "b1" in the example above, but
sligthly more complex for the backend inlined in b2.  The VCL
compiler solves this, by qualifying the ident string for the inlined
backend host with the prefix "b2 random :: 2 :: ", so that a reload
of the same director with the same (unchanged) inline backend host
will match, but none other will.

One implication of instantiating all directors for every VCL load,
is that private statistics cannot be reused, but stats on the
backend host can.  This is likely a very fine point of no consequence.

Once the backend is selected by the director, the generic code in
cache_backend.c will cope with reusing the connection pool,
establishing connections and all that, moving most of the nastyness
out of directors, leaving cache_dir_simple.c with only 96 lines of
code, of which the license is a large fraction.

Until now, we have done automatic DNS re-lookups, but they seem to
cause more grief than advantage (I suspect some of the DNS lookups
to be resposible for long timeouts), so that will be dropped, and
instead we might add an explicit CLI command for this later.

The code as here committed can handle a couple of simple requests,
but there are a large number of INCOMPL()'s that need to be resolved
before this is ready for prime time again.




Modified: trunk/varnish-cache/bin/varnishd/Makefile.am
===================================================================
--- trunk/varnish-cache/bin/varnishd/Makefile.am	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/Makefile.am	2008-02-06 15:19:49 UTC (rev 2437)
@@ -18,6 +18,7 @@
 	cache_ban.c \
 	cache_center.c \
 	cache_cli.c \
+	cache_dir_simple.c \
 	cache_expire.c \
 	cache_fetch.c \
 	cache_hash.c \

Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache.h	2008-02-06 15:19:49 UTC (rev 2437)
@@ -76,6 +76,7 @@
 struct workreq;
 struct addrinfo;
 struct esi_bit;
+struct vrt_backend;
 
 /*--------------------------------------------------------------------*/
 
@@ -345,6 +346,7 @@
 
 	VTAILQ_ENTRY(sess)	list;
 
+	struct director		*director;
 	struct backend		*backend;
 	struct bereq		*bereq;
 	struct object		*obj;
@@ -364,6 +366,23 @@
 	const char		**hashptr;
 };
 
+/* -------------------------------------------------------------------
+ * A director is a piece of code which selects one of possibly multiple
+ * backends to use.
+ */
+
+typedef struct backend *vdi_choose_f(struct sess *sp);
+typedef void vdi_fini_f(struct director *d);
+
+struct director {
+	unsigned		magic;
+#define DIRECTOR_MAGIC		0x3336351d
+	const char		*name;
+	vdi_choose_f		*choose;
+	vdi_fini_f		*fini;
+	void			*priv;
+};
+
 /* -------------------------------------------------------------------*/
 
 /* Backend connection */
@@ -376,46 +395,6 @@
 	void			*priv;
 };
 
-
-/* Backend method */
-typedef struct vbe_conn *vbe_getfd_f(const struct sess *sp);
-typedef void vbe_close_f(struct worker *w, struct vbe_conn *vc);
-typedef void vbe_recycle_f(struct worker *w, struct vbe_conn *vc);
-typedef void vbe_init_f(void);
-typedef const char *vbe_gethostname_f(const struct backend *);
-typedef void vbe_cleanup_f(const struct backend *);
-typedef void vbe_updatehealth_f(const struct sess *sp, const struct vbe_conn *vc, int);
-
-struct backend_method {
-	const char		*name;
-	vbe_getfd_f		*getfd;
-	vbe_close_f		*close;
-	vbe_recycle_f		*recycle;
-	vbe_cleanup_f		*cleanup;
-	vbe_gethostname_f	*gethostname;
-	vbe_updatehealth_f	*updatehealth;
-	vbe_init_f		*init;
-};
-
-/* Backend indstance */
-struct backend {
-	unsigned		magic;
-#define BACKEND_MAGIC		0x64c4c7c6
-	char			*vcl_name;
-
-	VTAILQ_ENTRY(backend)	list;
-	int			refcount;
-	pthread_mutex_t		mtx;
-
-	struct backend_method	*method;
-	const char 		*ident;
-	void			*priv;
-
-	int			health;
-	double			last_check;
-	int			minute_limit;
-};
-
 /*
  * NB: This list is not locked, it is only ever manipulated from the
  * cachers CLI thread.
@@ -435,7 +414,7 @@
 /* cache_backend.c */
 
 void VBE_Init(void);
-struct vbe_conn *VBE_GetFd(const struct sess *sp);
+struct vbe_conn *VBE_GetFd(struct sess *sp);
 void VBE_ClosedFd(struct worker *w, struct vbe_conn *vc);
 void VBE_RecycleFd(struct worker *w, struct vbe_conn *vc);
 struct bereq * VBE_new_bereq(void);
@@ -443,7 +422,7 @@
 extern struct backendlist backendlist;
 void VBE_DropRef(struct backend *);
 void VBE_DropRefLocked(struct backend *);
-int VBE_AddBackend(struct backend_method *method, const char *ident, struct backend **be);
+struct backend *VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb);
 struct vbe_conn *VBE_NewConn(void);
 void VBE_ReleaseConn(struct vbe_conn *);
 void VBE_UpdateHealth(const struct sess *sp, const struct vbe_conn *, int);
@@ -452,11 +431,6 @@
 int VBE_TryConnect(const struct sess *sp, const struct addrinfo *ai);
 int VBE_CheckFd(int fd);
 
-/* cache_backend_simple.c */
-extern struct backend_method	backend_method_simple;
-extern struct backend_method	backend_method_random;
-extern struct backend_method	backend_method_round_robin;
-
 /* cache_ban.c */
 void AddBan(const char *, int hash);
 void BAN_Init(void);

Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_backend.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_backend.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -32,6 +32,7 @@
  *
  */
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -43,7 +44,31 @@
 #include "heritage.h"
 #include "shmlog.h"
 #include "cache.h"
+#include "vrt.h"
+#include "cli_priv.h"
 
+/* Backend indstance */
+struct backend {
+	unsigned		magic;
+#define BACKEND_MAGIC		0x64c4c7c6
+	char			*vcl_name;
+
+	struct vrt_backend	vrt[1];
+
+	VTAILQ_ENTRY(backend)	list;
+	int			refcount;
+	pthread_mutex_t		mtx;
+
+	const char 		*ident;
+	struct addrinfo		*ai;
+	struct addrinfo		*last_ai;
+
+	VTAILQ_HEAD(, vbe_conn)	connlist;
+
+	int			health;
+	double			last_check;
+};
+
 static VTAILQ_HEAD(,bereq) bereq_head = VTAILQ_HEAD_INITIALIZER(bereq_head);
 static VTAILQ_HEAD(,vbe_conn) vbe_head = VTAILQ_HEAD_INITIALIZER(vbe_head);
 
@@ -217,20 +242,27 @@
 VBE_DropRefLocked(struct backend *b)
 {
 	int i;
+	struct vbe_conn *vbe, *vbe2;
 
 	CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
 
 	i = --b->refcount;
-	if (i == 0) {
-		ASSERT_CLI();	/* XXX: ?? */
-		VTAILQ_REMOVE(&backendlist, b, list);
-	}
 	UNLOCK(&b->mtx);
 	if (i)
 		return;
+
+	ASSERT_CLI();	/* XXX: ?? */
+	VTAILQ_REMOVE(&backendlist, b, list);
+	VTAILQ_FOREACH_SAFE(vbe, &b->connlist, list, vbe2) {
+		VTAILQ_REMOVE(&b->connlist, vbe, list);
+		if (vbe->fd >= 0)
+			AZ(close(vbe->fd));
+		FREE_OBJ(vbe);
+	}
+	free(TRUST_ME(b->vrt->ident));
+	free(TRUST_ME(b->vrt->hostname));
+	free(TRUST_ME(b->vrt->portname));
 	b->magic = 0;
-	b->method->cleanup(b);
-	free(b->vcl_name);
 	free(b);
 }
 
@@ -244,17 +276,116 @@
 	VBE_DropRefLocked(b);
 }
 
+/*--------------------------------------------------------------------
+ * Try to get a socket connected to one of the addresses on the list.
+ * We start from the cached "last good" address and try all items on
+ * the list exactly once.
+ * If a new DNS lookup is made while we try, we start over and try the
+ * new list exactly once.
+ */
+
+static int
+bes_conn_try_list(const struct sess *sp, struct backend *bp)
+{
+	struct addrinfo *ai, *from;
+	int s, loops;
+
+	CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
+	if (bp->last_ai == NULL)
+		return (-1);
+	AN(bp->ai);
+
+	/* Called with lock held */
+	loops = 0;
+	ai = from = bp->last_ai;
+	while (1) {
+
+		/* NB: releases/acquires backend lock */
+		s = VBE_TryConnect(sp, ai);
+
+		if (s >= 0) { 
+			bp->last_ai = ai;
+			return (s);
+		}
+
+		/* Try next one */
+		ai = ai->ai_next;
+		if (ai == NULL) {
+			loops++;
+			ai = bp->ai;
+		}
+		if (loops == 1 && ai == from)
+			return (-1);
+	}
+}
+
+
 /*--------------------------------------------------------------------*/
 
+static int
+bes_conn_try(const struct sess *sp, struct backend *bp)
+{
+	int s;
+
+	LOCK(&bp->mtx);
+
+	s = bes_conn_try_list(sp, bp);
+	if (s >= 0) {
+		bp->refcount++;
+		UNLOCK(&bp->mtx);
+		return (s);
+	}
+	UNLOCK(&bp->mtx);
+	return (-1);
+}
+
+/*--------------------------------------------------------------------*/
+
 struct vbe_conn *
-VBE_GetFd(const struct sess *sp)
+VBE_GetFd(struct sess *sp)
 {
+	struct backend *bp;
+	struct vbe_conn *vc;
 
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
-	AN(sp->backend->method);
-	AN(sp->backend->method->getfd);
-	return(sp->backend->method->getfd(sp));
+	CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
+	bp = sp->director->choose(sp);
+	CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
+	sp->backend = bp;
+
+	while (1) {
+		LOCK(&bp->mtx);
+		vc = VTAILQ_FIRST(&bp->connlist);
+		if (vc != NULL) {
+			bp->refcount++;
+			assert(vc->backend == bp);
+			assert(vc->fd >= 0);
+			VTAILQ_REMOVE(&bp->connlist, vc, list);
+		}
+		UNLOCK(&bp->mtx);
+		if (vc == NULL)
+			break;
+		if (VBE_CheckFd(vc->fd)) {
+			/* XXX locking of stats */
+			VSL_stats->backend_reuse += 1;
+			VSL_stats->backend_conn++;
+			return (vc);
+		}
+		VBE_ClosedFd(sp->wrk, vc);
+	}
+
+	vc = VBE_NewConn();
+	assert(vc->fd == -1);
+	AZ(vc->backend);
+	vc->fd = bes_conn_try(sp, bp);
+	if (vc->fd < 0) {
+		VBE_ReleaseConn(vc);
+		VSL_stats->backend_fail++;
+		return (NULL);
+	}
+	vc->backend = bp;
+	VSL_stats->backend_conn++;
+	return (vc);
 }
 
 /* Close a connection ------------------------------------------------*/
@@ -263,13 +394,19 @@
 VBE_ClosedFd(struct worker *w, struct vbe_conn *vc)
 {
 	struct backend *b;
+	int i;
 
 	CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC);
 	CHECK_OBJ_NOTNULL(vc->backend, BACKEND_MAGIC);
 	b = vc->backend;
-	AN(b->method);
-	AN(b->method->close);
-	b->method->close(w, vc);
+	assert(vc->fd >= 0);
+	WSL(w, SLT_BackendClose, vc->fd, "%s", vc->backend->vcl_name);
+	i = close(vc->fd);
+	assert(i == 0 || errno == ECONNRESET || errno == ENOTCONN);
+	vc->fd = -1;
+	VBE_DropRef(vc->backend);
+	vc->backend = NULL;
+	VBE_ReleaseConn(vc);
 	CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
 }
 
@@ -278,15 +415,18 @@
 void
 VBE_RecycleFd(struct worker *w, struct vbe_conn *vc)
 {
-	struct backend *b;
+	struct backend *bp;
 
 	CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC);
 	CHECK_OBJ_NOTNULL(vc->backend, BACKEND_MAGIC);
-	b = vc->backend;
-	AN(b->method);
-	AN(b->method->recycle);
-	b->method->recycle(w, vc);
-	CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
+	assert(vc->fd >= 0);
+	bp = vc->backend;
+	WSL(w, SLT_BackendReuse, vc->fd, "%s", vc->backend->vcl_name);
+	LOCK(&vc->backend->mtx);
+	VSL_stats->backend_recycle++;
+	VTAILQ_INSERT_HEAD(&bp->connlist, vc, list);
+	VBE_DropRefLocked(vc->backend);
+	CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
 }
 
 /* Update health ----------------------------------------------------*/
@@ -296,6 +436,11 @@
 void
 VBE_UpdateHealth(const struct sess *sp, const struct vbe_conn *vc, int a)
 {
+	(void)sp;
+	(void)vc;
+	(void)a;
+#if 0
+	INCOMPL();
 	struct backend *b;
 
 	if (vc != NULL) {
@@ -312,16 +457,47 @@
 	if(b->method->updatehealth != NULL)
 		b->method->updatehealth(sp, vc, a);
 	CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
+#endif
 }
 
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * DNS lookup of backend host/port
+ */
 
 static void
-VBE_AddBackendMethod(const struct backend_method *bem)
+vbe_dns_lookup(struct cli *cli, struct backend *bp)
 {
+	int error;
+	struct addrinfo *res, hint, *old;
 
-	if (bem->init != NULL)
-		bem->init();
+	CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
+
+	memset(&hint, 0, sizeof hint);
+	hint.ai_family = PF_UNSPEC;
+	hint.ai_socktype = SOCK_STREAM;
+	res = NULL;
+	error = getaddrinfo(bp->vrt->hostname, bp->vrt->portname,
+	    &hint, &res);
+	if (error) {
+		if (res != NULL)
+			freeaddrinfo(res);
+		/*
+		 * We cannot point to the source code any more, it may
+		 * be long gone from memory.   We already checked over in
+		 * the VCL compiler, so this is only relevant for refreshes.
+		 * XXX: which we do when exactly ?
+		 */
+		cli_out(cli, "DNS(/hosts) lookup failed for (%s/%s): %s",
+		    bp->vrt->hostname, bp->vrt->portname, gai_strerror(error));
+		return;
+	}
+	LOCK(&bp->mtx);
+	old = bp->ai;
+	bp->ai = res;
+	bp->last_ai = res;
+	UNLOCK(&bp->mtx);
+	if (old != NULL)
+		freeaddrinfo(old);
 }
 
 /*--------------------------------------------------------------------
@@ -331,51 +507,74 @@
  * and return zero.
  */
 
-int
-VBE_AddBackend(struct backend_method *method, const char *ident, struct backend **be)
+struct backend *
+VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb)
 {
 	struct backend *b;
 
+	AN(vb->hostname);
+	AN(vb->portname);
+	AN(vb->ident);
+	(void)cli;
 	ASSERT_CLI();
 	VTAILQ_FOREACH(b, &backendlist, list) {
 		CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
-		if (b->method != method)
+		if (strcmp(b->ident, vb->ident))
 			continue;
-		if (strcmp(b->ident, ident))
-			continue;
 		b->refcount++;
-		*be = b;
-		return (1);
+		return (b);
 	}
 
 	b = calloc(sizeof *b, 1);
 	XXXAN(b);
 	b->magic = BACKEND_MAGIC;
-	b->method = method;
-	b->ident = strdup(ident);
-	XXXAN(b->ident);
+	VTAILQ_INIT(&b->connlist);
 
+	memcpy(b->vrt, vb, sizeof *vb);
+	/*
+	 * This backend may live longer than the VCL that instantiated it
+	 * so we cannot simply reference the VCL's copy of the strings.
+	 */
+	b->vrt->ident = strdup(vb->ident);
+	XXXAN(b->vrt->ident);
+	b->vrt->hostname = strdup(vb->hostname);
+	XXXAN(b->vrt->hostname);
+	b->vrt->portname = strdup(vb->portname);
+	XXXAN(b->vrt->portname);
+
 	MTX_INIT(&b->mtx);
 	b->refcount = 1;
 
+	vbe_dns_lookup(cli, b);
+
 	b->last_check = TIM_mono();
-	b->minute_limit = 1;
 
+	vbe_dns_lookup(cli, b);
+
 	VTAILQ_INSERT_TAIL(&backendlist, b, list);
-	*be = b;
-	return (0);
+	return (b);
 }
 
+
 /*--------------------------------------------------------------------*/
 
 void
-VBE_Init(void)
+VRT_fini_dir(struct cli *cli, struct director *b)
 {
 
-	MTX_INIT(&VBE_mtx);
-	VBE_AddBackendMethod(&backend_method_simple);
-	VBE_AddBackendMethod(&backend_method_random);
+	ASSERT_CLI();
 #if 0
-	VBE_AddBackendMethod(&backend_method_round_robin);
+	VBE_DropRef(b);	
+#else
+	(void)b;
+	(void)cli;
 #endif
 }
+/*--------------------------------------------------------------------*/
+
+void
+VBE_Init(void)
+{
+
+	MTX_INIT(&VBE_mtx);
+}

Modified: trunk/varnish-cache/bin/varnishd/cache_backend_random.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_backend_random.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_backend_random.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -45,6 +45,7 @@
 #include "vrt.h"
 
 
+#if 0
 struct ber {
 	unsigned		magic;
 #define BER_MAGIC		0x645b03f4
@@ -434,22 +435,27 @@
 	.cleanup =		ber_Cleanup,
 };
 
+#endif
+
 /*--------------------------------------------------------------------*/
 
 void
-VRT_init_random_backend(struct backend **bp, const struct vrt_dir_random *t)
+VRT_init_dir_random(struct cli *cli, struct director **bp, const struct vrt_dir_random *t)
 {
-	struct backend *b;
+	(void)cli;
 	(void)bp;
 	(void)t;
+	
 
+#if 0
+	struct backend *b;
+
 	if (VBE_AddBackend(&backend_method_random, t->ident, bp))
 		return;		/* reuse existing backend */
 
-	b = *bp;
+	bp = *bp;
 	AN(t->name);
 	REPLACE(b->vcl_name, t->name);
-#if 0
 	struct backend *b;
 	struct ber *ber;
 	struct vrt_backend_entry *be;

Modified: trunk/varnish-cache/bin/varnishd/cache_backend_simple.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_backend_simple.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_backend_simple.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -44,6 +44,8 @@
 #include "cache.h"
 #include "vrt.h"
 
+#if 0
+
 struct bes {
 	unsigned		magic;
 #define BES_MAGIC		0x015e17ac
@@ -343,55 +345,5 @@
 	return (bes->hostname);
 }
 
-/*--------------------------------------------------------------------*/
 
-struct backend_method backend_method_simple = {
-	.name =			"simple",
-	.getfd =		bes_GetFd,
-	.close =		bes_ClosedFd,
-	.recycle =		bes_RecycleFd,
-	.gethostname =		bes_GetHostname,
-	.cleanup =		bes_Cleanup,
-};
-
-/*--------------------------------------------------------------------*/
-
-void
-VRT_init_simple_backend(struct backend **bp, const struct vrt_simple_backend *t)
-{
-	struct backend *b;
-	struct bes *bes;
-	const char *p;
-	
-	if (VBE_AddBackend(&backend_method_simple, t->ident, bp))
-		return;		/* ref to existing backend */
-
-	b = *bp;
-	AN(t->name);
-	REPLACE(b->vcl_name, t->name);
-
-	bes = calloc(sizeof *bes, 1);
-	XXXAN(bes);
-	bes->magic = BES_MAGIC;
-
-	b->priv = bes;
-
-	bes->dnsttl = 300;
-
-	AN(t->host->portname);
-	REPLACE(bes->portname, t->host->portname);
-
-	AN(t->host->hostname);
-	REPLACE(bes->hostname, t->host->hostname);
-
-	/*
-	 * The VCL compiler already did a lookup, but we'll do another one
-	 * here, just in case...
-	 */
-	LOCK(&b->mtx);
-	p = bes_dns_lookup(b);
-	UNLOCK(&b->mtx);
-	if (p != NULL)
-		printf("Warning: could not lookup backend %s (%s:%s): %s",
-		    b->vcl_name, bes->hostname, bes->portname, p);
-}
+#endif

Modified: trunk/varnish-cache/bin/varnishd/cache_center.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_center.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_center.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -195,7 +195,12 @@
 
 	AZ(sp->obj);
 	AZ(sp->bereq);
-	sp->backend = NULL;
+	sp->director = NULL;
+	sp->backend = NULL;		/*
+					 * XXX: we may want to leave this
+					 * behind to hint directors ?
+					 */
+					
 	if (sp->vcl != NULL) {
 		if (sp->wrk->vcl != NULL)
 			VCL_Rel(&sp->wrk->vcl);
@@ -320,9 +325,9 @@
 	CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC);
 
 	AN(sp->bereq);
-	CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
 	i = Fetch(sp);
-	CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
 
 	if (!i)
 		RFC2616_cache_policy(sp, sp->obj->http);	/* XXX -> VCL */
@@ -841,9 +846,9 @@
 	sp->doclose = http_DoConnection(sp->http);
 
 	/* By default we use the first backend */
-	AZ(sp->backend);
-	sp->backend = sp->vcl->backend[0];
-	CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
+	AZ(sp->director);
+	sp->director = sp->vcl->director[0];
+	CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
 
 	/* XXX: Handle TRACE & OPTIONS of Max-Forwards = 0 */
 
@@ -879,7 +884,7 @@
 		CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
 		CHECK_OBJ_ORNULL(w->nobj, OBJECT_MAGIC);
 		CHECK_OBJ_ORNULL(w->nobjhead, OBJHEAD_MAGIC);
-		CHECK_OBJ_ORNULL(sp->backend, BACKEND_MAGIC);
+		CHECK_OBJ_ORNULL(sp->director, DIRECTOR_MAGIC);
 
 		switch (sp->step) {
 #ifdef DIAGNOSTICS

Added: trunk/varnish-cache/bin/varnishd/cache_dir_simple.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_dir_simple.c	                        (rev 0)
+++ trunk/varnish-cache/bin/varnishd/cache_dir_simple.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -0,0 +1,96 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2008 Linpro AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * 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.
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "shmlog.h"
+#include "cache.h"
+#include "vrt.h"
+
+/*--------------------------------------------------------------------*/
+
+struct vdi_simple {
+	unsigned		magic;
+#define VDI_SIMPLE_MAGIC	0x476d25b7
+	struct director		dir;
+	struct backend		*backend;
+};
+
+static struct backend *
+vdi_simple_choose(struct sess *sp)
+{
+	struct vdi_simple *vs;
+
+	CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
+	CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_SIMPLE_MAGIC);
+	return (vs->backend);
+}
+
+static void
+vdi_simple_fini(struct director *d)
+{
+	struct vdi_simple *vs;
+
+	CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
+	CAST_OBJ_NOTNULL(vs, d->priv, VDI_SIMPLE_MAGIC);
+	
+	VBE_DropRef(vs->backend);
+	free(vs);
+}
+
+void
+VRT_init_dir_simple(struct cli *cli, struct director **bp, const struct vrt_dir_simple *t)
+{
+	struct vdi_simple *vs;
+	
+	(void)cli;
+
+	vs = calloc(sizeof *vs, 1);
+	XXXAN(vs);
+	vs->magic = VDI_SIMPLE_MAGIC;
+	vs->dir.magic = DIRECTOR_MAGIC;
+	vs->dir.priv = vs;
+	vs->dir.name = "simple";
+	vs->dir.choose = vdi_simple_choose;
+	vs->dir.fini = vdi_simple_fini;
+
+	vs->backend = VBE_AddBackend(cli, t->host);
+
+	*bp = &vs->dir;
+}

Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_fetch.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_fetch.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -309,7 +309,7 @@
 	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
 	CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
 	assert(sp->obj->busy != 0);
 	w = sp->wrk;
 	bereq = sp->bereq;

Modified: trunk/varnish-cache/bin/varnishd/cache_http.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_http.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_http.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -649,8 +649,11 @@
 
 	/* XXX: This really ought to go into the default VCL */
 	if (!http_GetHdr(hp, H_Host, &b)) {
+#if 0
 		http_PrintfHeader(sp->wrk, sp->fd, hp, "Host: %s",
 		    sp->backend->method->gethostname(sp->backend));
+#endif
+		INCOMPL();
 	}
 	sp->bereq = bereq;
 }

Modified: trunk/varnish-cache/bin/varnishd/cache_main.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_main.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_main.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -83,7 +83,6 @@
 	SZOF(struct objhead);
 	SZOF(struct sess);
 	SZOF(struct vbe_conn);
-	SZOF(struct backend);
 
 
 	CNT_Init();

Modified: trunk/varnish-cache/bin/varnishd/cache_panic.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_panic.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_panic.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -131,6 +131,7 @@
 	fp("  },\n");
 }
 
+#if 0
 /* dump a struct backend */
 static void
 dump_backend(const struct backend *be)
@@ -141,12 +142,15 @@
 	    be->vcl_name ? be->vcl_name : "(null)");
 	fp("  },\n");
 }
+#endif
 
 /* dump a struct sess */
 static void
 dump_sess(const struct sess *sp)
 {
+#if 0
 	const struct backend *be = sp->backend;
+#endif
 	const struct object *obj = sp->obj;
 
 	fp("sp = %p {\n", sp);
@@ -162,8 +166,11 @@
 		fp("  err_code = %d, err_reason = %s,\n", sp->err_code,
 		    sp->err_reason ? sp->err_reason : "(null)");
 
+#if 0
 	if (VALID_OBJ(be, BACKEND_MAGIC))
 		dump_backend(be);
+	INCOMPL():
+#endif
 
 	if (VALID_OBJ(obj, OBJECT_MAGIC))
 		dump_object(obj);

Modified: trunk/varnish-cache/bin/varnishd/cache_vcl.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_vcl.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_vcl.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -168,7 +168,7 @@
 		vcl_active = vcl;
 	UNLOCK(&vcl_mtx);
 	cli_out(cli, "Loaded \"%s\" as \"%s\"\n", fn , name);
-	vcl->conf->init_func();
+	vcl->conf->init_func(cli);
 	return (0);
 }
 
@@ -186,7 +186,7 @@
 	assert(vcl->conf->discard);
 	assert(vcl->conf->busy == 0);
 	VTAILQ_REMOVE(&vcl_head, vcl, list);
-	vcl->conf->fini_func();
+	vcl->conf->fini_func(NULL);
 	free(vcl->name);
 	free(vcl);
 }

Modified: trunk/varnish-cache/bin/varnishd/cache_vrt.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_vrt.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/bin/varnishd/cache_vrt.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -391,17 +391,17 @@
 /*--------------------------------------------------------------------*/
 
 void
-VRT_l_req_backend(struct sess *sp, struct backend *be)
+VRT_l_req_backend(struct sess *sp, struct director *be)
 {
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	sp->backend = be;
+	sp->director = be;
 }
 
-struct backend *
+struct director *
 VRT_r_req_backend(struct sess *sp)
 {
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	return (sp->backend);
+	return (sp->director);
 }
 
 /*--------------------------------------------------------------------*/
@@ -543,10 +543,14 @@
 int
 VRT_r_backend_health(const struct sess *sp)
 {
-	
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+#if 0	
 	CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
 	return (sp->backend->health);
+#else
+	INCOMPL();
+	return (0);
+#endif
 }
 
 /*--------------------------------------------------------------------*/
@@ -621,15 +625,3 @@
 	return (strcmp(s1, s2));
 }
 
-
-/*--------------------------------------------------------------------
- * Backend stuff
- */
-
-void
-VRT_fini_backend(struct backend *b)
-{
-
-	ASSERT_CLI();
-	VBE_DropRef(b);	
-}

Modified: trunk/varnish-cache/include/vcl.h
===================================================================
--- trunk/varnish-cache/include/vcl.h	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/include/vcl.h	2008-02-06 15:19:49 UTC (rev 2437)
@@ -7,17 +7,18 @@
  */
 
 struct sess;
+struct cli;
 
-typedef void vcl_init_f(void);
-typedef void vcl_fini_f(void);
+typedef void vcl_init_f(struct cli *);
+typedef void vcl_fini_f(struct cli *);
 typedef int vcl_func_f(struct sess *sp);
 
 struct VCL_conf {
 	unsigned        magic;
 #define VCL_CONF_MAGIC  0x7406c509      /* from /dev/random */
 
-        struct backend  **backend;
-        unsigned        nbackend;
+        struct director  **director;
+        unsigned        ndirector;
         struct vrt_ref  *ref;
         unsigned        nref;
         unsigned        busy;

Modified: trunk/varnish-cache/include/vrt.h
===================================================================
--- trunk/varnish-cache/include/vrt.h	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/include/vrt.h	2008-02-06 15:19:49 UTC (rev 2437)
@@ -36,55 +36,51 @@
 
 struct sess;
 struct vsb;
-struct backend;
+struct cli;
+struct director;
 struct VCL_conf;
 struct sockaddr;
 
-struct vrt_backend_host {
+/*
+ * A backend is a host+port somewhere on the network
+ */
+struct vrt_backend {
 	const char	*portname;
 	const char	*hostname;
 	const char	*ident;
 };
 
-struct vrt_simple_backend {
-	const char			*ident;
-	const char			*name;
-	const struct vrt_backend_host	*host;
-};
+/*
+ * A director with a predictable reply
+ */
 
-struct vrt_backend_entry {
-	const char	*port;
-	const char	*host;
-	double		weight;
-	struct vrt_backend_entry *next;
+struct vrt_dir_simple {
+	const char				*ident;
+	const char				*name;
+	const struct vrt_backend		*host;
 };
 
-struct vrt_round_robin_backend {
-	const char	*name;
-	unsigned	count;
-	struct vrt_backend_entry *bentry;
-};
+/*
+ * A director with an unpredictable reply
+ */
 
 struct vrt_dir_random_entry {
-	const struct vrt_backend_host	*host;
-	double				weight;
+	const struct vrt_backend		*host;
+	double					weight;
 };
 
 struct vrt_dir_random {
-	const char 			*ident;
-	const char 			*name;
-	unsigned 			nmember;
+	const char 				*ident;
+	const char 				*name;
+	unsigned 				nmember;
 	const struct vrt_dir_random_entry	*members;
 };
 
-struct vrt_random_backend {
-	const char	*name;
-	unsigned	weighted;
-	unsigned	count;
-	struct vrt_backend_entry *bentry;
-};
+/*
+ * other stuff.
+ * XXX: document when bored
+ */
 
-
 struct vrt_ref {
 	unsigned	source;
 	unsigned	offset;
@@ -134,10 +130,9 @@
 void VRT_Rollback(struct sess *sp);
 
 /* Backend related */
-void VRT_init_simple_backend(struct backend **, const struct vrt_simple_backend *);
-void VRT_init_round_robin_backend(struct backend **, const struct vrt_round_robin_backend *);
-void VRT_init_random_backend(struct backend **, const struct vrt_dir_random *);
-void VRT_fini_backend(struct backend *);
+void VRT_init_dir_simple(struct cli *, struct director **, const struct vrt_dir_simple *);
+void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *);
+void VRT_fini_dir(struct cli *, struct director *);
 
 char *VRT_IP_string(const struct sess *sp, const struct sockaddr *sa);
 char *VRT_int_string(const struct sess *sp, int);

Modified: trunk/varnish-cache/include/vrt_obj.h
===================================================================
--- trunk/varnish-cache/include/vrt_obj.h	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/include/vrt_obj.h	2008-02-06 15:19:49 UTC (rev 2437)
@@ -15,8 +15,8 @@
 const char * VRT_r_req_proto(const struct sess *);
 void VRT_l_req_proto(const struct sess *, const char *, ...);
 void VRT_l_req_hash(struct sess *, const char *);
-struct backend * VRT_r_req_backend(struct sess *);
-void VRT_l_req_backend(struct sess *, struct backend *);
+struct director * VRT_r_req_backend(struct sess *);
+void VRT_l_req_backend(struct sess *, struct director *);
 int VRT_r_req_restarts(const struct sess *);
 double VRT_r_req_grace(struct sess *);
 void VRT_l_req_grace(struct sess *, double);

Modified: trunk/varnish-cache/lib/libvcl/vcc_backend.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_backend.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/lib/libvcl/vcc_backend.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -70,10 +70,16 @@
  */
 
 static void
-vcc_EmitBeIdent(struct vsb *v, const struct token *first, const struct token *last)
+vcc_EmitBeIdent(struct vsb *v, const struct token *qual, int serial, const struct token *first, const struct token *last)
 {
 
 	vsb_printf(v, "\t.ident =");
+	if (qual != NULL) {
+		vsb_printf(v, "\n\t    \"%.*s \"", PF(qual));
+		qual = VTAILQ_NEXT(qual, list);
+		vsb_printf(v, "\n\t    \"%.*s \"", PF(qual));
+		vsb_printf(v, "\n\t    \":: %d :: \"", serial);
+	}
 	while (first != last) {
 		if (first->dec != NULL)
 			vsb_printf(v, "\n\t    \"\\\"\" %.*s \"\\\" \"",
@@ -201,11 +207,11 @@
  * be_element:
  *	'.' name '=' value ';'
  *
- * The struct vrt_backend_host is emitted to Fh().
+ * The struct vrt_backend is emitted to Fh().
  */
 
 static void
-vcc_ParseBackendHost(struct tokenlist *tl, int *nbh)
+vcc_ParseBackendHost(struct tokenlist *tl, int *nbh, const struct token *qual, int serial)
 {
 	struct token *t_field;
 	struct token *t_first;
@@ -240,7 +246,7 @@
 	vcc_NextToken(tl);
 
 	*nbh = tl->nbackend_host++;
-	Fh(tl, 0, "\nstatic const struct vrt_backend_host bh_%d = {\n", *nbh);
+	Fh(tl, 0, "\nstatic const struct vrt_backend bh_%d = {\n", *nbh);
 
 	/* Check for old syntax */
 	if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) {
@@ -298,7 +304,7 @@
 	EncToken(tl->fh, t_host);
 	Fh(tl, 0, ",\n");
 
-	/* Check that the hostname makes sense */
+	/* Check that the portname makes sense */
 	if (t_port != NULL) {
 		ep = CheckHostPort(t_host->dec, t_port->dec);
 		if (ep != NULL) {
@@ -310,10 +316,12 @@
 		Fh(tl, 0, "\t.portname = ");
 		EncToken(tl->fh, t_port);
 		Fh(tl, 0, ",\n");
+	} else {
+		Fh(tl, 0, "\t.portname = \"80\",\n");
 	}
 
 	ExpectErr(tl, '}');
-	vcc_EmitBeIdent(tl->fh, t_first, tl->t);
+	vcc_EmitBeIdent(tl->fh, qual, serial, t_first, tl->t);
 	Fh(tl, 0, "};\n");
 	vcc_NextToken(tl);
 }
@@ -338,27 +346,28 @@
 	h->name = tl->t;
 	vcc_NextToken(tl);
 
-	vcc_ParseBackendHost(tl, &nbh);
+	vcc_ParseBackendHost(tl, &nbh, NULL, 0);
 	ERRCHK(tl);
 
 	h->hnum = nbh;
 	VTAILQ_INSERT_TAIL(&tl->hosts, h, list);
 
 	/* In the compiled vcl we use these macros to refer to backends */
-	Fh(tl, 1, "\n#define VGC_backend_%.*s (VCL_conf.backend[%d])\n",
+	Fh(tl, 1, "\n#define VGC_backend_%.*s (VCL_conf.director[%d])\n",
 	    PF(h->name), tl->nbackend);
 
 	vcc_AddDef(tl, h->name, R_BACKEND);
 
-	Fi(tl, 0, "\tVRT_init_simple_backend(&VGC_backend_%.*s , &sbe_%.*s);\n",
+	Fi(tl, 0,
+	    "\tVRT_init_dir_simple(cli, &VGC_backend_%.*s , &sbe_%.*s);\n",
 	    PF(h->name), PF(h->name));
-	Ff(tl, 0, "\tVRT_fini_backend(VGC_backend_%.*s);\n", PF(h->name));
+	Ff(tl, 0, "\tVRT_fini_dir(cli, VGC_backend_%.*s);\n", PF(h->name));
 
-	Fc(tl, 0, "\nstatic const struct vrt_simple_backend sbe_%.*s = {\n",
+	Fc(tl, 0, "\nstatic const struct vrt_dir_simple sbe_%.*s = {\n",
 	    PF(h->name));
 	Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(h->name));
 	Fc(tl, 0, "\t.host = &bh_%d,\n", nbh);
-	vcc_EmitBeIdent(tl->fc, t_first, tl->t);
+	vcc_EmitBeIdent(tl->fc, NULL, 0, t_first, tl->t);
 	Fc(tl, 0, "};\n");
 
 	tl->nbackend++;
@@ -375,7 +384,7 @@
 	int nbh, nelem;
 	struct fld_spec *fs;
 
-	Fh(tl, 1, "\n#define VGC_backend_%.*s (VCL_conf.backend[%d])\n",
+	Fh(tl, 1, "\n#define VGC_backend_%.*s (VCL_conf.director[%d])\n",
 	    PF(t_dir), tl->nbackend);
 	vcc_AddDef(tl, t_dir, R_BACKEND);
 
@@ -402,7 +411,7 @@
 			vcc_IsField(tl, &t_field, fs);
 			ERRCHK(tl);
 			if (vcc_IdIs(t_field, "backend")) {
-				vcc_ParseBackendHost(tl, &nbh);
+				vcc_ParseBackendHost(tl, &nbh, t_dir, nelem);
 				Fc(tl, 0, " .host = &bh_%d,", nbh);
 				ERRCHK(tl);
 			} else if (vcc_IdIs(t_field, "weight")) {
@@ -428,12 +437,13 @@
 	Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(t_dir));
 	Fc(tl, 0, "\t.nmember = %d,\n", nelem);
 	Fc(tl, 0, "\t.members = vdre_%.*s,\n", PF(t_dir));
-	vcc_EmitBeIdent(tl->fc, t_first, tl->t);
+	vcc_EmitBeIdent(tl->fc, NULL, 0, t_first, tl->t);
 	Fc(tl, 0, "};\n");
 	vcc_NextToken(tl);
-	Fi(tl, 0, "\tVRT_init_random_backend(&VGC_backend_%.*s , &vdr_%.*s);\n",
+	Fi(tl, 0,
+	    "\tVRT_init_dir_random(cli, &VGC_backend_%.*s , &vdr_%.*s);\n",
 	    PF(t_dir), PF(t_dir));
-	Ff(tl, 0, "\tVRT_fini_backend(VGC_backend_%.*s);\n", PF(t_dir));
+	Ff(tl, 0, "\tVRT_fini_dir(cli, VGC_backend_%.*s);\n", PF(t_dir));
 }
 
 /*--------------------------------------------------------------------

Modified: trunk/varnish-cache/lib/libvcl/vcc_compile.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_compile.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/lib/libvcl/vcc_compile.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -295,7 +295,7 @@
 EmitInitFunc(const struct tokenlist *tl)
 {
 
-	Fc(tl, 0, "\nstatic void\nVGC_Init(void)\n{\n\n");
+	Fc(tl, 0, "\nstatic void\nVGC_Init(struct cli *cli)\n{\n\n");
 	vsb_finish(tl->fi);
 	/* XXX: check vsb_overflowed ? */
 	vsb_cat(tl->fc, vsb_data(tl->fi));
@@ -306,7 +306,7 @@
 EmitFiniFunc(const struct tokenlist *tl)
 {
 
-	Fc(tl, 0, "\nstatic void\nVGC_Fini(void)\n{\n\n");
+	Fc(tl, 0, "\nstatic void\nVGC_Fini(struct cli *cli)\n{\n\n");
 	vsb_finish(tl->ff);
 	/* XXX: check vsb_overflowed ? */
 	vsb_cat(tl->fc, vsb_data(tl->ff));
@@ -339,14 +339,14 @@
 	}
 	Fc(tl, 0, "};\n");
 
-	Fc(tl, 0, "\nstatic struct backend\t*backends[%d];\n", tl->nbackend);
+	Fc(tl, 0, "\nstatic struct director\t*directors[%d];\n", tl->nbackend);
 
 	Fc(tl, 0, "\nconst struct VCL_conf VCL_conf = {\n");
 	Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n");
 	Fc(tl, 0, "\t.init_func = VGC_Init,\n");
 	Fc(tl, 0, "\t.fini_func = VGC_Fini,\n");
-	Fc(tl, 0, "\t.nbackend = %d,\n", tl->nbackend);
-	Fc(tl, 0, "\t.backend = backends,\n");
+	Fc(tl, 0, "\t.ndirector = %d,\n", tl->nbackend);
+	Fc(tl, 0, "\t.director = directors,\n");
 	Fc(tl, 0, "\t.ref = VGC_ref,\n");
 	Fc(tl, 0, "\t.nref = VGC_NREFS,\n");
 	Fc(tl, 0, "\t.nsrc = %u,\n", tl->nsources);

Modified: trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c	2008-02-06 15:19:49 UTC (rev 2437)
@@ -311,17 +311,18 @@
 	vsb_cat(sb, " */\n");
 	vsb_cat(sb, "\n");
 	vsb_cat(sb, "struct sess;\n");
+	vsb_cat(sb, "struct cli;\n");
 	vsb_cat(sb, "\n");
-	vsb_cat(sb, "typedef void vcl_init_f(void);\n");
-	vsb_cat(sb, "typedef void vcl_fini_f(void);\n");
+	vsb_cat(sb, "typedef void vcl_init_f(struct cli *);\n");
+	vsb_cat(sb, "typedef void vcl_fini_f(struct cli *);\n");
 	vsb_cat(sb, "typedef int vcl_func_f(struct sess *sp);\n");
 	vsb_cat(sb, "\n");
 	vsb_cat(sb, "struct VCL_conf {\n");
 	vsb_cat(sb, "	unsigned        magic;\n");
 	vsb_cat(sb, "#define VCL_CONF_MAGIC  0x7406c509      /* from /dev/random */\n");
 	vsb_cat(sb, "\n");
-	vsb_cat(sb, "        struct backend  **backend;\n");
-	vsb_cat(sb, "        unsigned        nbackend;\n");
+	vsb_cat(sb, "        struct director  **director;\n");
+	vsb_cat(sb, "        unsigned        ndirector;\n");
 	vsb_cat(sb, "        struct vrt_ref  *ref;\n");
 	vsb_cat(sb, "        unsigned        nref;\n");
 	vsb_cat(sb, "        unsigned        busy;\n");
@@ -388,55 +389,51 @@
 	vsb_cat(sb, "\n");
 	vsb_cat(sb, "struct sess;\n");
 	vsb_cat(sb, "struct vsb;\n");
-	vsb_cat(sb, "struct backend;\n");
+	vsb_cat(sb, "struct cli;\n");
+	vsb_cat(sb, "struct director;\n");
 	vsb_cat(sb, "struct VCL_conf;\n");
 	vsb_cat(sb, "struct sockaddr;\n");
 	vsb_cat(sb, "\n");
-	vsb_cat(sb, "struct vrt_backend_host {\n");
+	vsb_cat(sb, "/*\n");
+	vsb_cat(sb, " * A backend is a host+port somewhere on the network\n");
+	vsb_cat(sb, " */\n");
+	vsb_cat(sb, "struct vrt_backend {\n");
 	vsb_cat(sb, "	const char	*portname;\n");
 	vsb_cat(sb, "	const char	*hostname;\n");
 	vsb_cat(sb, "	const char	*ident;\n");
 	vsb_cat(sb, "};\n");
 	vsb_cat(sb, "\n");
-	vsb_cat(sb, "struct vrt_simple_backend {\n");
-	vsb_cat(sb, "	const char			*ident;\n");
-	vsb_cat(sb, "	const char			*name;\n");
-	vsb_cat(sb, "	const struct vrt_backend_host	*host;\n");
-	vsb_cat(sb, "};\n");
+	vsb_cat(sb, "/*\n");
+	vsb_cat(sb, " * A director with a predictable reply\n");
+	vsb_cat(sb, " */\n");
 	vsb_cat(sb, "\n");
-	vsb_cat(sb, "struct vrt_backend_entry {\n");
-	vsb_cat(sb, "	const char	*port;\n");
-	vsb_cat(sb, "	const char	*host;\n");
-	vsb_cat(sb, "	double		weight;\n");
-	vsb_cat(sb, "	struct vrt_backend_entry *next;\n");
+	vsb_cat(sb, "struct vrt_dir_simple {\n");
+	vsb_cat(sb, "	const char				*ident;\n");
+	vsb_cat(sb, "	const char				*name;\n");
+	vsb_cat(sb, "	const struct vrt_backend		*host;\n");
 	vsb_cat(sb, "};\n");
 	vsb_cat(sb, "\n");
-	vsb_cat(sb, "struct vrt_round_robin_backend {\n");
-	vsb_cat(sb, "	const char	*name;\n");
-	vsb_cat(sb, "	unsigned	count;\n");
-	vsb_cat(sb, "	struct vrt_backend_entry *bentry;\n");
-	vsb_cat(sb, "};\n");
+	vsb_cat(sb, "/*\n");
+	vsb_cat(sb, " * A director with an unpredictable reply\n");
+	vsb_cat(sb, " */\n");
 	vsb_cat(sb, "\n");
 	vsb_cat(sb, "struct vrt_dir_random_entry {\n");
-	vsb_cat(sb, "	const struct vrt_backend_host	*host;\n");
-	vsb_cat(sb, "	double				weight;\n");
+	vsb_cat(sb, "	const struct vrt_backend		*host;\n");
+	vsb_cat(sb, "	double					weight;\n");
 	vsb_cat(sb, "};\n");
 	vsb_cat(sb, "\n");
 	vsb_cat(sb, "struct vrt_dir_random {\n");
-	vsb_cat(sb, "	const char 			*ident;\n");
-	vsb_cat(sb, "	const char 			*name;\n");
-	vsb_cat(sb, "	unsigned 			nmember;\n");
+	vsb_cat(sb, "	const char 				*ident;\n");
+	vsb_cat(sb, "	const char 				*name;\n");
+	vsb_cat(sb, "	unsigned 				nmember;\n");
 	vsb_cat(sb, "	const struct vrt_dir_random_entry	*members;\n");
 	vsb_cat(sb, "};\n");
 	vsb_cat(sb, "\n");
-	vsb_cat(sb, "struct vrt_random_backend {\n");
-	vsb_cat(sb, "	const char	*name;\n");
-	vsb_cat(sb, "	unsigned	weighted;\n");
-	vsb_cat(sb, "	unsigned	count;\n");
-	vsb_cat(sb, "	struct vrt_backend_entry *bentry;\n");
-	vsb_cat(sb, "};\n");
+	vsb_cat(sb, "/*\n");
+	vsb_cat(sb, " * other stuff.\n");
+	vsb_cat(sb, " * XXX: document when bored\n");
+	vsb_cat(sb, " */\n");
 	vsb_cat(sb, "\n");
-	vsb_cat(sb, "\n");
 	vsb_cat(sb, "struct vrt_ref {\n");
 	vsb_cat(sb, "	unsigned	source;\n");
 	vsb_cat(sb, "	unsigned	offset;\n");
@@ -486,10 +483,9 @@
 	vsb_cat(sb, "void VRT_Rollback(struct sess *sp);\n");
 	vsb_cat(sb, "\n");
 	vsb_cat(sb, "/* Backend related */\n");
-	vsb_cat(sb, "void VRT_init_simple_backend(struct backend **, const struct vrt_simple_backend *);\n");
-	vsb_cat(sb, "void VRT_init_round_robin_backend(struct backend **, const struct vrt_round_robin_backend *);\n");
-	vsb_cat(sb, "void VRT_init_random_backend(struct backend **, const struct vrt_dir_random *);\n");
-	vsb_cat(sb, "void VRT_fini_backend(struct backend *);\n");
+	vsb_cat(sb, "void VRT_init_dir_simple(struct cli *, struct director **, const struct vrt_dir_simple *);\n");
+	vsb_cat(sb, "void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *);\n");
+	vsb_cat(sb, "void VRT_fini_dir(struct cli *, struct director *);\n");
 	vsb_cat(sb, "\n");
 	vsb_cat(sb, "char *VRT_IP_string(const struct sess *sp, const struct sockaddr *sa);\n");
 	vsb_cat(sb, "char *VRT_int_string(const struct sess *sp, int);\n");
@@ -516,8 +512,8 @@
 	vsb_cat(sb, "const char * VRT_r_req_proto(const struct sess *);\n");
 	vsb_cat(sb, "void VRT_l_req_proto(const struct sess *, const char *, ...);\n");
 	vsb_cat(sb, "void VRT_l_req_hash(struct sess *, const char *);\n");
-	vsb_cat(sb, "struct backend * VRT_r_req_backend(struct sess *);\n");
-	vsb_cat(sb, "void VRT_l_req_backend(struct sess *, struct backend *);\n");
+	vsb_cat(sb, "struct director * VRT_r_req_backend(struct sess *);\n");
+	vsb_cat(sb, "void VRT_l_req_backend(struct sess *, struct director *);\n");
 	vsb_cat(sb, "int VRT_r_req_restarts(const struct sess *);\n");
 	vsb_cat(sb, "double VRT_r_req_grace(struct sess *);\n");
 	vsb_cat(sb, "void VRT_l_req_grace(struct sess *, double);\n");

Modified: trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl	2008-02-06 15:19:49 UTC (rev 2437)
@@ -123,17 +123,18 @@
 set fo [open ../../include/vcl.h w]
 warns $fo
 puts $fo {struct sess;
+struct cli;
 
-typedef void vcl_init_f(void);
-typedef void vcl_fini_f(void);
+typedef void vcl_init_f(struct cli *);
+typedef void vcl_fini_f(struct cli *);
 typedef int vcl_func_f(struct sess *sp);
 }
 puts $fo "struct VCL_conf {"
 puts $fo {	unsigned        magic;
 #define VCL_CONF_MAGIC  0x7406c509      /* from /dev/random */
 
-        struct backend  **backend;
-        unsigned        nbackend;
+        struct director  **director;
+        unsigned        ndirector;
         struct vrt_ref  *ref;
         unsigned        nref;
         unsigned        busy;

Modified: trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl	2008-02-06 09:47:24 UTC (rev 2436)
+++ trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl	2008-02-06 15:19:49 UTC (rev 2437)
@@ -211,7 +211,7 @@
 set tt(IP)		"struct sockaddr *"
 set tt(STRING)		"const char *"
 set tt(BOOL)		"unsigned"
-set tt(BACKEND)		"struct backend *"
+set tt(BACKEND)		"struct director *"
 set tt(TIME)		"double"
 set tt(RTIME)		"double"
 set tt(INT)		"int"




More information about the varnish-commit mailing list