r1892 - trunk/varnish-cache/bin/varnishd

phk at projects.linpro.no phk at projects.linpro.no
Mon Aug 20 13:46:26 CEST 2007


Author: phk
Date: 2007-08-20 13:46:26 +0200 (Mon, 20 Aug 2007)
New Revision: 1892

Added:
   trunk/varnish-cache/bin/varnishd/cache_backend_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_vrt.c
Log:
Separate the generic backend handling from the backend "method".

For now all we have is a "simple" method, but we want more complex
methods later on, round-robin, least-busy and so on.

For now, fall into the other ditch and move everything to 
cache_backend_simple.c, we will move bits back as the gain generality.



Modified: trunk/varnish-cache/bin/varnishd/Makefile.am
===================================================================
--- trunk/varnish-cache/bin/varnishd/Makefile.am	2007-08-20 11:37:11 UTC (rev 1891)
+++ trunk/varnish-cache/bin/varnishd/Makefile.am	2007-08-20 11:46:26 UTC (rev 1892)
@@ -12,6 +12,7 @@
 	cache_acceptor_poll.c \
 	cache_acceptor_kqueue.c \
 	cache_backend.c \
+	cache_backend_simple.c \
 	cache_ban.c \
 	cache_center.c \
 	cache_cli.c \

Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h	2007-08-20 11:37:11 UTC (rev 1891)
+++ trunk/varnish-cache/bin/varnishd/cache.h	2007-08-20 11:46:26 UTC (rev 1892)
@@ -178,7 +178,7 @@
 
 #include "hash_slinger.h"
 
-/* Backend Connection ------------------------------------------------*/
+/* Backend Request ---------------------------------------------------*/
 
 struct bereq {
 	unsigned		magic;
@@ -189,14 +189,6 @@
 	struct http		http[1];
 };
 
-struct vbe_conn {
-	unsigned		magic;
-#define VBE_CONN_MAGIC		0x0c5e6592
-	TAILQ_ENTRY(vbe_conn)	list;
-	struct backend		*backend;
-	int			fd;
-};
-
 /* Storage -----------------------------------------------------------*/
 
 struct storage {
@@ -325,10 +317,40 @@
 	const char		**hashptr;
 };
 
+/* -------------------------------------------------------------------*/
+
+/* Backend connection */
+struct vbe_conn {
+	unsigned		magic;
+#define VBE_CONN_MAGIC		0x0c5e6592
+	TAILQ_ENTRY(vbe_conn)	list;
+	struct backend		*backend;
+	int			fd;
+};
+
+
+/* Backend method */
+typedef struct vbe_conn *vbe_getfd_f(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);
+
+struct backend_method {
+	const char		*name;
+	vbe_getfd_f		*getfd;
+	vbe_close_f		*close;
+	vbe_recycle_f		*recycle;
+	vbe_init_f		*init;
+};
+
+/* Backend indstance */
 struct backend {
 	unsigned		magic;
 #define BACKEND_MAGIC		0x64c4c7c6
 	const char		*vcl_name;
+
+	struct backend_method	*method;
+
 	const char		*hostname;
 	const char		*portname;
 
@@ -364,6 +386,7 @@
 extern int vca_pipes[2];
 
 /* cache_backend.c */
+
 void VBE_Init(void);
 struct vbe_conn *VBE_GetFd(struct sess *sp);
 void VBE_ClosedFd(struct worker *w, struct vbe_conn *vc);
@@ -371,6 +394,9 @@
 struct bereq * VBE_new_bereq(void);
 void VBE_free_bereq(struct bereq *bereq);
 
+/* cache_backend_simple.c */
+extern struct backend_method	backend_method_simple;
+
 /* 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	2007-08-20 11:37:11 UTC (rev 1891)
+++ trunk/varnish-cache/bin/varnishd/cache_backend.c	2007-08-20 11:46:26 UTC (rev 1892)
@@ -28,44 +28,24 @@
  *
  * $Id$
  *
- * NB: This file is in transition:
- *   In the future it will contain the central part of the backend handling,
- *   refcounting, functions for DNS lookup and connection revalidation etc.
- *   The actual policies will be put in separate files, cache_backend_simple.c,
- *   cache_backend_round_robin.c etc etc.
+ * Manage backend connections and requests.
  *
- * Manage backend connections.
- *
- * XXX: When we switch VCL we can have vbe_conn's dangling from
- * XXX: the backends no longer used.  When the VCL's refcount
- * XXX: drops to zero we should zap them.
  */
 
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <netdb.h>
-#include <errno.h>
-#include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
-#include <poll.h>
-#include <sys/select.h>
-#include <sys/ioctl.h>
 
 #include "heritage.h"
 #include "shmlog.h"
 #include "cache.h"
 
-/* A backend IP */
-
-static TAILQ_HEAD(,vbe_conn) vbe_head = TAILQ_HEAD_INITIALIZER(vbe_head);
 static TAILQ_HEAD(,bereq) bereq_head = TAILQ_HEAD_INITIALIZER(bereq_head);
 
 static MTX vbemtx;
 
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * Get a http structure for talking to the backend.
+ */
 
 struct bereq *
 VBE_new_bereq(void)
@@ -108,245 +88,11 @@
 
 /*--------------------------------------------------------------------*/
 
-static struct vbe_conn *
-vbe_new_conn(void)
-{
-	struct vbe_conn *vbc;
-
-	vbc = calloc(sizeof *vbc, 1);
-	if (vbc == NULL)
-		return (NULL);
-	VSL_stats->n_vbe_conn++;
-	vbc->magic = VBE_CONN_MAGIC;
-	vbc->fd = -1;
-	return (vbc);
-}
-
-/*--------------------------------------------------------------------
- * XXX: There is a race here, we need to lock the replacement of the
- * XXX: resolved addresses, or some other thread might try to access
- * XXX: them while/during/after we changed them.
- * XXX: preferably, we should make a copy to the vbe while we hold a
- * XXX: lock anyway.
- */
-
-static void
-vbe_lookup(struct backend *bp)
-{
-	struct addrinfo *res, hint, *old;
-	int error;
-
-	memset(&hint, 0, sizeof hint);
-	hint.ai_family = PF_UNSPEC;
-	hint.ai_socktype = SOCK_STREAM;
-	res = NULL;
-	error = getaddrinfo(bp->hostname,
-	    bp->portname == NULL ? "http" : bp->portname,
-	    &hint, &res);
-	bp->dnstime = TIM_mono();
-	if (error) {
-		if (res != NULL)
-			freeaddrinfo(res);
-		printf("getaddrinfo: %s\n", gai_strerror(error)); /* XXX */
-		return;
-	}
-	old = bp->addr;
-	bp->last_addr = res;
-	bp->addr = res;
-	if (old != NULL)
-		freeaddrinfo(old);
-}
-
-/*--------------------------------------------------------------------*/
-
-static int
-vbe_sock_conn(const struct addrinfo *ai)
-{
-	int s;
-
-	s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-	if (s >= 0 && connect(s, ai->ai_addr, ai->ai_addrlen)) {
-		AZ(close(s));
-		s = -1;
-	}
-	return (s);
-}
-
-/*--------------------------------------------------------------------*/
-
-static int
-vbe_conn_try(struct backend *bp, struct addrinfo **pai)
-{
-	struct addrinfo *ai;
-	int s;
-
-	/* First try the cached good address, and any following it */
-	for (ai = bp->last_addr; ai != NULL; ai = ai->ai_next) {
-		s = vbe_sock_conn(ai);
-		if (s >= 0) {
-			bp->last_addr = ai;
-			*pai = ai;
-			return (s);
-		}
-	}
-
-	/* Then try the list until the cached last good address */
-	for (ai = bp->addr; ai != bp->last_addr; ai = ai->ai_next) {
-		s = vbe_sock_conn(ai);
-		if (s >= 0) {
-			bp->last_addr = ai;
-			*pai = ai;
-			return (s);
-		}
-	}
-
-	if (bp->dnstime + bp->dnsttl >= TIM_mono())
-		return (-1);
-
-	/* Then do another lookup to catch DNS changes */
-	vbe_lookup(bp);
-
-	/* And try the entire list */
-	for (ai = bp->addr; ai != NULL; ai = ai->ai_next) {
-		s = vbe_sock_conn(ai);
-		if (s >= 0) {
-			bp->last_addr = ai;
-			*pai = ai;
-			return (s);
-		}
-	}
-
-	return (-1);
-}
-
-static int
-vbe_connect(struct sess *sp, struct backend *bp)
-{
-	int s;
-	char abuf1[TCP_ADDRBUFSIZE], abuf2[TCP_ADDRBUFSIZE];
-	char pbuf1[TCP_PORTBUFSIZE], pbuf2[TCP_PORTBUFSIZE];
-	struct addrinfo *ai;
-
-	CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
-	AN(bp->hostname);
-
-	s = vbe_conn_try(bp, &ai);
-	if (s < 0)
-		return (s);
-
-	TCP_myname(s, abuf1, sizeof abuf1, pbuf1, sizeof pbuf1);
-	TCP_name(ai->ai_addr, ai->ai_addrlen,
-	    abuf2, sizeof abuf2, pbuf2, sizeof pbuf2);
-	WSL(sp->wrk, SLT_BackendOpen, s, "%s %s %s %s %s",
-	    bp->vcl_name, abuf1, pbuf1, abuf2, pbuf2);
-	return (s);
-}
-
-/* Get a backend connection ------------------------------------------
- *
- * Try all cached backend connections for this backend, and use the
- * first one that is looks like it is still connected.
- * If that fails to get us a connection, create a new one, reusing a
- * connection from the freelist, if possible.
- *
- * This function is slightly complicated by optimizations on vbemtx.
- */
-
-static struct vbe_conn *
-vbe_nextfd(struct sess *sp)
-{
-	struct vbe_conn *vc, *vc2;
-	struct pollfd pfd;
-	struct backend *bp;
-	int reuse = 0;
-
-	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	bp = sp->backend;
-	CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
-	vc2 = NULL;
-	while (1) {
-		LOCK(&vbemtx);
-		vc = TAILQ_FIRST(&bp->connlist);
-		if (vc != NULL) {
-			assert(vc->backend == bp);
-			assert(vc->fd >= 0);
-			TAILQ_REMOVE(&bp->connlist, vc, list);
-		} else {
-			vc2 = TAILQ_FIRST(&vbe_head);
-			if (vc2 != NULL) {
-				VSL_stats->backend_unused--;
-				TAILQ_REMOVE(&vbe_head, vc2, list);
-			}
-		}
-		UNLOCK(&vbemtx);
-		if (vc == NULL)
-			break;
-
-		/* Test the connection for remote close before we use it */
-		pfd.fd = vc->fd;
-		pfd.events = POLLIN;
-		pfd.revents = 0;
-		if (!poll(&pfd, 1, 0)) {
-			reuse = 1;
-			break;
-		}
-		VBE_ClosedFd(sp->wrk, vc);
-	}
-
-	if (vc == NULL) {
-		if (vc2 == NULL)
-			vc = vbe_new_conn();
-		else
-			vc = vc2;
-		if (vc != NULL) {
-			assert(vc->fd == -1);
-			AZ(vc->backend);
-			vc->fd = vbe_connect(sp, bp);
-			if (vc->fd < 0) {
-				LOCK(&vbemtx);
-				TAILQ_INSERT_HEAD(&vbe_head, vc, list);
-				VSL_stats->backend_unused++;
-				UNLOCK(&vbemtx);
-				vc = NULL;
-			} else {
-				vc->backend = bp;
-			}
-		}
-	}
-	LOCK(&vbemtx);
-	if (vc != NULL ) {
-		VSL_stats->backend_reuse += reuse;
-		VSL_stats->backend_conn++;
-	} else {
-		VSL_stats->backend_fail++;
-	}
-	UNLOCK(&vbemtx);
-	if (vc != NULL ) {
-		WSL(sp->wrk, SLT_BackendXID, vc->fd, "%u", sp->xid);
-		assert(vc->fd >= 0);
-		assert(vc->backend == bp);
-	}
-	return (vc);
-}
-
-/*--------------------------------------------------------------------*/
-
 struct vbe_conn *
 VBE_GetFd(struct sess *sp)
 {
-	struct vbe_conn *vc;
-	unsigned n;
 
-	for (n = 1; n < 5; n++) {
-		vc = vbe_nextfd(sp);
-		if (vc != NULL) {
-			WSL(sp->wrk, SLT_Backend, sp->fd, "%d %s", vc->fd,
-			    sp->backend->vcl_name);
-			return (vc);
-		}
-		usleep(100000 * n);
-	}
-	return (NULL);
+	return(sp->backend->method->getfd(sp));
 }
 
 /* Close a connection ------------------------------------------------*/
@@ -355,17 +101,7 @@
 VBE_ClosedFd(struct worker *w, struct vbe_conn *vc)
 {
 
-	CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC);
-	assert(vc->fd >= 0);
-	AN(vc->backend);
-	WSL(w, SLT_BackendClose, vc->fd, "%s", vc->backend->vcl_name);
-	AZ(close(vc->fd));
-	vc->fd = -1;
-	vc->backend = NULL;
-	LOCK(&vbemtx);
-	TAILQ_INSERT_HEAD(&vbe_head, vc, list);
-	VSL_stats->backend_unused++;
-	UNLOCK(&vbemtx);
+	vc->backend->method->close(w, vc);
 }
 
 /* Recycle a connection ----------------------------------------------*/
