From 1ec8ab9d55eef6cc729e9091e7d9c2e1bb1a4d26 Mon Sep 17 00:00:00 2001 From: phk Date: Mon, 20 Aug 2007 12:19:16 +0000 Subject: [PATCH] Give backends a reference count and reuse any existing identical backend when a new VCL instantiates a backend. Drop backends when their reference count goes to zero. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1894 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 18 ++++++-- varnish-cache/bin/varnishd/cache_backend.c | 49 +++++++++++++++++++--- varnish-cache/bin/varnishd/cache_vrt.c | 29 +++++++++---- 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index 158b69d6..d6895b19 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -347,12 +347,15 @@ struct backend_method { struct backend { unsigned magic; #define BACKEND_MAGIC 0x64c4c7c6 - const char *vcl_name; + char *vcl_name; + + TAILQ_ENTRY(backend) list; + int refcount; struct backend_method *method; - const char *hostname; - const char *portname; + char *hostname; + char *portname; struct addrinfo *addr; struct addrinfo *last_addr; @@ -375,6 +378,12 @@ struct backend { }; +/* + * NB: This list is not locked, it is only ever manipulated from the + * cachers CLI thread. + */ +TAILQ_HEAD(backendlist, backend); + /* Prototypes etc ----------------------------------------------------*/ @@ -393,6 +402,9 @@ 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); void VBE_free_bereq(struct bereq *bereq); +extern struct backendlist backendlist; +void VBE_DropRef(struct backend *); +struct backend *VBE_NewBackend(struct backend_method *method); /* cache_backend_simple.c */ extern struct backend_method backend_method_simple; diff --git a/varnish-cache/bin/varnishd/cache_backend.c b/varnish-cache/bin/varnishd/cache_backend.c index 1170d481..1d1bad19 100644 --- a/varnish-cache/bin/varnishd/cache_backend.c +++ b/varnish-cache/bin/varnishd/cache_backend.c @@ -41,7 +41,9 @@ static TAILQ_HEAD(,bereq) bereq_head = TAILQ_HEAD_INITIALIZER(bereq_head); -static MTX vbemtx; +static MTX VBE_mtx; + +struct backendlist backendlist = TAILQ_HEAD_INITIALIZER(backendlist); /*-------------------------------------------------------------------- * Get a http structure for talking to the backend. @@ -53,11 +55,11 @@ VBE_new_bereq(void) struct bereq *bereq; volatile unsigned len; - LOCK(&vbemtx); + LOCK(&VBE_mtx); bereq = TAILQ_FIRST(&bereq_head); if (bereq != NULL) TAILQ_REMOVE(&bereq_head, bereq, list); - UNLOCK(&vbemtx); + UNLOCK(&VBE_mtx); if (bereq != NULL) { CHECK_OBJ(bereq, BEREQ_MAGIC); } else { @@ -81,9 +83,44 @@ VBE_free_bereq(struct bereq *bereq) { CHECK_OBJ_NOTNULL(bereq, BEREQ_MAGIC); - LOCK(&vbemtx); + LOCK(&VBE_mtx); TAILQ_INSERT_HEAD(&bereq_head, bereq, list); - UNLOCK(&vbemtx); + UNLOCK(&VBE_mtx); +} + +/*--------------------------------------------------------------------*/ + +struct backend * +VBE_NewBackend(struct backend_method *method) +{ + struct backend *b; + + b = calloc(sizeof *b, 1); + XXXAN(b); + b->magic = BACKEND_MAGIC; + TAILQ_INIT(&b->connlist); + b->method = method; + b->refcount = 1; + TAILQ_INSERT_TAIL(&backendlist, b, list); + return (b); +} + +/*--------------------------------------------------------------------*/ + +void +VBE_DropRef(struct backend *b) +{ + + CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC); + + b->refcount--; + if (b->refcount > 0) + return; + TAILQ_REMOVE(&backendlist, b, list); + free(b->vcl_name); + free(b->portname); + free(b->hostname); + free(b); } /*--------------------------------------------------------------------*/ @@ -119,6 +156,6 @@ void VBE_Init(void) { - MTX_INIT(&vbemtx); + MTX_INIT(&VBE_mtx); backend_method_simple.init(); } diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index b6876422..6ccfaacd 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -520,11 +520,27 @@ VRT_init_simple_backend(struct backend **bp, struct vrt_simple_backend *t) { struct backend *b; - b = calloc(sizeof *b, 1); - XXXAN(b); - b->magic = BACKEND_MAGIC; + /* + * 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; - TAILQ_INIT(&b->connlist); b->last_check = TIM_mono(); b->minute_limit = 1; @@ -540,13 +556,12 @@ VRT_init_simple_backend(struct backend **bp, struct vrt_simple_backend *t) b->hostname = strdup(t->host); XXXAN(b->hostname); - b->method = &backend_method_simple; - *bp = b; } void VRT_fini_backend(struct backend *b) { - (void)b; + + VBE_DropRef(b); } -- 2.39.5