]> err.no Git - varnish/commitdiff
At the expense of some complexity and a small runtime overhead,
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 20 Jun 2006 10:31:50 +0000 (10:31 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 20 Jun 2006 10:31:50 +0000 (10:31 +0000)
isolate the compiled code from the internal structures of the cache
process through of VRT functions.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@211 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache.h
varnish-cache/bin/varnishd/cache_acceptor.c
varnish-cache/bin/varnishd/cache_http.c
varnish-cache/bin/varnishd/cache_pool.c
varnish-cache/bin/varnishd/cache_vrt.c
varnish-cache/include/vcl_lang.h
varnish-cache/include/vrt.h
varnish-cache/lib/libvcl/vcl_compile.c
varnish-cache/lib/libvcl/vcl_fixed_token.c

index 68e66bb6280f17810fc7e8598ef6c8c97120aef8..a7f70cfb5690dca64981dc635a65f9d563b482d6 100644 (file)
@@ -2,6 +2,8 @@
  * $Id$
  */
 
+#include <sys/queue.h>
+
 struct event_base;
 struct sbuf;
 
@@ -55,6 +57,73 @@ struct storage {
  */
 extern struct stevedore *stevedore;
 
+/* Storage -----------------------------------------------------------*/
+
+struct sess;
+typedef void sesscb_f(struct sess *sp);
+
+#define VCA_ADDRBUFSIZE                32
+
+struct object {        
+       unsigned char           hash[16];
+       unsigned                refcnt;
+       unsigned                valid;
+       unsigned                cacheable;
+
+       unsigned                busy;
+       unsigned                len;
+
+       char                    *header;
+
+       TAILQ_HEAD(, storage)   store;
+};
+
+#define        HND_Error       (1 << 0)
+#define        HND_Pipe        (1 << 1)
+#define        HND_Pass        (1 << 2)
+#define        HND_Lookup      (1 << 3)
+#define        HND_Fetch       (1 << 4)
+#define        HND_Insert      (1 << 5)
+#define        HND_Deliver     (1 << 6)
+
+struct sess {
+       int                     fd;
+
+       /* formatted ascii client address */
+       char                    addr[VCA_ADDRBUFSIZE];
+
+       /* HTTP request */
+       struct http             *http;
+
+       unsigned                handling;
+
+       TAILQ_ENTRY(sess)       list;
+
+       sesscb_f                *sesscb;
+
+       struct backend          *backend;
+       struct object           *obj;
+       struct VCL_conf         *vcl;
+
+       /* Various internal stuff */
+       struct event            *rd_e;
+       struct sessmem          *mem;
+};
+
+struct backend {
+       const char      *hostname;
+       const char      *portname;
+       struct addrinfo *addr;
+       unsigned        ip;
+       double          responsetime;
+       double          timeout;
+       double          bandwidth;
+       int             down;
+
+       /* internal stuff */
+       struct vbe      *vbe;
+};
+
 /* Prototypes etc ----------------------------------------------------*/
 
 
index 6d201fd99a4e7ed67850f7a5b1480029a80407af..62b1e22698ab1cc19544ce414328c9a112032d1a 100644 (file)
@@ -16,6 +16,7 @@
 #include <sys/uio.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/queue.h>
 
 #include <netdb.h>
 
@@ -25,7 +26,6 @@
 #include "config.h"
 #include "compat.h"
 #include "libvarnish.h"
-#include "vcl_lang.h"
 #include "heritage.h"
 #include "shmlog.h"
 #include "cache.h"
index 25358edb843828fcd2f26697c56ed5aee59c0163..b55977bc190d52a0756a949a82d8953b3540690f 100644 (file)
@@ -16,7 +16,6 @@
 
 #include "libvarnish.h"
 #include "shmlog.h"
-#include "vcl_lang.h"
 #include "cache.h"
 
 static unsigned                http_bufsize    = 4096;
index 8ef10d5ce301c05fbd901a2826f7387192a10199..5051097f80b7e8f1b87778e3d94f890b105815b0 100644 (file)
@@ -102,7 +102,7 @@ CacheWorker(void *priv)
 
                http_Dissect(sp->http, sp->fd, 1);
 
-               sp->backend = sp->vcl->default_backend;
+               sp->backend = sp->vcl->backend[0];
 
                VCL_recv_method(sp);
 
index 33c6c78b8d4e999802d8ec75217f933f047cd852..3c03090728a9e4d80be3a83bf385be12d4c5f05f 100644 (file)
@@ -16,9 +16,9 @@
 #include "cli.h"
 #include "cli_priv.h"
 #include "shmlog.h"
-#include "vcl_lang.h"
 #include "vrt.h"
 #include "libvarnish.h"
+#include "vcl_lang.h"
 #include "cache.h"
 
 /*--------------------------------------------------------------------*/
@@ -71,8 +71,58 @@ VRT_GetReq(struct sess *sp)
 /*--------------------------------------------------------------------*/
 
 void
-VRT_handling(struct sess *sp, enum handling hand)
+VRT_handling(struct sess *sp, unsigned hand)
+{
+
+       assert(!(hand & (hand -1)));    /* must be power of two */
+       switch (hand) {
+#define FOO(a,b)  case VRT_H_##a: sp->handling = HND_##b; break;
+       FOO(error, Error);
+       FOO(pipe, Pipe);
+       FOO(pass, Pass);
+       FOO(lookup, Lookup);
+       FOO(fetch, Fetch);
+       FOO(insert, Insert);
+       FOO(deliver, Deliver);
+#undef FOO
+       default:
+               assert(hand == 0);
+       }
+}
+
+int
+VRT_obj_valid(struct sess *sp)
+{
+       return (sp->obj->valid);
+}
+
+int
+VRT_obj_cacheable(struct sess *sp)
+{
+       return (sp->obj->cacheable);
+}
+
+void
+VRT_set_backend_hostname(struct backend *be, const char *h)
+{
+       be->hostname = h;
+}
+
+void
+VRT_set_backend_portname(struct backend *be, const char *p)
 {
+       be->portname = p;
+}
 
-       sp->handling = hand;
+void
+VRT_alloc_backends(struct VCL_conf *cp)
+{
+       int i;
+
+       cp->backend = calloc(sizeof *cp->backend, cp->nbackend);
+       assert(cp->backend != NULL);
+       for (i = 0; i < cp->nbackend; i++) {
+               cp->backend[i] = calloc(sizeof *cp->backend[i], 1);
+               assert(cp->backend[i] != NULL);
+       }
 }
index fed7dd7adfe5fe58aa1df6865a04dd18b6a4b1cb..2286356222c408c8153f4fd6dc34e21465fe6e0a 100644 (file)
@@ -5,79 +5,7 @@
  * XXX: *MUST* be rerun.
  */
 
-/* XXX: This include is bad.  The VCL compiler shouldn't know about it. */
-#include <sys/queue.h>
-
 struct sess;
-typedef void sesscb_f(struct sess *sp);
-
-#define VCA_ADDRBUFSIZE                32
-
-struct object {        
-       unsigned char           hash[16];
-       unsigned                refcnt;
-       unsigned                valid;
-       unsigned                cacheable;
-
-       unsigned                busy;
-       unsigned                len;
-
-       char                    *header;
-
-       TAILQ_HEAD(, storage)   store;
-};
-enum handling {
-       HND_Error       = (1 << 0),
-       HND_Pipe        = (1 << 1),
-       HND_Pass        = (1 << 2),
-       HND_Lookup      = (1 << 3),
-       HND_Fetch       = (1 << 4),
-       HND_Insert      = (1 << 5),
-       HND_Deliver     = (1 << 6),
-};
-
-struct sess {
-       int                     fd;
-
-       /* formatted ascii client address */
-       char                    addr[VCA_ADDRBUFSIZE];
-
-       /* HTTP request */
-       struct http             *http;
-
-       enum handling           handling;
-
-       TAILQ_ENTRY(sess)       list;
-
-       sesscb_f                *sesscb;
-
-       struct backend          *backend;
-       struct object           *obj;
-       struct VCL_conf         *vcl;
-
-       /* Various internal stuff */
-       struct event            *rd_e;
-       struct sessmem          *mem;
-};
-
-struct backend {
-       const char      *hostname;
-       const char      *portname;
-       struct addrinfo *addr;
-       unsigned        ip;
-       double          responsetime;
-       double          timeout;
-       double          bandwidth;
-       int             down;
-
-       /* internal stuff */
-       struct vbe      *vbe;
-};
-
-#if 0
-int ip_match(unsigned, struct vcl_acl *);
-int string_match(const char *, const char *);
-#endif
 
 typedef void vcl_init_f(void);
 typedef int vcl_func_f(struct sess *sp);
@@ -90,7 +18,8 @@ struct VCL_conf {
        vcl_func_f      *hit_func;
        vcl_func_f      *miss_func;
        vcl_func_f      *fetch_func;
-       struct backend  *default_backend;
+       struct backend  **backend;
+       unsigned        nbackend;
        struct vrt_ref  *ref;
        unsigned        nref;
        unsigned        busy;
index a3a24b66489f14cdc1a9bcd605525483124bb462..49d05fe2c2369605ff0e76eeb7999c278dff5c7c 100644 (file)
@@ -6,6 +6,18 @@
  * XXX: *MUST* be rerun.
  */
 
+#define        VRT_H_error     (1 << 0)
+#define        VRT_H_pipe      (1 << 1)
+#define        VRT_H_pass      (1 << 2)
+#define        VRT_H_lookup    (1 << 3)
+#define        VRT_H_fetch     (1 << 4)
+#define        VRT_H_insert    (1 << 5)
+#define        VRT_H_deliver   (1 << 6)
+
+struct sess;
+struct backend;
+struct VCL_conf;
+
 struct vrt_ref {
        unsigned        line;
        unsigned        pos;
@@ -31,7 +43,14 @@ int VRT_switch_config(const char *);
 
 char *VRT_GetHdr(struct sess *, const char *);
 char *VRT_GetReq(struct sess *);
-void VRT_handling(struct sess *sp, enum handling hand);
+void VRT_handling(struct sess *sp, unsigned hand);
+int VRT_obj_valid(struct sess *);
+int VRT_obj_cachable(struct sess *);
+
+void VRT_set_backend_hostname(struct backend *, const char *);
+void VRT_set_backend_portname(struct backend *, const char *);
+
+void VRT_alloc_backends(struct VCL_conf *cp);
 
 #define VRT_done(sp, hand)                     \
        do {                                    \
index ae7f3b97d30d657b562049b630123aa07dbe9c6a..52b41fc64a5e8e93959991626aa83b16609b28e9 100644 (file)
@@ -76,6 +76,7 @@ struct tokenlist {
        TAILQ_HEAD(, ref)       refs;
        struct sbuf             *sb;
        int                     err;
+       int                     nbackend;
 };
 
 enum var_type {
@@ -93,12 +94,6 @@ enum var_type {
        HEADER
 };
 
-struct var {
-       const char              *name;
-       enum var_type           fmt;
-       int                     len;
-       const char              *cname;
-};
 
 enum ref_type {
        R_FUNC,
@@ -114,17 +109,26 @@ struct ref {
        TAILQ_ENTRY(ref)        list;
 };
 
+struct var {
+       const char              *name;
+       enum var_type           fmt;
+       int                     len;
+       const char              *rname;
+       const char              *lname;
+};
 
 static struct var be_vars[] = {
-       { "backend.host",               HOSTNAME, 0,  "backend->hostname"    },
-       { "backend.port",               PORTNAME, 0,  "backend->portname"    },
+       { "backend.host",
+               HOSTNAME, 0,  NULL, "VRT_set_backend_hostname(backend, %s)" },
+       { "backend.port",
+               PORTNAME, 0,  NULL, "VRT_set_backend_portname(backend, %s)" },
 };
 
 
 static struct var vars[] = {
        { "req.request",                STRING,   0,  "VRT_GetReq(sp)"       },
-       { "obj.valid",                  BOOL,     0,  "sp->obj->valid"     },
-       { "obj.cacheable",              BOOL,     0,  "sp->obj->cacheable" },
+       { "obj.valid",                  BOOL,     0,  "VRT_obj_valid(sp)"     },
+       { "obj.cacheable",              BOOL,     0,  "VRT_obj_cacheable(sp)" },
        { "req.http.",                  HEADER,   0,  NULL },
 #if 0
        { "req.ttlfactor",              FLOAT, 0,   "req->ttlfactor" },
@@ -569,7 +573,7 @@ HeaderVar(struct tokenlist *tl, struct token *t, struct var *vh)
        v->fmt = STRING;
        asprintf(&p, "VRT_GetHdr(sp, \"%s\")", v->name + vh->len);
        assert(p != NULL);
-       v->cname = p;
+       v->rname = p;
        return (v);
 }
 
@@ -648,7 +652,7 @@ Cond_Ip(struct var *vp, struct tokenlist *tl)
                I(tl);
                AddRef(tl, tl->t, R_ACL);
                sbuf_printf(tl->fc, "ip_match(%s, acl_%*.*s)\n",
-                   vp->cname,
+                   vp->rname,
                    tl->t->e - tl->t->b,
                    tl->t->e - tl->t->b, tl->t->b);
                NextToken(tl);
@@ -657,7 +661,7 @@ Cond_Ip(struct var *vp, struct tokenlist *tl)
        case T_NEQ:
                I(tl);
                sbuf_printf(tl->fc, "%s %*.*s ",
-                   vp->cname,
+                   vp->rname,
                    tl->t->e - tl->t->b,
                    tl->t->e - tl->t->b, tl->t->b);
                NextToken(tl);
@@ -682,7 +686,7 @@ Cond_String(struct var *vp, struct tokenlist *tl)
 
        switch (tl->t->tok) {
        case '~':
-               I(tl); sbuf_printf(tl->fc, "string_match(%s, ", vp->cname);
+               I(tl); sbuf_printf(tl->fc, "string_match(%s, ", vp->rname);
                NextToken(tl);
                ExpectErr(tl, CSTR);
                sbuf_printf(tl->fc, "%*.*s)\n",
@@ -694,7 +698,7 @@ Cond_String(struct var *vp, struct tokenlist *tl)
        case T_NEQ:
                I(tl);
                sbuf_printf(tl->fc, "%sstrcmp(%s, ",
-                   tl->t->tok == T_EQ ? "!" : "", vp->cname);
+                   tl->t->tok == T_EQ ? "!" : "", vp->rname);
                NextToken(tl);
                ExpectErr(tl, CSTR);
                sbuf_printf(tl->fc, "%*.*s)\n",
@@ -703,7 +707,7 @@ Cond_String(struct var *vp, struct tokenlist *tl)
                NextToken(tl);
                break;
        default:
-               I(tl); sbuf_printf(tl->fc, "%s != (void*)0", vp->cname);
+               I(tl); sbuf_printf(tl->fc, "%s != (void*)0", vp->rname);
                break;
        }
 }
@@ -713,7 +717,7 @@ Cond_Int(struct var *vp, struct tokenlist *tl)
 {
 
        I(tl);
-       sbuf_printf(tl->fc, "%s ", vp->cname);
+       sbuf_printf(tl->fc, "%s ", vp->rname);
        switch (tl->t->tok) {
        case T_EQ:
        case T_NEQ:
@@ -764,7 +768,7 @@ Cond_Bool(struct var *vp, struct tokenlist *tl)
 {
 
        I(tl);
-       sbuf_printf(tl->fc, "%s\n", vp->cname);
+       sbuf_printf(tl->fc, "%s\n", vp->rname);
 }
 
 static void
@@ -921,19 +925,13 @@ Action(struct tokenlist *tl)
                sbuf_printf(tl->fc, "VCL_no_cache(sp);\n");
                return;
        case T_DELIVER:
-               I(tl); sbuf_printf(tl->fc, "VRT_done(sp, HND_Deliver);\n");
-               return;
        case T_LOOKUP:
-               I(tl); sbuf_printf(tl->fc, "VRT_done(sp, HND_Lookup);\n");
-               return;
        case T_PASS:
-               I(tl); sbuf_printf(tl->fc, "VRT_done(sp, HND_Pass);\n");
-               return;
        case T_FETCH:
-               I(tl); sbuf_printf(tl->fc, "VRT_done(sp, HND_Fetch);\n");
-               return;
        case T_INSERT:
-               I(tl); sbuf_printf(tl->fc, "VRT_done(sp, HND_Insert);\n");
+               I(tl); sbuf_printf(tl->fc, "VRT_done(sp, VRT_H_%*.*s);\n",
+                   at->e - at->b,
+                   at->e - at->b, at->b);
                return;
        case T_ERROR:
                if (tl->t->tok == CNUM)
@@ -949,7 +947,7 @@ Action(struct tokenlist *tl)
                        NextToken(tl);
                } else
                        sbuf_printf(tl->fc, "(const char *)0);\n");
-               I(tl); sbuf_printf(tl->fc, "VRT_done(sp, HND_Error);\n");
+               I(tl); sbuf_printf(tl->fc, "VRT_done(sp, VRT_H_error);\n");
                return;
        case T_SWITCH_CONFIG:
                ExpectErr(tl, ID);
@@ -988,7 +986,7 @@ Action(struct tokenlist *tl)
                ERRCHK(tl);
                assert(vp != NULL);
                I(tl);
-               sbuf_printf(tl->fc, "%s ", vp->cname);
+               sbuf_printf(tl->fc, "%s ", vp->rname);
                NextToken(tl);
                switch (vp->fmt) {
                case INT:
@@ -1186,20 +1184,22 @@ Backend(struct tokenlist *tl)
        t_be = tl->t;
        AddDef(tl, tl->t, R_BACKEND);
        I(tl);
-       sbuf_printf(tl->fh, "static struct backend VGC_backend_%*.*s;\n",
-           tl->t->e - tl->t->b,
-           tl->t->e - tl->t->b, tl->t->b);
-       sbuf_printf(tl->fc, "static struct backend VGC_backend_%*.*s;\n",
+       sbuf_printf(tl->fh,
+           "#define VGC_backend_%*.*s (VCL_conf.backend[%d])\n",
            tl->t->e - tl->t->b,
-           tl->t->e - tl->t->b, tl->t->b);
+           tl->t->e - tl->t->b, tl->t->b, tl->nbackend);
        sbuf_printf(tl->fc, "static void\n");
-       I(tl);
-       sbuf_printf(tl->fc,
-           "VGC_init_backend_%*.*s (struct backend *backend)\n",
+       I(tl); sbuf_printf(tl->fc,
+           "VGC_init_backend_%*.*s (void)\n",
            tl->t->e - tl->t->b,
            tl->t->e - tl->t->b, tl->t->b);
        I(tl);
        sbuf_printf(tl->fc, "{\n");
+       I(tl); sbuf_printf(tl->fc,
+           "\tstruct backend *backend = VGC_backend_%*.*s;\n",
+           tl->t->e - tl->t->b,
+           tl->t->e - tl->t->b, tl->t->b);
+       I(tl); sbuf_printf(tl->fc, "\tconst char *p;\n");
        NextToken(tl);
        ExpectErr(tl, '{');
        NextToken(tl);
@@ -1220,21 +1220,24 @@ Backend(struct tokenlist *tl)
                        ExpectErr(tl, CSTR);
                        t_host = tl->t;
                        host = EncString(tl->t);
-                       I(tl);
-                       sbuf_printf(tl->fc, "\t%s = %*.*s;\n",
-                           vp->cname,
+                       I(tl); sbuf_printf(tl->fc, "\tp = %*.*s;\n",
                            tl->t->e - tl->t->b,
                            tl->t->e - tl->t->b, tl->t->b);
+                       I(tl); sbuf_printf(tl->fc, "\t");
+                       sbuf_printf(tl->fc, vp->lname, "p");
+                       sbuf_printf(tl->fc, ";\n");
                        NextToken(tl);
                        break;
                case PORTNAME:
                        ExpectErr(tl, CSTR);
                        t_port = tl->t;
                        port = EncString(tl->t);
-                       sbuf_printf(tl->fc, "\t%s = %*.*s;\n",
-                           vp->cname,
+                       I(tl); sbuf_printf(tl->fc, "\tp = %*.*s;\n",
                            tl->t->e - tl->t->b,
                            tl->t->e - tl->t->b, tl->t->b);
+                       I(tl); sbuf_printf(tl->fc, "\t");
+                       sbuf_printf(tl->fc, vp->lname, "p");
+                       sbuf_printf(tl->fc, ";\n");
                        NextToken(tl);
                        break;
                default:
@@ -1279,6 +1282,7 @@ Backend(struct tokenlist *tl)
        I(tl);
        sbuf_printf(tl->fc, "}\n");
        sbuf_printf(tl->fc, "\n");
+       tl->nbackend++;
 }
 
 /*--------------------------------------------------------------------*/
@@ -1549,6 +1553,9 @@ EmitInitFunc(struct tokenlist *tl)
            "\nstatic void\n"
            "VGC_Init(void)\n"
            "{\n\n");
+
+       sbuf_printf(tl->fc,
+           "\tVRT_alloc_backends(&VCL_conf);\n");
        
        TAILQ_FOREACH(r, &tl->refs, list) {
                switch(r->type) {
@@ -1558,9 +1565,7 @@ EmitInitFunc(struct tokenlist *tl)
                        break;
                case R_BACKEND:
                        sbuf_printf(tl->fc,
-                           "\tVGC_init_backend_%*.*s(&VGC_backend_%*.*s);\n",
-                           r->name->e - r->name->b,
-                           r->name->e - r->name->b, r->name->b,
+                           "\tVGC_init_backend_%*.*s();\n",
                            r->name->e - r->name->b,
                            r->name->e - r->name->b, r->name->b);
                        break;
@@ -1585,7 +1590,7 @@ EmitStruct(struct tokenlist *tl)
        sbuf_printf(tl->fc, "\t.miss_func = VGC_function_vcl_miss,\n");
        sbuf_printf(tl->fc, "\t.fetch_func = VGC_function_vcl_fetch,\n");
        sbuf_printf(tl->fc,
-           "\t.default_backend = &VGC_backend_default,\n");
+           "\t.nbackend = %d,\n", tl->nbackend);
        sbuf_printf(tl->fc,
            "\t.ref = VGC_ref,\n");
        sbuf_printf(tl->fc,
@@ -1616,6 +1621,8 @@ VCC_Compile(struct sbuf *sb, const char *b, const char *e)
        tokens.fh = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
        assert(tokens.fh != NULL);
 
+       sbuf_printf(tokens.fc, "extern struct VCL_conf VCL_conf;\n");
+
        tokens.b = b;
        if (e == NULL)
                e = strchr(b, '\0');
index 14688b56ab881ecc33a1670d122c97ebc589659a..be7cbe58f96690b3d32a145d5d74b392306b08a5 100644 (file)
@@ -404,79 +404,7 @@ vcl_output_lang_h(FILE *f)
        fputs(" * XXX: *MUST* be rerun.\n", f);
        fputs(" */\n", f);
        fputs("\n", f);
-       fputs("/* XXX: This include is bad.  The VCL compiler shouldn't know about it. */\n", f);
-       fputs("#include <sys/queue.h>\n", f);
-       fputs("\n", f);
        fputs("struct sess;\n", f);
-       fputs("typedef void sesscb_f(struct sess *sp);\n", f);
-       fputs("\n", f);
-       fputs("#define VCA_ADDRBUFSIZE          32\n", f);
-       fputs("\n", f);
-       fputs("struct object {  \n", f);
-       fputs(" unsigned char           hash[16];\n", f);
-       fputs(" unsigned                refcnt;\n", f);
-       fputs(" unsigned                valid;\n", f);
-       fputs(" unsigned                cacheable;\n", f);
-       fputs("\n", f);
-       fputs(" unsigned                busy;\n", f);
-       fputs(" unsigned                len;\n", f);
-       fputs("\n", f);
-       fputs(" char                    *header;\n", f);
-       fputs("\n", f);
-       fputs(" TAILQ_HEAD(, storage)   store;\n", f);
-       fputs("};\n", f);
-       fputs("enum handling {\n", f);
-       fputs(" HND_Error       = (1 << 0),\n", f);
-       fputs(" HND_Pipe        = (1 << 1),\n", f);
-       fputs(" HND_Pass        = (1 << 2),\n", f);
-       fputs(" HND_Lookup      = (1 << 3),\n", f);
-       fputs(" HND_Fetch       = (1 << 4),\n", f);
-       fputs(" HND_Insert      = (1 << 5),\n", f);
-       fputs(" HND_Deliver     = (1 << 6),\n", f);
-       fputs("};\n", f);
-       fputs("\n", f);
-       fputs("struct sess {\n", f);
-       fputs(" int                     fd;\n", f);
-       fputs("\n", f);
-       fputs(" /* formatted ascii client address */\n", f);
-       fputs(" char                    addr[VCA_ADDRBUFSIZE];\n", f);
-       fputs("\n", f);
-       fputs(" /* HTTP request */\n", f);
-       fputs(" struct http             *http;\n", f);
-       fputs("\n", f);
-       fputs(" enum handling           handling;\n", f);
-       fputs("\n", f);
-       fputs(" TAILQ_ENTRY(sess)       list;\n", f);
-       fputs("\n", f);
-       fputs(" sesscb_f                *sesscb;\n", f);
-       fputs("\n", f);
-       fputs(" struct backend          *backend;\n", f);
-       fputs(" struct object           *obj;\n", f);
-       fputs(" struct VCL_conf         *vcl;\n", f);
-       fputs("\n", f);
-       fputs(" /* Various internal stuff */\n", f);
-       fputs(" struct event            *rd_e;\n", f);
-       fputs(" struct sessmem          *mem;\n", f);
-       fputs("};\n", f);
-       fputs("\n", f);
-       fputs("struct backend {\n", f);
-       fputs(" const char      *hostname;\n", f);
-       fputs(" const char      *portname;\n", f);
-       fputs(" struct addrinfo *addr;\n", f);
-       fputs(" unsigned        ip;\n", f);
-       fputs(" double          responsetime;\n", f);
-       fputs(" double          timeout;\n", f);
-       fputs(" double          bandwidth;\n", f);
-       fputs(" int             down;\n", f);
-       fputs("\n", f);
-       fputs(" /* internal stuff */\n", f);
-       fputs(" struct vbe      *vbe;\n", f);
-       fputs("};\n", f);
-       fputs("\n", f);
-       fputs("#if 0\n", f);
-       fputs("int ip_match(unsigned, struct vcl_acl *);\n", f);
-       fputs("int string_match(const char *, const char *);\n", f);
-       fputs("#endif\n", f);
        fputs("\n", f);
        fputs("typedef void vcl_init_f(void);\n", f);
        fputs("typedef int vcl_func_f(struct sess *sp);\n", f);
@@ -489,7 +417,8 @@ vcl_output_lang_h(FILE *f)
        fputs(" vcl_func_f      *hit_func;\n", f);
        fputs(" vcl_func_f      *miss_func;\n", f);
        fputs(" vcl_func_f      *fetch_func;\n", f);
-       fputs(" struct backend  *default_backend;\n", f);
+       fputs(" struct backend  **backend;\n", f);
+       fputs(" unsigned        nbackend;\n", f);
        fputs(" struct vrt_ref  *ref;\n", f);
        fputs(" unsigned        nref;\n", f);
        fputs(" unsigned        busy;\n", f);
@@ -502,6 +431,17 @@ vcl_output_lang_h(FILE *f)
        fputs(" * XXX: *MUST* be rerun.\n", f);
        fputs(" */\n", f);
        fputs("\n", f);
+       fputs("#define  VRT_H_error     (1 << 0)\n", f);
+       fputs("#define  VRT_H_pipe      (1 << 1)\n", f);
+       fputs("#define  VRT_H_pass      (1 << 2)\n", f);
+       fputs("#define  VRT_H_lookup    (1 << 3)\n", f);
+       fputs("#define  VRT_H_fetch     (1 << 4)\n", f);
+       fputs("#define  VRT_H_insert    (1 << 5)\n", f);
+       fputs("#define  VRT_H_deliver   (1 << 6)\n", f);
+       fputs("\n", f);
+       fputs("struct sess;\n", f);
+       fputs("struct backend;\n", f);
+       fputs("\n", f);
        fputs("struct vrt_ref {\n", f);
        fputs(" unsigned        line;\n", f);
        fputs(" unsigned        pos;\n", f);
@@ -527,7 +467,14 @@ vcl_output_lang_h(FILE *f)
        fputs("\n", f);
        fputs("char *VRT_GetHdr(struct sess *, const char *);\n", f);
        fputs("char *VRT_GetReq(struct sess *);\n", f);
-       fputs("void VRT_handling(struct sess *sp, enum handling hand);\n", f);
+       fputs("void VRT_handling(struct sess *sp, unsigned hand);\n", f);
+       fputs("int VRT_obj_valid(struct sess *);\n", f);
+       fputs("int VRT_obj_cachable(struct sess *);\n", f);
+       fputs("\n", f);
+       fputs("void VRT_set_backend_hostname(struct backend *, const char *);\n", f);
+       fputs("void VRT_set_backend_portname(struct backend *, const char *);\n", f);
+       fputs("\n", f);
+       fputs("void VRT_alloc_backends(struct VCL_conf *cp);\n", f);
        fputs("\n", f);
        fputs("#define VRT_done(sp, hand)                       \\\n", f);
        fputs(" do {                                    \\\n", f);