r1277 - in trunk/varnish-cache: bin/varnishd include lib/libvcl

phk at projects.linpro.no phk at projects.linpro.no
Tue Mar 6 23:40:07 CET 2007


Author: phk
Date: 2007-03-06 23:40:06 +0100 (Tue, 06 Mar 2007)
New Revision: 1277

Removed:
   trunk/varnish-cache/bin/varnishd/cache_pass.c
Modified:
   trunk/varnish-cache/bin/varnishd/Makefile.am
   trunk/varnish-cache/bin/varnishd/cache.h
   trunk/varnish-cache/bin/varnishd/cache_center.c
   trunk/varnish-cache/bin/varnishd/cache_fetch.c
   trunk/varnish-cache/bin/varnishd/cache_hash.c
   trunk/varnish-cache/bin/varnishd/cache_vrt.c
   trunk/varnish-cache/bin/varnishd/mgt_vcc.c
   trunk/varnish-cache/bin/varnishd/steps.h
   trunk/varnish-cache/include/vcl.h
   trunk/varnish-cache/include/vcl_returns.h
   trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c
   trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl
   trunk/varnish-cache/lib/libvcl/vcc_token_defs.h
Log:

Having thought long and hard about this, commit what I think is the
new and simpler flow for version2.

Pass is now handled like a miss where the object will not be cached.

The main result of this is that we drag the entire object, header
and body, from the backend before transmitting it to the client,
thus isolating the backend from slow clients.

>From a software engineering point of view it is a big improvement,
because it eliminates the need for all of cache_pass.c and we therefore
end up with less HTTP protocol implementations.

A side effect of this is that ticket #56 should be fixed now.

If the object is pass'ed before vcl_fetch{} that is, in vcl_recv{},
vcl_hit{} or vcl_miss{}, no "pass this" object is inserted in the
cache.  The confusion between "pass", "insert" and "insert_pass"
has been cleaned up, by the removal of the latter.

Pipe and Pass calls vcl_pipe{} and vcl_pass{} respectively, before
contacting the backend.  I havn't quite decided if they should
operate on the request header from the client or the one to the
backend, or both.

One possible use is to inject a "Connection: close" header to limit
pipe to one transaction.

A new vcl_hash{} has been added, it will allow customization of
which fields we hash on, instead of the default "url + Host:" but
this is not yet implemented.

vcl_fetch{} is now called after both the headers and body have been
picked up from the backend.  This will allow us to do more comprehensive
handling of backend errors later on.

A disadvantage to this is that if the object ends up as a "pass
this" object in the cache, we could possibly have released any
queued requests already after the headers were received.  If this
is transpires as a real-world problem, we can add a vcl_fetchhdr{}
which can do an early release (ie: "pass").



Modified: trunk/varnish-cache/bin/varnishd/Makefile.am
===================================================================
--- trunk/varnish-cache/bin/varnishd/Makefile.am	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/bin/varnishd/Makefile.am	2007-03-06 22:40:06 UTC (rev 1277)
@@ -21,7 +21,6 @@
 	cache_http.c \
 	cache_main.c \
 	cache_pool.c \
-	cache_pass.c \
 	cache_pipe.c \
 	cache_response.c \
 	cache_session.c \

Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/bin/varnishd/cache.h	2007-03-06 22:40:06 UTC (rev 1277)
@@ -279,7 +279,6 @@
 
 	TAILQ_ENTRY(sess)	list;
 
-	struct vbe_conn		*vbc;
 	struct backend		*backend;
 	struct object		*obj;
 	struct VCL_conf		*vcl;
@@ -348,10 +347,10 @@
 void EXP_TTLchange(struct object *o);
 
 /* cache_fetch.c */
-int FetchBody(struct sess *sp);
-int FetchHeaders(struct sess *sp);
+int Fetch(struct sess *sp);
 
 /* cache_hash.c */
+void HSH_Prealloc(struct sess *sp);
 struct object *HSH_Lookup(struct sess *sp);
 void HSH_Unbusy(struct object *o);
 void HSH_Ref(struct object *o);
@@ -390,10 +389,6 @@
 #include "http_headers.h"
 #undef HTTPH
 
-/* cache_pass.c */
-int PassSession(struct sess *sp);
-void PassBody(struct sess *sp);
-
 /* cache_pipe.c */
 void PipeSession(struct sess *sp);
 

Modified: trunk/varnish-cache/bin/varnishd/cache_center.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_center.c	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/bin/varnishd/cache_center.c	2007-03-06 22:40:06 UTC (rev 1277)
@@ -44,14 +44,24 @@
 
 /*
 DOT digraph vcl_center {
-DOT	page="8.2,11.7"
-DOT	size="6.3,9.7"
-DOT	margin="1.0"
+xDOT	page="8.2,11.5"
+DOT	size="7.2,10.5"
+DOT	margin="0.5"
+DOT	center="1"
 DOT start [
 DOT	shape=hexagon
-DOT	label="Start"
+DOT	label="Request received"
 DOT ]
-DOT start -> RECV
+DOT RECV [shape=plaintext]
+DOT PIPE [shape=plaintext]
+DOT LOOKUP [shape=plaintext]
+DOT HIT [shape=plaintext]
+DOT MISS [shape=plaintext]
+DOT PASS [shape=plaintext]
+DOT FETCH [shape=plaintext]
+DOT DELIVER [shape=plaintext]
+DOT ERROR [shape=plaintext]
+DOT start -> RECV [style=bold,color=green,weight=4]
  */
 
 #include <stdio.h>
@@ -71,8 +81,13 @@
 static unsigned xids;
 
 /*--------------------------------------------------------------------
- * The very first request
+ * AGAIN
+ * We come here when we just completed a request and already have
+ * received (part of) the next one.  Instead taking the detour
+ * around the acceptor and then back to a worker, just stay in this
+ * worker and do what it takes.
  */
