* $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>
void *priv;
};
-#include "hash_slinger.h"
-
/* Backend Request ---------------------------------------------------*/
struct bereq {
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 {
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);
#include "vcl.h"
#include "cli_priv.h"
#include "cache.h"
+#include "hash_slinger.h"
static unsigned xids;
#include "cache.h"
#include "vlu.h"
#include "vsb.h"
+#include "hash_slinger.h"
pthread_t cli_thread;
static struct lock cli_mtx;
#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
#include "shmlog.h"
#include "cache.h"
#include "stevedore.h"
+#include "hash_slinger.h"
static const struct hash_slinger *hash;
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);
}
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;
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]);
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)
#include "shmlog.h"
#include "cache.h"
#include "stevedore.h"
+#include "hash_slinger.h"
/*--------------------------------------------------------------------
* Per thread storage for the session currently being processed by
#include "cli_priv.h"
#include "cache.h"
#include "stevedore.h"
+#include "hash_slinger.h"
VTAILQ_HEAD(workerhead, worker);
#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;
#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;
};
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;
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);
}
/*--------------------------------------------------------------------
*/
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);
}
/*--------------------------------------------------------------------*/
#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;
/*--------------------------------------------------------------------
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);
}
*/
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;
*/
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;
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 */
#include "cache.h"
#include "vsb.h"
#include "stevedore.h"
+#include "hash_slinger.h"
static struct lock sms_mtx;