[master] 3fd1663 Now that things are properly prepared: Implement PRIV_SESS and PRIV_REQ

Poul-Henning Kamp phk at FreeBSD.org
Mon Sep 29 11:05:52 CEST 2014


commit 3fd16639cc7774578a3ec5fd4894cac9baec6242
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Sep 29 09:03:43 2014 +0000

    Now that things are properly prepared: Implement PRIV_SESS and PRIV_REQ
    
    Note that each VMOD only gets one of each, so that the same 'vmod_priv'
    will appear on all VMOD functions which use PRIV_REQ and similarly
    only a single vmod_priv appear for all PRIV_SESS uses in that VMOD.
    
    Feedback welcome.

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 39359b4..61298a3 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -120,6 +120,7 @@ struct sess;
 struct sesspool;
 struct vbc;
 struct vrt_backend;
+struct vrt_privs;
 struct vsb;
 struct waitinglist;
 struct worker;
@@ -681,11 +682,12 @@ struct sess {
 	char			*client_addr_str;
 	char			*client_port_str;
 
-
 	/* Timestamps, all on TIM_real() timescale */
 	double			t_open;		/* fd accepted */
 	double			t_idle;		/* fd accepted or resp sent */
 
+	VTAILQ_HEAD(,vrt_privs)	privs;
+
 #if defined(HAVE_EPOLL_CTL)
 	struct epoll_event ev;
 #endif
@@ -1116,6 +1118,7 @@ const char *VCL_Method_Name(unsigned);
  */
 const char *VRT_String(struct ws *ws, const char *h, const char *p, va_list ap);
 char *VRT_StringList(char *d, unsigned dl, const char *p, va_list ap);
+void VRTPRIV_dynamic_kill(struct sess *sp, uintptr_t id);
 
 void ESI_Deliver(struct req *);
 void ESI_DeliverChild(struct req *);
diff --git a/bin/varnishd/cache/cache_http1_fsm.c b/bin/varnishd/cache/cache_http1_fsm.c
index 8e4508a..b85b099 100644
--- a/bin/varnishd/cache/cache_http1_fsm.c
+++ b/bin/varnishd/cache/cache_http1_fsm.c
@@ -201,6 +201,7 @@ http1_cleanup(struct sess *sp, struct worker *wrk, struct req *req)
 		req->vcl = NULL;
 	}
 
+	VRTPRIV_dynamic_kill(sp, (uintptr_t)req);
 	/* Charge and log byte counters */
 	AN(req->vsl->wid);
 	CNT_AcctLogCharge(wrk->stats, req);
diff --git a/bin/varnishd/cache/cache_session.c b/bin/varnishd/cache/cache_session.c
index ca4574f..001dad7 100644
--- a/bin/varnishd/cache/cache_session.c
+++ b/bin/varnishd/cache/cache_session.c
@@ -90,6 +90,7 @@ ses_new(struct sesspool *pp)
 
 	sp->t_open = NAN;
 	sp->t_idle = NAN;
+	VTAILQ_INIT(&sp->privs);
 	Lck_New(&sp->mtx, lck_sess);
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 	return (sp);
@@ -302,6 +303,7 @@ SES_Delete(struct sess *sp, enum sess_close reason, double now)
 		now = VTIM_real();
 	AZ(isnan(sp->t_open));
 
+	VRTPRIV_dynamic_kill(sp, 0);
 	VSL(SLT_SessClose, sp->vxid, "%s %.3f",
 	    sess_close_2str(sp->reason, 0), now - sp->t_open);
 	VSL(SLT_End, sp->vxid, "%s", "");
diff --git a/bin/varnishd/cache/cache_vrt_priv.c b/bin/varnishd/cache/cache_vrt_priv.c
index aab904a..0893b4c 100644
--- a/bin/varnishd/cache/cache_vrt_priv.c
+++ b/bin/varnishd/cache/cache_vrt_priv.c
@@ -37,20 +37,78 @@
 
 #include "cache.h"
 
-#include "cache_backend.h"
-#include "hash/hash_slinger.h"
-#include "vav.h"
 #include "vcl.h"
 #include "vrt.h"
-#include "vrt_obj.h"
-#include "vtcp.h"
-#include "vtim.h"
+
+struct vrt_privs {
+	unsigned			magic;
+#define VRT_PRIVS_MAGIC			0x24157a52
+	VTAILQ_ENTRY(vrt_privs)		list;
+	struct vmod_priv		priv[1];
+	const struct VCL_conf		*vcl;
+	uintptr_t			id;
+};
+
+/*--------------------------------------------------------------------
+ */
+
+static struct vmod_priv *
+VRT_priv_dynamic(VRT_CTX, uintptr_t id)
+{
+	struct vrt_privs *vps;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	VTAILQ_FOREACH(vps, &ctx->req->sp->privs, list) {
+		CHECK_OBJ_NOTNULL(vps, VRT_PRIVS_MAGIC);
+		if (vps->vcl == ctx->vcl && vps->id == id)
+			return (vps->priv);
+	}
+	ALLOC_OBJ(vps, VRT_PRIVS_MAGIC);
+	AN(vps);
+	vps->vcl = ctx->vcl;
+	vps->id = id;
+	VTAILQ_INSERT_TAIL(&ctx->req->sp->privs, vps, list);
+	return (vps->priv);
+}
+
+void
+VRTPRIV_dynamic_kill(struct sess *sp, uintptr_t id)
+{
+	struct vrt_privs *vps, *vps1;
+
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+
+	VTAILQ_FOREACH_SAFE(vps, &sp->privs, list, vps1) {
+		CHECK_OBJ_NOTNULL(vps, VRT_PRIVS_MAGIC);
+		if (id == vps->id) {
+			VTAILQ_REMOVE(&sp->privs, vps, list);
+			VRT_priv_fini(vps->priv);
+			FREE_OBJ(vps);
+		}
+	}
+	if (id == 0)
+		assert(VTAILQ_EMPTY(&sp->privs));
+}
+
+struct vmod_priv *
+VRT_priv_req(VRT_CTX)
+{
+	return (VRT_priv_dynamic(ctx, (uintptr_t)ctx->req));
+}
+
+struct vmod_priv *
+VRT_priv_sess(VRT_CTX)
+{
+	return (VRT_priv_dynamic(ctx, (uintptr_t)NULL));
+}
+
 /*--------------------------------------------------------------------
  */
 
 void
 VRT_priv_fini(const struct vmod_priv *p)
 {
+
 	if (p->priv != (void*)0 && p->free != (void*)0)
 		p->free(p->priv);
 }
