Commit 884f8ebd authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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: http://www.varnish-cache.org/svn/trunk/varnish-cache@3405 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent ee4e0f91
......@@ -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 <sys/time.h>
#include <sys/uio.h>
#include <sys/socket.h>
......@@ -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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
......
......@@ -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)
......
......@@ -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
......
......@@ -71,6 +71,7 @@
#include "cli_priv.h"
#include "cache.h"
#include "stevedore.h"
#include "hash_slinger.h"
VTAILQ_HEAD(workerhead, worker);
......
......@@ -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;
......
......@@ -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);
}
/*--------------------------------------------------------------------*/
......
......@@ -33,23 +33,17 @@
#include "config.h"
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
......
......@@ -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 */
......@@ -42,6 +42,7 @@
#include "cache.h"
#include "vsb.h"
#include "stevedore.h"
#include "hash_slinger.h"
static struct lock sms_mtx;
......
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