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);
}
int
VRY_Match(const struct sess *sp, const uint8_t *vary)
/*
* Find length of a vary entry
*/
static unsigned
vry_len(const uint8_t *p)
{
char *h, *e;
int i, l, lh;
unsigned l = vbe16dec(p);
while (1) {
l = vary[0] * 256 + vary[1];
vary += 2;
if (!*vary)
break;
return (2 + p[2] + 2 + (l == 0xffff ? 0 : l));
}
if (params->http_gzip_support &&
!strcasecmp(H_Accept_Encoding, (const char*)vary)) {
/*
* 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.
* 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;
retval = 0;
} else {
/* Same header, different content */
retval = 2;
}
/* 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;
return (retval);
}
int
VRY_Match(const struct sess *sp, const uint8_t *vary)
{
uint8_t *vsp = sp->wrk->vary_b;
char *h, *e;
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--;
/* Fail if wrong length */
lh = e - h;
if (lh != l)
return (0);
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 */
}
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