r1506 - trunk/varnish-cache/bin/varnishd

phk at projects.linpro.no phk at projects.linpro.no
Sun Jun 10 10:49:43 CEST 2007


Author: phk
Date: 2007-06-10 10:49:43 +0200 (Sun, 10 Jun 2007)
New Revision: 1506

Added:
   trunk/varnish-cache/bin/varnishd/cache_vary.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_hash.c
Log:
Take a shot at light-weight "Vary:" processing.

When we cache an object with a "Vary:" header, we generate
a "vary matching string" which can be used to efficiently
check for compliance when doing a cache lookup.

Only very lightly tested (ie: cnn.com).

For a full description of the reasoning, please see
	http://varnish.projects.linpro.no/wiki/ArchitectureVary



Modified: trunk/varnish-cache/bin/varnishd/Makefile.am
===================================================================
--- trunk/varnish-cache/bin/varnishd/Makefile.am	2007-06-10 07:47:50 UTC (rev 1505)
+++ trunk/varnish-cache/bin/varnishd/Makefile.am	2007-06-10 08:49:43 UTC (rev 1506)
@@ -25,6 +25,7 @@
 	cache_response.c \
 	cache_session.c \
 	cache_synthetic.c \
+	cache_vary.c \
 	cache_vcl.c \
 	cache_vrt.c \
 	cache_vrt_acl.c \

Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h	2007-06-10 07:47:50 UTC (rev 1505)
+++ trunk/varnish-cache/bin/varnishd/cache.h	2007-06-10 08:49:43 UTC (rev 1506)
@@ -225,6 +225,8 @@
 	unsigned		xid;
 	struct objhead		*objhead;
 
+	unsigned char		*vary;
+
 	unsigned		heap_idx;
 	unsigned		ban_seq;
 
@@ -463,6 +465,10 @@
 /* cache_synthetic.c */
 void SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl);
 
+/* cache_vary.c */
+void VRY_Create(struct sess *sp);
+int VRY_Match(struct sess *sp, unsigned char *vary);
+
 /* cache_vcl.c */
 void VCL_Init(void);
 void VCL_Refresh(struct VCL_conf **vcc);

Modified: trunk/varnish-cache/bin/varnishd/cache_center.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_center.c	2007-06-10 07:47:50 UTC (rev 1505)
+++ trunk/varnish-cache/bin/varnishd/cache_center.c	2007-06-10 08:49:43 UTC (rev 1506)
@@ -298,6 +298,7 @@
 
 	sp->obj->cacheable = 1;
 	if (sp->obj->objhead != NULL) {
+		VRY_Create(sp);
 		HSH_Ref(sp->obj); /* get another, STP_DELIVER will deref */
 		HSH_Unbusy(sp->obj);
 	}

Modified: trunk/varnish-cache/bin/varnishd/cache_hash.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_hash.c	2007-06-10 07:47:50 UTC (rev 1505)
+++ trunk/varnish-cache/bin/varnishd/cache_hash.c	2007-06-10 08:49:43 UTC (rev 1506)
@@ -148,7 +148,6 @@
 			return (NULL);
 		}
 	were_back:
-		/* XXX: check Vary: */
 		if (!o->cacheable) {
 			/* ignore */
 		} else if (o->ttl == 0) {
@@ -159,7 +158,7 @@
 			o->ttl = 0;
 			VSL(SLT_ExpBan, 0, "%u was banned", o->xid);
 			EXP_TTLchange(o);
-		} else
+		} else if (VRY_Match(sp, o->vary))
 			break;
 		o->refcnt--;
 	}
@@ -254,6 +253,9 @@
 	if (o->http.ws->s != NULL)
 		free(o->http.ws->s);
 
+	if (o->vary != NULL)
+		free(o->vary);
+
 	HSH_Freestore(o);
 	free(o);
 	VSL_stats->n_object--;

