From: phk Date: Wed, 19 Nov 2008 11:58:48 +0000 (+0000) Subject: Kick the hash_slinger interface around a bit: X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7fabaffb39f282ca09eeec74313fec25483bae38;p=varnish Kick the hash_slinger interface around a bit: Isolate more stuff in hash_slinger.h. Remove hash_slinger from cache.h, include in .c's as necessary. Save a malloc per objhead by putting a few fields into the objhead for the hash_slingers to use. Preinitialize the refcount when we precreate the objhead. Move the hash-string allocation into HSH_Copy(), no point in duplication of mandatory step. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3405 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index 601bdd11..03581566 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -29,6 +29,12 @@ * $Id$ */ +/* + * This macro can be used in .h files to isolate bits that the manager + * should not (need to) see, such as pthread mutexes etc. + */ +#define VARNISH_CACHE_CHILD 1 + #include #include #include @@ -213,8 +219,6 @@ struct workreq { void *priv; }; -#include "hash_slinger.h" - /* Backend Request ---------------------------------------------------*/ struct bereq { @@ -291,19 +295,6 @@ struct object { int hits; }; -struct objhead { - unsigned magic; -#define OBJHEAD_MAGIC 0x1b96615d - void *hashpriv; - - struct lock mtx; - unsigned refcnt; - VTAILQ_HEAD(,object) objects; - char *hash; - unsigned hashlen; - VTAILQ_HEAD(, sess) waitinglist; -}; - /* -------------------------------------------------------------------*/ struct sess { @@ -449,18 +440,6 @@ int Fetch(struct sess *sp); int FetchReqBody(struct sess *sp); void Fetch_Init(void); -/* cache_hash.c */ -void HSH_Prealloc(struct sess *sp); -void HSH_Freestore(struct object *o); -int HSH_Compare(const struct sess *sp, const struct objhead *o); -void HSH_Copy(const struct sess *sp, const struct objhead *o); -struct object *HSH_Lookup(struct sess *sp); -void HSH_Unbusy(const struct sess *sp); -void HSH_Ref(struct object *o); -void HSH_Deref(struct object *o); -double HSH_Grace(double g); -void HSH_Init(void); - /* cache_http.c */ const char *http_StatusMessage(unsigned); void HTTP_Init(void); diff --git a/varnish-cache/bin/varnishd/cache_center.c b/varnish-cache/bin/varnishd/cache_center.c index 9d451f4f..f40a78f2 100644 --- a/varnish-cache/bin/varnishd/cache_center.c +++ b/varnish-cache/bin/varnishd/cache_center.c @@ -75,6 +75,7 @@ DOT acceptor -> start [style=bold,color=green,weight=4] #include "vcl.h" #include "cli_priv.h" #include "cache.h" +#include "hash_slinger.h" static unsigned xids; diff --git a/varnish-cache/bin/varnishd/cache_cli.c b/varnish-cache/bin/varnishd/cache_cli.c index 5abdbe65..2a948165 100644 --- a/varnish-cache/bin/varnishd/cache_cli.c +++ b/varnish-cache/bin/varnishd/cache_cli.c @@ -52,6 +52,7 @@ #include "cache.h" #include "vlu.h" #include "vsb.h" +#include "hash_slinger.h" pthread_t cli_thread; static struct lock cli_mtx; diff --git a/varnish-cache/bin/varnishd/cache_expire.c b/varnish-cache/bin/varnishd/cache_expire.c index c97b94a1..4fa9b067 100644 --- a/varnish-cache/bin/varnishd/cache_expire.c +++ b/varnish-cache/bin/varnishd/cache_expire.c @@ -60,6 +60,7 @@ #include "shmlog.h" #include "binary_heap.h" #include "cache.h" +#include "hash_slinger.h" /* * Objects have sideways references in the binary heap and the LRU list diff --git a/varnish-cache/bin/varnishd/cache_hash.c b/varnish-cache/bin/varnishd/cache_hash.c index f03d02fa..8596c61b 100644 --- a/varnish-cache/bin/varnishd/cache_hash.c +++ b/varnish-cache/bin/varnishd/cache_hash.c @@ -65,6 +65,7 @@ #include "shmlog.h" #include "cache.h" #include "stevedore.h" +#include "hash_slinger.h" static const struct hash_slinger *hash; @@ -91,12 +92,23 @@ HSH_Prealloc(struct sess *sp) w->nobjhead = calloc(sizeof *w->nobjhead, 1); XXXAN(w->nobjhead); w->nobjhead->magic = OBJHEAD_MAGIC; + w->nobjhead->refcnt = 1; VTAILQ_INIT(&w->nobjhead->objects); VTAILQ_INIT(&w->nobjhead->waitinglist); Lck_New(&w->nobjhead->mtx); VSL_stats->n_objecthead++; } else CHECK_OBJ_NOTNULL(w->nobjhead, OBJHEAD_MAGIC); + +#if 0 + /* Make sure there is space enough for the hash-string */ + if (w->nobjhead->hashlen < sp->lhashptr) { + w->objhead->hash = realloc(w->objhead->hash, sp->lhashptr); + w->objhead->hashlen = sp->lhashptr; + AN(w->objhead->hash); + } +#endif + if (w->nobj == NULL) { st = STV_alloc(sp, params->obj_workspace); XXXAN(st); @@ -167,7 +179,7 @@ HSH_Compare(const struct sess *sp, const struct objhead *oh) } void -HSH_Copy(const struct sess *sp, const struct objhead *oh) +HSH_Copy(const struct sess *sp, struct objhead *oh) { unsigned u, v; char *b; @@ -175,7 +187,9 @@ HSH_Copy(const struct sess *sp, const struct objhead *oh) CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); - assert(oh->hashlen >= sp->lhashptr); + oh->hash = malloc(sp->lhashptr); + XXXAN(oh->hash); + oh->hashlen = sp->lhashptr; b = oh->hash; for (u = 0; u < sp->ihashptr; u += 2) { v = pdiff(sp->hashptr[u], sp->hashptr[u + 1]); @@ -210,6 +224,7 @@ HSH_Lookup(struct sess *sp) CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); Lck_Lock(&oh->mtx); } else { + AN(w->nobjhead); oh = hash->lookup(sp, w->nobjhead); CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); if (oh == w->nobjhead) diff --git a/varnish-cache/bin/varnishd/cache_main.c b/varnish-cache/bin/varnishd/cache_main.c index 52a26282..fef04237 100644 --- a/varnish-cache/bin/varnishd/cache_main.c +++ b/varnish-cache/bin/varnishd/cache_main.c @@ -39,6 +39,7 @@ #include "shmlog.h" #include "cache.h" #include "stevedore.h" +#include "hash_slinger.h" /*-------------------------------------------------------------------- * Per thread storage for the session currently being processed by diff --git a/varnish-cache/bin/varnishd/cache_pool.c b/varnish-cache/bin/varnishd/cache_pool.c index 90e9b90f..59973fd4 100644 --- a/varnish-cache/bin/varnishd/cache_pool.c +++ b/varnish-cache/bin/varnishd/cache_pool.c @@ -71,6 +71,7 @@ #include "cli_priv.h" #include "cache.h" #include "stevedore.h" +#include "hash_slinger.h" VTAILQ_HEAD(workerhead, worker); diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index c29d3be8..c99c0e28 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -50,6 +50,7 @@ #include "vrt_obj.h" #include "vcl.h" #include "cache.h" +#include "hash_slinger.h" #include "cache_backend.h" void *vrt_magic_string_end = &vrt_magic_string_end; diff --git a/varnish-cache/bin/varnishd/hash_classic.c b/varnish-cache/bin/varnishd/hash_classic.c index 280d50eb..fb14ddc2 100644 --- a/varnish-cache/bin/varnishd/hash_classic.c +++ b/varnish-cache/bin/varnishd/hash_classic.c @@ -40,23 +40,14 @@ #include "shmlog.h" #include "cache.h" +#include "hash_slinger.h" /*--------------------------------------------------------------------*/ -struct hcl_entry { - unsigned magic; -#define HCL_ENTRY_MAGIC 0x0ba707bf - VTAILQ_ENTRY(hcl_entry) list; - struct hcl_hd *head; - struct objhead *oh; - unsigned digest; - unsigned hash; -}; - struct hcl_hd { unsigned magic; #define HCL_HEAD_MAGIC 0x0f327016 - VTAILQ_HEAD(, hcl_entry) head; + VTAILQ_HEAD(, objhead) head; struct lock mtx; }; @@ -126,16 +117,13 @@ hcl_start(void) static struct objhead * hcl_lookup(const struct sess *sp, struct objhead *noh) { - struct objhead *roh; - struct hcl_entry *he, *he2; + struct objhead *oh; struct hcl_hd *hp; - unsigned u1, digest, r; + unsigned u1, digest; unsigned u, v; int i; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); - CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); - CHECK_OBJ_NOTNULL(sp->http, HTTP_MAGIC); CHECK_OBJ_ORNULL(noh, OBJHEAD_MAGIC); digest = ~0U; @@ -147,73 +135,39 @@ hcl_lookup(const struct sess *sp, struct objhead *noh) u1 = digest % hcl_nhash; hp = &hcl_head[u1]; - he2 = NULL; - for (r = 0; r < 2; r++ ) { - Lck_Lock(&hp->mtx); - VTAILQ_FOREACH(he, &hp->head, list) { - CHECK_OBJ_NOTNULL(he, HCL_ENTRY_MAGIC); - if (sp->lhashptr < he->oh->hashlen) - continue; - if (sp->lhashptr > he->oh->hashlen) - break; - if (he->digest < digest) - continue; - if (he->digest > digest) - break; - i = HSH_Compare(sp, he->oh); - if (i < 0) - continue; - if (i > 0) - break; - he->oh->refcnt++; - roh = he->oh; - Lck_Unlock(&hp->mtx); - /* - * If we loose the race, we need to clean up - * the work we did for our second attempt. - */ - if (he2 != NULL) - free(he2); - if (noh != NULL && noh->hash != NULL) { - free(noh->hash); - noh->hash = NULL; - } - return (roh); - } - if (noh == NULL) { - Lck_Unlock(&hp->mtx); - return (NULL); - } - if (he2 != NULL) { - if (he != NULL) - VTAILQ_INSERT_BEFORE(he, he2, list); - else - VTAILQ_INSERT_TAIL(&hp->head, he2, list); - he2->oh->refcnt++; - noh = he2->oh; - Lck_Unlock(&hp->mtx); - return (noh); - } + Lck_Lock(&hp->mtx); + VTAILQ_FOREACH(oh, &hp->head, hoh_list) { + if (sp->lhashptr < oh->hashlen) + continue; + if (sp->lhashptr > oh->hashlen) + break; + if (oh->hoh_digest < digest) + continue; + if (oh->hoh_digest > digest) + break; + i = HSH_Compare(sp, oh); + if (i < 0) + continue; + if (i > 0) + break; + oh->refcnt++; Lck_Unlock(&hp->mtx); + return (oh); + } - he2 = calloc(sizeof *he2, 1); - XXXAN(he2); - he2->magic = HCL_ENTRY_MAGIC; - he2->oh = noh; - he2->digest = digest; - he2->hash = u1; - he2->head = hp; + if (oh != NULL) + VTAILQ_INSERT_BEFORE(oh, noh, hoh_list); + else + VTAILQ_INSERT_TAIL(&hp->head, noh, hoh_list); - noh->hashpriv = he2; - AZ(noh->hash); - noh->hash = malloc(sp->lhashptr); - XXXAN(noh->hash); - noh->hashlen = sp->lhashptr; - HSH_Copy(sp, noh); - } - assert(he2 == NULL); /* FlexeLint */ - INCOMPL(); + noh->hoh_digest = digest; + noh->hoh_head = hp; + + HSH_Copy(sp, noh); + + Lck_Unlock(&hp->mtx); + return (noh); } /*-------------------------------------------------------------------- @@ -221,28 +175,22 @@ hcl_lookup(const struct sess *sp, struct objhead *noh) */ static int -hcl_deref(const struct objhead *oh) +hcl_deref(struct objhead *oh) { - struct hcl_entry *he; struct hcl_hd *hp; + int ret; CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); - CAST_OBJ_NOTNULL(he, oh->hashpriv, HCL_ENTRY_MAGIC); - hp = he->head; - CHECK_OBJ_NOTNULL(hp, HCL_HEAD_MAGIC); - assert(he->oh->refcnt > 0); - assert(he->hash < hcl_nhash); - assert(hp == &hcl_head[he->hash]); + CAST_OBJ_NOTNULL(hp, oh->hoh_head, HCL_HEAD_MAGIC); + assert(oh->refcnt > 0); Lck_Lock(&hp->mtx); - if (--he->oh->refcnt == 0) - VTAILQ_REMOVE(&hp->head, he, list); - else - he = NULL; + if (--oh->refcnt == 0) { + VTAILQ_REMOVE(&hp->head, oh, hoh_list); + ret = 0; + } else + ret = 1; Lck_Unlock(&hp->mtx); - if (he == NULL) - return (1); - free(he); - return (0); + return (ret); } /*--------------------------------------------------------------------*/ diff --git a/varnish-cache/bin/varnishd/hash_simple_list.c b/varnish-cache/bin/varnishd/hash_simple_list.c index a317b761..5cc7475b 100644 --- a/varnish-cache/bin/varnishd/hash_simple_list.c +++ b/varnish-cache/bin/varnishd/hash_simple_list.c @@ -33,23 +33,17 @@ #include "config.h" -#include - #include #include #include #include "shmlog.h" #include "cache.h" +#include "hash_slinger.h" /*--------------------------------------------------------------------*/ -struct hsl_entry { - VTAILQ_ENTRY(hsl_entry) list; - struct objhead *oh; -}; - -static VTAILQ_HEAD(, hsl_entry) hsl_head = VTAILQ_HEAD_INITIALIZER(hsl_head); +static VTAILQ_HEAD(, objhead) hsl_head = VTAILQ_HEAD_INITIALIZER(hsl_head); static struct lock hsl_mtx; /*-------------------------------------------------------------------- @@ -74,38 +68,28 @@ hsl_start(void) static struct objhead * hsl_lookup(const struct sess *sp, struct objhead *noh) { - struct hsl_entry *he, *he2; + struct objhead *oh; int i; Lck_Lock(&hsl_mtx); - VTAILQ_FOREACH(he, &hsl_head, list) { - i = HSH_Compare(sp, he->oh); + VTAILQ_FOREACH(oh, &hsl_head, hoh_list) { + i = HSH_Compare(sp, oh); if (i < 0) continue; if (i > 0) break; - he->oh->refcnt++; - noh = he->oh; + oh->refcnt++; Lck_Unlock(&hsl_mtx); - return (noh); - } - if (noh != NULL) { - he2 = calloc(sizeof *he2, 1); - XXXAN(he2); - he2->oh = noh; - he2->oh->refcnt = 1; - - noh->hashpriv = he2; - noh->hash = malloc(sp->lhashptr); - XXXAN(noh->hash); - noh->hashlen = sp->lhashptr; - HSH_Copy(sp, noh); - - if (he != NULL) - VTAILQ_INSERT_BEFORE(he, he2, list); - else - VTAILQ_INSERT_TAIL(&hsl_head, he2, list); + return (oh); } + + if (oh != NULL) + VTAILQ_INSERT_BEFORE(oh, noh, hoh_list); + else + VTAILQ_INSERT_TAIL(&hsl_head, noh, hoh_list); + + HSH_Copy(sp, noh); + Lck_Unlock(&hsl_mtx); return (noh); } @@ -115,17 +99,13 @@ hsl_lookup(const struct sess *sp, struct objhead *noh) */ static int -hsl_deref(const struct objhead *oh) +hsl_deref(struct objhead *oh) { - struct hsl_entry *he; int ret; - AN(oh->hashpriv); - he = oh->hashpriv; Lck_Lock(&hsl_mtx); - if (--he->oh->refcnt == 0) { - VTAILQ_REMOVE(&hsl_head, he, list); - free(he); + if (--oh->refcnt == 0) { + VTAILQ_REMOVE(&hsl_head, oh, hoh_list); ret = 0; } else ret = 1; diff --git a/varnish-cache/bin/varnishd/hash_slinger.h b/varnish-cache/bin/varnishd/hash_slinger.h index 1131ae90..753788b7 100644 --- a/varnish-cache/bin/varnishd/hash_slinger.h +++ b/varnish-cache/bin/varnishd/hash_slinger.h @@ -30,12 +30,13 @@ */ struct sess; +struct object; typedef void hash_init_f(int ac, char * const *av); typedef void hash_start_f(void); typedef struct objhead * hash_lookup_f(const struct sess *sp, struct objhead *nobj); -typedef int hash_deref_f(const struct objhead *obj); +typedef int hash_deref_f(struct objhead *obj); struct hash_slinger { unsigned magic; @@ -46,3 +47,38 @@ struct hash_slinger { hash_lookup_f *lookup; hash_deref_f *deref; }; + +/* cache_hash.c */ +void HSH_Prealloc(struct sess *sp); +void HSH_Freestore(struct object *o); +int HSH_Compare(const struct sess *sp, const struct objhead *o); +void HSH_Copy(const struct sess *sp, struct objhead *o); +struct object *HSH_Lookup(struct sess *sp); +void HSH_Unbusy(const struct sess *sp); +void HSH_Ref(struct object *o); +void HSH_Deref(struct object *o); +double HSH_Grace(double g); +void HSH_Init(void); + + +#ifdef VARNISH_CACHE_CHILD +struct objhead { + unsigned magic; +#define OBJHEAD_MAGIC 0x1b96615d + + struct lock mtx; + unsigned refcnt; + VTAILQ_HEAD(,object) objects; + char *hash; + unsigned hashlen; + VTAILQ_HEAD(, sess) waitinglist; + + /*------------------------------------------------------------ + * The fields below are for the sole private use of the hash + * implementation. + */ + VTAILQ_ENTRY(objhead) hoh_list; + void *hoh_head; + unsigned hoh_digest; +}; +#endif /* VARNISH_CACHE_CHILD */ diff --git a/varnish-cache/bin/varnishd/storage_synth.c b/varnish-cache/bin/varnishd/storage_synth.c index bcef0a3c..6acd5877 100644 --- a/varnish-cache/bin/varnishd/storage_synth.c +++ b/varnish-cache/bin/varnishd/storage_synth.c @@ -42,6 +42,7 @@ #include "cache.h" #include "vsb.h" #include "stevedore.h" +#include "hash_slinger.h" static struct lock sms_mtx;