From 06efba877c0bfbf0cf067b2f7b78ca5303cc72ea Mon Sep 17 00:00:00 2001 From: phk Date: Sat, 28 Feb 2009 21:56:49 +0000 Subject: [PATCH] Postpone allocating the actual object until we have received the headers and vcl_fetch{} has told os what to do with it. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3845 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 1 + varnish-cache/bin/varnishd/cache_center.c | 54 +++++++++++++++-------- varnish-cache/bin/varnishd/cache_fetch.c | 9 ++-- varnish-cache/bin/varnishd/cache_hash.c | 34 ++++++++++++-- varnish-cache/bin/varnishd/hash_slinger.h | 1 + 5 files changed, 75 insertions(+), 24 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index bd1a155c..5f87f99a 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -396,6 +396,7 @@ struct sess { struct vbe_conn *vbe; struct bereq *bereq; struct object *obj; + struct objcore *objcore; struct objhead *objhead; struct VCL_conf *vcl; diff --git a/varnish-cache/bin/varnishd/cache_center.c b/varnish-cache/bin/varnishd/cache_center.c index 27ed5923..706bab62 100644 --- a/varnish-cache/bin/varnishd/cache_center.c +++ b/varnish-cache/bin/varnishd/cache_center.c @@ -378,6 +378,7 @@ cnt_fetch(struct sess *sp) { int i; struct http *hp, *hp2; + struct object *o; char *b; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); @@ -387,9 +388,6 @@ cnt_fetch(struct sess *sp) AN(sp->director); AZ(sp->vbe); - sp->obj->xid = sp->xid; - WS_Assert(sp->obj->ws_o); - i = FetchHdr(sp); /* @@ -402,7 +400,11 @@ cnt_fetch(struct sess *sp) sp->err_code = 503; sp->step = STP_ERROR; VBE_free_bereq(&sp->bereq); - HSH_Drop(sp); + if (sp->objhead) { + CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC); + CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC); + HSH_DerefObjCore(sp); + } AZ(sp->obj); return (0); } @@ -440,6 +442,21 @@ cnt_fetch(struct sess *sp) VCL_fetch_method(sp); + o = HSH_NewObject(sp, sp->handling != VCL_RET_DELIVER); + + if (sp->objhead != NULL) { + CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC); + CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC); + sp->objcore->obj = o; + o->objcore = sp->objcore; + o->objhead = sp->objhead; + sp->objhead = NULL; /* refcnt follows pointer. */ + } + sp->obj = o; + + BAN_NewObj(sp->obj); + + sp->obj->xid = sp->xid; sp->obj->response = sp->err_code; sp->obj->cacheable = sp->bereq->cacheable; sp->obj->ttl = sp->bereq->ttl; @@ -448,6 +465,7 @@ cnt_fetch(struct sess *sp) sp->obj->cacheable = 0; sp->obj->age = sp->bereq->age; sp->obj->entered = sp->bereq->entered; + WS_Assert(sp->obj->ws_o); /* Filter into object */ hp = sp->bereq->beresp; @@ -602,6 +620,9 @@ cnt_hit(struct sess *sp) /* Drop our object, we won't need it */ HSH_Deref(sp->wrk, &sp->obj); + sp->objcore = NULL; + AZ(sp->objhead); + sp->objhead = NULL; switch(sp->handling) { case VCL_RET_PASS: @@ -675,6 +696,7 @@ cnt_lookup(struct sess *sp) return (1); } + CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); /* If we inserted a new object it's a miss */ @@ -682,14 +704,8 @@ cnt_lookup(struct sess *sp) VSL_stats->cache_miss++; AZ(oc->obj); - o = HSH_NewObject(sp, 0); - - o->objhead = oh; - o->objcore = oc; - oc->obj = o; - sp->obj = o; - - BAN_NewObj(o); + sp->objhead = oh; + sp->objcore = oc; sp->step = STP_MISS; return (0); } @@ -702,6 +718,8 @@ cnt_lookup(struct sess *sp) VSL_stats->cache_hitpass++; WSP(sp, SLT_HitPass, "%u", sp->obj->xid); HSH_Deref(sp->wrk, &sp->obj); + sp->objcore = NULL; + sp->objhead = NULL; sp->step = STP_PASS; return (0); } @@ -740,27 +758,29 @@ cnt_miss(struct sess *sp) { CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); - CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC); + AZ(sp->obj); + AN(sp->objcore); + AN(sp->objhead); http_FilterHeader(sp, HTTPH_R_FETCH); VCL_miss_method(sp); - AZ(sp->obj->cacheable); switch(sp->handling) { case VCL_RET_ERROR: - HSH_Drop(sp); + HSH_DerefObjCore(sp); VBE_free_bereq(&sp->bereq); sp->step = STP_ERROR; return (0); case VCL_RET_PASS: - HSH_Drop(sp); VBE_free_bereq(&sp->bereq); + HSH_DerefObjCore(sp); sp->step = STP_PASS; return (0); case VCL_RET_FETCH: sp->step = STP_FETCH; return (0); case VCL_RET_RESTART: + HSH_DerefObjCore(sp); VBE_free_bereq(&sp->bereq); INCOMPL(); default: @@ -818,8 +838,6 @@ cnt_pass(struct sess *sp) } assert(sp->handling == VCL_RET_PASS); sp->acct_req.pass++; - HSH_Prealloc(sp); - sp->obj = HSH_NewObject(sp, 1); sp->sendbody = 1; sp->step = STP_FETCH; return (0); diff --git a/varnish-cache/bin/varnishd/cache_fetch.c b/varnish-cache/bin/varnishd/cache_fetch.c index 29900651..4030bbc5 100644 --- a/varnish-cache/bin/varnishd/cache_fetch.c +++ b/varnish-cache/bin/varnishd/cache_fetch.c @@ -319,11 +319,14 @@ FetchHdr(struct sess *sp) CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); - CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(sp->bereq, BEREQ_MAGIC); AN(sp->director); - if (sp->obj->objcore != NULL) /* pass has no objcore */ - AN(ObjIsBusy(sp->obj)); + AZ(sp->obj); + if (sp->objcore != NULL) { /* pass has no objcore */ + CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC); + AN(sp->objhead); /* details in hash_slinger.h */ + AN(sp->objcore->flags & OC_F_BUSY); + } AN(sp->bereq); /* Transmit request */ diff --git a/varnish-cache/bin/varnishd/cache_hash.c b/varnish-cache/bin/varnishd/cache_hash.c index f891eb64..73b252eb 100644 --- a/varnish-cache/bin/varnishd/cache_hash.c +++ b/varnish-cache/bin/varnishd/cache_hash.c @@ -308,6 +308,8 @@ HSH_Lookup(struct sess *sp, struct objhead **poh) busy_oc = NULL; grace_oc = NULL; VTAILQ_FOREACH(oc, &oh->objcs, list) { + /* Must be at least our own ref + the objcore we examine */ + assert(oh->refcnt > 1); CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); if (oc->flags & OC_F_BUSY) { @@ -359,6 +361,7 @@ HSH_Lookup(struct sess *sp, struct objhead **poh) o->refcnt++; if (o->hits < INT_MAX) o->hits++; + assert(oh->refcnt > 1); Lck_Unlock(&oh->mtx); assert(hash->deref(oh)); *poh = oh; @@ -454,10 +457,10 @@ HSH_Unbusy(const struct sess *sp) Lck_Lock(&oh->mtx); } o->objcore->flags &= ~OC_F_BUSY; - if (oh != NULL) + if (oh != NULL) { hsh_rush(oh); - if (oh != NULL) Lck_Unlock(&oh->mtx); + } } void @@ -474,6 +477,29 @@ HSH_Ref(struct object *o) Lck_Unlock(&oh->mtx); } +void +HSH_DerefObjCore(struct sess *sp) +{ + struct objhead *oh; + struct objcore *oc; + + CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC); + CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC); + + oh = sp->objhead; + sp->objhead = NULL; + oc = sp->objcore; + sp->objcore = NULL; + + Lck_Lock(&oh->mtx); + VTAILQ_REMOVE(&oh->objcs, oc, list); + Lck_Unlock(&oh->mtx); + assert(oh->refcnt > 0); + if (hash->deref(oh)) + return; + HSH_DeleteObjHead(sp->wrk, oh); +} + void HSH_Deref(const struct worker *w, struct object **oo) { @@ -492,7 +518,7 @@ HSH_Deref(const struct worker *w, struct object **oo) assert(o->refcnt > 0); r = --o->refcnt; } else { - CHECK_OBJ(oh, OBJHEAD_MAGIC); + CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); oc = o->objcore; CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); @@ -525,6 +551,7 @@ HSH_Deref(const struct worker *w, struct object **oo) STV_free(o->objstore); else FREE_OBJ(o); + o = NULL; w->stats->n_object--; if (oh == NULL) { @@ -540,6 +567,7 @@ HSH_Deref(const struct worker *w, struct object **oo) HSH_DeleteObjHead(w, oh); } + void HSH_Init(void) { diff --git a/varnish-cache/bin/varnishd/hash_slinger.h b/varnish-cache/bin/varnishd/hash_slinger.h index 9b834f19..c778d267 100644 --- a/varnish-cache/bin/varnishd/hash_slinger.h +++ b/varnish-cache/bin/varnishd/hash_slinger.h @@ -63,6 +63,7 @@ double HSH_Grace(double g); void HSH_Init(void); void HSH_AddString(struct sess *sp, const char *str); void HSH_Prepare(struct sess *sp, unsigned hashcount); +void HSH_DerefObjCore(struct sess *sp); #ifdef VARNISH_CACHE_CHILD -- 2.39.5