From 3c3e8259404138e8ca65a4fc4d1b65f9268a49af Mon Sep 17 00:00:00 2001 From: phk Date: Mon, 7 Jul 2008 21:01:25 +0000 Subject: [PATCH] More polishing of backend compilation. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2889 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- .../bin/varnishtest/tests/v00002.vtc | 34 ++++++++++++++ varnish-cache/lib/libvcl/vcc_action.c | 2 + varnish-cache/lib/libvcl/vcc_backend.c | 46 +++++++++++++++---- varnish-cache/lib/libvcl/vcc_compile.c | 10 ++-- varnish-cache/lib/libvcl/vcc_compile.h | 10 ++-- varnish-cache/lib/libvcl/vcc_dir_random.c | 2 +- varnish-cache/lib/libvcl/vcc_token.c | 32 +++++++++++++ varnish-cache/lib/libvcl/vcc_xref.c | 2 +- 8 files changed, 116 insertions(+), 22 deletions(-) diff --git a/varnish-cache/bin/varnishtest/tests/v00002.vtc b/varnish-cache/bin/varnishtest/tests/v00002.vtc index 17fc064f..db1f91c0 100644 --- a/varnish-cache/bin/varnishtest/tests/v00002.vtc +++ b/varnish-cache/bin/varnishtest/tests/v00002.vtc @@ -2,6 +2,20 @@ test "VCL: test syntax/semantic checks on backend decls." +# Missing backend +varnish v1 -badvcl { +} + +# Reference to non-existent backend +varnish v1 -badvcl { + backend b1 { + .host = "localhost"; + } + sub vcl_recv { + set req.backend = b2; + } +} + # Missing .host varnish v1 -badvcl { backend b1 { @@ -44,3 +58,23 @@ varnish v1 -badvcl { { .weight = 1; .backend = 3745; } // Brownie points for getting the joke } } + +# Check backend reference by name +varnish v1 -badvcl { + backend b1 { .host = "127.0.0.2"; } + backend b2 b1; +} + +# Check backend reference by non-C-compat name +varnish v1 -badvcl { + backend b-1 { .host = "127.0.0.2"; } +} + +# Assign backend by non-C-compat name +# Check backend reference by non-C-compat name +varnish v1 -badvcl { + backend b1 { .host = "127.0.0.2"; } + sub vcl_recv { + set req.backend = b-1; + } +} diff --git a/varnish-cache/lib/libvcl/vcc_action.c b/varnish-cache/lib/libvcl/vcc_action.c index ae8940b7..f4194906 100644 --- a/varnish-cache/lib/libvcl/vcc_action.c +++ b/varnish-cache/lib/libvcl/vcc_action.c @@ -221,6 +221,8 @@ parse_set(struct tokenlist *tl) return; } vcc_NextToken(tl); + vcc_ExpectCid(tl); + ERRCHK(tl); vcc_AddRef(tl, tl->t, R_BACKEND); Fb(tl, 0, "VGC_backend_%.*s", PF(tl->t)); vcc_NextToken(tl); diff --git a/varnish-cache/lib/libvcl/vcc_backend.c b/varnish-cache/lib/libvcl/vcc_backend.c index 01472f0e..70fba9c5 100644 --- a/varnish-cache/lib/libvcl/vcc_backend.c +++ b/varnish-cache/lib/libvcl/vcc_backend.c @@ -27,6 +27,27 @@ * SUCH DAMAGE. * * $Id$ + * + * A necessary explanation of a convoluted policy: + * + * In VCL we have backends and directors. + * + * In VRT we have directors which reference (a number of) backend hosts. + * + * A VCL backend therefore has an implicit director of type "simple" created + * by the compiler, but not visible in VCL. + * + * A VCL backend is a "named host", these can be referenced by name form + * VCL directors, but not from VCL backends. + * + * The reason for this quasimadness is that we want to collect statistics + * for each actual kickable hardware backend machine, but we want to be + * able to refer to them multiple times in different directors. + * + * At the same time, we do not want to force users to declare each backend + * host with a name, if all they want to do is put it into a director, so + * backend hosts can be declared inline in the director, in which case + * its identity is the director and its numerical index therein. */ #include "config.h" @@ -45,6 +66,13 @@ #include "vcc_compile.h" #include "libvarnish.h" +struct host { + VTAILQ_ENTRY(host) list; + int hnum; + struct token *name; +}; + + static const char * CheckHostPort(const char *host, const char *port) { @@ -365,25 +393,24 @@ void vcc_ParseBackend(struct tokenlist *tl) { struct host *h; - int nbh; h = TlAlloc(tl, sizeof *h); vcc_NextToken(tl); - ExpectErr(tl, ID); /* name */ + vcc_ExpectCid(tl); /* ID: name */ + ERRCHK(tl); h->name = tl->t; vcc_NextToken(tl); - vcc_ParseHostDef(tl, &nbh, h->name, "backend", 0); + vcc_ParseHostDef(tl, &h->hnum, h->name, "backend", 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.director[%d])\n", - PF(h->name), tl->nbackend); + PF(h->name), tl->ndirector); vcc_AddDef(tl, h->name, R_BACKEND); @@ -395,10 +422,10 @@ vcc_ParseBackend(struct tokenlist *tl) 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); + Fc(tl, 0, "\t.host = &bh_%d,\n", h->hnum); Fc(tl, 0, "};\n"); - tl->nbackend++; + tl->ndirector++; } /*-------------------------------------------------------------------- @@ -413,7 +440,8 @@ vcc_ParseDirector(struct tokenlist *tl) t_first = tl->t; vcc_NextToken(tl); /* ID: director */ - ExpectErr(tl, ID); /* ID: name */ + vcc_ExpectCid(tl); /* ID: name */ + ERRCHK(tl); t_dir = tl->t; vcc_NextToken(tl); @@ -434,5 +462,5 @@ vcc_ParseDirector(struct tokenlist *tl) vcc_ErrWhere(tl, t_first); return; } - tl->nbackend++; + tl->ndirector++; } diff --git a/varnish-cache/lib/libvcl/vcc_compile.c b/varnish-cache/lib/libvcl/vcc_compile.c index d55eae7f..58d339c4 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.c +++ b/varnish-cache/lib/libvcl/vcc_compile.c @@ -341,13 +341,14 @@ EmitStruct(const struct tokenlist *tl) } Fc(tl, 0, "};\n"); - Fc(tl, 0, "\nstatic struct director\t*directors[%d];\n", tl->nbackend); + Fc(tl, 0, "\nstatic struct director\t*directors[%d];\n", + tl->ndirector); 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.ndirector = %d,\n", tl->nbackend); + Fc(tl, 0, "\t.ndirector = %d,\n", tl->ndirector); Fc(tl, 0, "\t.director = directors,\n"); Fc(tl, 0, "\t.ref = VGC_ref,\n"); Fc(tl, 0, "\t.nref = VGC_NREFS,\n"); @@ -596,9 +597,10 @@ vcc_CompileSource(struct vsb *sb, struct source *sp) return (vcc_DestroyTokenList(tl, NULL)); /* Check if we have any backends at all */ - if (tl->nbackend == 0) { + if (tl->ndirector == 0) { vsb_printf(tl->sb, - "No backends in VCL program, at least one is necessary.\n"); + "No backends or directors found in VCL program, " + "at least one is necessary.\n"); tl->err = 1; return (vcc_DestroyTokenList(tl, NULL)); } diff --git a/varnish-cache/lib/libvcl/vcc_compile.h b/varnish-cache/lib/libvcl/vcc_compile.h index fddbeaa8..3f800cfc 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.h +++ b/varnish-cache/lib/libvcl/vcc_compile.h @@ -59,12 +59,6 @@ struct token { char *dec; }; -struct host { - VTAILQ_ENTRY(host) list; - unsigned hnum; - struct token *name; -}; - VTAILQ_HEAD(tokenhead, token); struct tokenlist { @@ -86,7 +80,7 @@ struct tokenlist { struct vsb *sb; int err; int nbackend_host; - int nbackend; + int ndirector; VTAILQ_HEAD(, proc) procs; struct proc *curproc; struct proc *mprocs[N_METHODS]; @@ -205,6 +199,8 @@ void vcc_ErrWhere(struct tokenlist *tl, const struct token *t); void vcc__Expect(struct tokenlist *tl, unsigned tok, int line); int vcc_Teq(const struct token *t1, const struct token *t2); int vcc_IdIs(const struct token *t, const char *p); +int vcc_isCid(struct token *t); +void vcc_ExpectCid(struct tokenlist *tl); void vcc_Lexer(struct tokenlist *tl, struct source *sp); void vcc_NextToken(struct tokenlist *tl); void vcc__ErrInternal(struct tokenlist *tl, const char *func, unsigned line); diff --git a/varnish-cache/lib/libvcl/vcc_dir_random.c b/varnish-cache/lib/libvcl/vcc_dir_random.c index 6cd9de1b..2525a1c4 100644 --- a/varnish-cache/lib/libvcl/vcc_dir_random.c +++ b/varnish-cache/lib/libvcl/vcc_dir_random.c @@ -58,7 +58,7 @@ vcc_ParseRandomDirector(struct tokenlist *tl, struct token *t_dir) unsigned u; Fh(tl, 1, "\n#define VGC_backend_%.*s (VCL_conf.director[%d])\n", - PF(t_dir), tl->nbackend); + PF(t_dir), tl->ndirector); vcc_AddDef(tl, t_dir, R_BACKEND); fs = vcc_FldSpec(tl, "!backend", "!weight", NULL); diff --git a/varnish-cache/lib/libvcl/vcc_token.c b/varnish-cache/lib/libvcl/vcc_token.c index b716033f..b13dca4f 100644 --- a/varnish-cache/lib/libvcl/vcc_token.c +++ b/varnish-cache/lib/libvcl/vcc_token.c @@ -187,6 +187,38 @@ vcc_IdIs(const struct token *t, const char *p) return (1); } +/*-------------------------------------------------------------------- + * Check that we have a C-identifier + */ + +int +vcc_isCid(struct token *t) +{ + const char *q; + + assert(t->tok == ID); + for (q = t->b; q < t->e; q++) { + if (!isalnum(*q) && *q != '_') + return (0); + } + return (1); +} + +void +vcc_ExpectCid(struct tokenlist *tl) +{ + + ExpectErr(tl, ID); + ERRCHK(tl); + if (vcc_isCid(tl->t)) + return; + vsb_printf(tl->sb, "Identifier "); + vcc_ErrToken(tl, tl->t); + vsb_printf(tl->sb, + " contains illegal characters, use [0-9a-zA-Z_] only.\n"); + vcc_ErrWhere(tl, tl->t); +} + /*-------------------------------------------------------------------- * Decode %xx in a string */ diff --git a/varnish-cache/lib/libvcl/vcc_xref.c b/varnish-cache/lib/libvcl/vcc_xref.c index ab2be5ac..21c324a3 100644 --- a/varnish-cache/lib/libvcl/vcc_xref.c +++ b/varnish-cache/lib/libvcl/vcc_xref.c @@ -143,7 +143,7 @@ vcc_AddDef(struct tokenlist *tl, struct token *t, enum ref_type type) r->name = t; /* The first backend is the default and thus has an implicit ref */ - if (type == R_BACKEND && tl->nbackend == 0) + if (type == R_BACKEND && tl->ndirector == 0) r->refcnt++; } -- 2.39.5