diff --git a/bin/varnishtest/tests/v00041.vtc b/bin/varnishtest/tests/v00041.vtc
new file mode 100644
index 0000000..af951f9
--- /dev/null
+++ b/bin/varnishtest/tests/v00041.vtc
@@ -0,0 +1,41 @@
+varnishtest "Test priv_sess and priv_req"
+
+server s1 {
+	rxreq
+	txresp
+	rxreq
+	txresp
+} -start
+
+varnish v1 -vcl+backend {
+	import ${vmod_debug};
+
+	sub vcl_recv {
+		set req.http.x0 = debug.test_priv_req(req.url);
+		set req.http.y0 = debug.test_priv_sess(req.url);
+	}
+
+	sub vcl_deliver {
+		set resp.http.x0 = req.http.x0;
+		set resp.http.x1 = debug.test_priv_req("");
+		set resp.http.y0 = req.http.y0;
+		set resp.http.y1 = debug.test_priv_sess("");
+	}
+} -start
+
+
+client c1 {
+	txreq -url /foobar
+	rxresp
+	expect resp.http.x0 == /foobar
+	expect resp.http.x1 == /foobar
+	expect resp.http.y0 == /foobar
+	expect resp.http.y1 == /foobar
+
+	txreq -url /snafu
+	rxresp
+	expect resp.http.x0 == /snafu
+	expect resp.http.x1 == /snafu
+	expect resp.http.y0 == /foobar
+	expect resp.http.y1 == /foobar
+} -run
diff --git a/include/vrt.h b/include/vrt.h
index 3e21a5f..5b7ab7a 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -246,6 +246,8 @@ struct vmod_priv {
 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_sess(VRT_CTX);
+struct vmod_priv *VRT_priv_req(VRT_CTX);
 
 /* Stevedore related functions */
 int VRT_Stv(const char *nm);
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 3557a4b..acc7b51 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -566,6 +566,12 @@ vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
 			VSB_printf(ifp->fin, "\tVRT_priv_fini(&%s);", buf);
 			e2 = vcc_mk_expr(VOID, "&%s", buf);
 			p += strlen(p) + 1;
+		} else if (fmt == VOID && !strcmp(p, "PRIV_REQ")) {
+			e2 = vcc_mk_expr(VOID, "VRT_priv_req(ctx)");
+			p += strlen(p) + 1;
+		} else if (fmt == VOID && !strcmp(p, "PRIV_SESS")) {
+			e2 = vcc_mk_expr(VOID, "VRT_priv_sess(ctx)");
+			p += strlen(p) + 1;
 		} else if (fmt == ENUM) {
 			ExpectErr(tl, ID);
 			ERRCHK(tl);
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index 6ad9504..14d9c95 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -58,6 +58,8 @@ ctypes = {
 	'IP':		"VCL_IP",
 	'PRIV_CALL':	"struct vmod_priv *",
 	'PRIV_VCL':	"struct vmod_priv *",
+	'PRIV_SESS':	"struct vmod_priv *",
+	'PRIV_REQ':	"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 74ec02f..468fc51 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -51,6 +51,14 @@ $Function VOID test_priv_vcl(PRIV_VCL)
 
 Test function for VCL private pointers
 
+$Function STRING test_priv_req(PRIV_REQ, STRING)
+
+Test function for REQ private pointers
+
+$Function STRING test_priv_sess(PRIV_SESS, STRING)
+
+Test function for SESS private pointers
+
 $Function BLOB str2blob(STRING src)
 
 Turn a string into a blob
diff --git a/lib/libvmod_debug/vmod_debug.c b/lib/libvmod_debug/vmod_debug.c
index 76e5a5f..08b5aa8 100644
--- a/lib/libvmod_debug/vmod_debug.c
+++ b/lib/libvmod_debug/vmod_debug.c
@@ -88,6 +88,30 @@ vmod_test_priv_call(VRT_CTX, struct vmod_priv *priv)
 	}
 }
 
+VCL_STRING __match_proto__(td_debug_test_priv_sess)
+vmod_test_priv_sess(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_STRING __match_proto__(td_debug_test_priv_req)
+vmod_test_priv_req(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