+
 static int
 cnt_again(struct sess *sp)
 {
@@ -101,19 +116,19 @@
 /*--------------------------------------------------------------------
  * We have a refcounted object on the session, now deliver it.
  *
-DOT subgraph cluster_deliver {
+DOT subgraph xcluster_deliver {
 DOT 	deliver [
 DOT		shape=ellipse
 DOT		label="Build & send header"
 DOT	]
-DOT	DELIVER -> deliver [style=bold]
+DOT	DELIVER -> deliver [style=bold,color=green,weight=4]
 DOT	deliver2 [
 DOT		shape=ellipse
 DOT		label="Send object"
 DOT	]
-DOT	deliver -> deliver2 [style=bold]
+DOT	deliver -> deliver2 [style=bold,color=green,weight=4]
 DOT }
-DOT deliver2 -> DONE [style=bold]
+DOT deliver2 -> DONE [style=bold,color=green,weight=4]
  */
 
 static int
@@ -154,7 +169,6 @@
 	double dh, dp, da;
 
 	AZ(sp->obj);
-	AZ(sp->vbc);
 	sp->backend = NULL;
 	if (sp->vcl != NULL) {
 		if (sp->wrk->vcl != NULL)
@@ -211,7 +225,7 @@
 /*--------------------------------------------------------------------
  * Emit an error
  *
-DOT subgraph cluster_error {
+DOT subgraph xcluster_error {
 DOT	error [
 DOT		shape=ellipse
 DOT		label="Issue HTTP error"
@@ -237,99 +251,61 @@
  * We have fetched the headers from the backend, ask the VCL code what
  * to do next, then head off in that direction.
  *
-DOT subgraph cluster_fetch {
+DOT subgraph xcluster_fetch {
 DOT	fetch [
 DOT		shape=ellipse
-DOT		label="find obj.ttl\nobj.cacheable"
+DOT		label="fetch from backend\n(find obj.ttl)"
 DOT	]
-DOT	FETCH -> fetch [style=bold]
+DOT	FETCH -> fetch [style=bold,color=blue,weight=2]
 DOT	vcl_fetch [
 DOT		shape=box
 DOT		label="vcl_fetch()"
 DOT	]
-DOT	fetch -> vcl_fetch [style=bold]
-DOT	fetch_lookup [
-DOT		shape=ellipse
-DOT		label="obj.cacheable=false\nunbusy obj\ndiscard body\n"
-DOT	]
-DOT	vcl_fetch -> fetch_lookup [label="lookup", style=dotted, weight=0]
+DOT	fetch -> vcl_fetch [style=bold,color=blue,weight=2]
 DOT	fetch_pass [
 DOT		shape=ellipse
-DOT		label="obj.cacheable=false\nunbusy obj"
+DOT		label="obj.pass=true"
 DOT	]
 DOT	vcl_fetch -> fetch_pass [label="pass"]
-DOT	fetch_ipass [
-DOT		shape=ellipse
-DOT		label="obj.cacheable=true\nobj.pass=true\nunbusy obj"
-DOT	]
-DOT	vcl_fetch -> fetch_ipass [label="insert_pass"]
-DOT	fetch_insert [
-DOT		shape=ellipse
-DOT		label="rcv body\nobj.cacheable=true\nunbusy"
-DOT	]
-DOT	vcl_fetch -> fetch_insert [label="insert", style=bold]
-DOT	fetch_error [
-DOT		shape=ellipse
-DOT		label="disc body\nobj.cacheable=false\nunbusy"
-DOT	]
-DOT	vcl_fetch -> fetch_error [label="error"]
 DOT }
-DOT fetch_lookup -> LOOKUP [style=dotted, weight=0]
-DOT fetch_pass -> PASSBODY
-DOT fetch_ipass -> PASSBODY
-DOT fetch_insert -> DELIVER [style=bold]
-DOT fetch_error -> ERROR
+DOT fetch_pass -> DELIVER
+DOT vcl_fetch -> DELIVER [label="insert",style=bold,color=blue,weight=2]
+DOT vcl_fetch -> errfetch [label="error"]
+DOT errfetch [label="ERROR",shape=plaintext]
  */
 
 static int
 cnt_fetch(struct sess *sp)
 {
 
-	CHECK_OBJ_NOTNULL(sp->vbc, VBE_CONN_MAGIC);
-	RFC2616_cache_policy(sp, sp->vbc->http);
 
-	VCL_fetch_method(sp);
-
-	if (sp->handling == VCL_RET_LOOKUP)
-		INCOMPL();
-	if (sp->handling == VCL_RET_PASS) {
+	if (Fetch(sp)) {
 		sp->obj->cacheable = 0;
 		HSH_Unbusy(sp->obj);
 		HSH_Deref(sp->obj);
 		sp->obj = NULL;
-		sp->step = STP_PASSBODY;
+		sp->step = STP_DONE;
+		RES_Error(sp, 503, NULL);
 		return (0);
 	}
-	if (sp->handling == VCL_RET_INSERT_PASS) {
-		sp->obj->pass = 1;
-		sp->obj->cacheable = 1;
-		HSH_Unbusy(sp->obj);
-		/* Don't HSH_Deref(sp->obj); we need the ref for storage */
-		sp->obj = NULL;
-		sp->step = STP_PASSBODY;
-		return (0);
-	}
-	if (sp->handling == VCL_RET_INSERT) {
-		if (FetchBody(sp)) {
-			sp->obj->cacheable = 0;
-			HSH_Unbusy(sp->obj);
-			HSH_Deref(sp->obj);
-			sp->obj = NULL;
-			RES_Error(sp, 503, NULL);
-			sp->step = STP_DONE;
-			return (0);
-		}
-		sp->obj->cacheable = 1;
-		AZ(sp->vbc);
-		HSH_Ref(sp->obj); /* get another, STP_DELIVER will deref */
-		HSH_Unbusy(sp->obj);
-		sp->wrk->acct.fetch++;
-		sp->step = STP_DELIVER;
-		return (0);
-	}
+
+	RFC2616_cache_policy(sp, &sp->obj->http);	/* XXX -> VCL */
+
+	VCL_fetch_method(sp);
+
 	if (sp->handling == VCL_RET_ERROR)
 		INCOMPL();
-	INCOMPL();
+
+	if (sp->handling == VCL_RET_PASS)
+		sp->obj->pass = 1;
+
+	sp->obj->cacheable = 1;
+	HSH_Ref(sp->obj); /* get another, STP_DELIVER will deref */
+	if (sp->obj->objhead != NULL)
+		HSH_Unbusy(sp->obj);
+	sp->wrk->acct.fetch++;
+	sp->step = STP_DELIVER;
+	return (0);
 }
 
 /*--------------------------------------------------------------------
@@ -370,120 +346,96 @@
 }
 
 /*--------------------------------------------------------------------
+ * HIT
  * We had a cache hit.  Ask VCL, then march off as instructed.
  *
-DOT subgraph cluster_hit {
+DOT subgraph xcluster_hit {
 DOT	hit [
 DOT		shape=box
 DOT		label="vcl_hit()"
 DOT	]
-DOT	HIT -> hit [style=bold]
-DOT	hit2 [
-DOT		shape=diamond
-DOT		label="obj.pass ?"
-DOT	]
-DOT	hit -> hit2 [label=deliver, style=bold]
-DOT	hit_lookup [
-DOT		shape=ellipse
-DOT		label="unbusy"
-DOT	]
-DOT	hit -> hit_lookup [label="lookup", style=dotted, weight=0]
-DOT	hit_error [
-DOT		shape=ellipse
-DOT		label="unbusy"
-DOT	]
-DOT	hit -> hit_error [label="error", weight=0]
-DOT	hit_pass [
-DOT		shape=ellipse
-DOT		label="unbusy"
-DOT	]
-DOT	hit -> hit_pass [label=pass]
-DOT	hit2 -> hit_pass
+DOT	HIT -> hit [style=bold,color=green,weight=4]
 DOT }
-DOT hit_error -> ERROR
-DOT hit_pass -> PASS
-DOT hit_lookup -> LOOKUP [style=dotted, weight=0]
-DOT hit2 -> DELIVER [style=bold]
+DOT hit -> err_hit [label="error"]
+DOT err_hit [label="ERROR",shape=plaintext]
+DOT hit -> PASS [label=pass]
+DOT hit -> DELIVER [label="deliver",style=bold,color=green,weight=4]
  */
 
 static int
 cnt_hit(struct sess *sp)
 {
 
+	assert(!sp->obj->pass);
+
 	VCL_hit_method(sp);
 
-	if (sp->handling == VCL_RET_DELIVER && sp->obj->pass)
-		sp->handling = VCL_RET_PASS;
-
 	if (sp->handling == VCL_RET_DELIVER) {
 		sp->step = STP_DELIVER;
 		return (0);
 	}
+
+	/* Drop our object, we won't need it */
+	HSH_Deref(sp->obj);
+	sp->obj = NULL;
+
 	if (sp->handling == VCL_RET_PASS) {
-		HSH_Deref(sp->obj);
-		sp->obj = NULL;
 		sp->step = STP_PASS;
 		return (0);
 	}
 
 	if (sp->handling == VCL_RET_ERROR) {
-		HSH_Deref(sp->obj);
-		sp->obj = NULL;
 		sp->step = STP_ERROR;
 		return (0);
 	}
 
-	if (sp->handling == VCL_RET_LOOKUP)
-		INCOMPL();
 
 	INCOMPL();
 }
 
 
 /*--------------------------------------------------------------------
- * Look up request in hash table
+ * LOOKUP
+ * Hash things together and look object up in hash-table.
  *
  * LOOKUP consists of two substates so that we can reenter if we
  * encounter a busy object.
  *
-DOT subgraph cluster_lookup {
+DOT subgraph xcluster_lookup {
+DOT	hash [
+DOT		shape=box
+DOT		label="vcl_hash()"
+DOT	]
 DOT	lookup [
 DOT		shape=ellipse
-DOT		label="find obj in cache"
+DOT		label="obj in cache ?"
 DOT	]
-DOT	LOOKUP -> lookup [style=bold]
-DOT	lookup3 [
+DOT	lookup2 [
 DOT		shape=ellipse
-DOT		label="Insert new busy object"
+DOT		label="obj.pass ?"
 DOT	]
-DOT	lookup -> lookup3 [style=bold]
+DOT	LOOKUP -> hash [style=bold,color=green,weight=4]
+DOT	hash -> lookup [label="hash",style=bold,color=green,weight=4]
+DOT	lookup -> lookup2 [label="yes",style=bold,color=green,weight=4]
 DOT }
-DOT lookup -> HIT [label="hit", style=bold]
-DOT lookup3 -> MISS [label="miss", style=bold]
+DOT lookup2 -> HIT [label="no", style=bold,color=green,weight=4]
+DOT lookup2 -> PASS [label="yes"]
+DOT lookup -> MISS [label="no",style=bold,color=blue,weight=2]
  */
 
 static int
 cnt_lookup(struct sess *sp)
 {
-
-	AZ(sp->obj);
-	sp->step = STP_LOOKUP2;
-	return (0);
-}
-
-static int
-cnt_lookup2(struct sess *sp)
-{
 	struct object *o;
 
-	/*
-	 * We don't assign to sp->obj directly because it is used
-	 * to cache state when we encounter a busy object.
-	 */
-	o = HSH_Lookup(sp);
+	VCL_hash_method(sp);		/* XXX: no-op for now */
 
-	/* If we encountered busy-object, disembark worker thread */
+	o = HSH_Lookup(sp);
 	if (o == NULL) {
+		/*
+		 * We hit a busy object, disembark worker thread and expect
+		 * hash code to restart us, still in STP_LOOKUP, later.
+		 */
 		WSL(sp->wrk, SLT_Debug, sp->fd,
 		    "on waiting list on obj %u", sp->obj->xid);
 		SES_Charge(sp);
@@ -499,14 +451,17 @@
 		return (0);
 	}
 
-	/* Account separately for pass and cache objects */
 	if (sp->obj->pass) {
 		VSL_stats->cache_hitpass++;
 		WSL(sp->wrk, SLT_HitPass, sp->fd, "%u", sp->obj->xid);
-	} else {
-		VSL_stats->cache_hit++;
-		WSL(sp->wrk, SLT_Hit, sp->fd, "%u", sp->obj->xid);
-	}
+		HSH_Deref(sp->obj);
+		sp->obj = NULL;
+		sp->step = STP_PASS;
+		return (0);
+	} 
+
+	VSL_stats->cache_hit++;
+	WSL(sp->wrk, SLT_Hit, sp->fd, "%u", sp->obj->xid);
 	sp->step = STP_HIT;
 	return (0);
 }
@@ -515,37 +470,21 @@
 /*--------------------------------------------------------------------
  * We had a miss, ask VCL, proceed as instructed
  *
-DOT subgraph cluster_miss {
+DOT subgraph xcluster_miss {
 DOT	miss [
 DOT		shape=box
 DOT		label="vcl_miss()"
 DOT	]
-DOT	MISS -> miss [style=bold]
-DOT	miss_error [
-DOT		shape=ellipse
-DOT		label="obj.cacheable=false\nunbusy"
+DOT	MISS -> miss [style=bold,color=blue,weight=2]
+DOT	miss_ins [
+DOT		label="insert new object"
 DOT	]
-DOT	miss -> miss_error [label="error"]
-DOT	miss_pass [
-DOT		shape=ellipse
-DOT		label="obj.cacheable=false\nunbusy"
-DOT	]
-DOT	miss -> miss_pass [label="pass"]
-DOT	miss_lookup [
-DOT		shape=ellipse
-DOT		label="obj.cacheable=false\nunbusy"
-DOT	]
-DOT	miss -> miss_lookup [label="lookup", style=dotted, weight=0]
-DOT	miss_fetch [
-DOT		shape=ellipse
-DOT		label="fetch obj headers\nfrom backend"
-DOT	]
-DOT	miss -> miss_fetch [label="fetch", style=bold]
+DOT	miss -> miss_ins [label="fetch",style=bold,color=blue,weight=2]
 DOT }
-DOT miss_error -> ERROR
-DOT miss_pass -> PASS
-DOT miss_fetch -> FETCH [style=bold]
-DOT miss_lookup -> LOOKUP [style=dotted, weight=0]
+DOT miss -> err_miss [label="error"]
+DOT err_miss [label="ERROR",shape=plaintext]
+DOT miss_ins -> FETCH [style=bold,color=blue,weight=2]
+DOT miss -> PASS [label="pass"]
 DOT
  */
 
@@ -570,21 +509,8 @@
 		sp->step = STP_PASS;
 		return (0);
 	}
-	if (sp->handling == VCL_RET_LOOKUP)
-		INCOMPL();
 	if (sp->handling == VCL_RET_FETCH) {
-		AZ(sp->vbc);
-		if (FetchHeaders(sp)) {
-			sp->obj->cacheable = 0;
-			HSH_Unbusy(sp->obj);
-			HSH_Deref(sp->obj);
-			sp->obj = NULL;
-			sp->step = STP_DONE;
-			RES_Error(sp, 503, NULL);
-			return (0);
-		}
 		sp->step = STP_FETCH;
-		AN(sp->vbc);
 		return (0);
 	}
 	INCOMPL();
@@ -595,69 +521,61 @@
  * Start pass processing by getting headers from backend, then
  * continue in passbody.
  *
-DOT subgraph cluster_pass {
+DOT subgraph xcluster_pass {
 DOT	pass [
+DOT		shape=box
+DOT		label="vcl_pass()"
+DOT	]
+DOT	pass_do [
 DOT		shape=ellipse
-DOT		label="send to bke\nrx bkehdr"
+DOT		label="create new object\n"
 DOT	]
 DOT	PASS -> pass
+DOT	pass -> pass_do [label="pass"]
 DOT }
-DOT pass -> PASSBODY
+DOT pass_do -> FETCH
+DOT pass -> err_pass [label="error"]
+DOT err_pass [label="ERROR",shape=plaintext]
  */
 
 static int
 cnt_pass(struct sess *sp)
 {
 
-	AZ(sp->vbc);
-	if (!PassSession(sp)) {
-		AN(sp->vbc);
-		sp->step = STP_PASSBODY;
-	} else
-		sp->step = STP_DONE;
-	return (0);
-}
+	AZ(sp->obj);
 
-
-/*--------------------------------------------------------------------
- * We get here when we have the backends headers, send them to client
- * and pass any body the backend may have on as well.
- *
-DOT subgraph cluster_passbody {
-DOT	passbody [
-DOT		shape=ellipse
-DOT		label="send hdrs\npass body\n"
-DOT	]
-DOT	PASSBODY -> passbody
-DOT }
-DOT passbody -> DONE
- */
-
-static int
-cnt_passbody(struct sess *sp)
-{
-
-	sp->wrk->acct.pass++;
-	AN(sp->vbc);
-	PassBody(sp);
-	AZ(sp->vbc);
-	sp->step = STP_DONE;
+	VCL_pass_method(sp);
+	if (sp->handling == VCL_RET_ERROR) {
+		sp->step = STP_ERROR;
+		return (0);
+	}
+	HSH_Prealloc(sp);
+	sp->obj = sp->wrk->nobj;
+	sp->wrk->nobj = NULL;
+	sp->obj->busy = 1;
+	sp->step = STP_FETCH;
 	return (0);
 }
 
-
 /*--------------------------------------------------------------------
  * Ship the request header to the backend unchanged, then pipe
  * until one of the ends close the connection.
  *
-DOT subgraph cluster_pipe {
+DOT subgraph xcluster_pipe {
 DOT	pipe [
+DOT		shape=box
+DOT		label="vcl_pipe()"
+DOT	]
+DOT	pipe_do [
 DOT		shape=ellipse
 DOT		label="build&send hdr\npipe until close"
 DOT	]
 DOT	PIPE -> pipe
+DOT	pipe -> pipe_do [label="pipe"]
 DOT }
-DOT pipe -> DONE
+DOT pipe_do -> DONE
+DOT pipe -> err_pipe [label="error"]
+DOT err_pipe [label="ERROR",shape=plaintext]
  */
 
 static int
@@ -672,29 +590,22 @@
 
 
 /*--------------------------------------------------------------------
- * Dispatch the request as instructed by VCL
+ * RECV
+ * We have a complete request, get a VCL reference and dispatch it
+ * as instructed by vcl_recv{}
  *
-DOT subgraph cluster_recv {
+DOT subgraph xcluster_recv {
 DOT	recv [
 DOT		shape=box
 DOT		label="vcl_recv()"
 DOT	]
-DOT	RECV -> recv
-DOT	recv_lookup [
-DOT		shape=ellipse
-DOT		label="discard any body"
-DOT	]
-DOT	recv -> recv_lookup [label="lookup"]
-DOT	recv_error [
-DOT		shape=ellipse
-DOT		label="discard any body"
-DOT	]
-DOT	recv -> recv_error [label="error"]
+DOT	RECV -> recv [style=bold,color=green,weight=4]
 DOT }
 DOT recv -> PIPE [label="pipe"]
 DOT recv -> PASS [label="pass"]
-DOT recv_lookup -> LOOKUP
-DOT recv_error -> ERROR
+DOT recv -> err_recv [label="error"]
+DOT err_recv [label="ERROR",shape=plaintext]
+DOT recv -> LOOKUP [label="lookup",style=bold,color=green,weight=4]
  */
 
 static int
@@ -702,43 +613,45 @@
 {
 	int done;
 
-	VSL_stats->client_req++;
+	AZ(sp->vcl);
+	AZ(sp->obj);
+
+	/* Update stats of various sorts */
+	VSL_stats->client_req++;			/* XXX not locked */
 	clock_gettime(CLOCK_REALTIME, &sp->t_req);
 	sp->wrk->idle = sp->t_req.tv_sec;
-	sp->xid = ++xids;
+	sp->wrk->acct.req++;
+
+	/* Assign XID and log */
+	sp->xid = ++xids;				/* XXX not locked */
 	WSL(sp->wrk, SLT_ReqStart, sp->fd,
 	    "%s %s %u", sp->addr, sp->port,  sp->xid);
 
-	AZ(sp->vcl);
+	/* Borrow VCL reference from worker thread */
 	VCL_Refresh(&sp->wrk->vcl);
 	sp->vcl = sp->wrk->vcl;
 	sp->wrk->vcl = NULL;
 
-	AZ(sp->obj);
-	AZ(sp->vbc);
-
-	sp->wrk->acct.req++;
 	done = http_DissectRequest(sp->wrk, sp->http, sp->fd);
 	if (done != 0) {
-		RES_Error(sp, done, NULL);
+		RES_Error(sp, done, NULL);		/* XXX: STP_ERROR ? */
 		sp->step = STP_DONE;
 		return (0);
 	}
 
 	http_DoConnection(sp);
 
+	/* By default we use the first backend */
 	sp->backend = sp->vcl->backend[0];
 
 	/* XXX: Handle TRACE & OPTIONS of Max-Forwards = 0 */
 
-	/* XXX: determine if request comes with body */
-
 	VCL_recv_method(sp);
 
+	sp->wantbody = !strcmp(sp->http->hd[HTTP_HDR_REQ].b, "GET");
 	switch(sp->handling) {
 	case VCL_RET_LOOKUP:
 		/* XXX: discard req body, if any */
-		sp->wantbody = !strcmp(sp->http->hd[HTTP_HDR_REQ].b, "GET");
 		sp->step = STP_LOOKUP;
 		return (0);
 	case VCL_RET_PIPE:
@@ -760,8 +673,7 @@
 /*--------------------------------------------------------------------
  * Central state engine dispatcher.
  *
- * We grab a VCL reference, and keeps kicking the session around until
- * it has had enough.
+ * Kick the session around until it has had enough.
  *
  */
 
@@ -776,6 +688,10 @@
 	CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
 
 	for (done = 0; !done; ) {
+		/*
+		 * This is a good place to be paranoid about the various
+		 * pointers still pointing to the things we expect.
+		 */
 		CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 		if (sp->obj != NULL)
 			CHECK_OBJ(sp->obj, OBJECT_MAGIC);
@@ -784,11 +700,9 @@
 			CHECK_OBJ(w->nobj, OBJECT_MAGIC);
 		if (w->nobjhead != NULL)
 			CHECK_OBJ(w->nobjhead, OBJHEAD_MAGIC);
+
 		switch (sp->step) {
-#define STEP(l,u) \
-		case STP_##u: \
-			done = cnt_##l(sp); \
-			break;
+#define STEP(l,u) case STP_##u: done = cnt_##l(sp); break;
 #include "steps.h"
 #undef STEP
 		default:	INCOMPL();

Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_fetch.c	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/bin/varnishd/cache_fetch.c	2007-03-06 22:40:06 UTC (rev 1277)
@@ -243,11 +243,12 @@
 /*--------------------------------------------------------------------*/
 
 int
-FetchBody(struct sess *sp)
+Fetch(struct sess *sp)
 {
-	int cls;
 	struct vbe_conn *vc;
+	struct worker *w;
 	char *b;
+	int cls;
 	int body = 1;		/* XXX */
 	struct http *hp;
 	struct storage *st;
@@ -256,10 +257,54 @@
 	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
 	assert(sp->obj->busy != 0);
+	w = sp->wrk;
 
-	vc = sp->vbc;
-	sp->vbc = NULL;
+	sp->obj->xid = sp->xid;
 
+	vc = VBE_GetFd(sp);
+	if (vc == NULL)
+		return (1);
+
+	http_ClrHeader(vc->http);
+	vc->http->logtag = HTTP_Tx;
+	http_GetReq(w, vc->fd, vc->http, sp->http);
+	http_FilterHeader(w, vc->fd, vc->http, sp->http, HTTPH_R_FETCH);
+	http_PrintfHeader(w, vc->fd, vc->http, "X-Varnish: %u", sp->xid);
+	http_PrintfHeader(w, vc->fd, vc->http,
+	    "X-Forwarded-for: %s", sp->addr);
+	if (!http_GetHdr(vc->http, H_Host, &b)) {
+		http_PrintfHeader(w, vc->fd, vc->http, "Host: %s",
+		    sp->backend->hostname);
+	}
+
+	WRK_Reset(w, &vc->fd);
+	http_Write(w, vc->http, 0);
+	if (WRK_Flush(w)) {
+		/* XXX: cleanup */
+		return (1);
+	}
+
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
+
+	if (http_RecvHead(vc->http, vc->fd)) {
+		/* XXX: cleanup */
+		return (1);
+	}
+	if (http_DissectResponse(sp->wrk, vc->http, vc->fd)) {
+		/* XXX: cleanup */
+		return (1);
+	}
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
+
+	sp->obj->entered = time(NULL);
+
+
+	assert(sp->obj->busy != 0);
+
 	if (http_GetHdr(vc->http, H_Last_Modified, &b))
 		sp->obj->last_modified = TIM_parse(b);
 
@@ -314,66 +359,3 @@
 
 	return (0);
 }
-
-/*--------------------------------------------------------------------*/
-
-int
-FetchHeaders(struct sess *sp)
-{
-	struct vbe_conn *vc;
-	struct worker *w;
-	char *b;
-
-	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
-	assert(sp->obj->busy != 0);
-	w = sp->wrk;
-
-	sp->obj->xid = sp->xid;
-
-	vc = VBE_GetFd(sp);
-	if (vc == NULL)
-		return (1);
-
-	http_ClrHeader(vc->http);
-	vc->http->logtag = HTTP_Tx;
-	http_GetReq(w, vc->fd, vc->http, sp->http);
-	http_FilterHeader(w, vc->fd, vc->http, sp->http, HTTPH_R_FETCH);
-	http_PrintfHeader(w, vc->fd, vc->http, "X-Varnish: %u", sp->xid);
-	http_PrintfHeader(w, vc->fd, vc->http,
-	    "X-Forwarded-for: %s", sp->addr);
-	if (!http_GetHdr(vc->http, H_Host, &b)) {
-		http_PrintfHeader(w, vc->fd, vc->http, "Host: %s",
-		    sp->backend->hostname);
-	}
-
-	WRK_Reset(w, &vc->fd);
-	http_Write(w, vc->http, 0);
-	if (WRK_Flush(w)) {
-		/* XXX: cleanup */
-		return (1);
-	}
-
-	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
-
-	if (http_RecvHead(vc->http, vc->fd)) {
-		/* XXX: cleanup */
-		return (1);
-	}
-	if (http_DissectResponse(sp->wrk, vc->http, vc->fd)) {
-		/* XXX: cleanup */
-		return (1);
-	}
-	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
-	AZ(sp->vbc);
-	sp->vbc = vc;
-
-	sp->obj->entered = time(NULL);
-
-	return (0);
-}

Modified: trunk/varnish-cache/bin/varnishd/cache_hash.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_hash.c	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/bin/varnishd/cache_hash.c	2007-03-06 22:40:06 UTC (rev 1277)
@@ -64,23 +64,15 @@
 
 static struct hash_slinger      *hash;
 
-struct object *
-HSH_Lookup(struct sess *sp)
+/* Precreate an objhead and object for later use */
+void
+HSH_Prealloc(struct sess *sp)
 {
 	struct worker *w;
-	struct http *h;
-	struct objhead *oh;
-	struct object *o;
-	char *url, *host;
 
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->http, HTTP_MAGIC);
-	AN(hash);
 	w = sp->wrk;
-	h = sp->http;
 
-	/* Precreate an objhead and object in case we need them */
 	if (w->nobjhead == NULL) {
 		w->nobjhead = calloc(sizeof *w->nobjhead, 1);
 		XXXAN(w->nobjhead);
@@ -102,7 +94,25 @@
 		VSL_stats->n_object++;
 	} else
 		CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC);
+}
 
+struct object *
+HSH_Lookup(struct sess *sp)
+{
+	struct worker *w;
+	struct http *h;
+	struct objhead *oh;
+	struct object *o;
+	char *url, *host;
+
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->http, HTTP_MAGIC);
+	AN(hash);
+	w = sp->wrk;
+	h = sp->http;
+
+	HSH_Prealloc(sp);
 	url = h->hd[HTTP_HDR_URL].b;
 	if (!http_GetHdr(h, H_Host, &host))
 		host = url;
@@ -189,11 +199,14 @@
 
 	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
 	oh = o->objhead;
-	CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
-	LOCK(&oh->mtx);
+	if (oh != NULL) {
+		CHECK_OBJ(oh, OBJHEAD_MAGIC);
+		LOCK(&oh->mtx);
+	}
 	assert(o->refcnt > 0);
 	o->refcnt++;
-	UNLOCK(&oh->mtx);
+	if (oh != NULL)
+		UNLOCK(&oh->mtx);
 }
 
 void
@@ -205,8 +218,14 @@
 
 	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
 	oh = o->objhead;
-	CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
+	if (oh == NULL) {
+		/* Pass object, not referenced anywhere */
+		free(o);
+		return;
+	}
 
+	CHECK_OBJ(oh, OBJHEAD_MAGIC);
+
 	/* drop ref on object */
 	LOCK(&oh->mtx);
 	assert(o->refcnt > 0);

Deleted: trunk/varnish-cache/bin/varnishd/cache_pass.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_pass.c	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/bin/varnishd/cache_pass.c	2007-03-06 22:40:06 UTC (rev 1277)
@@ -1,269 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006 Linpro AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id$
- *
- * XXX: charge bytes to srcaddr
- * XXX: buffer to relieve backed ASAP.
- * XXX: Check if response has any body
- * XXX: Don't pass chunked to HTTP/1.0 client
- */
-
-#include <stdio.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#ifndef HAVE_CLOCK_GETTIME
-#include "compat/clock_gettime.h"
-#endif
-
-#include "shmlog.h"
-#include "cache.h"
-
-#define			PASS_BUFSIZ		8192
-
-/*--------------------------------------------------------------------*/
-
-static int
-pass_straight(struct sess *sp, int fd, struct http *hp, char *bi)
-{
-	int i;
-	off_t	cl;
-	unsigned c;
-	char buf[PASS_BUFSIZ];
-
-	if (bi != NULL)
-		cl = strtoumax(bi, NULL, 0);
-	else
-		cl = (1 << 30);
-
-	i = fcntl(fd, F_GETFL);		/* XXX ? */
-	i &= ~O_NONBLOCK;
-	i = fcntl(fd, F_SETFL, i);
-
-	while (cl != 0) {
-		c = cl;
-		if (c > sizeof buf)
-			c = sizeof buf;
-		i = http_Read(hp, fd, buf, c);
-		if (i == 0 && bi == NULL)
-			return (1);
-		if (i <= 0) {
-			vca_close_session(sp, "backend closed");
-			return (1);
-		}
-		sp->wrk->acct.bodybytes += WRK_Write(sp->wrk, buf, i);
-		if (WRK_Flush(sp->wrk))
-			vca_close_session(sp, "remote closed");
-		cl -= i;
-	}
-	return (0);
-}
-
-
-/*--------------------------------------------------------------------*/
-
-static int
-pass_chunked(struct sess *sp, int fd, struct http *hp)
-{
-	int i, j;
-	char *p, *q;
-	unsigned u;
-	char buf[PASS_BUFSIZ];
-	char *bp, *be;
-
-	i = fcntl(fd, F_GETFL);		/* XXX ? */
-	i &= ~O_NONBLOCK;
-	i = fcntl(fd, F_SETFL, i);
-
-	bp = buf;
-	be = buf + sizeof buf;
-	p = buf;
-	while (1) {
-		i = http_Read(hp, fd, bp, be - bp);
-		xxxassert(i >= 0);
-		if (i == 0 && p == bp)
-			break;
-		bp += i;
-		/* buffer valid from p to bp */
-		assert(bp >= p);
-
-		/* chunk starts with f("%x\r\n", len) */
-		u = strtoul(p, &q, 16);
-		while (q && q < bp && *q == ' ')
-			/* shouldn't happen - but sometimes it does */
-			q++;
-		if (q == NULL || q > bp - 2 /* want \r\n in same buffer */) {
-			/* short - move to start of buffer and extend */
-			memmove(buf, p, bp - p);
-			bp -= p - buf;
-			p = buf;
-			continue;
-		}
-		assert(*q == '\r');
-		q++;
-		assert(*q == '\n');
-		q++;
-
-		/* we just received the final zero-length chunk */
-		if (u == 0) {
-			sp->wrk->acct.bodybytes += WRK_Write(sp->wrk, p, q - p);
-			break;
-		}
-
-		/* include chunk header */
-		u += q - p;
-
-		/* include trailing \r\n with chunk */
-		u += 2;
-
-		for (;;) {
-			j = u;
-			if (bp - p < j)
-				j = bp - p;
-			sp->wrk->acct.bodybytes += WRK_Write(sp->wrk, p, j);
-			WRK_Flush(sp->wrk);
-			p += j;
-			assert(u >= j);
-			u -= j;
-			if (u == 0)
-				break;
-			p = bp = buf;
-			j = u;
-			if (j > be - bp)
-				j = be - bp;
-			i = http_Read(hp, fd, bp, j);
-			xxxassert(i > 0);
-			bp += i;
-		}
-	}
-	if (WRK_Flush(sp->wrk))
-		vca_close_session(sp, "remote closed");
-	return (0);
-}
-
-
-/*--------------------------------------------------------------------*/
-
-void
-PassBody(struct sess *sp)
-{
-	struct vbe_conn *vc;
-	char *b;
-	int cls;
-
-	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->vbc, VBE_CONN_MAGIC);
-	vc = sp->vbc;
-	sp->vbc = NULL;
-
-	clock_gettime(CLOCK_REALTIME, &sp->t_resp);
-
-	http_ClrHeader(sp->http);
-	http_CopyResp(sp->wrk, sp->fd, sp->http, vc->http);
-	http_FilterHeader(sp->wrk, sp->fd, sp->http, vc->http, HTTPH_A_PASS);
-	http_PrintfHeader(sp->wrk, sp->fd, sp->http, "X-Varnish: %u", sp->xid);
-	http_PrintfHeader(sp->wrk, sp->fd, sp->http,
-	    "X-Forwarded-for: %s", sp->addr);
-	/* XXX */
-	if (http_HdrIs(vc->http, H_Transfer_Encoding, "chunked"))
-		http_PrintfHeader(sp->wrk, sp->fd, sp->http, "Transfer-Encoding: chunked");
-	WRK_Reset(sp->wrk, &sp->fd);
-	sp->wrk->acct.hdrbytes += http_Write(sp->wrk, sp->http, 1);
-
-	if (http_GetHdr(vc->http, H_Content_Length, &b))
-		cls = pass_straight(sp, vc->fd, vc->http, b);
-	else if (http_HdrIs(vc->http, H_Connection, "close"))
-		cls = pass_straight(sp, vc->fd, vc->http, NULL);
-	else if (http_HdrIs(vc->http, H_Transfer_Encoding, "chunked"))
-		cls = pass_chunked(sp, vc->fd, vc->http);
-	else if (http_IsBodyless(vc->http))
-		cls = 0;
-	else {
-		cls = pass_straight(sp, vc->fd, vc->http, NULL);
-	}
-
-	if (WRK_Flush(sp->wrk))
-		vca_close_session(sp, "remote closed");
-
-	if (http_GetHdr(vc->http, H_Connection, &b) && !strcasecmp(b, "close"))
-		cls = 1;
-
-	if (cls)
-		VBE_ClosedFd(sp->wrk, vc, 0);
-	else
-		VBE_RecycleFd(sp->wrk, vc);
-}
-
-
-/*--------------------------------------------------------------------*/
-
-int
-PassSession(struct sess *sp)
-{
-	int i;
-	struct vbe_conn *vc;
-	struct worker *w;
-	char *b;
-
-	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
-	w = sp->wrk;
-
-	vc = VBE_GetFd(sp);
-	if (vc == NULL)
-		return (1);
-
-	http_CopyReq(w, vc->fd, vc->http, sp->http);
-	http_FilterHeader(w, vc->fd, vc->http, sp->http, HTTPH_R_PASS);
-	http_PrintfHeader(w, vc->fd, vc->http, "X-Varnish: %u", sp->xid);
-	if (!http_GetHdr(vc->http, H_Host, &b)) {
-		http_PrintfHeader(w, vc->fd, vc->http, "Host: %s",
-		    sp->backend->hostname);
-	}
-	WRK_Reset(w, &vc->fd);
-	http_Write(w, vc->http, 0);
-	i = WRK_Flush(w);
-	xxxassert(i == 0);
-
-	/* XXX: copy any contents */
-
-	i = http_RecvHead(vc->http, vc->fd);
-	xxxassert(i == 0);
-	http_DissectResponse(w, vc->http, vc->fd);
-
-	assert(sp->vbc == NULL);
-	sp->vbc = vc;
-	return (0);
-}

Modified: trunk/varnish-cache/bin/varnishd/cache_vrt.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_vrt.c	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/bin/varnishd/cache_vrt.c	2007-03-06 22:40:06 UTC (rev 1277)
@@ -82,7 +82,7 @@
 		hp = sp->http;
 		break;
 	case 2:
-		hp = sp->vbc->http;
+		hp = &sp->obj->http;
 		break;
 	default:
 		INCOMPL();

Modified: trunk/varnish-cache/bin/varnishd/mgt_vcc.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt_vcc.c	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/bin/varnishd/mgt_vcc.c	2007-03-06 22:40:06 UTC (rev 1277)
@@ -79,6 +79,18 @@
     "    lookup;\n"
     "}\n"
     "\n"
+    "sub default_vcl_pipe {\n"
+    "    pipe;\n"
+    "}\n"
+    "\n"
+    "sub default_vcl_pass {\n"
+    "    pass;\n"
+    "}\n"
+    "\n"
+    "sub default_vcl_hash {\n"
+    "    hash;\n"
+    "}\n"
+    "\n"
     "sub default_vcl_hit {\n"
     "    if (!obj.cacheable) {\n"
     "        pass;\n"
@@ -95,10 +107,10 @@
     "        error;\n"
     "    }\n"
     "    if (!obj.cacheable) {\n"
-    "        insert_pass;\n"
+    "        pass;\n"
     "    }\n"
     "    if (resp.http.Set-Cookie) {\n"
-    "        insert_pass;\n"
+    "        pass;\n"
     "    }\n"
     "    insert;\n"
     "}\n"

Modified: trunk/varnish-cache/bin/varnishd/steps.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/steps.h	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/bin/varnishd/steps.h	2007-03-06 22:40:06 UTC (rev 1277)
@@ -34,9 +34,7 @@
 STEP(recv,	RECV)
 STEP(pipe,	PIPE)
 STEP(pass,	PASS)
-STEP(passbody,	PASSBODY)
 STEP(lookup,	LOOKUP)
-STEP(lookup2,	LOOKUP2)
 STEP(miss,	MISS)
 STEP(hit,	HIT)
 STEP(fetch,	FETCH)

Modified: trunk/varnish-cache/include/vcl.h
===================================================================
--- trunk/varnish-cache/include/vcl.h	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/include/vcl.h	2007-03-06 22:40:06 UTC (rev 1277)
@@ -28,6 +28,9 @@
         vcl_fini_f      *fini_func;
 
 	vcl_func_f	*recv_func;
+	vcl_func_f	*pipe_func;
+	vcl_func_f	*pass_func;
+	vcl_func_f	*hash_func;
 	vcl_func_f	*miss_func;
 	vcl_func_f	*hit_func;
 	vcl_func_f	*fetch_func;

Modified: trunk/varnish-cache/include/vcl_returns.h
===================================================================
--- trunk/varnish-cache/include/vcl_returns.h	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/include/vcl_returns.h	2007-03-06 22:40:06 UTC (rev 1277)
@@ -11,9 +11,9 @@
 VCL_RET_MAC_E(error, ERROR, (1 << 0), 0)
 #endif
 VCL_RET_MAC(lookup, LOOKUP, (1 << 1), 1)
-VCL_RET_MAC(pipe, PIPE, (1 << 2), 2)
-VCL_RET_MAC(pass, PASS, (1 << 3), 3)
-VCL_RET_MAC(insert_pass, INSERT_PASS, (1 << 4), 4)
+VCL_RET_MAC(hash, HASH, (1 << 2), 2)
+VCL_RET_MAC(pipe, PIPE, (1 << 3), 3)
+VCL_RET_MAC(pass, PASS, (1 << 4), 4)
 VCL_RET_MAC(fetch, FETCH, (1 << 5), 5)
 VCL_RET_MAC(insert, INSERT, (1 << 6), 6)
 VCL_RET_MAC(deliver, DELIVER, (1 << 7), 7)
@@ -21,9 +21,9 @@
 #else
 #define VCL_RET_ERROR  (1 << 0)
 #define VCL_RET_LOOKUP  (1 << 1)
-#define VCL_RET_PIPE  (1 << 2)
-#define VCL_RET_PASS  (1 << 3)
-#define VCL_RET_INSERT_PASS  (1 << 4)
+#define VCL_RET_HASH  (1 << 2)
+#define VCL_RET_PIPE  (1 << 3)
+#define VCL_RET_PASS  (1 << 4)
 #define VCL_RET_FETCH  (1 << 5)
 #define VCL_RET_INSERT  (1 << 6)
 #define VCL_RET_DELIVER  (1 << 7)
@@ -33,8 +33,11 @@
 
 #ifdef VCL_MET_MAC
 VCL_MET_MAC(recv,RECV,(VCL_RET_ERROR|VCL_RET_PASS|VCL_RET_PIPE|VCL_RET_LOOKUP))
-VCL_MET_MAC(miss,MISS,(VCL_RET_ERROR|VCL_RET_PASS|VCL_RET_PIPE|VCL_RET_FETCH))
-VCL_MET_MAC(hit,HIT,(VCL_RET_ERROR|VCL_RET_PASS|VCL_RET_PIPE|VCL_RET_DELIVER))
-VCL_MET_MAC(fetch,FETCH,(VCL_RET_ERROR|VCL_RET_PASS|VCL_RET_PIPE|VCL_RET_INSERT|VCL_RET_INSERT_PASS))
+VCL_MET_MAC(pipe,PIPE,(VCL_RET_ERROR|VCL_RET_PIPE))
+VCL_MET_MAC(pass,PASS,(VCL_RET_ERROR|VCL_RET_PASS))
+VCL_MET_MAC(hash,HASH,(VCL_RET_HASH))
+VCL_MET_MAC(miss,MISS,(VCL_RET_ERROR|VCL_RET_PASS|VCL_RET_FETCH))
+VCL_MET_MAC(hit,HIT,(VCL_RET_ERROR|VCL_RET_PASS|VCL_RET_DELIVER))
+VCL_MET_MAC(fetch,FETCH,(VCL_RET_ERROR|VCL_RET_PASS|VCL_RET_INSERT))
 VCL_MET_MAC(timeout,TIMEOUT,(VCL_RET_FETCH|VCL_RET_DISCARD))
 #endif

Modified: trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c	2007-03-06 22:40:06 UTC (rev 1277)
@@ -228,15 +228,15 @@
 			return (T_FETCH);
 		}
 		return (0);
+	case 'h':
+		if (p[0] == 'h' && p[1] == 'a' && p[2] == 's' && 
+		    p[3] == 'h' && !isvar(p[4])) {
+			*q = p + 4;
+			return (T_HASH);
+		}
+		return (0);
 	case 'i':
 		if (p[0] == 'i' && p[1] == 'n' && p[2] == 's' && 
-		    p[3] == 'e' && p[4] == 'r' && p[5] == 't' && 
-		    p[6] == '_' && p[7] == 'p' && p[8] == 'a' && 
-		    p[9] == 's' && p[10] == 's' && !isvar(p[11])) {
-			*q = p + 11;
-			return (T_INSERT_PASS);
-		}
-		if (p[0] == 'i' && p[1] == 'n' && p[2] == 's' && 
 		    p[3] == 'e' && p[4] == 'r' && p[5] == 't'
 		     && !isvar(p[6])) {
 			*q = p + 6;
@@ -396,11 +396,11 @@
 	vcl_tnames[T_FETCH] = "fetch";
 	vcl_tnames[T_FUNC] = "func";
 	vcl_tnames[T_GEQ] = ">=";
+	vcl_tnames[T_HASH] = "hash";
 	vcl_tnames[T_IF] = "if";
 	vcl_tnames[T_INC] = "++";
 	vcl_tnames[T_INCR] = "+=";
 	vcl_tnames[T_INSERT] = "insert";
-	vcl_tnames[T_INSERT_PASS] = "insert_pass";
 	vcl_tnames[T_LEQ] = "<=";
 	vcl_tnames[T_LOOKUP] = "lookup";
 	vcl_tnames[T_MUL] = "*=";
@@ -424,9 +424,9 @@
 {
 	fputs("#define VCL_RET_ERROR  (1 << 0)\n", f);
 	fputs("#define VCL_RET_LOOKUP  (1 << 1)\n", f);
-	fputs("#define VCL_RET_PIPE  (1 << 2)\n", f);
-	fputs("#define VCL_RET_PASS  (1 << 3)\n", f);
-	fputs("#define VCL_RET_INSERT_PASS  (1 << 4)\n", f);
+	fputs("#define VCL_RET_HASH  (1 << 2)\n", f);
+	fputs("#define VCL_RET_PIPE  (1 << 3)\n", f);
+	fputs("#define VCL_RET_PASS  (1 << 4)\n", f);
 	fputs("#define VCL_RET_FETCH  (1 << 5)\n", f);
 	fputs("#define VCL_RET_INSERT  (1 << 6)\n", f);
 	fputs("#define VCL_RET_DELIVER  (1 << 7)\n", f);
@@ -461,6 +461,9 @@
 	fputs("        vcl_fini_f      *fini_func;\n", f);
 	fputs("\n", f);
 	fputs("	vcl_func_f	*recv_func;\n", f);
+	fputs("	vcl_func_f	*pipe_func;\n", f);
+	fputs("	vcl_func_f	*pass_func;\n", f);
+	fputs("	vcl_func_f	*hash_func;\n", f);
 	fputs("	vcl_func_f	*miss_func;\n", f);
 	fputs("	vcl_func_f	*hit_func;\n", f);
 	fputs("	vcl_func_f	*fetch_func;\n", f);

Modified: trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl	2007-03-06 22:40:06 UTC (rev 1277)
@@ -35,9 +35,12 @@
 #
 set methods {
 	{recv		{error pass pipe lookup}}
-	{miss		{error pass pipe fetch}}
-	{hit		{error pass pipe deliver}}
-	{fetch		{error pass pipe insert insert_pass}}
+	{pipe		{error pipe}}
+	{pass		{error pass}}
+	{hash		{hash}}
+	{miss		{error pass fetch}}
+	{hit		{error pass deliver}}
+	{fetch		{error pass insert}}
 	{timeout	{fetch discard}}
 }
 
@@ -46,9 +49,9 @@
 set returns {
 	error
 	lookup
+	hash
 	pipe
 	pass
-	insert_pass
 	fetch
 	insert
 	deliver

Modified: trunk/varnish-cache/lib/libvcl/vcc_token_defs.h
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_token_defs.h	2007-02-27 20:33:42 UTC (rev 1276)
+++ trunk/varnish-cache/lib/libvcl/vcc_token_defs.h	2007-03-06 22:40:06 UTC (rev 1277)
@@ -24,9 +24,9 @@
 #define T_SWITCH_CONFIG 142
 #define T_ERROR 143
 #define T_LOOKUP 144
-#define T_PIPE 145
-#define T_PASS 146
-#define T_INSERT_PASS 147
+#define T_HASH 145
+#define T_PIPE 146
+#define T_PASS 147
 #define T_FETCH 148
 #define T_INSERT 149
 #define T_DELIVER 150




More information about the varnish-commit mailing list