]> err.no Git - varnish/commitdiff
Postpone allocating the actual object until we have received the
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Sat, 28 Feb 2009 21:56:49 +0000 (21:56 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Sat, 28 Feb 2009 21:56:49 +0000 (21:56 +0000)
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
varnish-cache/bin/varnishd/cache_center.c
varnish-cache/bin/varnishd/cache_fetch.c
varnish-cache/bin/varnishd/cache_hash.c
varnish-cache/bin/varnishd/hash_slinger.h

index bd1a155c2263690133148680c34a5e2a8c6960db..5f87f99ad185cbf2ff1f3af0f9b928a03636a3fe 100644 (file)
@@ -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;
 
index 27ed592369265fb6a329fc7c7c89b5fc94d08536..706bab62feb294db3417d8941734c66de2bae969 100644 (file)
@@ -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);
index 2990065133c52e26c6b4604940de98170a7b6bcc..4030bbc506a8fa8392d939005ab748e3d015ebb4 100644 (file)
@@ -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 */
index f891eb641553300ce023002d6bb9457c41747db2..73b252ebf87541cc5ba5b2bcb1008600e0a80f21 100644 (file)
@@ -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)
 {
index 9b834f198c58363acf67a28699846fe83dd34e87..c778d267f364c6e560d8ea8ba7299833b876d5a9 100644 (file)
@@ -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