[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