[master] aacdd6d Add PRIV_TOP for per "top request" / req->top state
Nils Goroll
nils.goroll at uplex.de
Wed Mar 11 15:52:43 CET 2015
commit aacdd6dee06edbddfa12fa3a3cfcaf24a4354a86
Author: Nils Goroll <nils.goroll at uplex.de>
Date: Wed Mar 11 15:52:39 2015 +0100
Add PRIV_TOP for per "top request" / req->top state
diff --git a/bin/varnishd/cache/cache_vrt_priv.c b/bin/varnishd/cache/cache_vrt_priv.c
index 9ece734..a2052d4 100644
--- a/bin/varnishd/cache/cache_vrt_priv.c
+++ b/bin/varnishd/cache/cache_vrt_priv.c
@@ -122,6 +122,22 @@ VRT_priv_task(VRT_CTX, void *vmod_id)
return (VRT_priv_dynamic(ctx, id, (uintptr_t)vmod_id));
}
+struct vmod_priv *
+VRT_priv_top(VRT_CTX, void *vmod_id)
+{
+ uintptr_t id;
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ if (ctx->req) {
+ CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
+ CHECK_OBJ_NOTNULL(ctx->req->top, REQ_MAGIC);
+ id = (uintptr_t)&ctx->req->top->top;
+ } else {
+ return NULL;
+ }
+ return (VRT_priv_dynamic(ctx, id, (uintptr_t)vmod_id));
+}
+
/*--------------------------------------------------------------------
*/
diff --git a/bin/varnishd/http1/cache_http1_fsm.c b/bin/varnishd/http1/cache_http1_fsm.c
index b2b6470..866e914 100644
--- a/bin/varnishd/http1/cache_http1_fsm.c
+++ b/bin/varnishd/http1/cache_http1_fsm.c
@@ -160,6 +160,7 @@ http1_cleanup(struct sess *sp, struct worker *wrk, struct req *req)
req->restarts = 0;
AZ(req->esi_level);
+ assert(req->top == req);
if (req->vcl != NULL) {
if (wrk->vcl != NULL)
@@ -169,6 +170,8 @@ http1_cleanup(struct sess *sp, struct worker *wrk, struct req *req)
}
VRTPRIV_dynamic_kill(sp->privs, (uintptr_t)req);
+ VRTPRIV_dynamic_kill(sp->privs, (uintptr_t)&req->top);
+
/* Charge and log byte counters */
AN(req->vsl->wid);
CNT_AcctLogCharge(wrk->stats, req);
diff --git a/bin/varnishtest/tests/v00043.vtc b/bin/varnishtest/tests/v00043.vtc
new file mode 100644
index 0000000..ae562a7
--- /dev/null
+++ b/bin/varnishtest/tests/v00043.vtc
@@ -0,0 +1,70 @@
+varnishtest "Test PRIV_TOP"
+
+# same as v00042.vtc, but the priv remains the same across esi includes
+
+server s1 {
+ rxreq
+ expect req.url == "/a"
+ expect req.http.x0 == "/a0"
+ expect req.http.x1 == "/a0"
+ txresp -body {
+ <html>
+ <esi:include src="/foo"/>
+ }
+
+ rxreq
+ expect req.url == "/foo"
+ expect req.http.x0 == "/a0"
+ expect req.http.x1 == "/a0"
+ txresp -body {
+ <html>
+ <esi:include src="/bar"/>
+ }
+
+ rxreq
+ expect req.url == "/bar"
+ expect req.http.x0 == "/a0"
+ expect req.http.x1 == "/a0"
+ txresp
+
+ rxreq
+ expect req.url == "/b"
+ expect req.http.x0 == "/b0"
+ expect req.http.x1 == "/b0"
+
+ txresp
+} -start
+
+varnish v1 -cliok "param.set debug +syncvsl" -vcl+backend {
+ import ${vmod_debug};
+
+ sub vcl_recv {
+ set req.http.x0 = debug.test_priv_top(req.url + req.esi_level);
+ }
+
+ sub vcl_miss {
+ set req.http.x1 = debug.test_priv_top("");
+ }
+
+ sub vcl_backend_response {
+ set beresp.do_esi = true;
+
+ }
+
+ sub vcl_deliver {
+ set resp.http.x1 = debug.test_priv_top("");
+ }
+} -start
+
+
+client c1 {
+ txreq -url /a
+ rxresp
+ expect resp.http.x1 == "/a0"
+
+ txreq -url /b
+ rxresp
+ expect resp.http.x1 == "/b0"
+} -run
+
+varnish v1 -expect s_req == 2
diff --git a/doc/sphinx/reference/vmod.rst b/doc/sphinx/reference/vmod.rst
index e0a1d9a..14bb027 100644
--- a/doc/sphinx/reference/vmod.rst
+++ b/doc/sphinx/reference/vmod.rst
@@ -197,6 +197,9 @@ PRIV_CALL
PRIV_TASK
See below
+PRIV_TOP
+ See below
+
VOID
C-type: ``void``
@@ -254,6 +257,11 @@ The VCL compiler supports the following private pointers:
``vcl_backend_*`` will yield a different private pointer from the
one used on the client side.
+* ``PRIV_TOP`` "per top-request" private pointers live for the
+ duration of one request and all its ESI-includes. They are only
+ defined for the client side. When used from backend VCL subs, a NULL
+ pointer will be passed.
+
The way it works in the vmod code, is that a ``struct vmod_priv *`` is
passed to the functions where one of the ``PRIV_*`` argument types is
specified.
diff --git a/include/vrt.h b/include/vrt.h
index 60a0f14..e034f91 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -259,6 +259,7 @@ typedef int vmod_init_f(struct vmod_priv *, const struct VCL_conf *);
void VRT_priv_fini(const struct vmod_priv *p);
struct vmod_priv *VRT_priv_task(VRT_CTX, void *vmod_id);
+struct vmod_priv *VRT_priv_top(VRT_CTX, void *vmod_id);
/* Stevedore related functions */
int VRT_Stv(const char *nm);
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 957d017..6a03bff 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -557,6 +557,12 @@ vcc_priv_arg(struct vcc *tl, const char *p, const char *name)
e2 = vcc_mk_expr(VOID,
"VRT_priv_task(ctx, &VGC_vmod_%.*s)",
(int) (r - name), name);
+ } else if (!strcmp(p, "PRIV_TOP")) {
+ r = strchr(name, '.');
+ AN(r);
+ e2 = vcc_mk_expr(VOID,
+ "VRT_priv_top(ctx, &VGC_vmod_%.*s)",
+ (int) (r - name), name);
} else {
WRONG("Wrong PRIV_ type");
}
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index dbd5051..1dd412d 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -59,6 +59,7 @@ ctypes = {
'PRIV_CALL': "struct vmod_priv *",
'PRIV_VCL': "struct vmod_priv *",
'PRIV_TASK': "struct vmod_priv *",
+ 'PRIV_TOP': "struct vmod_priv *",
'REAL': "VCL_REAL",
'STRING': "VCL_STRING",
'STRING_LIST': "const char *, ...",
diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc
index 8e940f4..434ee78 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -55,6 +55,10 @@ $Function STRING test_priv_task(PRIV_TASK, STRING)
Test function for TASK private pointers
+$Function STRING test_priv_top(PRIV_TOP, STRING)
+
+Test function for TOP private pointers
+
$Function BLOB str2blob(STRING src="foo")
Turn a string into a blob
diff --git a/lib/libvmod_debug/vmod_debug.c b/lib/libvmod_debug/vmod_debug.c
index f102247..6ef7c15 100644
--- a/lib/libvmod_debug/vmod_debug.c
+++ b/lib/libvmod_debug/vmod_debug.c
@@ -97,6 +97,18 @@ vmod_test_priv_task(VRT_CTX, struct vmod_priv *priv, VCL_STRING s)
return (priv->priv);
}
+VCL_STRING __match_proto__(td_debug_test_priv_top)
+vmod_test_priv_top(VRT_CTX, struct vmod_priv *priv, VCL_STRING s)
+{
+
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+ if (priv->priv == NULL) {
+ priv->priv = strdup(s);
+ priv->free = free;
+ }
+ return (priv->priv);
+}
+
VCL_VOID __match_proto__(td_debug_test_priv_vcl)
vmod_test_priv_vcl(VRT_CTX, struct vmod_priv *priv)
{
More information about the varnish-commit
mailing list