Commit 70f121bf authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add an utterly evil feature to VMODs: Per-call private pointers.

Will describe evil details in sphinx docs in a moment.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@5221 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 837bf1e1
......@@ -185,11 +185,27 @@ void VRT_init_dir(struct cli *, struct director **, const char *name,
int idx, const void *priv);
void VRT_fini_dir(struct cli *, struct director *);
/* Modules related */
/* VMOD/Modules related */
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 *);
struct vmod_priv;
typedef void vmod_priv_free_f(void *);
struct vmod_priv {
void *priv;
vmod_priv_free_f *free;
};
typedef int vmod_init_f(struct vmod_priv *, const struct VCL_conf *);
static inline void
vmod_priv_fini(struct vmod_priv *p)
{
if (p->priv != (void*)0 && p->free != (void*)0)
p->free(p->priv);
}
/* Convert things to string */
......
......@@ -298,8 +298,17 @@ EmitInitFunc(const struct vcc *tl)
static void
EmitFiniFunc(const struct vcc *tl)
{
unsigned u;
Fc(tl, 0, "\nstatic void\nVGC_Fini(struct cli *cli)\n{\n\n");
/*
* We do this here, so we are sure they happen before any
* per-vcl vmod_privs get cleaned.
*/
for (u = 0; u < tl->nvmodpriv; u++)
Fc(tl, 0, "\tvmod_priv_fini(&vmod_priv_%u);\n", u);
vsb_finish(tl->ff);
AZ(vsb_overflowed(tl->ff));
vsb_cat(tl->fc, vsb_data(tl->ff));
......
......@@ -151,6 +151,7 @@ struct vcc {
unsigned recnt;
unsigned nsockaddr;
unsigned nvmodpriv;
};
enum ref_type {
......
......@@ -425,6 +425,7 @@ vcc_expr_call(struct vcc *tl, struct expr **e, const struct symbol *sym)
const char *p, *q, *r;
struct expr *e1;
enum var_type fmt;
char buf[32];
(void)tl;
(void)e;
......@@ -450,6 +451,14 @@ vcc_expr_call(struct vcc *tl, struct expr **e, const struct symbol *sym)
vsb_finish(e1->vsb);
AZ(vsb_overflowed(e1->vsb));
p += strlen(p) + 1;
} else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) {
bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++);
e1 = vcc_new_expr();
Fh(tl, 0, "struct vmod_priv %s;\n", buf);
vsb_printf(e1->vsb, "&%s", buf);
vsb_finish(e1->vsb);
AZ(vsb_overflowed(e1->vsb));
p += strlen(p) + 1;
} else {
vcc_expr0(tl, &e1, fmt);
ERRCHK(tl);
......
......@@ -143,13 +143,12 @@ vcc_ParseImport(struct vcc *tl)
vcc_ErrWhere(tl, mod);
return;
}
Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod));
for (; *spec != NULL; spec++) {
p = *spec;
if (!strcmp(p, "META")) {
if (!strcmp(p, "INIT")) {
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, SYM_FUNC);
p += strlen(p) + 1;
......@@ -164,6 +163,7 @@ vcc_ParseImport(struct vcc *tl)
}
Fh(tl, 0, "\n%s\n", proto);
/* XXX: zero the function pointer structure */
/* XXX: zero the function pointer structure ?*/
Ff(tl, 0, "\tvmod_priv_fini(&vmod_priv_%.*s);\n", PF(mod));
Ff(tl, 0, "\tVRT_Vmod_Fini(&VGC_vmod_%.*s);\n", PF(mod));
}
......@@ -59,13 +59,14 @@ ctypes = {
'DURATION': "double",
'INT': "int",
'HEADER': "const char *",
'PRIV_VCL': "void **",
'PRIV_VCL': "struct vmod_priv *",
'PRIV_CALL': "struct vmod_priv *",
'VOID': "void",
}
#######################################################################
metaname = ""
initname = ""
modname = "???"
pstruct = ""
pinit = ""
......@@ -131,8 +132,8 @@ for l0 in f:
modname = l[2].strip();
continue
if l[0] == "Meta":
metaname = l[2].strip();
if l[0] == "Init":
initname = l[2].strip();
continue
if l[0] != "Function":
......@@ -166,11 +167,11 @@ 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'
if initname != "":
plist += "int " + initname + "(struct vmod_priv *, const struct VCL_conf *);\n"
pstruct += "\tvmod_init_f\t*_init;\n"
pinit += "\t" + initname + ",\n"
slist += '\t"INIT\\0Vmod_Func_' + modname + '._init",\n'
#######################################################################
......@@ -179,6 +180,7 @@ fh = open("vcc_if.h", "w")
fh.write('struct sess;\n')
fh.write('struct VCL_conf;\n')
fh.write('struct vmod_priv;\n')
fh.write("\n");
fh.write(plist)
......
Module std
Meta meta_function
Function STRING toupper(STRING_LIST)
Init init_function
Function STRING toupper(PRIV_CALL, STRING_LIST)
Function STRING tolower(PRIV_VCL, STRING_LIST)
Function VOID set_ip_tos(INT)
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <netinet/in.h>
#include "vrt.h"
#include "../../bin/varnishd/cache.h"
......@@ -48,12 +49,18 @@ vmod_updown(struct sess *sp, int up, const char *s, va_list ap)
}
const char *
vmod_toupper(struct sess *sp, const char *s, ...)
vmod_toupper(struct sess *sp, struct vmod_priv *priv, const char *s, ...)
{
const char *p;
va_list ap;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
if (priv->priv == NULL) {
priv->priv = strdup("BAR");
priv->free = free;
} else {
assert(!strcmp(priv->priv, "BAR"));
}
va_start(ap, s);
p = vmod_updown(sp, 1, s, ap);
va_end(ap);
......@@ -61,13 +68,13 @@ vmod_toupper(struct sess *sp, const char *s, ...)
}
const char *
vmod_tolower(struct sess *sp, void **vcl_priv, const char *s, ...)
vmod_tolower(struct sess *sp, struct vmod_priv *priv, const char *s, ...)
{
const char *p;
va_list ap;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
assert(*vcl_priv == (void *)8);
assert(!strcmp(priv->priv, "FOO"));
va_start(ap, s);
p = vmod_updown(sp, 0, s, ap);
va_end(ap);
......@@ -75,17 +82,11 @@ vmod_tolower(struct sess *sp, void **vcl_priv, const char *s, ...)
}
int
meta_function(void **priv, const struct VCL_conf *cfg)
init_function(struct vmod_priv *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;
}
(void)cfg;
priv->priv = strdup("FOO");
priv->free = free;
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