Commit 8f25fe89 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

We are still not fully adapted to the fact that objcore is the

main handle and the object something which only the objcore knows
how to procure.

Replace the crude callbacks into the persistent module with a set
of methods on the objcore, which does whatever magic is necessary.

->getobj() returns a the object associated with this objcore, and
performs any cleanup necessary.

->updatemeta() signals that ban/ttl info on an objcore has changed.

->freeobj() releases any resources associated with the object.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@5543 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 68e122ad
......@@ -98,9 +98,6 @@ struct ban;
struct SHA256Context;
struct vsc_lck;
struct smp_object;
struct smp_seg;
struct lock { void *priv; }; // Opaque
#define DIGEST_LEN 32
......@@ -306,27 +303,62 @@ struct storage {
* housekeeping fields parts of an object.
*/
typedef struct object *getobj_f(struct worker *wrk, struct objcore *oc);
typedef void updatemeta_f(struct objcore *oc);
typedef void freeobj_f(struct objcore *oc);
struct objcore_methods {
getobj_f *getobj;
updatemeta_f *updatemeta;
freeobj_f *freeobj;
};
extern struct objcore_methods default_oc_methods;
struct objcore {
unsigned magic;
#define OBJCORE_MAGIC 0x4d301302
unsigned refcnt;
struct object *obj;
struct objcore_methods *methods;
void *priv;
void *priv2;
struct objhead *objhead;
double timer_when;
unsigned flags;
#define OC_F_ONLRU (1<<0)
#define OC_F_BUSY (1<<1)
#define OC_F_PASS (1<<2)
#define OC_F_PERSISTENT (1<<3)
#define OC_F_LRUDONTMOVE (1<<4)
#define OC_F_PRIV (1<<5) /* Stevedore private flag */
unsigned timer_idx;
VTAILQ_ENTRY(objcore) list;
VLIST_ENTRY(objcore) lru_list;
VTAILQ_ENTRY(objcore) ban_list;
struct smp_seg *smp_seg;
struct ban *ban;
};
static inline struct object *
oc_getobj(struct worker *wrk, struct objcore *oc)
{
return (oc->methods->getobj(wrk, oc));
}
static inline void
oc_updatemeta(struct objcore *oc)
{
if (oc->methods->updatemeta != NULL)
oc->methods->updatemeta(oc);
}
static inline void
oc_freeobj(struct objcore *oc)
{
oc->methods->freeobj(oc);
}
/*--------------------------------------------------------------------*/
struct lru {
......@@ -748,10 +780,6 @@ struct vsb *SMS_Makesynth(struct object *obj);
void SMS_Finish(struct object *obj);
/* storage_persistent.c */
void SMP_Fixup(struct sess *sp, const struct objhead *oh, struct objcore *oc);
void SMP_BANchanged(const struct object *o, double t);
void SMP_TTLchanged(const struct object *o);
void SMP_FreeObj(const struct object *o);
void SMP_Ready(void);
void SMP_NewBan(double t0, const char *ban);
......
......@@ -462,15 +462,13 @@ ban_check_object(struct object *o, const struct sess *sp, int has_req)
if (b == o->ban) { /* not banned */
o->ban = b0;
o->ban_t = o->ban->t0;
if (o->objcore->smp_seg != NULL)
SMP_BANchanged(o, b0->t0);
oc_updatemeta(o->objcore);
return (0);
} else {
o->ttl = 0;
o->cacheable = 0;
o->ban = NULL;
if (o->objcore->smp_seg != NULL)
SMP_TTLchanged(o);
oc_updatemeta(o->objcore);
/* BAN also changed, but that is not important any more */
WSP(sp, SLT_ExpBan, "%u was banned", o->xid);
EXP_Rearm(o);
......@@ -532,8 +530,8 @@ ban_lurker(struct sess *sp, void *priv)
TIM_sleep(1.0);
continue;
}
AZ(oc->flags & OC_F_PERSISTENT);
o = oc->obj;
// AZ(oc->flags & OC_F_PERSISTENT);
o = oc_getobj(sp->wrk, oc);
i = ban_check_object(o, sp, 0);
WSP(sp, SLT_Debug, "lurker: %p %g %d", oc, o->ttl, i);
HSH_Deref(sp->wrk, &o);
......
......@@ -575,7 +575,7 @@ cnt_fetch(struct sess *sp)
if (sp->objhead != NULL) {
CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC);
CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC);
sp->objcore->obj = sp->obj;
sp->objcore->priv = sp->obj; /* XXX */
sp->obj->objcore = sp->objcore;
sp->objcore->objhead = sp->objhead;
sp->objhead = NULL; /* refcnt follows pointer. */
......@@ -830,14 +830,14 @@ cnt_lookup(struct sess *sp)
if (oc->flags & OC_F_BUSY) {
sp->wrk->stats.cache_miss++;
AZ(oc->obj);
// AZ(oc->obj);
sp->objhead = oh;
sp->objcore = oc;
sp->step = STP_MISS;
return (0);
}
o = oc->obj;
o = oc_getobj(sp->wrk, oc);
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
sp->obj = o;
......
......@@ -145,8 +145,7 @@ EXP_Insert(struct object *o)
oc->flags |= OC_F_ONLRU;
}
Lck_Unlock(&exp_mtx);
if (o->objcore->smp_seg != NULL)
SMP_TTLchanged(o);
oc_updatemeta(oc);
}
/*--------------------------------------------------------------------
......@@ -237,8 +236,7 @@ EXP_Rearm(const struct object *o)
assert(oc->timer_idx != BINHEAP_NOIDX);
}
Lck_Unlock(&exp_mtx);
if (o->objcore->smp_seg != NULL)
SMP_TTLchanged(o);
oc_updatemeta(oc);
}
......@@ -289,9 +287,9 @@ exp_timer(struct sess *sp, void *priv)
VSC_main->n_expired++;
CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC);
if (!(oc->flags & OC_F_PERSISTENT)) {
o = oc->obj;
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
if (oc->methods == &default_oc_methods) {
o = oc_getobj(sp->wrk, oc);
AN(o);
WSL(sp->wrk, SLT_ExpKill, 0, "%u %d",
o->xid, (int)(o->ttl - t));
HSH_Deref(sp->wrk, &o);
......@@ -299,8 +297,7 @@ exp_timer(struct sess *sp, void *priv)
WSL(sp->wrk, SLT_ExpKill, 1, "-1 %d",
(int)(oc->timer_when - t));
/* XXX: Should we tell -spersistent ? */
oc->obj = NULL;
oc->priv = NULL;
HSH_DerefObjCore(sp->wrk, oc);
sp->wrk->stats.n_vampireobject--;
}
......@@ -355,8 +352,8 @@ EXP_NukeOne(const struct sess *sp, const struct lru *lru)
if (oc == NULL)
return (-1);
WSL(sp->wrk, SLT_ExpKill, 0, "%u LRU", oc->obj->xid);
o = oc->obj;
o = oc_getobj(sp->wrk, oc);
WSL(sp->wrk, SLT_ExpKill, 0, "%u LRU", o->xid);
HSH_Deref(sp->wrk, &o);
return (1);
}
......
......@@ -71,6 +71,43 @@ SVNID("$Id$")
static const struct hash_slinger *hash;
/*---------------------------------------------------------------------
* Default objcore methods
*/
static struct object *
default_oc_getobj(struct worker *wrk, struct objcore *oc)
{
struct object *o;
(void)wrk;
if (oc->priv == NULL)
return (NULL);
CAST_OBJ_NOTNULL(o, oc->priv, OBJECT_MAGIC);
return (o);
}
static void
default_oc_freeobj(struct objcore *oc)
{
struct object *o;
CAST_OBJ_NOTNULL(o, oc->priv, OBJECT_MAGIC);
oc->priv = NULL;
HSH_Freestore(o);
if (o->objstore != NULL)
STV_free(o->objstore);
else
FREE_OBJ(o);
}
struct objcore_methods default_oc_methods = {
.getobj = default_oc_getobj,
.freeobj = default_oc_freeobj,
};
/*---------------------------------------------------------------------*/
double
HSH_Grace(double g)
{
......@@ -111,6 +148,7 @@ HSH_Prealloc(const struct sess *sp)
ALLOC_OBJ(oc, OBJCORE_MAGIC);
XXXAN(oc);
w->nobjcore = oc;
oc->methods = &default_oc_methods;
w->stats.n_objectcore++;
oc->flags |= OC_F_BUSY;
}
......@@ -127,7 +165,6 @@ HSH_Prealloc(const struct sess *sp)
w->stats.n_objecthead++;
}
CHECK_OBJ_NOTNULL(w->nobjhead, OBJHEAD_MAGIC);
}
void
......@@ -361,16 +398,13 @@ HSH_Lookup(struct sess *sp, struct objhead **poh)
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
assert(oc->objhead == oh);
if (oc->flags & OC_F_PERSISTENT)
SMP_Fixup(sp, oh, oc);
if (oc->flags & OC_F_BUSY) {
if (!sp->hash_ignore_busy)
busy_oc = oc;
continue;
}
o = oc->obj;
o = oc_getobj(sp->wrk, oc);
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
if (!o->cacheable)
......@@ -405,14 +439,14 @@ HSH_Lookup(struct sess *sp, struct objhead **poh)
&& (busy_oc != NULL /* Somebody else is already busy */
|| !VDI_Healthy(sp->t_req, sp->director, (uintptr_t)oh))) {
/* Or it is impossible to fetch */
o = grace_oc->obj;
o = oc_getobj(sp->wrk, grace_oc);
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
if (o->ttl + HSH_Grace(sp->grace) >= sp->t_req)
oc = grace_oc;
}
if (oc != NULL && !sp->hash_always_miss) {
o = oc->obj;
o = oc_getobj(sp->wrk, oc);
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
assert(oc->objhead == oh);
......@@ -520,8 +554,7 @@ HSH_Purge(struct sess *sp, struct objhead *oh, double ttl, double grace)
continue;
}
if (oc->flags & OC_F_PERSISTENT)
SMP_Fixup(sp, oh, oc);
(void)oc_getobj(sp->wrk, oc); /* XXX: still needed ? */
xxxassert(spc >= sizeof *ocp);
oc->refcnt++;
......@@ -535,7 +568,7 @@ HSH_Purge(struct sess *sp, struct objhead *oh, double ttl, double grace)
for (n = 0; n < nobj; n++) {
oc = ocp[n];
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
o = oc->obj;
o = oc_getobj(sp->wrk, oc);
if (o == NULL)
continue;
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
......@@ -589,7 +622,7 @@ HSH_Unbusy(const struct sess *sp)
AN(ObjIsBusy(o));
AN(o->ban);
assert(o->objcore->obj == o);
assert(oc_getobj(sp->wrk, o->objcore) == o);
assert(o->objcore->refcnt > 0);
assert(oh->refcnt > 0);
if (o->ws_o->overflow)
......@@ -629,7 +662,7 @@ HSH_DerefObjCore(struct worker *wrk, struct objcore *oc)
oh = oc->objhead;
CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
AZ(oc->obj);
AZ(oc->priv);
Lck_Lock(&oh->mtx);
VTAILQ_REMOVE(&oh->objcs, oc, list);
......@@ -672,8 +705,8 @@ HSH_FindBan(struct sess *sp, struct objcore **oc)
VTAILQ_FOREACH(oc2, &oh->objcs, list)
if (oc1 == oc2)
break;
if (oc2 != NULL && oc2->flags & OC_F_PERSISTENT)
SMP_Fixup(sp, oh, oc2);
if (oc2 != NULL)
oc_getobj(sp->wrk, oc2);
if (oc2 != NULL)
oc2->refcnt++;
Lck_Unlock(&oh->mtx);
......@@ -723,15 +756,8 @@ HSH_Deref(struct worker *w, struct object **oo)
if (o->esidata != NULL)
ESI_Destroy(o);
if (o->objcore != NULL && o->objcore->smp_seg != NULL) {
SMP_FreeObj(o);
} else {
HSH_Freestore(o);
if (o->objstore != NULL)
STV_free(o->objstore);
else
FREE_OBJ(o);
}
if (o->objcore != NULL)
oc_freeobj(o->objcore);
o = NULL;
w->stats.n_object--;
......
......@@ -67,6 +67,8 @@ SVNID("$Id$")
#define RDN2(x, y) ((x)&(~((y)-1))) /* if y is powers of two */
#define RUP2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
#define OC_F_NEEDFIXUP OC_F_PRIV
/*
* Context for a signature.
*
......@@ -642,43 +644,106 @@ smp_save_segs(struct smp_sc *sc)
smp_save_seg(sc, &sc->seg2);
}
/*--------------------------------------------------------------------
* Fixup an object
/*---------------------------------------------------------------------
* objcore methods for zombie objects
*/
void
SMP_Fixup(struct sess *sp, const struct objhead *oh, struct objcore *oc)
static struct object *
smp_oc_getobj(struct worker *wrk, struct objcore *oc)
{
struct object *o;
struct smp_seg *sg;
struct smp_object *so;
Lck_AssertHeld(&oh->mtx);
(void)sp;
sg = oc->smp_seg;
CHECK_OBJ_NOTNULL(sg, SMP_SEG_MAGIC);
CAST_OBJ_NOTNULL(sg, oc->priv2, SMP_SEG_MAGIC);
/*
* XXX: failed checks here should fail gracefully and not assert
*/
so = (void*)oc->obj;
so = oc->priv;
xxxassert(so >= sg->objs && so <= sg->objs + sg->nalloc2);
oc->obj = so->ptr;
o = so->ptr;
CHECK_OBJ_NOTNULL(oc->obj, OBJECT_MAGIC);
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
AN(oc->flags & OC_F_PERSISTENT);
oc->flags &= ~OC_F_PERSISTENT;
if (wrk == NULL)
AZ(oc->flags & OC_F_NEEDFIXUP);
/* refcnt is one because the object is in the hash */
oc->obj->objcore = oc;
oc->obj->ban = oc->ban;
if (oc->flags & OC_F_NEEDFIXUP) {
AN(wrk);
Lck_Lock(&sg->sc->mtx);
if (oc->flags & OC_F_NEEDFIXUP) {
oc->flags &= ~OC_F_NEEDFIXUP;
sg->nfixed++;
sp->wrk->stats.n_object++;
sp->wrk->stats.n_vampireobject--;
/* refcnt is one because the object is in the hash */
o->objcore = oc;
o->ban = oc->ban;
sg->nfixed++;
wrk->stats.n_object++;
wrk->stats.n_vampireobject--;
}
Lck_Unlock(&sg->sc->mtx);
}
return (o);
}
static void
smp_oc_updatemeta(struct objcore *oc)
{
struct object *o;
struct smp_seg *sg;
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
o = smp_oc_getobj(NULL, oc);
AN(o);
CAST_OBJ_NOTNULL(sg, oc->priv2, SMP_SEG_MAGIC);
CHECK_OBJ_NOTNULL(sg->sc, SMP_SC_MAGIC);
if (sg == sg->sc->cur_seg) {
/* Lock necessary, we might race close_seg */
Lck_Lock(&sg->sc->mtx);
sg->objs[o->smp_index].ban = o->ban_t;
sg->objs[o->smp_index].ttl = o->ttl;
Lck_Unlock(&sg->sc->mtx);
} else {
sg->objs[o->smp_index].ban = o->ban_t;
sg->objs[o->smp_index].ttl = o->ttl;
}
}
static void
smp_oc_freeobj(struct objcore *oc)
{
struct smp_seg *sg;
struct object *o;
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
o = smp_oc_getobj(NULL, oc);
AN(o);
CAST_OBJ_NOTNULL(sg, oc->priv2, SMP_SEG_MAGIC);
Lck_Lock(&sg->sc->mtx);
sg->objs[o->smp_index].ttl = 0;
sg->objs[o->smp_index].ptr = 0;
assert(sg->nobj > 0);
assert(sg->nfixed > 0);
sg->nobj--;
sg->nfixed--;
Lck_Unlock(&sg->sc->mtx);
}
static struct objcore_methods smp_oc_methods = {
.getobj = smp_oc_getobj,
.updatemeta = smp_oc_updatemeta,
.freeobj = smp_oc_freeobj,
};
/*--------------------------------------------------------------------
* Add a new ban to all silos
*/
......@@ -779,71 +844,6 @@ smp_open_bans(struct smp_sc *sc, struct smp_signctx *ctx)
return (retval);
}
/*--------------------------------------------------------------------
* Update objects
*/
void
SMP_FreeObj(const struct object *o)
{
struct smp_seg *sg;
CHECK_OBJ_NOTNULL(o->objcore, OBJCORE_MAGIC);
AZ(o->objcore->flags & OC_F_PERSISTENT);
sg = o->objcore->smp_seg;
CHECK_OBJ_NOTNULL(sg, SMP_SEG_MAGIC);
Lck_Lock(&sg->sc->mtx);
sg->objs[o->smp_index].ttl = 0;
sg->objs[o->smp_index].ptr = 0;
assert(sg->nobj > 0);
assert(sg->nfixed > 0);
sg->nobj--;
sg->nfixed--;
Lck_Unlock(&sg->sc->mtx);
}
void
SMP_BANchanged(const struct object *o, double t)
{
struct smp_seg *sg;
CHECK_OBJ_NOTNULL(o->objcore, OBJCORE_MAGIC);
sg = o->objcore->smp_seg;
CHECK_OBJ_NOTNULL(sg, SMP_SEG_MAGIC);
CHECK_OBJ_NOTNULL(sg->sc, SMP_SC_MAGIC);
if (sg == sg->sc->cur_seg) {
/* Lock necessary, we might race close_seg */
Lck_Lock(&sg->sc->mtx);
sg->objs[o->smp_index].ban = t;
Lck_Unlock(&sg->sc->mtx);
} else {
sg->objs[o->smp_index].ban = t;
}
}
void
SMP_TTLchanged(const struct object *o)
{
struct smp_seg *sg;
CHECK_OBJ_NOTNULL(o->objcore, OBJCORE_MAGIC);
sg = o->objcore->smp_seg;
CHECK_OBJ_NOTNULL(sg, SMP_SEG_MAGIC);
CHECK_OBJ_NOTNULL(sg->sc, SMP_SC_MAGIC);
if (sg == sg->sc->cur_seg) {
/* Lock necessary, we might race close_seg */
Lck_Lock(&sg->sc->mtx);
sg->objs[o->smp_index].ttl = o->ttl;
Lck_Unlock(&sg->sc->mtx);
} else {
sg->objs[o->smp_index].ttl = o->ttl;
}
}
/*--------------------------------------------------------------------*/
......@@ -908,10 +908,11 @@ smp_load_seg(struct sess *sp, const struct smp_sc *sc, struct smp_seg *sg)
continue;
HSH_Prealloc(sp);
oc = sp->wrk->nobjcore;
oc->flags |= OC_F_PERSISTENT | OC_F_LRUDONTMOVE;
oc->flags |= OC_F_NEEDFIXUP | OC_F_LRUDONTMOVE;
oc->flags &= ~OC_F_BUSY;
oc->obj = (void*)so;
oc->smp_seg = sg;
oc->priv = so;
oc->priv2 = sg;
oc->methods = &smp_oc_methods;
oc->ban = BAN_RefBan(oc, so->ban, sc->tailban);
memcpy(sp->wrk->nobjhead->digest, so->hash, SHA256_LEN);
(void)HSH_Insert(sp);
......@@ -1300,13 +1301,13 @@ smp_object(const struct sess *sp)
CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
CHECK_OBJ_NOTNULL(sp->obj->objstore, STORAGE_MAGIC);
CHECK_OBJ_NOTNULL(sp->obj->objstore->stevedore, STEVEDORE_MAGIC);
CHECK_OBJ_NOTNULL(sp->obj->objcore->smp_seg, SMP_SEG_MAGIC);
CHECK_OBJ_NOTNULL(sp->obj->objcore, OBJCORE_MAGIC);
CAST_OBJ_NOTNULL(sg, sp->obj->objcore->priv2, SMP_SEG_MAGIC);
CAST_OBJ_NOTNULL(sc, sp->obj->objstore->priv, SMP_SC_MAGIC);
sp->obj->objcore->flags |= OC_F_LRUDONTMOVE;
Lck_Lock(&sc->mtx);
sg = sp->obj->objcore->smp_seg;
assert(sg->nalloc2 < sg->nalloc1);
sp->obj->smp_index = sg->nalloc2++;
......@@ -1407,7 +1408,7 @@ smp_alloc(struct stevedore *st, size_t size, struct objcore *oc)
sg->nalloc1++;
sc->objreserv += sizeof (struct smp_object);
assert(sc->objreserv <= smp_spaceleft(sg));
oc->smp_seg = sg;
oc->priv2 = sg;
}
sg->nalloc++;
......
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