From f2140cba364596bbff64ec4f88ebedba69b76559 Mon Sep 17 00:00:00 2001 From: phk Date: Mon, 26 Jun 2006 14:33:49 +0000 Subject: [PATCH] Start releasing objects when they expire git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@235 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 4 +- varnish-cache/bin/varnishd/cache_expire.c | 1 + varnish-cache/bin/varnishd/cache_fetch.c | 7 +-- varnish-cache/bin/varnishd/cache_hash.c | 57 +++++++++++++++---- varnish-cache/bin/varnishd/cache_pool.c | 2 + varnish-cache/bin/varnishd/hash_simple_list.c | 8 ++- 6 files changed, 60 insertions(+), 19 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index 8f1cac6a..e4f353d5 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -30,7 +30,7 @@ struct worker; typedef void hash_init_f(void); typedef struct objhead *hash_lookup_f(const char *key, struct objhead *nobj); -typedef void hash_deref_f(struct objhead *obj); +typedef int hash_deref_f(struct objhead *obj); struct hash_slinger { const char *name; @@ -155,7 +155,7 @@ int FetchSession(struct worker *w, struct sess *sp); /* cache_hash.c */ struct object *HSH_Lookup(struct worker *w, struct http *h); void HSH_Unbusy(struct object *o); -void HSH_Unref(struct object *o); +void HSH_Deref(struct object *o); void HSH_Init(void); /* cache_http.c */ diff --git a/varnish-cache/bin/varnishd/cache_expire.c b/varnish-cache/bin/varnishd/cache_expire.c index 733bd611..8da8d449 100644 --- a/varnish-cache/bin/varnishd/cache_expire.c +++ b/varnish-cache/bin/varnishd/cache_expire.c @@ -52,6 +52,7 @@ exp_main(void *arg) printf("Root: %p %d (%d)\n", (void*)o, o->ttl, o->ttl - t); binheap_delete(exp_heap, 0); AZ(pthread_mutex_unlock(&expmtx)); + HSH_Deref(o); } return ("FOOBAR"); diff --git a/varnish-cache/bin/varnishd/cache_fetch.c b/varnish-cache/bin/varnishd/cache_fetch.c index 9b22615b..e100d25a 100644 --- a/varnish-cache/bin/varnishd/cache_fetch.c +++ b/varnish-cache/bin/varnishd/cache_fetch.c @@ -271,10 +271,9 @@ FetchSession(struct worker *w, struct sess *sp) else VBE_RecycleFd(fd_token); - /* XXX: unbusy, and kick other sessions into action */ - sp->obj->busy = 0; - - /* XXX: if not cachable, destroy */ + HSH_Unbusy(sp->obj); + if (!sp->obj->cacheable) + HSH_Deref(sp->obj); return (1); } diff --git a/varnish-cache/bin/varnishd/cache_hash.c b/varnish-cache/bin/varnishd/cache_hash.c index 0949c886..389d7eef 100644 --- a/varnish-cache/bin/varnishd/cache_hash.c +++ b/varnish-cache/bin/varnishd/cache_hash.c @@ -16,7 +16,6 @@ static struct hash_slinger *hash; - struct object * HSH_Lookup(struct worker *w, struct http *h) { @@ -25,18 +24,19 @@ HSH_Lookup(struct worker *w, struct http *h) char *b; assert(hash != NULL); - /* Make sure we have both a new objhead and object if we need them */ + /* Precreate an objhead and object in case we need them */ if (w->nobjhead == NULL) { w->nobjhead = calloc(sizeof *w->nobjhead, 1); assert(w->nobjhead != NULL); TAILQ_INIT(&w->nobjhead->objects); + AZ(pthread_mutex_init(&oh->mtx, NULL)); } if (w->nobj == NULL) { w->nobj = calloc(sizeof *w->nobj, 1); assert(w->nobj != NULL); w->nobj->busy = 1; TAILQ_INIT(&w->nobj->store); - pthread_cond_init(&w->nobj->cv, NULL); + AZ(pthread_cond_init(&w->nobj->cv, NULL)); } assert(http_GetURL(h, &b)); @@ -53,11 +53,19 @@ HSH_Lookup(struct worker *w, struct http *h) break; o->refcnt--; } - if (o == NULL) { - o = w->nobj; - w->nobj = NULL; - TAILQ_INSERT_TAIL(&oh->objects, o, list); + if (o != NULL) { + AZ(pthread_mutex_unlock(&oh->mtx)); + hash->deref(oh); + return (o); } + + /* Insert (precreated) object in objecthead */ + o = w->nobj; + w->nobj = NULL; + o->refcnt = 1; + o->objhead = oh; + TAILQ_INSERT_TAIL(&oh->objects, o, list); + /* NB: do not deref objhead the new object inherits our reference */ AZ(pthread_mutex_unlock(&oh->mtx)); return (o); } @@ -73,12 +81,39 @@ HSH_Unbusy(struct object *o) } void -HSH_Unref(struct object *o) +HSH_Deref(struct object *o) { + struct objhead *oh; + struct storage *st, *stn; - AZ(pthread_mutex_lock(&o->objhead->mtx)); - o->refcnt--; - AZ(pthread_mutex_unlock(&o->objhead->mtx)); + oh = o->objhead; + + /* drop ref on object */ + AZ(pthread_mutex_lock(&oh->mtx)); + if (--o->refcnt == 0) + TAILQ_REMOVE(&oh->objects, o, list); + else + o = NULL; + AZ(pthread_mutex_unlock(&oh->mtx)); + + /* If still referenced, done */ + if (o == NULL) + return; + + AZ(pthread_cond_destroy(&o->cv)); + + TAILQ_FOREACH_SAFE(st, &o->store, list, stn) { + TAILQ_REMOVE(&o->store, st, list); + st->stevedore->free(st); + } + free(o); + + /* Drop our ref on the objhead */ + if (hash->deref(oh)) + return; + assert(TAILQ_EMPTY(&oh->objects)); + AZ(pthread_mutex_destroy(&oh->mtx)); + free(oh); } void diff --git a/varnish-cache/bin/varnishd/cache_pool.c b/varnish-cache/bin/varnishd/cache_pool.c index ed9fad7b..34834b5e 100644 --- a/varnish-cache/bin/varnishd/cache_pool.c +++ b/varnish-cache/bin/varnishd/cache_pool.c @@ -49,6 +49,8 @@ DeliverSession(struct worker *w, struct sess *sp) "\r\n", sp->obj->header, sp->obj->len); vca_write_obj(sp, w->sb); + HSH_Deref(sp->obj); + sp->obj = NULL; return (1); } diff --git a/varnish-cache/bin/varnishd/hash_simple_list.c b/varnish-cache/bin/varnishd/hash_simple_list.c index 69c8a88f..d9fe9b78 100644 --- a/varnish-cache/bin/varnishd/hash_simple_list.c +++ b/varnish-cache/bin/varnishd/hash_simple_list.c @@ -88,10 +88,11 @@ hsl_lookup(const char *key, struct objhead *nobj) * Dereference and if no references are left, free. */ -static void +static int hsl_deref(struct objhead *obj) { struct hsl_entry *he; + int ret; assert(obj->hashpriv != NULL); he = obj->hashpriv; @@ -100,8 +101,11 @@ hsl_deref(struct objhead *obj) free(he->key); TAILQ_REMOVE(&hsl_head, he, list); free(he); - } + ret = 0; + } else + ret = 1; AZ(pthread_mutex_unlock(&hsl_mutex)); + return (ret); } /*--------------------------------------------------------------------*/ -- 2.39.5