From: phk Date: Wed, 6 Feb 2008 15:19:49 +0000 (+0000) Subject: First part of major backend overhaul. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80cebdcce4ae9b40d70e40084a74655777c90861;p=varnish 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. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2437 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index e152b0f8..7303da0f 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -18,6 +18,7 @@ varnishd_SOURCES = \ cache_ban.c \ cache_center.c \ cache_cli.c \ + cache_dir_simple.c \ cache_expire.c \ cache_fetch.c \ cache_hash.c \ diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index c2369334..7a404b74 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -76,6 +76,7 @@ struct objhead; struct workreq; struct addrinfo; struct esi_bit; +struct vrt_backend; /*--------------------------------------------------------------------*/ @@ -345,6 +346,7 @@ struct sess { VTAILQ_ENTRY(sess) list; + struct director *director; struct backend *backend; struct bereq *bereq; struct object *obj; @@ -364,6 +366,23 @@ struct sess { 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 @@ struct vbe_conn { 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 @@ extern int vca_pipes[2]; /* 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 @@ void VBE_free_bereq(struct bereq *bereq); 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 @@ void VBE_UpdateHealth(const struct sess *sp, const struct vbe_conn *, int); 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); diff --git a/varnish-cache/bin/varnishd/cache_backend.c b/varnish-cache/bin/varnishd/cache_backend.c index 68450b6e..efd809de 100644 --- a/varnish-cache/bin/varnishd/cache_backend.c +++ b/varnish-cache/bin/varnishd/cache_backend.c @@ -32,6 +32,7 @@ * */ +#include #include #include #include @@ -43,6 +44,30 @@ #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 @@ void 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_DropRef(struct backend *b) 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 @@ void 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 @@ VBE_ClosedFd(struct worker *w, struct vbe_conn *vc) 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 @@ VBE_RecycleFd(struct worker *w, struct vbe_conn *vc) 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 @@ VBE_UpdateHealth(const struct sess *sp, const struct vbe_conn *vc, int a) 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) { - - if (bem->init != NULL) - bem->init(); + int error; + struct addrinfo *res, hint, *old; + + 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 @@ VBE_AddBackendMethod(const struct backend_method *bem) * 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) - continue; - if (strcmp(b->ident, ident)) + if (strcmp(b->ident, vb->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); +} diff --git a/varnish-cache/bin/varnishd/cache_backend_random.c b/varnish-cache/bin/varnishd/cache_backend_random.c index f1889133..c4586e58 100644 --- a/varnish-cache/bin/varnishd/cache_backend_random.c +++ b/varnish-cache/bin/varnishd/cache_backend_random.c @@ -45,6 +45,7 @@ #include "vrt.h" +#if 0 struct ber { unsigned magic; #define BER_MAGIC 0x645b03f4 @@ -434,22 +435,27 @@ struct backend_method backend_method_random = { .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; diff --git a/varnish-cache/bin/varnishd/cache_backend_simple.c b/varnish-cache/bin/varnishd/cache_backend_simple.c index 3fcf56bb..60a6a83c 100644 --- a/varnish-cache/bin/varnishd/cache_backend_simple.c +++ b/varnish-cache/bin/varnishd/cache_backend_simple.c @@ -44,6 +44,8 @@ #include "cache.h" #include "vrt.h" +#if 0 + struct bes { unsigned magic; #define BES_MAGIC 0x015e17ac @@ -343,55 +345,5 @@ bes_GetHostname(const struct backend *b) 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 diff --git a/varnish-cache/bin/varnishd/cache_center.c b/varnish-cache/bin/varnishd/cache_center.c index de5693d6..8a1929a1 100644 --- a/varnish-cache/bin/varnishd/cache_center.c +++ b/varnish-cache/bin/varnishd/cache_center.c @@ -195,7 +195,12 @@ cnt_done(struct sess *sp) 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 @@ cnt_fetch(struct sess *sp) 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 @@ cnt_start(struct sess *sp) 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 @@ CNT_Session(struct sess *sp) 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 diff --git a/varnish-cache/bin/varnishd/cache_dir_simple.c b/varnish-cache/bin/varnishd/cache_dir_simple.c new file mode 100644 index 00000000..227f7cdc --- /dev/null +++ b/varnish-cache/bin/varnishd/cache_dir_simple.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2008 Linpro AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * 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 +#include + +#include +#include +#include +#include +#include + +#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; +} diff --git a/varnish-cache/bin/varnishd/cache_fetch.c b/varnish-cache/bin/varnishd/cache_fetch.c index 40b24772..929fe773 100644 --- a/varnish-cache/bin/varnishd/cache_fetch.c +++ b/varnish-cache/bin/varnishd/cache_fetch.c @@ -309,7 +309,7 @@ Fetch(struct sess *sp) 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; diff --git a/varnish-cache/bin/varnishd/cache_http.c b/varnish-cache/bin/varnishd/cache_http.c index 334eca68..78c26085 100644 --- a/varnish-cache/bin/varnishd/cache_http.c +++ b/varnish-cache/bin/varnishd/cache_http.c @@ -649,8 +649,11 @@ http_FilterHeader(struct sess *sp, unsigned how) /* 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; } diff --git a/varnish-cache/bin/varnishd/cache_main.c b/varnish-cache/bin/varnishd/cache_main.c index 1e85a453..b3cb1694 100644 --- a/varnish-cache/bin/varnishd/cache_main.c +++ b/varnish-cache/bin/varnishd/cache_main.c @@ -83,7 +83,6 @@ child_main(void) SZOF(struct objhead); SZOF(struct sess); SZOF(struct vbe_conn); - SZOF(struct backend); CNT_Init(); diff --git a/varnish-cache/bin/varnishd/cache_panic.c b/varnish-cache/bin/varnishd/cache_panic.c index 2ff64151..83d10bb5 100644 --- a/varnish-cache/bin/varnishd/cache_panic.c +++ b/varnish-cache/bin/varnishd/cache_panic.c @@ -131,6 +131,7 @@ dump_object(const struct object *o) fp(" },\n"); } +#if 0 /* dump a struct backend */ static void dump_backend(const struct backend *be) @@ -141,12 +142,15 @@ dump_backend(const struct backend *be) 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 @@ dump_sess(const struct sess *sp) 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); diff --git a/varnish-cache/bin/varnishd/cache_vcl.c b/varnish-cache/bin/varnishd/cache_vcl.c index eb563874..a2ae4b9d 100644 --- a/varnish-cache/bin/varnishd/cache_vcl.c +++ b/varnish-cache/bin/varnishd/cache_vcl.c @@ -168,7 +168,7 @@ VCL_Load(const char *fn, const char *name, struct cli *cli) 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 @@ VCL_Nuke(struct vcls *vcl) 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); } diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index d4e8d138..503b7a78 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -391,17 +391,17 @@ VOBJ(unsigned, cacheable, cacheable) /*--------------------------------------------------------------------*/ 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 @@ VRT_r_obj_lastuse(const struct sess *sp) 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 @@ VRT_strcmp(const char *s1, const char *s2) return (strcmp(s1, s2)); } - -/*-------------------------------------------------------------------- - * Backend stuff - */ - -void -VRT_fini_backend(struct backend *b) -{ - - ASSERT_CLI(); - VBE_DropRef(b); -} diff --git a/varnish-cache/include/vcl.h b/varnish-cache/include/vcl.h index 98c5424b..18d0479a 100644 --- a/varnish-cache/include/vcl.h +++ b/varnish-cache/include/vcl.h @@ -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; diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index 1c6e06f4..e6e4eabd 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -36,54 +36,50 @@ 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; @@ -134,10 +130,9 @@ void VRT_ESI(struct sess *sp); 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); diff --git a/varnish-cache/include/vrt_obj.h b/varnish-cache/include/vrt_obj.h index d3aa010b..ba294512 100644 --- a/varnish-cache/include/vrt_obj.h +++ b/varnish-cache/include/vrt_obj.h @@ -15,8 +15,8 @@ void VRT_l_req_url(const struct sess *, const char *, ...); 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); diff --git a/varnish-cache/lib/libvcl/vcc_backend.c b/varnish-cache/lib/libvcl/vcc_backend.c index 49f2a613..afeb9383 100644 --- a/varnish-cache/lib/libvcl/vcc_backend.c +++ b/varnish-cache/lib/libvcl/vcc_backend.c @@ -70,10 +70,16 @@ CheckHostPort(const char *host, const char *port) */ 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 @@ vcc_FieldsOk(struct tokenlist *tl, const struct fld_spec *fs) * 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_ParseBackendHost(struct tokenlist *tl, int *nbh) 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 @@ vcc_ParseBackendHost(struct tokenlist *tl, int *nbh) 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 @@ vcc_ParseBackendHost(struct tokenlist *tl, int *nbh) 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 @@ vcc_ParseBackend(struct tokenlist *tl) 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 @@ vcc_ParseRandomDirector(struct tokenlist *tl, const struct token *t_first, struc 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_ParseRandomDirector(struct tokenlist *tl, const struct token *t_first, struc 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 @@ vcc_ParseRandomDirector(struct tokenlist *tl, const struct token *t_first, struc 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)); } /*-------------------------------------------------------------------- diff --git a/varnish-cache/lib/libvcl/vcc_compile.c b/varnish-cache/lib/libvcl/vcc_compile.c index cf34db36..9416452c 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.c +++ b/varnish-cache/lib/libvcl/vcc_compile.c @@ -295,7 +295,7 @@ static void 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 @@ static void 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 @@ EmitStruct(const struct tokenlist *tl) } 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); diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index 65ab9e21..19f976e9 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -311,17 +311,18 @@ vcl_output_lang_h(struct vsb *sb) 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,54 +389,50 @@ vcl_output_lang_h(struct vsb *sb) 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, "/*\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, "struct vrt_ref {\n"); vsb_cat(sb, " unsigned source;\n"); @@ -486,10 +483,9 @@ vcl_output_lang_h(struct vsb *sb) 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 @@ vcl_output_lang_h(struct vsb *sb) 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"); diff --git a/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl b/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl index 20c20d11..43b18140 100755 --- a/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl +++ b/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl @@ -123,17 +123,18 @@ proc warns {fd} { 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; diff --git a/varnish-cache/lib/libvcl/vcc_gen_obj.tcl b/varnish-cache/lib/libvcl/vcc_gen_obj.tcl index 3c7a9c25..45c8d4ee 100755 --- a/varnish-cache/lib/libvcl/vcc_gen_obj.tcl +++ b/varnish-cache/lib/libvcl/vcc_gen_obj.tcl @@ -211,7 +211,7 @@ set spobj { 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"