[master] adab8d8 Make it possible to return(purge) in vcl_recv{}.

Poul-Henning Kamp phk at varnish-cache.org
Sun May 12 23:05:55 CEST 2013


commit adab8d84727227565b7f3a92a78f10448ab21420
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Sun May 12 21:04:39 2013 +0000

    Make it possible to return(purge) in vcl_recv{}.
    
    After the purge, you will end up in vcl_purge{} from where it will
    (at some future date) be possible to order a fresh fetch of the
    object.
    
    Doing purge from vcl_recv{} solves half of the object existence
    problems in vcl_lookup{}.

diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c
index 3f4fb79..e9ef4fc 100644
--- a/bin/varnishd/cache/cache_hash.c
+++ b/bin/varnishd/cache/cache_hash.c
@@ -348,6 +348,7 @@ HSH_Lookup(struct req *req, struct objcore **ocp, struct objcore **bocp,
 	Lck_AssertHeld(&oh->mtx);
 
 	if (always_insert) {
+		/* XXX: should we do predictive Vary in this case ? */
 		/* Insert new objcore in objecthead and release mutex */
 		*bocp = hsh_insert_busyobj(wrk, oh);
 		/* NB: no deref of objhead, new object inherits reference */
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index 90a4a1a..3970e63 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -1182,6 +1182,9 @@ cnt_recv(struct worker *wrk, struct req *req)
 		req->wantbody = 1;
 
 	switch(recv_handling) {
+	case VCL_RET_PURGE:
+		req->req_step = R_STP_PURGE;
+		return (REQ_FSM_MORE);
 	case VCL_RET_HASH:
 		req->req_step = R_STP_LOOKUP;
 		return (REQ_FSM_MORE);
@@ -1205,6 +1208,44 @@ cnt_recv(struct worker *wrk, struct req *req)
 }
 
 /*--------------------------------------------------------------------
+ * PURGE
+ * Find the objhead, purge it and ask VCL if we should fetch or
+ * just return.
+ * XXX: fetching not implemented yet.
+ */
+
+static enum req_fsm_nxt
+cnt_purge(struct worker *wrk, struct req *req)
+{
+	struct objcore *oc, *boc;
+	enum lookup_e lr;
+
+	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+	AZ(req->objcore);
+
+	CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC);
+	AZ(req->busyobj);
+
+	VRY_Prep(req);
+
+	AZ(req->objcore);
+	lr = HSH_Lookup(req, &oc, &boc, 1, 1);
+	assert (lr == HSH_MISS);
+	AZ(oc);
+	CHECK_OBJ_NOTNULL(boc, OBJCORE_MAGIC);
+	VRY_Finish(req, NULL);
+
+	HSH_Purge(req, boc->objhead, 0, 0);
+
+	AZ(HSH_Deref(&wrk->stats, boc, NULL));
+
+	VCL_purge_method(req->vcl, wrk, req, NULL, req->http->ws);
+	req->req_step = R_STP_ERROR;
+	return (REQ_FSM_MORE);
+}
+
+/*--------------------------------------------------------------------
  * Central state engine dispatcher.
  *
  * Kick the session around until it has had enough.
diff --git a/bin/varnishd/default.vcl b/bin/varnishd/default.vcl
index 4918349..488cf0c 100644
--- a/bin/varnishd/default.vcl
+++ b/bin/varnishd/default.vcl
@@ -93,6 +93,10 @@ sub vcl_hash {
     return (lookup);
 }
 
+sub vcl_purge {
+    return (error(200, "Purged"));
+}
+
 sub vcl_lookup {
 /*
     if (!obj) {
diff --git a/bin/varnishtest/tests/b00036.vtc b/bin/varnishtest/tests/b00036.vtc
new file mode 100644
index 0000000..cb0b6e5
--- /dev/null
+++ b/bin/varnishtest/tests/b00036.vtc
@@ -0,0 +1,37 @@
+varnishtest "builtin purge from vcl_recv{}"
+
+server s1 {
+	rxreq
+	txresp -hdr "foo: 1"
+	rxreq
+	txresp -hdr "foo: 2"
+} -start
+
+varnish v1 -vcl+backend {
+	sub vcl_recv {
+		if (req.request == "PURGE") {
+			return (purge);
+		}
+	}
+} -start
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.http.foo == 1
+
+	txreq
+	rxresp
+	expect resp.http.foo == 1
+
+	txreq -req PURGE
+	rxresp
+	expect resp.msg == "Purged"
+} -run
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.http.foo == 2
+
+} -run
diff --git a/include/tbl/steps.h b/include/tbl/steps.h
index ece22cb..a4c19b0 100644
--- a/include/tbl/steps.h
+++ b/include/tbl/steps.h
@@ -41,6 +41,7 @@ REQ_STEP(recv,		RECV,		(wrk, req))
 REQ_STEP(pipe,		PIPE,		(wrk, req))
 REQ_STEP(pass,		PASS,		(wrk, req))
 REQ_STEP(lookup,	LOOKUP,		(wrk, req))
+REQ_STEP(purge,		PURGE,		(wrk, req))
 REQ_STEP(miss,		MISS,		(wrk, req))
 REQ_STEP(fetch,		FETCH,		(wrk, req))
 REQ_STEP(fetchbody,	FETCHBODY,	(wrk, req))
diff --git a/lib/libvcl/generate.py b/lib/libvcl/generate.py
index 349500a..1402e13 100755
--- a/lib/libvcl/generate.py
+++ b/lib/libvcl/generate.py
@@ -78,10 +78,11 @@ tokens = {
 # Our methods and actions
 
 returns =(
-	('recv',		"C", ('error', 'pass', 'pipe', 'hash',)),
+	('recv',		"C", ('error', 'pass', 'pipe', 'hash', 'purge',)),
 	('pipe',		"C", ('error', 'pipe',)),
 	('pass',		"C", ('error', 'restart', 'pass',)),
 	('hash',		"C", ('lookup',)),
+	('purge',		"C", ('error', 'fetch',)),
 	('miss',		"C", ('error', 'restart', 'pass', 'fetch',)),
 	('lookup',		"C", ('error', 'restart', 'pass', 'deliver',)),
 	('backend_fetch',	"B", ('fetch', 'pass',)),



More information about the varnish-commit mailing list