Mailing List Archive

r1506 - trunk/varnish-cache/bin/varnishd
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);
+}
r1506 - trunk/varnish-cache/bin/varnishd [ In reply to ]
phk at projects.linpro.no writes:
> 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

This is awesome! Thanks!

/me runs off to test it

DES
--
Dag-Erling Sm?rgrav
Senior Software Developer
Linpro AS - www.linpro.no