Commit 7bc0068d authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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 0f354aca
......@@ -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