Commit 939aa1ba authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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: http://www.varnish-cache.org/svn/trunk/varnish-cache@449 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 6fc9320e
......@@ -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;
......
......@@ -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);
......@@ -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++)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment