Commit 35dc3964 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp Committed by Tollef Fog Heen

Introduce the "busyobj" structure which is only valid for busy objects.

Use it to hold the derived vary string for the request (if any) and
skip busy objects with non-matching Vary during hash lookup.

Idea by:	sky
parent e3deca91
......@@ -97,6 +97,7 @@ struct director;
struct object;
struct objhead;
struct objcore;
struct busyobj;
struct storage;
struct workreq;
struct vrt_backend;
......@@ -281,6 +282,7 @@ struct worker {
struct objhead *nobjhead;
struct objcore *nobjcore;
struct waitinglist *nwaitinglist;
struct busyobj *nbusyobj;
void *nhashpriv;
struct dstat stats;
......@@ -416,6 +418,7 @@ struct objcore {
void *priv;
unsigned priv2;
struct objhead *objhead;
struct busyobj *busyobj;
double timer_when;
unsigned flags;
#define OC_F_BUSY (1<<1)
......@@ -470,7 +473,16 @@ oc_getlru(const struct objcore *oc)
return (oc->methods->getlru(oc));
}
/* Busy Object structure ---------------------------------------------*/
struct busyobj {
unsigned magic;
#define BUSYOBJ_MAGIC 0x23b95567
uint8_t *vary;
};
/* Object structure --------------------------------------------------*/
VTAILQ_HEAD(storagehead, storage);
struct object {
......
......@@ -111,6 +111,11 @@ HSH_Prealloc(const struct sess *sp)
}
CHECK_OBJ_NOTNULL(w->nwaitinglist, WAITINGLIST_MAGIC);
if (w->nbusyobj == NULL) {
ALLOC_OBJ(w->nbusyobj, BUSYOBJ_MAGIC);
XXXAN(w->nbusyobj);
}
if (hash->prep != NULL)
hash->prep(sp);
}
......@@ -342,8 +347,15 @@ HSH_Lookup(struct sess *sp, struct objhead **poh)
assert(oc->objhead == oh);
if (oc->flags & OC_F_BUSY) {
if (!sp->hash_ignore_busy)
busy_oc = oc;
CHECK_OBJ_NOTNULL(oc->busyobj, BUSYOBJ_MAGIC);
if (sp->hash_ignore_busy)
continue;
if (oc->busyobj->vary != NULL &&
!VRY_Match(sp, oc->busyobj->vary))
continue;
busy_oc = oc;
continue;
}
......@@ -445,6 +457,10 @@ HSH_Lookup(struct sess *sp, struct objhead **poh)
AN(oc->flags & OC_F_BUSY);
oc->refcnt = 1;
w->nbusyobj->vary = sp->vary_b;
oc->busyobj = w->nbusyobj;
w->nbusyobj = NULL;
/*
* Busy objects go on the tail, so they will not trip up searches.
* HSH_Unbusy() will move them to the front.
......@@ -609,6 +625,9 @@ HSH_Unbusy(const struct sess *sp)
VTAILQ_REMOVE(&oh->objcs, oc, list);
VTAILQ_INSERT_HEAD(&oh->objcs, oc, list);
oc->flags &= ~OC_F_BUSY;
AZ(sp->wrk->nbusyobj);
sp->wrk->nbusyobj = oc->busyobj;
oc->busyobj = NULL;
hsh_rush(oh);
AN(oc->ban);
Lck_Unlock(&oh->mtx);
......
varnishtest "predictive vary"
server s1 {
rxreq
txresp -hdr "Vary: foo" -bodylen 1
rxreq
sema r2 sync 2
sema r1 sync 2
txresp -hdr "Vary: foo" -bodylen 2
} -start
server s2 {
rxreq
txresp -hdr "Vary: foo" -bodylen 3
} -start
varnish v1 -vcl+backend {
sub vcl_recv {
if (req.http.bar) {
set req.backend = s2;
}
}
} -start
client c1 {
txreq -hdr "Foo: vary1"
rxresp
expect resp.bodylen == 1
txreq -hdr "Foo: vary2"
rxresp
expect resp.bodylen == 2
} -start
client c2 {
sema r2 sync 2
txreq -hdr "Foo: vary3" -hdr "bar: yes"
rxresp
sema r1 sync 2
expect resp.bodylen == 3
} -start
client c1 -wait
client c2 -wait
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