Added: trunk/varnish-cache/bin/varnishd/cache_vary.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_vary.c	                        (rev 0)
+++ trunk/varnish-cache/bin/varnishd/cache_vary.c	2007-06-10 08:49:43 UTC (rev 1506)
@@ -0,0 +1,176 @@
+/*-
+ * Copyright (c) 2006-2007 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 THE 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$
+ *
+ * Do Vary processing.
+ *
+ * When we insert an object into the cache which has a Vary: header,
+ * we encode a vary matching string containing the headers mentioned
+ * and their value.
+ *
+ * When we match an object in the cache, we check the present request
+ * against the vary matching string.
+ *
+ * The only kind of header-munging we do is leading & trailing space
+ * removal.  All the potential "q=foo" gymnastics is not worth the
+ * effort.
+ *
+ * The vary matching string has the following format:
+ *
+ * Sequence of: {
+ *	<length of header + 1>	\
+ *	<header>		 \  Same format as argument to http_GetHdr()
+ *	':'			 /
+ *	'\0'			/
+ *	<msb>			\   Length of header contents.
+ *	<lsb>			/
+ *      <header>		    Only present if length != 0xffff
+ * }
+ *      '\0'
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cache.h"
+
+void
+VRY_Create(struct sess *sp)
+{
+	char *v, *p, *q, *h, *e;
+	struct vsb *sb, *sbh;
+	unsigned l;
+
+	/* For vary matching string */
+	sb = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND);
+	AN(sb);
+
+	/* For header matching strings */
+	sbh = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND);
+	AN(sbh);
+
+	/* No Vary: header, no worries */
+	if (!http_GetHdr(&sp->obj->http, H_Vary, &v))
+		return;
+
+	for (p = v; *p; p++) {
+
+		/* Find next header-name */
+		if (isspace(*p))
+			continue;
+		for (q = p; *q && !isspace(*q) && *q != ','; q++)
+			continue;
+
+		/* Build a header-matching string out of it */
+		vsb_clear(sbh);
+		vsb_printf(sbh, "%c%.*s:%c", 1 + (q - p), q - p, p, 0);
+		vsb_finish(sbh);
+
+		/* Append to vary matching string */
+		vsb_bcat(sb, vsb_data(sbh), vsb_len(sbh));
+
+		if (http_GetHdr(sp->http, vsb_data(sbh), &h)) {
+			/* Trim leading and trailing space */
+			while (isspace(*h))
+				h++;
+			e = strchr(h, '\0');
+			while (e > h && isspace(e[-1]))
+				e--;
+			/* Encode two byte length and contents */
+			l = e - h;
+			vsb_printf(sb, "%c%c", l >> 8, l & 0xff);
+			vsb_bcat(sb, h, e - h);
+		} else {
+			/* Mark as "not present" */
+			vsb_printf(sb, "%c%c", 0xff, 0xff);
+		}
+		
+		while (isspace(*q)) 
+			q++;
+		if (*q == '\0')
+			break;
+		xxxassert(*q == ',');
+		p = q;
+	}
+	/* Terminate vary matching string */
+	vsb_printf(sb, "%c", 0);
+
+	vsb_finish(sb);
+	l = vsb_len(sb);
+	sp->obj->vary = malloc(l);
+	AN(sp->obj->vary);
+	memcpy(sp->obj->vary, vsb_data(sb), l);
+}
+
+int
+VRY_Match(struct sess *sp, unsigned char *vary)
+{
+	char *h, *e;
+	int i, l, lh;
+
+	while (*vary) {
+
+		/* Look for header */
+		i = http_GetHdr(sp->http, (char*)vary, &h);
+		vary += *vary + 2;
+
+		/* Expected length of header (or 0xffff) */
+		l = vary[0] * 256 + vary[1];
+		vary += 2;
+
+		/* Fail if we have the header, but shouldn't */
+		if (i && l == 0xffff)
+			return (0);
+		/* or if we don't when we should */
+		if (l != 0xffff && !i)
+			return (0);
+
+		/* Nothing to match */
+		if (!i)
+			continue;
+
+		/* Trim leading & trailing space */
+		while (isspace(*h))
+			h++;
+		e = strchr(h, '\0');
+		while (e > h && isspace(e[-1]))
+			e--;
+
+		/* Fail if wrong length */
+		lh = e - h;
+		if (lh != l)
+			return (0);
+
+		/* or if wrong contents */
+		if (memcmp(h, vary, l))
+			return (0);
+		vary += l;
+	}
+	return (1);
+}




More information about the varnish-commit mailing list