Commit f57c4513 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add a "metafunction" facility to VMOD, which tells modules whenever

a new VCL program initializes of finishes.

This also gives access to a per-VCL private void* which can be passed
as a hidden argument to the member functions.

If modules hold any global state, they should use the meta function to
keep track of when the last VCL program finishes and clean up their
internal global state then.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@5166 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 5022d3f2
......@@ -189,6 +189,7 @@ void VRT_fini_dir(struct cli *, struct director *);
void VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm,
const char *path);
void VRT_Vmod_Fini(void **hdl);
typedef int vmod_meta_f(void **, const struct VCL_conf *);
/* Convert things to string */
......
......@@ -422,7 +422,7 @@ vcc_arg_type(const char **p)
static void
vcc_expr_call(struct vcc *tl, struct expr **e, const struct symbol *sym)
{
const char *p, *q;
const char *p, *q, *r;
struct expr *e1;
enum var_type fmt;
......@@ -441,18 +441,30 @@ vcc_expr_call(struct vcc *tl, struct expr **e, const struct symbol *sym)
while (*p != '\0') {
e1 = NULL;
fmt = vcc_arg_type(&p);
if (fmt == VOID && !strcmp(p, "PRIV_VCL")) {
e1 = vcc_new_expr();
r = strchr(sym->name, '.');
AN(r);
vsb_printf(e1->vsb, "&vmod_priv_%.*s",
r - sym->name, sym->name);
vsb_finish(e1->vsb);
AZ(vsb_overflowed(e1->vsb));
p += strlen(p) + 1;
} else {
vcc_expr0(tl, &e1, fmt);
ERRCHK(tl);
assert(e1->fmt == fmt);
if (e1->fmt == STRING_LIST) {
e1 = vcc_expr_edit(STRING_LIST,
"\v+\n\v1,\nvrt_magic_string_end\v-", e1, NULL);
"\v+\n\v1,\nvrt_magic_string_end\v-",
e1, NULL);
}
*e = vcc_expr_edit((*e)->fmt, q, *e, e1);
q = "\v1,\n\v2";
if (*p != '\0')
SkipToken(tl, ',');
}
*e = vcc_expr_edit((*e)->fmt, q, *e, e1);
q = "\v1,\n\v2";
}
SkipToken(tl, ')');
*e = vcc_expr_edit((*e)->fmt, "\v1\n)\v-", *e, NULL);
}
......
......@@ -128,11 +128,18 @@ vcc_ParseImport(struct vcc *tl)
}
for (; *spec != NULL; spec++) {
p = *spec;
if (!strcmp(p, "META")) {
p += strlen(p) + 1;
Fh(tl, 0, "static void *vmod_priv_%.*s;\n", PF(mod));
Fi(tl, 0, "\t%s(&vmod_priv_%.*s, &VCL_conf);\n", p, PF(mod));
Ff(tl, 0, "\t%s(&vmod_priv_%.*s, 0);\n", p, PF(mod));
} else {
sym = VCC_AddSymbol(tl, p);
p += strlen(p) + 1;
sym->cfunc = p;
p += strlen(p) + 1;
sym->args = p;
}
}
Fh(tl, 0, "\n%s\n", proto);
}
......@@ -59,10 +59,12 @@ ctypes = {
'DURATION': "double",
'INT': "int",
'HEADER': "const char *",
'PRIV_VCL': "void **",
}
#######################################################################
metaname = ""
modname = "???"
pstruct = ""
pinit = ""
......@@ -79,7 +81,7 @@ def do_func(fname, rval, args):
print(fname, rval, args)
proto = ctypes[rval] + " vmod_" + fname + "(struct sess *"
sproto = ctypes[rval] + " td_" + fname + "(struct sess *"
sproto = ctypes[rval] + " td_" + modname + "_" + fname + "(struct sess *"
s=", "
for i in args:
proto += s + ctypes[i]
......@@ -88,9 +90,9 @@ def do_func(fname, rval, args):
sproto += ")"
plist += proto + ";\n"
tdl += "typedef\t" + sproto + ";\n"
tdl += "typedef " + sproto + ";\n"
pstruct += "\ttd_" + fname + "\t*" + fname + ";\n"
pstruct += "\ttd_" + modname + "_" + fname + "\t*" + fname + ";\n"
pinit += "\tvmod_" + fname + ",\n"
s = modname + '.' + fname + "\\0"
......@@ -120,6 +122,10 @@ for l0 in f:
modname = l[2].strip();
continue
if l[0] == "Meta":
metaname = l[2].strip();
continue
if l[0] != "Function":
assert False
......@@ -151,18 +157,28 @@ def dumps(s):
#######################################################################
if metaname != "":
plist += "int " + metaname + "(void **, const struct VCL_conf *);\n"
pstruct += "\tvmod_meta_f\t*_meta;\n"
pinit += "\t" + metaname + ",\n"
slist += '\t"META\\0Vmod_Func_' + modname + '._meta",\n'
#######################################################################
fc = open("vcc_if.c", "w")
fh = open("vcc_if.h", "w")
fh.write('struct sess;\n')
fh.write('struct VCL_conf;\n')
fh.write("\n");
fh.write(plist)
fc.write('#include "vcc_if.h"\n')
fc.write('#include "vrt.h"\n')
fc.write("\n");
fc.write('struct sess;\n')
fc.write("\n");
fc.write(tdl);
......@@ -186,3 +202,6 @@ fc.write('\t;\n')
fc.write("\n");
fc.write('const char *Vmod_Spec[] = {\n' + slist + '\t0\n};\n')
fc.write("\n")
Module std
Meta meta_function
Function STRING toupper(STRING_LIST)
Function STRING tolower(STRING_LIST)
Function STRING tolower(PRIV_VCL, STRING_LIST)
......@@ -53,14 +53,31 @@ vmod_toupper(struct sess *sp, const char *s, ...)
}
const char *
vmod_tolower(struct sess *sp, const char *s, ...)
vmod_tolower(struct sess *sp, void **vcl_priv, const char *s, ...)
{
const char *p;
va_list ap;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
assert(*vcl_priv == (void *)8);
va_start(ap, s);
p = vmod_updown(sp, 0, s, ap);
va_end(ap);
return (p);
}
int
meta_function(void **priv, const struct VCL_conf *cfg)
{
if (cfg != NULL) {
// Initialization in new VCL program
// Hang any private data/state off *priv
*priv = (void *)8;
} else {
// Cleaup in new VCL program
// Cleanup/Free any private data/state hanging of *priv
assert(*priv == (void *)8);
*priv = NULL;
}
return (0);
}
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