From 79e518a0ba9db14a65d488081e1268069e325a05 Mon Sep 17 00:00:00 2001 From: phk Date: Mon, 20 Aug 2007 12:45:58 +0000 Subject: [PATCH] Privatize the "simple" aspect of the simple backend. Move the VRT initializer for simple backends home. Add a backend method to get hostname. This may be a hack. Move fields private to "simple" to its private structure. Add cleanup method to backend, so we can collect the garbage. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1895 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 24 +-- varnish-cache/bin/varnishd/cache_backend.c | 6 +- .../bin/varnishd/cache_backend_simple.c | 154 +++++++++++++++--- varnish-cache/bin/varnishd/cache_http.c | 4 +- varnish-cache/bin/varnishd/cache_vrt.c | 45 +---- 5 files changed, 147 insertions(+), 86 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index d6895b19..21c74f01 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -334,12 +334,16 @@ 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); +typedef const char *vbe_gethostname_f(struct backend *); +typedef void vbe_cleanup_f(struct backend *); 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_init_f *init; }; @@ -353,29 +357,11 @@ struct backend { int refcount; struct backend_method *method; - - char *hostname; - char *portname; - - struct addrinfo *addr; - struct addrinfo *last_addr; - - TAILQ_HEAD(,vbe_conn) connlist; - - double dnsttl; - double dnstime; + void *priv; int health; double last_check; int minute_limit; - -#if 0 - double responsetime; - double timeout; - double bandwidth; - int down; -#endif - }; /* diff --git a/varnish-cache/bin/varnishd/cache_backend.c b/varnish-cache/bin/varnishd/cache_backend.c index 1d1bad19..8d392c16 100644 --- a/varnish-cache/bin/varnishd/cache_backend.c +++ b/varnish-cache/bin/varnishd/cache_backend.c @@ -98,9 +98,10 @@ VBE_NewBackend(struct backend_method *method) b = calloc(sizeof *b, 1); XXXAN(b); b->magic = BACKEND_MAGIC; - TAILQ_INIT(&b->connlist); b->method = method; b->refcount = 1; + b->last_check = TIM_mono(); + b->minute_limit = 1; TAILQ_INSERT_TAIL(&backendlist, b, list); return (b); } @@ -117,9 +118,8 @@ VBE_DropRef(struct backend *b) if (b->refcount > 0) return; TAILQ_REMOVE(&backendlist, b, list); + b->method->cleanup(b); free(b->vcl_name); - free(b->portname); - free(b->hostname); free(b); } diff --git a/varnish-cache/bin/varnishd/cache_backend_simple.c b/varnish-cache/bin/varnishd/cache_backend_simple.c index d36272a2..53623cfa 100644 --- a/varnish-cache/bin/varnishd/cache_backend_simple.c +++ b/varnish-cache/bin/varnishd/cache_backend_simple.c @@ -47,11 +47,24 @@ #include "shmlog.h" #include "cache.h" +#include "vrt.h" static TAILQ_HEAD(,vbe_conn) vbe_head = TAILQ_HEAD_INITIALIZER(vbe_head); static MTX besmtx; +struct bes { + unsigned magic; +#define BES_MAGIC 0x015e17ac + char *hostname; + char *portname; + struct addrinfo *addr; + struct addrinfo *last_addr; + double dnsttl; + double dnstime; + TAILQ_HEAD(, vbe_conn) connlist; +}; + /*--------------------------------------------------------------------*/ static struct vbe_conn * @@ -81,24 +94,27 @@ bes_lookup(struct backend *bp) { struct addrinfo *res, hint, *old; int error; + struct bes *bes; + + CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC); 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, + error = getaddrinfo(bes->hostname, + bes->portname == NULL ? "http" : bes->portname, &hint, &res); - bp->dnstime = TIM_mono(); + bes->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; + old = bes->addr; + bes->last_addr = res; + bes->addr = res; if (old != NULL) freeaddrinfo(old); } @@ -125,38 +141,41 @@ bes_conn_try(struct backend *bp, struct addrinfo **pai) { struct addrinfo *ai; int s; + struct bes *bes; + + CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC); /* First try the cached good address, and any following it */ - for (ai = bp->last_addr; ai != NULL; ai = ai->ai_next) { + for (ai = bes->last_addr; ai != NULL; ai = ai->ai_next) { s = bes_sock_conn(ai); if (s >= 0) { - bp->last_addr = ai; + bes->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) { + for (ai = bes->addr; ai != bes->last_addr; ai = ai->ai_next) { s = bes_sock_conn(ai); if (s >= 0) { - bp->last_addr = ai; + bes->last_addr = ai; *pai = ai; return (s); } } - if (bp->dnstime + bp->dnsttl >= TIM_mono()) + if (bes->dnstime + bes->dnsttl >= TIM_mono()) return (-1); /* Then do another lookup to catch DNS changes */ bes_lookup(bp); /* And try the entire list */ - for (ai = bp->addr; ai != NULL; ai = ai->ai_next) { + for (ai = bes->addr; ai != NULL; ai = ai->ai_next) { s = bes_sock_conn(ai); if (s >= 0) { - bp->last_addr = ai; + bes->last_addr = ai; *pai = ai; return (s); } @@ -172,9 +191,12 @@ bes_connect(struct sess *sp, struct backend *bp) char abuf1[TCP_ADDRBUFSIZE], abuf2[TCP_ADDRBUFSIZE]; char pbuf1[TCP_PORTBUFSIZE], pbuf2[TCP_PORTBUFSIZE]; struct addrinfo *ai; + struct bes *bes; + CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC); - AN(bp->hostname); + CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC); + AN(bes->hostname); s = bes_conn_try(bp, &ai); if (s < 0) @@ -205,18 +227,20 @@ bes_nextfd(struct sess *sp) struct pollfd pfd; struct backend *bp; int reuse = 0; + struct bes *bes; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); bp = sp->backend; CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC); + CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC); vc2 = NULL; while (1) { LOCK(&besmtx); - vc = TAILQ_FIRST(&bp->connlist); + vc = TAILQ_FIRST(&bes->connlist); if (vc != NULL) { assert(vc->backend == bp); assert(vc->fd >= 0); - TAILQ_REMOVE(&bp->connlist, vc, list); + TAILQ_REMOVE(&bes->connlist, vc, list); } else { vc2 = TAILQ_FIRST(&vbe_head); if (vc2 != NULL) { @@ -319,34 +343,126 @@ bes_ClosedFd(struct worker *w, struct vbe_conn *vc) static void bes_RecycleFd(struct worker *w, struct vbe_conn *vc) { + struct bes *bes; CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC); + CHECK_OBJ_NOTNULL(vc->backend, BACKEND_MAGIC); + CAST_OBJ_NOTNULL(bes, vc->backend->priv, BES_MAGIC); + assert(vc->fd >= 0); AN(vc->backend); WSL(w, SLT_BackendReuse, vc->fd, "%s", vc->backend->vcl_name); LOCK(&besmtx); VSL_stats->backend_recycle++; - TAILQ_INSERT_HEAD(&vc->backend->connlist, vc, list); + TAILQ_INSERT_HEAD(&bes->connlist, vc, list); UNLOCK(&besmtx); } /*--------------------------------------------------------------------*/ static void -bes_Init(void) +bes_Cleanup(struct backend *b) { + struct bes *bes; + struct vbe_conn *vbe; - MTX_INIT(&besmtx); + CAST_OBJ_NOTNULL(bes, b->priv, BES_MAGIC); + free(bes->portname); + free(bes->hostname); + freeaddrinfo(bes->addr); + while (1) { + vbe = TAILQ_FIRST(&bes->connlist); + if (vbe == NULL) + break; + TAILQ_REMOVE(&bes->connlist, vbe, list); + if (vbe->fd >= 0) + close(vbe->fd); + free(vbe); + } + free(bes); } +/*--------------------------------------------------------------------*/ + +static const char * +bes_GetHostname(struct backend *b) +{ + struct bes *bes; + + CHECK_OBJ_NOTNULL(b, SESS_MAGIC); + CAST_OBJ_NOTNULL(bes, b->priv, BES_MAGIC); + return (bes->hostname); +} /*--------------------------------------------------------------------*/ +static void +bes_Init(void) +{ + + MTX_INIT(&besmtx); +} + +/*--------------------------------------------------------------------*/ struct backend_method backend_method_simple = { .name = "simple", .getfd = bes_GetFd, .close = bes_ClosedFd, .recycle = bes_RecycleFd, + .gethostname = bes_GetHostname, + .cleanup = bes_Cleanup, .init = bes_Init }; + +/*--------------------------------------------------------------------*/ + +void +VRT_init_simple_backend(struct backend **bp, struct vrt_simple_backend *t) +{ + struct backend *b; + struct bes *bes; + + /* + * Scan existing backends to see if we can recycle one of them. + */ + TAILQ_FOREACH(b, &backendlist, list) { + CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC); + if (b->method != &backend_method_simple) + continue; + if (strcmp(b->vcl_name, t->name)) + continue; + CAST_OBJ_NOTNULL(bes, b->priv, BES_MAGIC); + if (strcmp(bes->portname, t->port)) + continue; + if (strcmp(bes->hostname, t->host)) + continue; + b->refcount++; + *bp = b; + return; + } + + b = VBE_NewBackend(&backend_method_simple); + + bes = calloc(sizeof *bes, 1); + XXXAN(bes); + bes->magic = BES_MAGIC; + + b->priv = bes; + + bes->dnsttl = 300; + + AN(t->name); + b->vcl_name = strdup(t->name); + XXXAN(b->vcl_name); + + AN(t->port); + bes->portname = strdup(t->port); + XXXAN(bes->portname); + + AN(t->host); + bes->hostname = strdup(t->host); + XXXAN(bes->hostname); + + *bp = b; +} diff --git a/varnish-cache/bin/varnishd/cache_http.c b/varnish-cache/bin/varnishd/cache_http.c index 8834437e..50609e1e 100644 --- a/varnish-cache/bin/varnishd/cache_http.c +++ b/varnish-cache/bin/varnishd/cache_http.c @@ -800,9 +800,11 @@ http_FilterHeader(struct sess *sp, unsigned how) http_PrintfHeader(sp->wrk, sp->fd, hp, "X-Varnish: %u", sp->xid); http_PrintfHeader(sp->wrk, sp->fd, hp, "X-Forwarded-for: %s", sp->addr); + + /* XXX: This really ought to go into the default VCL */ if (!http_GetHdr(hp, H_Host, &b)) { http_PrintfHeader(sp->wrk, sp->fd, hp, "Host: %s", - sp->backend->hostname); + sp->backend->method->gethostname(sp->backend)); } sp->bereq = bereq; } diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index 6ccfaacd..d0429587 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -513,51 +513,8 @@ VRT_strcmp(const char *s1, const char *s2) /*-------------------------------------------------------------------- - * Backend stuff, should probably move to its own file eventually + * Backend stuff */ -void -VRT_init_simple_backend(struct backend **bp, struct vrt_simple_backend *t) -{ - struct backend *b; - - /* - * Scan existing backends to see if we can recycle one of them. - */ - TAILQ_FOREACH(b, &backendlist, list) { - CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC); - if (b->method != &backend_method_simple) - continue; - if (strcmp(b->vcl_name, t->name)) - continue; - if (strcmp(b->portname, t->port)) - continue; - if (strcmp(b->hostname, t->host)) - continue; - b->refcount++; - *bp = b; - return; - } - - b = VBE_NewBackend(&backend_method_simple); - - b->dnsttl = 300; - b->last_check = TIM_mono(); - b->minute_limit = 1; - - AN(t->name); - b->vcl_name = strdup(t->name); - XXXAN(b->vcl_name); - - AN(t->port); - b->portname = strdup(t->port); - XXXAN(b->portname); - - AN(t->host); - b->hostname = strdup(t->host); - XXXAN(b->hostname); - - *bp = b; -} void VRT_fini_backend(struct backend *b) -- 2.39.5