Commit f289def3 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Make all objects have an objcore, even for the vcl_recv->pass case.

This simplifies some nasty corner cases.
parent 390fa49f
......@@ -447,6 +447,7 @@ BAN_NewObjCore(struct objcore *oc)
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
AZ(oc->ban);
AN(oc->objhead);
Lck_Lock(&ban_mtx);
oc->ban = ban_start;
ban_start->refcount++;
......
......@@ -152,7 +152,7 @@ VBO_DerefBusyObj(struct worker *wrk, struct busyobj **pbo)
*pbo = NULL;
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
CHECK_OBJ_ORNULL(bo->fetch_obj, OBJECT_MAGIC);
if (bo->fetch_obj != NULL && bo->fetch_obj->objcore != NULL) {
if (bo->fetch_obj != NULL && bo->fetch_obj->objcore->objhead != NULL) {
oc = bo->fetch_obj->objcore;
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC);
......
......@@ -256,7 +256,7 @@ cnt_prepresp(struct sess *sp, struct worker *wrk, struct req *req)
}
req->t_resp = W_TIM_real(wrk);
if (req->obj->objcore != NULL) {
if (req->obj->objcore->objhead != NULL) {
if ((req->t_resp - req->obj->last_lru) >
cache_param->lru_timeout &&
EXP_Touch(req->obj->objcore))
......@@ -340,11 +340,8 @@ cnt_deliver(struct sess *sp, struct worker *wrk, struct req *req)
RES_WriteObj(sp);
/* No point in saving the body if it is hit-for-pass */
if (req->obj->objcore != NULL) {
CHECK_OBJ_NOTNULL(req->obj->objcore, OBJCORE_MAGIC);
if (req->obj->objcore->flags & OC_F_PASS)
STV_Freestore(req->obj);
}
if (req->obj->objcore->flags & OC_F_PASS)
STV_Freestore(req->obj);
assert(WRW_IsReleased(wrk));
(void)HSH_Deref(&wrk->stats, NULL, &req->obj);
......@@ -492,6 +489,7 @@ cnt_error(struct sess *sp, struct worker *wrk, struct req *req)
bo->vsl->wid = sp->vsl_id;
AZ(bo->stats);
bo->stats = &wrk->stats;
req->objcore = HSH_NewObjCore(wrk);
req->obj = STV_NewObject(bo, &req->objcore,
TRANSIENT_STORAGE, cache_param->http_resp_size,
(uint16_t)cache_param->http_max_hdr);
......@@ -586,7 +584,7 @@ cnt_fetch(struct sess *sp, struct worker *wrk, struct req *req)
wrk->acct_tmp.fetch++;
i = FetchHdr(sp, need_host_hdr, req->objcore == NULL);
i = FetchHdr(sp, need_host_hdr, req->objcore->objhead == NULL);
/*
* If we recycle a backend connection, there is a finite chance
* that the backend closed it before we get a request to it.
......@@ -594,7 +592,7 @@ cnt_fetch(struct sess *sp, struct worker *wrk, struct req *req)
*/
if (i == 1) {
VSC_C_main->backend_retry++;
i = FetchHdr(sp, need_host_hdr, req->objcore == NULL);
i = FetchHdr(sp, need_host_hdr, req->objcore->objhead == NULL);
}
if (i) {
......@@ -626,7 +624,7 @@ cnt_fetch(struct sess *sp, struct worker *wrk, struct req *req)
RFC2616_Ttl(bo, sp->req->xid);
/* pass from vclrecv{} has negative TTL */
if (req->objcore == NULL)
if (req->objcore->objhead == NULL)
bo->exp.ttl = -1.;
AZ(bo->do_esi);
......@@ -634,7 +632,7 @@ cnt_fetch(struct sess *sp, struct worker *wrk, struct req *req)
VCL_fetch_method(sp);
if (req->objcore != NULL && bo->do_pass)
if (bo->do_pass)
req->objcore->flags |= OC_F_PASS;
switch (req->handling) {
......@@ -652,7 +650,7 @@ cnt_fetch(struct sess *sp, struct worker *wrk, struct req *req)
/* Clean up partial fetch */
AZ(bo->vbc);
if (req->objcore != NULL) {
if (req->objcore->objhead != NULL || req->handling == VCL_RET_ERROR) {
CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
AZ(HSH_Deref(&wrk->stats, req->objcore, NULL));
req->objcore = NULL;
......@@ -707,7 +705,7 @@ cnt_fetchbody(struct sess *sp, struct worker *wrk, struct req *req)
assert(req->handling == VCL_RET_DELIVER);
if (req->objcore == NULL) {
if (req->objcore->objhead == NULL) {
/* This is a pass from vcl_recv */
pass = 1;
/* VCL may have fiddled this, but that doesn't help */
......@@ -785,7 +783,7 @@ cnt_fetchbody(struct sess *sp, struct worker *wrk, struct req *req)
pass ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp);
/* Create Vary instructions */
if (req->objcore != NULL) {
if (req->objcore->objhead != NULL) {
CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
vary = VRY_Create(req, bo->beresp);
if (vary != NULL) {
......@@ -884,7 +882,7 @@ cnt_fetchbody(struct sess *sp, struct worker *wrk, struct req *req)
assert(bo->refcount == 2); /* one for each thread */
if (req->obj->objcore != NULL) {
if (req->obj->objcore->objhead != NULL) {
EXP_Insert(req->obj);
AN(req->obj->objcore->ban);
AZ(req->obj->ws_o->overflow);
......@@ -895,7 +893,7 @@ cnt_fetchbody(struct sess *sp, struct worker *wrk, struct req *req)
Pool_Task(wrk->pool, &bo->fetch_task, POOL_NO_QUEUE))
FetchBody(wrk, bo);
if (req->obj->objcore != NULL)
if (req->obj->objcore->objhead != NULL)
HSH_Ref(req->obj->objcore);
if (bo->state == BOS_FINISHED) {
......@@ -1249,6 +1247,9 @@ cnt_pass(struct sess *sp, struct worker *wrk, struct req *req)
assert(req->handling == VCL_RET_PASS);
wrk->acct_tmp.pass++;
sp->step = STP_FETCH;
req->objcore = HSH_NewObjCore(wrk);
req->objcore->busyobj = bo;
return (0);
}
......
......@@ -453,10 +453,8 @@ FetchHdr(struct sess *sp, int need_host_hdr, int sendbody)
AN(req->director);
AZ(req->obj);
if (req->objcore != NULL) { /* pass has no objcore */
CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
AN(req->objcore->flags & OC_F_BUSY);
}
CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
AN(req->objcore->flags & OC_F_BUSY);
hp = bo->bereq;
......@@ -687,7 +685,7 @@ FetchBody(struct worker *wrk, void *priv)
/* XXX: Atomic assignment, needs volatile/membar ? */
bo->state = BOS_FINISHED;
}
if (obj->objcore != NULL)
if (obj->objcore->objhead != NULL)
HSH_Complete(obj->objcore);
bo->stats = NULL;
VBO_DerefBusyObj(wrk, &bo);
......
......@@ -65,24 +65,32 @@
static const struct hash_slinger *hash;
/*---------------------------------------------------------------------*/
struct objcore *
HSH_NewObjCore(struct worker *wrk)
{
struct objcore *oc;
ALLOC_OBJ(oc, OBJCORE_MAGIC);
XXXAN(oc);
wrk->stats.n_objectcore++;
oc->flags |= OC_F_BUSY;
return (oc);
}
/*---------------------------------------------------------------------*/
/* Precreate an objhead and object for later use */
static void
hsh_prealloc(struct worker *wrk)
{
struct objhead *oh;
struct objcore *oc;
struct waitinglist *wl;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
if (wrk->nobjcore == NULL) {
ALLOC_OBJ(oc, OBJCORE_MAGIC);
XXXAN(oc);
wrk->nobjcore = oc;
wrk->stats.n_objectcore++;
oc->flags |= OC_F_BUSY;
}
if (wrk->nobjcore == NULL)
wrk->nobjcore = HSH_NewObjCore(wrk);
CHECK_OBJ_NOTNULL(wrk->nobjcore, OBJCORE_MAGIC);
if (wrk->nobjhead == NULL) {
......@@ -663,40 +671,31 @@ HSH_Deref(struct dstat *ds, struct objcore *oc, struct object **oo)
oc = o->objcore;
}
if (o != NULL && oc == NULL) {
/*
* A pass object with neither objcore nor objhdr reference.
* -> simply free the (Transient) storage
*/
STV_Freestore(o);
STV_free(o->objstore);
ds->n_object--;
return (0);
}
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
oh = oc->objhead;
CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
if (oh != NULL) {
CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
Lck_Lock(&oh->mtx);
assert(oh->refcnt > 0);
assert(oc->refcnt > 0);
r = --oc->refcnt;
if (!r)
VTAILQ_REMOVE(&oh->objcs, oc, list);
else {
/* Must have an object */
AN(oc->methods);
}
if (oh->waitinglist != NULL)
hsh_rush(ds, oh);
Lck_Unlock(&oh->mtx);
if (r != 0)
return (r);
Lck_Lock(&oh->mtx);
assert(oh->refcnt > 0);
assert(oc->refcnt > 0);
r = --oc->refcnt;
if (!r)
VTAILQ_REMOVE(&oh->objcs, oc, list);
else {
/* Must have an object */
AN(oc->methods);
}
if (oh->waitinglist != NULL)
hsh_rush(ds, oh);
Lck_Unlock(&oh->mtx);
if (r != 0)
return (r);
BAN_DestroyObj(oc);
AZ(oc->ban);
BAN_DestroyObj(oc);
AZ(oc->ban);
}
if (oc->methods != NULL) {
oc_freeobj(oc);
......@@ -705,11 +704,13 @@ HSH_Deref(struct dstat *ds, struct objcore *oc, struct object **oo)
FREE_OBJ(oc);
ds->n_objectcore--;
/* Drop our ref on the objhead */
assert(oh->refcnt > 0);
if (hash->deref(oh))
return (0);
HSH_DeleteObjHead(ds, oh);
if (oh != NULL) {
/* Drop our ref on the objhead */
assert(oh->refcnt > 0);
if (hash->deref(oh))
return (0);
HSH_DeleteObjHead(ds, oh);
}
return (0);
}
......
......@@ -141,7 +141,7 @@ VRT_l_beresp_saintmode(const struct sess *sp, double a)
if (!vbc->backend)
return;
CHECK_OBJ_NOTNULL(vbc->backend, BACKEND_MAGIC);
if (!sp->req->objcore)
if (!sp->req->objcore->objhead)
return;
CHECK_OBJ_NOTNULL(sp->req->objcore, OBJCORE_MAGIC);
......
......@@ -60,6 +60,7 @@ void HSH_AddString(const struct sess *sp, const char *str);
void HSH_Insert(struct worker *, const void *hash, struct objcore *);
void HSH_Purge(const struct sess *, struct objhead *, double ttl, double grace);
void HSH_config(const char *h_arg);
struct objcore *HSH_NewObjCore(struct worker *wrk);
#ifdef VARNISH_CACHE_CHILD
......
......@@ -237,6 +237,7 @@ STV_MkObject(struct stevedore *stv, struct busyobj *bo, struct objcore **ocp,
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
CHECK_OBJ_NOTNULL(soc, STV_OBJ_SECRETES_MAGIC);
AN(ocp);
CHECK_OBJ_NOTNULL((*ocp), OBJCORE_MAGIC);
assert(PAOK(ptr));
assert(PAOK(soc->wsl));
......@@ -262,17 +263,14 @@ STV_MkObject(struct stevedore *stv, struct busyobj *bo, struct objcore **ocp,
VTAILQ_INIT(&o->store);
bo->stats->n_object++;
if (*ocp != NULL) {
CHECK_OBJ_NOTNULL((*ocp), OBJCORE_MAGIC);
o->objcore = *ocp;
*ocp = NULL; /* refcnt follows pointer. */
o->objcore = *ocp;
*ocp = NULL; /* refcnt follows pointer. */
if (o->objcore->objhead != NULL)
BAN_NewObjCore(o->objcore);
o->objcore->methods = &default_oc_methods;
o->objcore->priv = o;
o->objcore->priv2 = (uintptr_t)stv;
}
o->objcore->methods = &default_oc_methods;
o->objcore->priv = o;
o->objcore->priv2 = (uintptr_t)stv;
return (o);
}
......@@ -356,8 +354,11 @@ STV_NewObject(struct busyobj *bo, struct objcore **ocp, const char *hint,
}
}
if (o == NULL)
if (o == NULL) {
AN(*ocp);
return (NULL);
}
AZ(*ocp);
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
CHECK_OBJ_NOTNULL(o->objstore, STORAGE_MAGIC);
return (o);
......
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