@@ -374,14 +110,7 @@
 VBE_RecycleFd(struct worker *w, struct vbe_conn *vc)
 {
 
-	CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC);
-	assert(vc->fd >= 0);
-	AN(vc->backend);
-	WSL(w, SLT_BackendReuse, vc->fd, "%s", vc->backend->vcl_name);
-	LOCK(&vbemtx);
-	VSL_stats->backend_recycle++;
-	TAILQ_INSERT_HEAD(&vc->backend->connlist, vc, list);
-	UNLOCK(&vbemtx);
+	vc->backend->method->recycle(w, vc);
 }
 
 /*--------------------------------------------------------------------*/
@@ -391,4 +120,5 @@
 {
 
 	MTX_INIT(&vbemtx);
+	backend_method_simple.init();
 }

Added: trunk/varnish-cache/bin/varnishd/cache_backend_simple.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_backend_simple.c	                        (rev 0)
+++ trunk/varnish-cache/bin/varnishd/cache_backend_simple.c	2007-08-20 11:46:26 UTC (rev 1892)
@@ -0,0 +1,352 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2007 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$
+ *
+ *
+ * XXX: When we switch VCL we can have vbe_conn's dangling from
+ * XXX: the backends no longer used.  When the VCL's refcount
+ * XXX: drops to zero we should zap them.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include "shmlog.h"
+#include "cache.h"
+
+static TAILQ_HEAD(,vbe_conn) vbe_head = TAILQ_HEAD_INITIALIZER(vbe_head);
+
+static MTX vbemtx;
+
+/*--------------------------------------------------------------------*/
+
+static struct vbe_conn *
+vbe_new_conn(void)
+{
+	struct vbe_conn *vbc;
+
+	vbc = calloc(sizeof *vbc, 1);
+	if (vbc == NULL)
+		return (NULL);
+	VSL_stats->n_vbe_conn++;
+	vbc->magic = VBE_CONN_MAGIC;
+	vbc->fd = -1;
+	return (vbc);
+}
+
+/*--------------------------------------------------------------------
+ * XXX: There is a race here, we need to lock the replacement of the
+ * XXX: resolved addresses, or some other thread might try to access
+ * XXX: them while/during/after we changed them.
+ * XXX: preferably, we should make a copy to the vbe while we hold a
+ * XXX: lock anyway.
+ */
+
+static void
+vbe_lookup(struct backend *bp)
+{
+	struct addrinfo *res, hint, *old;
+	int error;
+
+	memset(&hint, 0, sizeof hint);
+	hint.ai_family = PF_UNSPEC;
+	hint.ai_socktype = SOCK_STREAM;
+	res = NULL;
+	error = getaddrinfo(bp->hostname,
+	    bp->portname == NULL ? "http" : bp->portname,
+	    &hint, &res);
+	bp->dnstime = TIM_mono();
+	if (error) {
+		if (res != NULL)
+			freeaddrinfo(res);
+		printf("getaddrinfo: %s\n", gai_strerror(error)); /* XXX */
+		return;
+	}
+	old = bp->addr;
+	bp->last_addr = res;
+	bp->addr = res;
+	if (old != NULL)
+		freeaddrinfo(old);
+}
+
+/*--------------------------------------------------------------------*/
+
+static int
+vbe_sock_conn(const struct addrinfo *ai)
+{
+	int s;
+
+	s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+	if (s >= 0 && connect(s, ai->ai_addr, ai->ai_addrlen)) {
+		AZ(close(s));
+		s = -1;
+	}
+	return (s);
+}
+
+/*--------------------------------------------------------------------*/
+
+static int
+vbe_conn_try(struct backend *bp, struct addrinfo **pai)
+{
+	struct addrinfo *ai;
+	int s;
+
+	/* First try the cached good address, and any following it */
+	for (ai = bp->last_addr; ai != NULL; ai = ai->ai_next) {
+		s = vbe_sock_conn(ai);
+		if (s >= 0) {
+			bp->last_addr = ai;
+			*pai = ai;
+			return (s);
+		}
+	}
+
+	/* Then try the list until the cached last good address */
+	for (ai = bp->addr; ai != bp->last_addr; ai = ai->ai_next) {
+		s = vbe_sock_conn(ai);
+		if (s >= 0) {
+			bp->last_addr = ai;
+			*pai = ai;
+			return (s);
+		}
+	}
+
+	if (bp->dnstime + bp->dnsttl >= TIM_mono())
+		return (-1);
+
+	/* Then do another lookup to catch DNS changes */
+	vbe_lookup(bp);
+
+	/* And try the entire list */
+	for (ai = bp->addr; ai != NULL; ai = ai->ai_next) {
+		s = vbe_sock_conn(ai);
+		if (s >= 0) {
+			bp->last_addr = ai;
+			*pai = ai;
+			return (s);
+		}
+	}
+
+	return (-1);
+}
+
+static int
+vbe_connect(struct sess *sp, struct backend *bp)
+{
+	int s;
+	char abuf1[TCP_ADDRBUFSIZE], abuf2[TCP_ADDRBUFSIZE];
+	char pbuf1[TCP_PORTBUFSIZE], pbuf2[TCP_PORTBUFSIZE];
+	struct addrinfo *ai;
+
+	CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
+	AN(bp->hostname);
+
+	s = vbe_conn_try(bp, &ai);
+	if (s < 0)
+		return (s);
+
+	TCP_myname(s, abuf1, sizeof abuf1, pbuf1, sizeof pbuf1);
+	TCP_name(ai->ai_addr, ai->ai_addrlen,
+	    abuf2, sizeof abuf2, pbuf2, sizeof pbuf2);
+	WSL(sp->wrk, SLT_BackendOpen, s, "%s %s %s %s %s",
+	    bp->vcl_name, abuf1, pbuf1, abuf2, pbuf2);
+	return (s);
+}
+
+/* Get a backend connection ------------------------------------------
+ *
+ * Try all cached backend connections for this backend, and use the
+ * first one that is looks like it is still connected.
+ * If that fails to get us a connection, create a new one, reusing a
+ * connection from the freelist, if possible.
+ *
+ * This function is slightly complicated by optimizations on vbemtx.
+ */
+
+static struct vbe_conn *
+vbe_nextfd(struct sess *sp)
+{
+	struct vbe_conn *vc, *vc2;
+	struct pollfd pfd;
+	struct backend *bp;
+	int reuse = 0;
+
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+	bp = sp->backend;
+	CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
+	vc2 = NULL;
+	while (1) {
+		LOCK(&vbemtx);
+		vc = TAILQ_FIRST(&bp->connlist);
+		if (vc != NULL) {
+			assert(vc->backend == bp);
+			assert(vc->fd >= 0);
+			TAILQ_REMOVE(&bp->connlist, vc, list);
+		} else {
+			vc2 = TAILQ_FIRST(&vbe_head);
+			if (vc2 != NULL) {
+				VSL_stats->backend_unused--;
+				TAILQ_REMOVE(&vbe_head, vc2, list);
+			}
+		}
+		UNLOCK(&vbemtx);
+		if (vc == NULL)
+			break;
+
+		/* Test the connection for remote close before we use it */
+		pfd.fd = vc->fd;
+		pfd.events = POLLIN;
+		pfd.revents = 0;
+		if (!poll(&pfd, 1, 0)) {
+			reuse = 1;
+			break;
+		}
+		VBE_ClosedFd(sp->wrk, vc);
+	}
+
+	if (vc == NULL) {
+		if (vc2 == NULL)
+			vc = vbe_new_conn();
+		else
+			vc = vc2;
+		if (vc != NULL) {
+			assert(vc->fd == -1);
+			AZ(vc->backend);
+			vc->fd = vbe_connect(sp, bp);
+			if (vc->fd < 0) {
+				LOCK(&vbemtx);
+				TAILQ_INSERT_HEAD(&vbe_head, vc, list);
+				VSL_stats->backend_unused++;
+				UNLOCK(&vbemtx);
+				vc = NULL;
+			} else {
+				vc->backend = bp;
+			}
+		}
+	}
+	LOCK(&vbemtx);
+	if (vc != NULL ) {
+		VSL_stats->backend_reuse += reuse;
+		VSL_stats->backend_conn++;
+	} else {
+		VSL_stats->backend_fail++;
+	}
+	UNLOCK(&vbemtx);
+	if (vc != NULL ) {
+		WSL(sp->wrk, SLT_BackendXID, vc->fd, "%u", sp->xid);
+		assert(vc->fd >= 0);
+		assert(vc->backend == bp);
+	}
+	return (vc);
+}
+
+/*--------------------------------------------------------------------*/
+
+static struct vbe_conn *
+bes_GetFd(struct sess *sp)
+{
+	struct vbe_conn *vc;
+	unsigned n;
+
+	for (n = 1; n < 5; n++) {
+		vc = vbe_nextfd(sp);
+		if (vc != NULL) {
+			WSL(sp->wrk, SLT_Backend, sp->fd, "%d %s", vc->fd,
+			    sp->backend->vcl_name);
+			return (vc);
+		}
+		usleep(100000 * n);
+	}
+	return (NULL);
+}
+
+/* Close a connection ------------------------------------------------*/
+
+static void
+bes_ClosedFd(struct worker *w, struct vbe_conn *vc)
+{
+
+	CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC);
+	assert(vc->fd >= 0);
+	AN(vc->backend);
+	WSL(w, SLT_BackendClose, vc->fd, "%s", vc->backend->vcl_name);
+	AZ(close(vc->fd));
+	vc->fd = -1;
+	vc->backend = NULL;
+	LOCK(&vbemtx);
+	TAILQ_INSERT_HEAD(&vbe_head, vc, list);
+	VSL_stats->backend_unused++;
+	UNLOCK(&vbemtx);
+}
+
+/* Recycle a connection ----------------------------------------------*/
+
+static void
+bes_RecycleFd(struct worker *w, struct vbe_conn *vc)
+{
+
+	CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC);
+	assert(vc->fd >= 0);
+	AN(vc->backend);
+	WSL(w, SLT_BackendReuse, vc->fd, "%s", vc->backend->vcl_name);
+	LOCK(&vbemtx);
+	VSL_stats->backend_recycle++;
+	TAILQ_INSERT_HEAD(&vc->backend->connlist, vc, list);
+	UNLOCK(&vbemtx);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+bes_Init(void)
+{
+
+	MTX_INIT(&vbemtx);
+}
+
+
+/*--------------------------------------------------------------------*/
+
+
+struct backend_method backend_method_simple = {
+	.name =			"simple",
+	.getfd =		bes_GetFd,
+	.close =		bes_ClosedFd,
+	.recycle =		bes_RecycleFd,
+	.init =			bes_Init
+};

Modified: trunk/varnish-cache/bin/varnishd/cache_vrt.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_vrt.c	2007-08-20 11:37:11 UTC (rev 1891)
+++ trunk/varnish-cache/bin/varnishd/cache_vrt.c	2007-08-20 11:46:26 UTC (rev 1892)
@@ -540,6 +540,8 @@
 	b->hostname = strdup(t->host);
 	XXXAN(b->hostname);
 
+	b->method = &backend_method_simple;
+
 	*bp = b;
 }
 




More information about the varnish-commit mailing list