Commit 26c00497 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp Committed by Tollef Fog Heen

Overhaul the Vary matching code to make it faster, by assuming (but

do not trusting) that all objects under an objhdr have the same
Vary string.

Build a vary string for the request on the wrk->ws as we do the
comparison and use it as a cache for subsequent comparisons.

This will also be first step of sky's "pre-vary"
parent b6e6fe93
......@@ -298,7 +298,11 @@ struct worker {
uint32_t *wlb, *wlp, *wle;
unsigned wlr;
/* Lookup stuff */
struct SHA256Context *sha256ctx;
uint8_t *vary_b;
uint8_t *vary_l;
uint8_t *vary_e;
struct http_conn htc[1];
struct ws ws[1];
......@@ -880,7 +884,7 @@ void RES_StreamPoll(const struct sess *sp);
/* cache_vary.c */
struct vsb *VRY_Create(const struct sess *sp, const struct http *hp);
int VRY_Match(const struct sess *sp, const unsigned char *vary);
int VRY_Match(const struct sess *sp, const uint8_t *vary);
/* cache_vcl.c */
void VCL_Init(void);
......
......@@ -330,6 +330,13 @@ HSH_Lookup(struct sess *sp, struct objhead **poh)
}
CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
AZ(sp->wrk->vary_b);
AZ(sp->wrk->vary_l);
AZ(sp->wrk->vary_e);
WS_Reserve(sp->wrk->ws, 0);
sp->wrk->vary_b = (void*)sp->wrk->ws->f;
sp->wrk->vary_e = (void*)sp->wrk->ws->r;
sp->wrk->vary_b[2] = '\0';
Lck_Lock(&oh->mtx);
assert(oh->refcnt > 0);
busy_oc = NULL;
......@@ -374,6 +381,11 @@ HSH_Lookup(struct sess *sp, struct objhead **poh)
}
}
WS_ReleaseP(sp->wrk->ws, (void*)sp->wrk->vary_b);
sp->wrk->vary_b = NULL;
sp->wrk->vary_l = NULL;
sp->wrk->vary_e = NULL;
/*
* If we have seen a busy object or the backend is unhealthy, and
* we have an object in grace, use it, if req.grace is also
......
......@@ -58,6 +58,7 @@
#include <stdlib.h>
#include "cache.h"
#include "vend.h"
#include "vct.h"
struct vsb *
......@@ -131,63 +132,112 @@ VRY_Create(const struct sess *sp, const struct http *hp)
return(sb);
}
/*
* Find length of a vary entry
*/
static unsigned
vry_len(const uint8_t *p)
{
unsigned l = vbe16dec(p);
return (2 + p[2] + 2 + (l == 0xffff ? 0 : l));
}
/*
* Compare two vary entries
*/
static int
vry_cmp(const uint8_t * const *v1, uint8_t * const *v2)
{
unsigned retval = 0;
if (!memcmp(*v1, *v2, vry_len(*v1))) {
/* Same same */
retval = 0;
} else if (memcmp((*v1) + 2, (*v2) + 2, (*v1)[2] + 2)) {
/* Different header */
retval = 1;
} else if (params->http_gzip_support &&
!strcasecmp(H_Accept_Encoding, (const char*)((*v1)+2))) {
/*
* If we do gzip processing, we do not vary on Accept-Encoding,
* because we want everybody to get the gzip'ed object, and
* varnish will gunzip as necessary. We implement the skip at
* check time, rather than create time, so that object in
* persistent storage can be used with either setting of
* http_gzip_support.
*/
retval = 0;
} else {
/* Same header, different content */
retval = 2;
}
return (retval);
}
int
VRY_Match(const struct sess *sp, const uint8_t *vary)
{
uint8_t *vsp = sp->wrk->vary_b;
char *h, *e;
int i, l, lh;
while (1) {
l = vary[0] * 256 + vary[1];
vary += 2;
if (!*vary)
break;
if (params->http_gzip_support &&
!strcasecmp(H_Accept_Encoding, (const char*)vary)) {
/*
* If we do gzip processing, we do not vary on
* Accept-Encoding, because we want everybody to
* get the gzip'ed object, and varnish will gunzip
* as necessary. We implement the skip at check
* time, rather than create time, so that object
* in persistent storage can be used with either
* setting of http_gzip_support.
*/
vary += *vary + 2;
if (l != 0xffff)
vary += l;
continue;
unsigned lh, ln;
int i, retval = 1, oflo = 0;
AN(vsp);
while (vary[2]) {
i = vry_cmp(&vary, &vsp);
if (i == 1) {
/* Build a new entry */
i = http_GetHdr(sp->http, (const char*)(vary+2), &h);
if (i) {
/* Trim trailing space */
e = strchr(h, '\0');
while (e > h && vct_issp(e[-1]))
e--;
lh = e - h;
assert(lh < 0xffff);
} else {
e = h = NULL;
lh = 0xffff;
}
/* Length of the entire new vary entry */
ln = 2 + vary[2] + 2 + (lh == 0xffff ? 0 : lh);
if (vsp + ln >= sp->wrk->vary_e) {
vsp = sp->wrk->vary_b;
oflo = 1;
}
/* We MUST have space for one entry */
assert(vsp + ln < sp->wrk->vary_e);
vbe16enc(vsp, (uint16_t)lh);
memcpy(vsp + 2, vary + 2, vary[2] + 2);
if (h != NULL && e != NULL)
memcpy(vsp + 2 + vsp[2] + 2, h, e - h);
i = vry_cmp(&vary, &vsp);
assert(i != 1); /* hdr must be the same now */
}
/* Look for header */
i = http_GetHdr(sp->http, (const char*)vary, &h);
vary += *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 trailing space */
e = strchr(h, '\0');
while (e > h && vct_issp(e[-1]))
e--;
/* Fail if wrong length */
lh = e - h;
if (lh != l)
return (0);
if (i != 0)
retval = 0;
vsp += vry_len(vsp);
vary += vry_len(vary);
}
if (vsp + 3 > sp->wrk->vary_e)
oflo = 1;
/* or if wrong contents */
if (memcmp(h, vary, l))
return (0);
vary += l;
if (oflo) {
/* XXX: Should log this */
vsp = sp->wrk->vary_b;
}
return (1);
vsp[0] = 0xff;
vsp[1] = 0xff;
vsp[2] = 0;
if (oflo)
sp->wrk->vary_l = NULL;
else
sp->wrk->vary_l = vsp + 3;
return (retval);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment