Commit 4db9d233 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

This is really complicated to explain, but quite simple behind all

the gunk:

A persistent storage method, needs to know about "struct object" in
addition to regular storage allocations, in order to track ttl and
ban information etc.

Therefore, when we create an object, we call into the stevedore.c
to do so with STV_NewObject(), it picks an stevedore, and calls
the ->allocobj() method, which will allocate some storage, call
STV_MkObject() to turn it into an object, which can then be
fondled, before passing it back to STV_NewObject() an from there
to cache_center.c::cnt_fetch().

Non-persistent stevedores, don't define ->allocobj() and when
initialized by stevedore.c, get a suitable default function.

XXX: next steps, remove objcore argument from stv->alloc() and
remove stv->object() method entirely, now that we have a proper
calling order.





git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@5558 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent ecd3344b
......@@ -557,7 +557,8 @@ cnt_fetch(struct sess *sp)
AZ(sp->objcore);
}
l = http_EstimateWS(sp->wrk->beresp, sp->pass ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp);
l = http_EstimateWS(sp->wrk->beresp,
sp->pass ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp);
if (vary != NULL)
l += varyl;
......@@ -571,17 +572,7 @@ cnt_fetch(struct sess *sp)
*/
sp->obj = STV_NewObject(sp, l, sp->wrk->ttl, nhttp);
if (sp->objhead != NULL) {
CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC);
CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC);
sp->objcore->priv = sp->obj; /* XXX */
sp->obj->objcore = sp->objcore;
sp->objcore->objhead = sp->objhead;
sp->objhead = NULL; /* refcnt follows pointer. */
sp->objcore = NULL; /* refcnt follows pointer. */
BAN_NewObj(sp->obj);
}
CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
if (vary != NULL) {
sp->obj->vary =
......@@ -609,7 +600,8 @@ cnt_fetch(struct sess *sp)
hp2->logtag = HTTP_Obj;
http_CopyResp(hp2, hp);
http_FilterFields(sp->wrk, sp->fd, hp2, hp, sp->pass ? HTTPH_R_PASS : HTTPH_A_INS);
http_FilterFields(sp->wrk, sp->fd, hp2, hp,
sp->pass ? HTTPH_R_PASS : HTTPH_A_INS);
http_CopyHome(sp->wrk, sp->fd, hp2);
if (http_GetHdr(hp, H_Last_Modified, &b))
......@@ -633,8 +625,13 @@ cnt_fetch(struct sess *sp)
return (0);
}
if (sp->wrk->cacheable)
if (sp->wrk->cacheable) {
/*
* Needs ttl & ban to be in order.
* XXX call oc->updatemeta() instead ?
*/
STV_Object(sp);
}
if (sp->wrk->do_esi)
ESI_Parse(sp);
......
......@@ -53,7 +53,7 @@ static VTAILQ_HEAD(, stevedore) stevedores =
static const struct stevedore * volatile stv_next;
static const struct stevedore *stv_transient;
static struct stevedore *stv_transient;
/*********************************************************************
* NB! Dirty trick alert:
......@@ -143,46 +143,52 @@ stv_alloc(const struct sess *sp, size_t size, struct objcore *oc)
}
/*********************************************************************/
/*********************************************************************
* Structure used to transport internal knowledge from STV_NewObject()
* to STV_MkObject(). Nobody else should mess with this struct.
*/
struct stv_objsecrets {
unsigned magic;
#define STV_OBJ_SECRETES_MAGIC 0x78c87247
unsigned nhttp;
unsigned lhttp;
unsigned wsl;
double ttl;
};
/*********************************************************************
* This function is called by stevedores ->allocobj() method, which
* very often will be stv_default_allocobj() below, to convert a slab
* of storage into object which the stevedore can then register in its
* internal state, before returning it to STV_NewObject().
* As you probably guessed: All this for persistence.
*/
struct object *
STV_NewObject(const struct sess *sp, unsigned wsl, double ttl, unsigned nhttp)
STV_MkObject(struct sess *sp, void *ptr, unsigned ltot,
struct stv_objsecrets *soc)
{
struct object *o;
struct storage *st;
unsigned lhttp;
(void)ttl;
assert(wsl > 0);
wsl = PRNDUP(wsl);
lhttp = HTTP_estimate(nhttp);
lhttp = PRNDUP(lhttp);
if (!sp->wrk->cacheable) {
o = malloc(sizeof *o + wsl + lhttp);
XXXAN(o);
st = NULL;
} else {
st = stv_alloc(sp, sizeof *o + wsl + lhttp, sp->objcore);
XXXAN(st);
xxxassert(st->space >= (sizeof *o + wsl + lhttp));
unsigned l;
st->len = st->space;
CHECK_OBJ_NOTNULL(soc, STV_OBJ_SECRETES_MAGIC);
o = (void *)st->ptr; /* XXX: align ? */
wsl = PRNDDN(st->space - (sizeof *o + lhttp));
}
assert(PAOK(ptr));
assert(ltot >= sizeof *o + soc->lhttp + soc->wsl);
o = ptr;
memset(o, 0, sizeof *o);
o->magic = OBJECT_MAGIC;
assert(PAOK(wsl));
assert(PAOK(lhttp));
l = PRNDDN(ltot - (sizeof *o + soc->lhttp));
assert(l >= soc->wsl);
assert(PAOK(soc->wsl));
assert(PAOK(soc->lhttp));
o->http = HTTP_create(o + 1, nhttp);
WS_Init(o->ws_o, "obj", (char *)(o + 1) + lhttp, wsl);
o->http = HTTP_create(o + 1, soc->nhttp);
WS_Init(o->ws_o, "obj", (char *)(o + 1) + soc->lhttp, soc->wsl);
WS_Assert(o->ws_o);
http_Setup(o->http, o->ws_o);
......@@ -191,10 +197,78 @@ STV_NewObject(const struct sess *sp, unsigned wsl, double ttl, unsigned nhttp)
o->entered = NAN;
VTAILQ_INIT(&o->store);
sp->wrk->stats.n_object++;
if (sp->objhead != NULL) {
CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC);
CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC);
sp->objcore->priv = o; /* XXX */
o->objcore = sp->objcore;
sp->objcore->objhead = sp->objhead;
sp->objhead = NULL; /* refcnt follows pointer. */
sp->objcore = NULL; /* refcnt follows pointer. */
BAN_NewObj(o);
}
return (o);
}
/*********************************************************************
* This is the default ->allocobj() which all stevedores who do not
* implement persistent storage can rely on.
*/
static struct object *
stv_default_allocobj(struct stevedore *stv, struct sess *sp, unsigned ltot,
struct stv_objsecrets *soc)
{
struct object *o;
struct storage *st;
(void)stv; /* XXX */
CHECK_OBJ_NOTNULL(soc, STV_OBJ_SECRETES_MAGIC);
st = stv_alloc(sp, ltot, sp->objcore);
XXXAN(st);
xxxassert(st->space >= ltot);
ltot = st->len = st->space;
o = STV_MkObject(sp, st->ptr, ltot, soc);
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
o->objstore = st;
return (o);
}
/*********************************************************************/
struct object *
STV_NewObject(struct sess *sp, unsigned wsl, double ttl, unsigned nhttp)
{
struct object *o;
struct stevedore *stv;
unsigned lhttp, ltot;
struct stv_objsecrets soc;
assert(wsl > 0);
wsl = PRNDUP(wsl);
lhttp = HTTP_estimate(nhttp);
lhttp = PRNDUP(lhttp);
soc.magic = STV_OBJ_SECRETES_MAGIC;
soc.nhttp = nhttp;
soc.lhttp = lhttp;
soc.wsl = wsl;
soc.ttl = ttl;
ltot = sizeof *o + wsl + lhttp;
if (!sp->wrk->cacheable)
stv = stv_transient;
else
stv = stv_pick_stevedore();
AN(stv->allocobj);
o = stv->allocobj(stv, sp, ltot, &soc);
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
return (o);
}
/*---------------------------------------------------------------------
* Default objcore methods
*/
......@@ -361,6 +435,8 @@ STV_Config(const char *spec)
*stv = *stv2;
AN(stv->name);
AN(stv->alloc);
if (stv->allocobj == NULL)
stv->allocobj = stv_default_allocobj;
if (p == NULL)
bprintf(stv->ident, "s%u", seq++);
......
......@@ -34,6 +34,7 @@ struct sess;
struct iovec;
struct object;
struct objcore;
struct stv_objsecrets;
typedef void storage_init_f(struct stevedore *, int ac, char * const *av);
typedef void storage_open_f(const struct stevedore *);
......@@ -42,6 +43,8 @@ typedef struct storage *storage_alloc_f(struct stevedore *, size_t size,
typedef void storage_trim_f(struct storage *, size_t size);
typedef void storage_free_f(struct storage *);
typedef void storage_object_f(const struct sess *sp);
typedef struct object *storage_allocobj_f(struct stevedore *, struct sess *sp,
unsigned ltot, struct stv_objsecrets *);
typedef void storage_close_f(const struct stevedore *);
......@@ -57,6 +60,7 @@ struct stevedore {
storage_free_f *free; /* --//-- */
storage_object_f *object; /* --//-- */
storage_close_f *close; /* --//-- */
storage_allocobj_f *allocobj; /* --//-- */
struct lru *lru;
......@@ -67,7 +71,10 @@ struct stevedore {
char ident[16]; /* XXX: match vsm_chunk.ident */
};
struct object *STV_NewObject(const struct sess *sp, unsigned len, double ttl,
struct object *STV_MkObject(struct sess *sp, void *ptr, unsigned ltot,
struct stv_objsecrets *soc);
struct object *STV_NewObject(struct sess *sp, unsigned len, double ttl,
unsigned nhttp);
struct storage *STV_alloc(const struct sess *sp, size_t size);
void STV_trim(struct storage *st, size_t size);
......
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