From: phk Date: Wed, 12 Jul 2006 08:34:48 +0000 (+0000) Subject: Teach the VCL compiler about default functions, so that users will X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6338756a58488a335add4894ceaf21bb75488bd3;p=varnish Teach the VCL compiler about default functions, so that users will not have to copy&paste the default methods if they have no special requirements for a particular method. No such facility exists for backends, so a backend description is now the minumum VCL program. When we initialize the VCL compiler we hand it a piece of source code with the "default code", this must include definitions of all methods named with a "default_" prefix (ie: "default_vcl_recv" etc). During compilation we always compile this piece of source code in (after the user supplied VCL source). If the user did not provide a particular method, the default method is used instead. The user can also call the default method directly, for instance by: sub vcl_recv { if (req.http.Expect) { error; } call default_vcl_recv; } Later on, this could be expanded to allow other subroutines to be included in the default VCL for the users calling convenience. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@449 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/varnishd.c b/varnish-cache/bin/varnishd/varnishd.c index d7321267..8315532b 100644 --- a/varnish-cache/bin/varnishd/varnishd.c +++ b/varnish-cache/bin/varnishd/varnishd.c @@ -33,6 +33,46 @@ /*--------------------------------------------------------------------*/ +static const char *default_vcl = + "sub default_vcl_recv {\n" + " if (req.request != \"GET\" && req.request != \"HEAD\") {\n" + " pipe;\n" + " }\n" + " if (req.http.Expect) {\n" + " pipe;\n" + " }\n" + " if (req.http.Authenticate || req.http.Cookie) {\n" + " pass;\n" + " }\n" + " lookup;\n" + "}\n" + "\n" + "sub default_vcl_hit {\n" + " if (!obj.cacheable) {\n" + " pass;\n" + " }\n" + " deliver;\n" + "}\n" + "\n" + "sub default_vcl_miss {\n" + " fetch;\n" + "}\n" + "\n" + "sub default_vcl_fetch {\n" + " if (!obj.valid) {\n" + " error;\n" + " }\n" + " if (!obj.cacheable) {\n" + " pass;\n" + " }\n" + " insert;\n" + "}\n" + "sub default_vcl_timeout {\n" + " discard;\n" + "}\n"; + +/*--------------------------------------------------------------------*/ + struct heritage heritage; struct event_base *mgt_eb; @@ -90,44 +130,7 @@ vcl_default(const char *bflag) "backend default {\n" " set backend.host = \"%*.*s\";\n" " set backend.port = \"%s\";\n" - "}\n" - "sub vcl_recv {\n" - " if (req.request != \"GET\" && req.request != \"HEAD\") {\n" - " pipe;\n" - " }\n" - " if (req.http.Expect) {\n" - " pipe;\n" - " }\n" - " if (req.http.Authenticate || req.http.Cookie) {\n" - " pass;\n" - " }\n" - " lookup;\n" - "}\n" - "\n" - "sub vcl_hit {\n" - " if (!obj.cacheable) {\n" - " pass;\n" - " }\n" - " deliver;\n" - "}\n" - "\n" - "sub vcl_miss {\n" - " fetch;\n" - "}\n" - "\n" - "sub vcl_fetch {\n" - " if (!obj.valid) {\n" - " error;\n" - " }\n" - " if (!obj.cacheable) {\n" - " pass;\n" - " }\n" - " insert;\n" - "}\n" - "sub vcl_timeout {\n" - " discard;\n" - "}\n" - "", p - bflag, p - bflag, bflag, q); + "}\n", p - bflag, p - bflag, bflag, q); assert(buf != NULL); sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); assert(sb != NULL); @@ -243,6 +246,9 @@ static void m_cli_func_exit(struct cli *cli, char **av, void *priv) { + (void)cli; + (void)av; + (void)priv; mgt_child_kill(); exit (0); } @@ -503,7 +509,7 @@ main(int argc, char *argv[]) setbuf(stdout, NULL); setbuf(stderr, NULL); - VCC_InitCompile(); + VCC_InitCompile(default_vcl); heritage.default_ttl = 120; heritage.wthread_min = 1; diff --git a/varnish-cache/include/libvcl.h b/varnish-cache/include/libvcl.h index 65e1fa7a..3c17e3a1 100644 --- a/varnish-cache/include/libvcl.h +++ b/varnish-cache/include/libvcl.h @@ -4,6 +4,6 @@ char *VCC_Compile(struct sbuf *sb, const char *b, const char *e); char *VCC_CompileFile(struct sbuf *sb, const char *fn); -void VCC_InitCompile(void); +void VCC_InitCompile(const char *default_vcl); diff --git a/varnish-cache/lib/libvcl/vcl_compile.c b/varnish-cache/lib/libvcl/vcl_compile.c index ad384915..54613611 100644 --- a/varnish-cache/lib/libvcl/vcl_compile.c +++ b/varnish-cache/lib/libvcl/vcl_compile.c @@ -128,10 +128,11 @@ struct var { static struct method { const char *name; + const char *defname; unsigned returns; } method_tab[] = { #define VCL_RET_MAC(a,b,c) -#define VCL_MET_MAC(a,b,c) { "vcl_"#a, c }, +#define VCL_MET_MAC(a,b,c) { "vcl_"#a, "default_vcl_"#a, c }, #include "vcl_returns.h" #undef VCL_MET_MAC #undef VCL_RET_MAC @@ -195,6 +196,7 @@ static void Compound(struct tokenlist *tl); static void Cond_0(struct tokenlist *tl); static struct proc *AddProc(struct tokenlist *tl, struct token *t, int def); static void AddCall(struct tokenlist *tl, struct token *t); +static const char *vcc_default_vcl_b, *vcc_default_vcl_e; /*--------------------------------------------------------------------*/ @@ -223,13 +225,22 @@ static void ErrWhere(struct tokenlist *tl, struct token *t) { unsigned lin, pos, x, y; - const char *p, *l; + const char *p, *l, *f, *b, *e; lin = 1; pos = 0; if (t->tok == METHOD) return; - for (l = p = tl->b; p < t->b; p++) { + if (t->b >= vcc_default_vcl_b && t->b < vcc_default_vcl_e) { + f = "Default VCL code (compiled in)"; + b = vcc_default_vcl_b; + e = vcc_default_vcl_e; + } else { + f = "VCL code"; + b = tl->b; + e = tl->e; + } + for (l = p = b; p < t->b; p++) { if (*p == '\n') { lin++; pos = 0; @@ -240,9 +251,9 @@ ErrWhere(struct tokenlist *tl, struct token *t) } else pos++; } - sbuf_printf(tl->sb, "Line %d Pos %d\n", lin, pos); + sbuf_printf(tl->sb, "In %s Line %d Pos %d\n", f, lin, pos); x = y = 0; - for (p = l; p < tl->e && *p != '\n'; p++) { + for (p = l; p < e && *p != '\n'; p++) { if (*p == '\t') { y &= ~7; y += 8; @@ -258,7 +269,7 @@ ErrWhere(struct tokenlist *tl, struct token *t) } sbuf_cat(tl->sb, "\n"); x = y = 0; - for (p = l; p < tl->e && *p != '\n'; p++) { + for (p = l; p < e && *p != '\n'; p++) { if (p >= t->b && p < t->e) { sbuf_bcat(tl->sb, "#", 1); x++; @@ -452,6 +463,20 @@ FindRef(struct tokenlist *tl, struct token *t, enum ref_type type) return (r); } +static int +FindRefStr(struct tokenlist *tl, const char *s, enum ref_type type) +{ + struct ref *r; + + TAILQ_FOREACH(r, &tl->refs, list) { + if (r->type != type) + continue; + if (IdIs(r->name, s)) + return (1); + } + return (0); +} + static void AddRef(struct tokenlist *tl, struct token *t, enum ref_type type) { @@ -1381,8 +1406,13 @@ AddToken(struct tokenlist *tl, unsigned tok, const char *b, const char *e) t->e = e; TAILQ_INSERT_TAIL(&tl->tokens, t, list); tl->t = t; - if (0) - fprintf(stderr, "+ %s\n", vcl_tnames[tok]); + if (0) { + fprintf(stderr, "[%s %*.*s] ", + vcl_tnames[tok], + e - b, e - b, b); + if (tok == EOI) + fprintf(stderr, "\n"); + } } /*-------------------------------------------------------------------- @@ -1478,8 +1508,6 @@ Lexer(struct tokenlist *tl, const char *b, const char *e) ErrWhere(tl, tl->t); return; } - /* Add End Of Input token */ - AddToken(tl, EOI, p, p); } /*-------------------------------------------------------------------- @@ -1575,6 +1603,8 @@ Consistency(struct tokenlist *tl) TAILQ_FOREACH(p, &tl->procs, list) { for(m = method_tab; m->name != NULL; m++) { + if (IdIs(p->name, m->defname)) + p->called = 1; if (IdIs(p->name, m->name)) break; } @@ -1722,8 +1752,13 @@ EmitStruct(struct tokenlist *tl) Fc(tl, 0, "\t.nref = VGC_NREFS,\n"); #define VCL_RET_MAC(l,u,b) #define VCL_MET_MAC(l,u,b) \ - Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n"); \ - AddRefStr(tl, "vcl_" #l, R_FUNC); + if (FindRefStr(tl, "vcl_" #l, R_FUNC)) { \ + Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n"); \ + AddRefStr(tl, "vcl_" #l, R_FUNC); \ + } else { \ + Fc(tl, 0, "\t." #l "_func = VGC_function_default_vcl_" #l ",\n"); \ + } \ + AddRefStr(tl, "default_vcl_" #l, R_FUNC); #include "vcl_returns.h" #undef VCL_MET_MAC #undef VCL_RET_MAC @@ -1762,6 +1797,8 @@ VCC_Compile(struct sbuf *sb, const char *b, const char *e) assert(e != NULL); tokens.e = e; Lexer(&tokens, b, e); + Lexer(&tokens, vcc_default_vcl_b, vcc_default_vcl_e); + AddToken(&tokens, EOI, e, e); if (tokens.err) goto done; tokens.t = TAILQ_FIRST(&tokens.tokens); @@ -1870,10 +1907,14 @@ VCC_T_arginfo(const struct printf_info *info __unused, size_t n, int *argtypes) /*--------------------------------------------------------------------*/ void -VCC_InitCompile(void) +VCC_InitCompile(const char *default_vcl) { struct var *v; + vcc_default_vcl_b = default_vcl; + vcc_default_vcl_e = strchr(default_vcl, '\0'); + assert(vcc_default_vcl_e != NULL); + register_printf_function ('T', VCC_T_render, VCC_T_arginfo); vcl_init_tnames(); for (v = vars; v->name != NULL; v++)