This patch is generated from the compactsentry branch of HEAD in squid
Wed Sep 29 01:33:08 2004 GMT
See http://devel.squid-cache.org/

Index: squid/include/hash.h
diff -u squid/include/hash.h:1.3 squid/include/hash.h:1.3.2.1
--- squid/include/hash.h:1.3	Fri Nov  3 00:39:19 2000
+++ squid/include/hash.h	Fri Jan 12 17:32:05 2001
@@ -4,17 +4,18 @@
 
 typedef void HASHFREE(void *);
 typedef int HASHCMP(const void *, const void *);
+typedef const void *HASHKEY(const void *);
 typedef unsigned int HASHHASH(const void *, unsigned int);
 typedef struct _hash_link hash_link;
 typedef struct _hash_table hash_table;
 
 struct _hash_link {
-    void *key;
     hash_link *next;
 };
 
 struct _hash_table {
     hash_link **buckets;
+    HASHKEY *key;
     HASHCMP *cmp;
     HASHHASH *hash;
     unsigned int size;
@@ -23,7 +24,7 @@
     int count;
 };
 
-extern hash_table *hash_create(HASHCMP *, int, HASHHASH *);
+extern hash_table *hash_create(HASHKEY *, HASHCMP *, int, HASHHASH *);
 extern void hash_join(hash_table *, hash_link *);
 extern void hash_remove_link(hash_table *, hash_link *);
 extern int hashPrime(int n);
@@ -36,7 +37,7 @@
 extern void hashFreeItems(hash_table *, HASHFREE *);
 extern HASHHASH hash_string;
 extern HASHHASH hash4;
-extern const char *hashKeyStr(hash_link *);
+extern const char *hashKeyStr(hash_table *, hash_link *);
 
 /*
  *  Here are some good prime number choices.  It's important not to
Index: squid/include/heap.h
diff -u squid/include/heap.h:1.4 squid/include/heap.h:1.4.2.2
--- squid/include/heap.h:1.4	Fri Jan 12 00:20:31 2001
+++ squid/include/heap.h	Fri Jan 12 19:55:44 2001
@@ -62,9 +62,9 @@
  * key_func can generate a key from.
  */
 typedef struct _heap_node {
+    void *data;
     heap_key key;
     unsigned long id;
-    heap_t data;
 } heap_node;
 
 
@@ -103,7 +103,7 @@
  * should be done with this data structure (especially modifying it!)  The
  * heap does not assume ownership of the data passed to it.
  */
-extern heap_node *heap_insert(heap *, heap_t dat);
+extern heap_node *heap_insert(heap *, heap_node *node, void *data);
 
 /*
  * Delete a node out of a heap.  Returns the heap data from the deleted
@@ -136,6 +136,7 @@
  * free as necessary.
  */
 extern heap_t heap_extractmin(heap *);
+extern heap_node *heap_extractmin_node(heap *);
 
 /* 
  * Extract the last leaf node (does not change the heap property).
Index: squid/lib/hash.c
diff -u squid/lib/hash.c:1.6 squid/lib/hash.c:1.5.2.2
--- squid/lib/hash.c:1.6	Wed Mar  7 14:14:44 2001
+++ squid/lib/hash.c	Sun Mar 11 13:37:26 2001
@@ -141,7 +141,7 @@
  *  otherwise returns a negative number on error.
  */
 hash_table *
-hash_create(HASHCMP * cmp_func, int hash_sz, HASHHASH * hash_func)
+hash_create(HASHKEY *key_func, HASHCMP * cmp_func, int hash_sz, HASHHASH * hash_func)
 {
     hash_table *hid = xcalloc(1, sizeof(hash_table));
     if (!hash_sz)
@@ -150,6 +150,7 @@
 	hid->size = (unsigned int) hash_sz;
     /* allocate and null the buckets */
     hid->buckets = xcalloc(hid->size, sizeof(hash_link *));
+    hid->key = key_func;
     hid->cmp = cmp_func;
     hid->hash = hash_func;
     hid->next = NULL;
@@ -158,7 +159,7 @@
 }
 
 /*
- *  hash_join - joins a hash_link under its key lnk->key
+ *  hash_join - joins a hash_link under its key
  *  into the hash table 'hid'.  
  *
  *  It does not copy any data into the hash table, only links pointers.
@@ -167,7 +168,7 @@
 hash_join(hash_table * hid, hash_link * lnk)
 {
     int i;
-    i = hid->hash(lnk->key, hid->size);
+    i = hid->hash(hid->key(lnk), hid->size);
     lnk->next = hid->buckets[i];
     hid->buckets[i] = lnk;
     hid->count++;
@@ -186,7 +187,7 @@
     assert(k != NULL);
     b = hid->hash(k, hid->size);
     for (walker = hid->buckets[b]; walker != NULL; walker = walker->next) {
-	if ((hid->cmp) (k, walker->key) == 0)
+	if ((hid->cmp) (k, hid->key(walker)) == 0)
 	    return (walker);
 	assert(walker != walker->next);
     }
@@ -258,7 +259,7 @@
     hash_link **P;
     int i;
     assert(hl != NULL);
-    i = hid->hash(hl->key, hid->size);
+    i = hid->hash(hid->key(hl), hid->size);
     for (P = &hid->buckets[i]; *P; P = &(*P)->next) {
 	if (*P != hl)
 	    continue;
@@ -351,9 +352,9 @@
  * return the key of a hash_link as a const string
  */
 const char *
-hashKeyStr(hash_link * hl)
+hashKeyStr(hash_table *hid, hash_link * hl)
 {
-    return (const char *) hl->key;
+    return (const char *) hid->key(hl);
 }
 
 
Index: squid/lib/heap.c
diff -u squid/lib/heap.c:1.5 squid/lib/heap.c:1.4.2.4
--- squid/lib/heap.c:1.5	Wed Feb  7 11:11:47 2001
+++ squid/lib/heap.c	Sun Mar 11 13:37:26 2001
@@ -121,11 +121,7 @@
 void
 delete_heap(heap * hp)
 {
-    int i;
     assert(hp);
-    for (i = 0; i < hp->last; i++) {
-	xfree(hp->nodes[i]);
-    }
     xfree(hp->nodes);
     xfree(hp);
 }
@@ -141,10 +137,8 @@
  * deletion.
  */
 heap_node *
-heap_insert(heap * hp, void *dat)
+heap_insert(heap * hp, heap_node *elm, void *dat)
 {
-    heap_node *elm = xmalloc(sizeof(*elm));
-
     elm->key = heap_gen_key(hp, dat);
     elm->data = dat;
 
@@ -167,7 +161,7 @@
  * in, which the caller must free if necessary.
  */
 heap_t
-heap_delete(heap * hp, heap_node * elm)
+heap_remove(heap * hp, heap_node * elm)
 {
     heap_node *lastNode;
     heap_t data = elm->data;
@@ -192,6 +186,14 @@
     return data;
 }
 
+heap_t
+heap_delete(heap * hp, heap_node * elm)
+{
+    heap_t data = heap_remove(hp, elm);
+    elm->data = NULL;
+    return data;
+}
+
 /* 
  * Delete the last element (leaf) out of the heap.  Does not require a
  * heapify operation.
@@ -231,6 +233,22 @@
     return data;
 }
 
+heap_node *
+heap_extractmin_node(heap *hp)
+{
+    heap_node *elm;
+
+    if (hp->last <= 0)
+	return NULL;
+
+    mutex_lock(hp->lock);
+    elm = hp->nodes[0];
+    (void)heap_remove(hp, elm);
+    mutex_unlock(hp->lock);
+
+    return elm;
+}
+
 
 /* 
  * Remove the last node in HP.  Frees the heap internal structure and
@@ -243,7 +261,6 @@
     assert(_heap_node_exist(hp, hp->last - 1));
     hp->last -= 1;
     data = hp->nodes[hp->last]->data;
-    xfree(hp->nodes[hp->last]);
     return data;
 }
 
@@ -455,12 +472,6 @@
 	newSize = hp->size * NormalRate;
 
     hp->nodes = xrealloc(hp->nodes, newSize * sizeof(heap_node *));
-#if COMMENTED_OUT
-    for (i = 0; i < hp->size; i++)
-	newNodes[i] = hp->nodes[i];
-    xfree(hp->nodes);
-    hp->nodes = newNodes;
-#endif
     hp->size = newSize;
 }
 
Index: squid/src/HttpHdrRange.c
diff -u squid/src/HttpHdrRange.c:1.6 squid/src/HttpHdrRange.c:1.5.2.2
--- squid/src/HttpHdrRange.c:1.6	Wed Feb  7 11:11:47 2001
+++ squid/src/HttpHdrRange.c	Sun Mar 11 13:37:26 2001
@@ -467,7 +467,7 @@
     assert(http);
     stringAppend(&b, full_appname_string, strlen(full_appname_string));
     stringAppend(&b, ":", 1);
-    key = storeKeyText(http->entry->hash.key);
+    key = storeKeyText(http->entry->key);
     stringAppend(&b, key, strlen(key));
     return b;
 }
Index: squid/src/access_log.c
diff -u squid/src/access_log.c:1.11 squid/src/access_log.c:1.9.2.3
--- squid/src/access_log.c:1.11	Tue Apr 10 22:53:08 2001
+++ squid/src/access_log.c	Fri Apr 13 13:55:52 2001
@@ -447,7 +447,7 @@
     fv = hash_lookup(hash, key);
     if (NULL == fv) {
 	fv = xcalloc(1, sizeof(fvdb_entry));
-	fv->hash.key = xstrdup(key);
+	fv->key = xstrdup(key);
 	hash_join(hash, &fv->hash);
     }
     fv->n++;
@@ -496,7 +496,7 @@
 fvdbFreeEntry(void *data)
 {
     fvdb_entry *fv = data;
-    xfree(fv->hash.key);
+    xfree(fv->key);
     xfree(fv);
 }
 
Index: squid/src/authenticate.c
diff -u squid/src/authenticate.c:1.13 squid/src/authenticate.c:1.10.2.3
--- squid/src/authenticate.c:1.13	Fri Mar  9 16:58:00 2001
+++ squid/src/authenticate.c	Sun Mar 11 13:37:26 2001
@@ -563,13 +563,19 @@
     memFree(u, MEM_AUTH_USER_T);
 }
 
+const void *auth_user_hash_pointer_key(const void *data)
+{
+    const auth_user_hash_pointer *usernamehash = data;
+    return authenticateUserUsername(usernamehash->auth_user);
+}
+
 void
 authenticateInitUserCache(void)
 {
     if (!proxy_auth_username_cache) {
 	/* First time around, 7921 should be big enough */
 	proxy_auth_username_cache =
-	    hash_create((HASHCMP *) strcmp, 7921, hash_string);
+	    hash_create(auth_user_hash_pointer_key, (HASHCMP *) strcmp, 7921, hash_string);
 	assert(proxy_auth_username_cache);
 	eventAdd("User Cache Maintenance", authenticateProxyUserCacheCleanup, NULL, Config.authenticateGCInterval, 1);
     }
@@ -582,6 +588,7 @@
      * We walk the hash by username as that is the unique key we use.
      * For big hashs we could consider stepping through the cache, 100/200
      * entries at a time. Lets see how it flys first.
+     * XXX Perhaps consider using a heap?
      */
     auth_user_hash_pointer *usernamehash;
     auth_user_t *auth_user;
@@ -659,7 +666,6 @@
 {
     auth_user_hash_pointer *usernamehash;
     usernamehash = memAllocate(MEM_AUTH_USER_HASH);
-    usernamehash->key = authenticateUserUsername(auth_user);
     usernamehash->auth_user = auth_user;
     hash_join(proxy_auth_username_cache, (hash_link *) usernamehash);
     auth_user->usernamehash = usernamehash;
Index: squid/src/client_db.c
diff -u squid/src/client_db.c:1.6 squid/src/client_db.c:1.5.2.2
--- squid/src/client_db.c:1.6	Fri Feb 23 13:03:30 2001
+++ squid/src/client_db.c	Sun Mar 11 13:37:27 2001
@@ -44,19 +44,37 @@
 {
     ClientInfo *c;
     c = memAllocate(MEM_CLIENT_INFO);
-    c->hash.key = xstrdup(inet_ntoa(addr));
     c->addr = addr;
     hash_join(client_table, &c->hash);
     statCounter.client_http.clients++;
     return c;
 }
 
+const void * ClientInfo_key(const void *data)
+{
+    ClientInfo *c = (void *)data;
+    return &c->addr;
+}
+
+int in_addr_cmp(const void *data1, const void *data2)
+{
+    const struct in_addr *a = data1;
+    const struct in_addr *b = data2;
+    return a->s_addr != b->s_addr;
+}
+
+unsigned int in_addr_hash(const void *data, unsigned int size)
+{
+    const struct in_addr *addr = data;
+    return hash_string(inet_ntoa(*addr), size);
+}
+    
 void
 clientdbInit(void)
 {
     if (client_table)
 	return;
-    client_table = hash_create((HASHCMP *) strcmp, 467, hash_string);
+    client_table = hash_create(ClientInfo_key, in_addr_cmp, 467, in_addr_hash);
     cachemgrRegister("client_list",
 	"Cache Client List",
 	clientdbDump,
@@ -66,12 +84,10 @@
 void
 clientdbUpdate(struct in_addr addr, log_type ltype, protocol_t p, size_t size)
 {
-    char *key;
     ClientInfo *c;
     if (!Config.onoff.client_db)
 	return;
-    key = inet_ntoa(addr);
-    c = (ClientInfo *) hash_lookup(client_table, key);
+    c = (ClientInfo *) hash_lookup(client_table, &addr);
     if (c == NULL)
 	c = clientdbAdd(addr);
     if (c == NULL)
@@ -101,12 +117,10 @@
 int
 clientdbEstablished(struct in_addr addr, int delta)
 {
-    char *key;
     ClientInfo *c;
     if (!Config.onoff.client_db)
 	return 0;
-    key = inet_ntoa(addr);
-    c = (ClientInfo *) hash_lookup(client_table, key);
+    c = (ClientInfo *) hash_lookup(client_table, &addr);
     if (c == NULL)
 	c = clientdbAdd(addr);
     if (c == NULL)
@@ -119,15 +133,13 @@
 int
 clientdbCutoffDenied(struct in_addr addr)
 {
-    char *key;
     int NR;
     int ND;
     double p;
     ClientInfo *c;
     if (!Config.onoff.client_db)
 	return 0;
-    key = inet_ntoa(addr);
-    c = (ClientInfo *) hash_lookup(client_table, key);
+    c = (ClientInfo *) hash_lookup(client_table, &addr);
     if (c == NULL)
 	return 0;
     /*
@@ -146,7 +158,7 @@
     p = 100.0 * ND / NR;
     if (p < 95.0)
 	return 0;
-    debug(1, 0) ("WARNING: Probable misconfigured neighbor at %s\n", key);
+    debug(1, 0) ("WARNING: Probable misconfigured neighbor at %s\n", inet_ntoa(addr));
     debug(1, 0) ("WARNING: %d of the last %d ICP replies are DENIED\n", ND, NR);
     debug(1, 0) ("WARNING: No replies will be sent for the next %d seconds\n",
 	CUTOFF_SECONDS);
@@ -169,7 +181,7 @@
     storeAppendPrintf(sentry, "Cache Clients:\n");
     hash_first(client_table);
     while ((c = (ClientInfo *) hash_next(client_table))) {
-	storeAppendPrintf(sentry, "Address: %s\n", hashKeyStr(&c->hash));
+	storeAppendPrintf(sentry, "Address: %s\n", hashKeyStr(client_table, &c->hash));
 	storeAppendPrintf(sentry, "Name: %s\n", fqdnFromAddr(c->addr));
 	storeAppendPrintf(sentry, "Currently established connections: %d\n",
 	    c->n_established);
@@ -214,7 +226,6 @@
 clientdbFreeItem(void *data)
 {
     ClientInfo *c = data;
-    safe_free(c->hash.key);
     memFree(c, MEM_CLIENT_INFO);
 }
 
@@ -231,12 +242,10 @@
 client_entry(struct in_addr *current)
 {
     ClientInfo *c = NULL;
-    char *key;
     if (current) {
-	key = inet_ntoa(*current);
 	hash_first(client_table);
 	while ((c = (ClientInfo *) hash_next(client_table))) {
-	    if (!strcmp(key, hashKeyStr(&c->hash)))
+	    if (in_addr_cmp(current, &c->addr) == 0)
 		break;
 	}
 	c = (ClientInfo *) hash_next(client_table);
@@ -256,17 +265,19 @@
 snmp_meshCtblFn(variable_list * Var, snint * ErrP)
 {
     variable_list *Answer = NULL;
-    static char key[15];
+    static char ip[15];
     ClientInfo *c = NULL;
     int aggr = 0;
     log_type l;
+    struct in_addr addr;
     *ErrP = SNMP_ERR_NOERROR;
     debug(49, 6) ("snmp_meshCtblFn: Current : \n");
     snmpDebugOid(6, Var->name, Var->name_length);
-    snprintf(key, sizeof(key), "%d.%d.%d.%d", Var->name[LEN_SQ_NET + 3], Var->name[LEN_SQ_NET + 4],
+    snprintf(ip, sizeof(ip), "%d.%d.%d.%d", Var->name[LEN_SQ_NET + 3], Var->name[LEN_SQ_NET + 4],
 	Var->name[LEN_SQ_NET + 5], Var->name[LEN_SQ_NET + 6]);
-    debug(49, 5) ("snmp_meshCtblFn: [%s] requested!\n", key);
-    c = (ClientInfo *) hash_lookup(client_table, key);
+    inet_aton(ip, &addr);
+    debug(49, 5) ("snmp_meshCtblFn: [%s] requested!\n", ip);
+    c = (ClientInfo *) hash_lookup(client_table, &addr);
     if (c == NULL) {
 	debug(49, 5) ("snmp_meshCtblFn: not found.\n");
 	*ErrP = SNMP_ERR_NOSUCHNAME;
Index: squid/src/delay_pools.c
diff -u squid/src/delay_pools.c:1.5 squid/src/delay_pools.c:1.4.2.2
--- squid/src/delay_pools.c:1.5	Mon Mar 19 05:41:14 2001
+++ squid/src/delay_pools.c	Fri Apr 13 13:55:53 2001
@@ -91,7 +91,6 @@
 static delayPool *delay_data = NULL;
 static fd_set delay_no_delay;
 static time_t delay_pools_last_update = 0;
-static hash_table *delay_id_ptr_hash = NULL;
 static long memory_used = 0;
 
 static OBJH delayPoolStats;
@@ -146,7 +145,6 @@
     delay_data = xcalloc(pools, sizeof(*delay_data));
     memory_used += sizeof(*delay_data);
     eventAdd("delayPoolsUpdate", delayPoolsUpdate, NULL, 1.0, 1);
-    delay_id_ptr_hash = hash_create(delayIdPtrHashCmp, 256, delayIdPtrHash);
 }
 
 static void
@@ -164,45 +162,6 @@
 {
     safe_free(delay_data);
     memory_used -= sizeof(*delay_data);
-    if (!delay_id_ptr_hash)
-	return;
-    hashFreeItems(delay_id_ptr_hash, delayIdZero);
-    hashFreeMemory(delay_id_ptr_hash);
-    delay_id_ptr_hash = NULL;
-}
-
-void
-delayRegisterDelayIdPtr(delay_id * loc)
-{
-    hash_link *lnk;
-    if (!delay_id_ptr_hash)
-	return;
-    if (*loc == 0)
-	return;
-    lnk = xmalloc(sizeof(hash_link));
-    memory_used += sizeof(hash_link);
-    lnk->key = (char *) loc;
-    hash_join(delay_id_ptr_hash, lnk);
-}
-
-void
-delayUnregisterDelayIdPtr(delay_id * loc)
-{
-    hash_link *lnk;
-    if (!delay_id_ptr_hash)
-	return;
-    /*
-     * If we went through a reconfigure, then all the delay_id's
-     * got set to zero, and they were removed from our hash
-     * table.
-     */
-    if (*loc == 0)
-	return;
-    lnk = hash_lookup(delay_id_ptr_hash, loc);
-    assert(lnk);
-    hash_remove_link(delay_id_ptr_hash, lnk);
-    xxfree(lnk);
-    memory_used -= sizeof(*lnk);
 }
 
 void
@@ -686,7 +645,6 @@
 {
     assert(sc != NULL);
     sc->delay_id = delay_id;
-    delayRegisterDelayIdPtr(&sc->delay_id);
 }
 
 static void
Index: squid/src/enums.h
diff -u squid/src/enums.h:1.19 squid/src/enums.h:1.12.2.5
--- squid/src/enums.h:1.19	Fri Apr 13 17:31:02 2001
+++ squid/src/enums.h	Sat Apr 14 06:36:17 2001
@@ -497,6 +497,7 @@
 #if UNUSED_CODE
     ENTRY_DONT_LOG
 #endif
+    KEY_SET
 };
 
 typedef enum {
Index: squid/src/fqdncache.c
diff -u squid/src/fqdncache.c:1.14 squid/src/fqdncache.c:1.12.2.3
--- squid/src/fqdncache.c:1.14	Sat Mar  3 02:44:32 2001
+++ squid/src/fqdncache.c	Sun Mar 11 13:37:27 2001
@@ -42,6 +42,7 @@
 
 struct _fqdncache_entry {
     hash_link hash;		/* must be first */
+    char *key;
     time_t lastref;
     time_t expires;
     unsigned char name_count;
@@ -102,9 +103,9 @@
     for (k = 0; k < (int) f->name_count; k++)
 	safe_free(f->names[k]);
     debug(35, 5) ("fqdncacheRelease: Released FQDN record for '%s'.\n",
-	hashKeyStr(&f->hash));
+	hashKeyStr(fqdn_table, &f->hash));
     dlinkDelete(&f->lru, &lru_list);
-    safe_free(f->hash.key);
+    safe_free(f->key);
     safe_free(f->error_message);
     memFree(f, MEM_FQDNCACHE_ENTRY);
 }
@@ -181,7 +182,7 @@
 {
     static fqdncache_entry *f;
     f = memAllocate(MEM_FQDNCACHE_ENTRY);
-    f->hash.key = xstrdup(name);
+    f->key = xstrdup(name);
     f->expires = squid_curtime + Config.negativeDnsTtl;
     return f;
 }
@@ -189,12 +190,10 @@
 static void
 fqdncacheAddEntry(fqdncache_entry * f)
 {
-    hash_link *e = hash_lookup(fqdn_table, f->hash.key);
-    if (NULL != e) {
-	/* avoid colission */
-	fqdncache_entry *q = (fqdncache_entry *) e;
-	fqdncacheRelease(q);
-    }
+    fqdncache_entry *e = hash_lookup(fqdn_table, f->key);
+    /* avoid colission */
+    if (e)
+	fqdncacheRelease(e);
     hash_join(fqdn_table, &f->hash);
     dlinkAdd(f, &f->lru, &lru_list);
     f->lastref = squid_curtime;
@@ -396,6 +395,12 @@
 #endif
 }
 
+const void * fqdncache_entry_key(const void *data)
+{
+    const fqdncache_entry *e = data;
+    return e->key;
+}
+
 /* initialize the fqdncache */
 void
 fqdncache_init(void)
@@ -411,7 +416,7 @@
     fqdncache_low = (long) (((float) Config.fqdncache.size *
 	    (float) FQDN_LOW_WATER) / (float) 100);
     n = hashPrime(fqdncache_high / 4);
-    fqdn_table = hash_create((HASHCMP *) strcmp, n, hash4);
+    fqdn_table = hash_create(fqdncache_entry_key, (HASHCMP *) strcmp, n, hash4);
     cachemgrRegister("fqdncache",
 	"FQDN Cache Stats and Contents",
 	fqdnStats, 0, 1);
@@ -481,7 +486,7 @@
     while ((f = (fqdncache_entry *) hash_next(fqdn_table))) {
 	ttl = (f->flags.fromhosts ? -1 : (f->expires - squid_curtime));
 	storeAppendPrintf(sentry, "%-15.15s  %c%c %3.3d % 3d",
-	    hashKeyStr(&f->hash),
+	    hashKeyStr(fqdn_table, &f->hash),
 	    f->flags.negcached ? 'N' : ' ',
 	    f->flags.fromhosts ? 'H' : ' ',
 	    ttl,
@@ -534,7 +539,7 @@
     int k;
     for (k = 0; k < (int) f->name_count; k++)
 	safe_free(f->names[k]);
-    safe_free(f->hash.key);
+    safe_free(f->key);
     safe_free(f->error_message);
     memFree(f, MEM_FQDNCACHE_ENTRY);
 }
Index: squid/src/htcp.c
diff -u squid/src/htcp.c:1.8 squid/src/htcp.c:1.6.2.3
--- squid/src/htcp.c:1.8	Fri Apr 13 17:31:02 2001
+++ squid/src/htcp.c	Sat Apr 14 06:36:18 2001
@@ -919,7 +919,7 @@
     }
     htcpSend(pkt, (int) pktlen, &p->in_addr);
     save_key = queried_keys[stuff.msg_id % N_QUERIED_KEYS];
-    storeKeyCopy(save_key, e->hash.key);
+    storeKeyCopy(save_key, e->key);
     debug(31, 3) ("htcpQuery: key (%p) %s\n", save_key, storeKeyText(save_key));
     xfree(pkt);
 }
Index: squid/src/http.c
diff -u squid/src/http.c:1.13 squid/src/http.c:1.11.2.3
--- squid/src/http.c:1.13	Fri Apr 13 17:31:02 2001
+++ squid/src/http.c	Sat Apr 14 06:36:18 2001
@@ -390,7 +390,7 @@
     HttpReply *reply = entry->mem_obj->reply;
     Ctx ctx;
     debug(11, 3) ("httpProcessReplyHeader: key '%s'\n",
-	storeKeyText(entry->hash.key));
+	storeKeyText(entry->key));
     if (httpState->reply_hdr == NULL)
 	httpState->reply_hdr = memAllocate(MEM_8K_BUF);
     assert(httpState->reply_hdr_state == 0);
Index: squid/src/ident.c
diff -u squid/src/ident.c:1.8 squid/src/ident.c:1.6.2.4
--- squid/src/ident.c:1.8	Fri Apr 13 17:31:02 2001
+++ squid/src/ident.c	Sat Apr 14 06:36:18 2001
@@ -48,6 +48,7 @@
 
 typedef struct _IdentStateData {
     hash_link hash;		/* must be first */
+    char *key;
     int fd;			/* IDENT fd */
     struct sockaddr_in me;
     struct sockaddr_in my_peer;
@@ -217,7 +218,7 @@
     }
     CBDATA_INIT_TYPE(IdentStateData);
     state = cbdataAlloc(IdentStateData);
-    state->hash.key = xstrdup(key);
+    state->key = xstrdup(key);
     state->fd = fd;
     state->me = *me;
     state->my_peer = *my_peer;
@@ -234,10 +235,16 @@
 	state);
 }
 
+const void *identStateKey(const void *data)
+{
+    const IdentStateData *state = data;
+    return state->key;
+}
+
 void
 identInit(void)
 {
-    ident_hash = hash_create((HASHCMP *) strcmp,
+    ident_hash = hash_create(identStateKey, (HASHCMP *) strcmp,
 	hashPrime(Squid_MaxFD / 8),
 	hash4);
 }
Index: squid/src/ipcache.c
diff -u squid/src/ipcache.c:1.15 squid/src/ipcache.c:1.13.2.3
--- squid/src/ipcache.c:1.15	Sat Mar  3 02:44:32 2001
+++ squid/src/ipcache.c	Sun Mar 11 13:37:27 2001
@@ -39,6 +39,7 @@
 
 struct _ipcache_entry {
     hash_link hash;		/* must be first */
+    char *key;
     time_t lastref;
     time_t expires;
     ipcache_addrs addrs;
@@ -191,7 +192,7 @@
 {
     static ipcache_entry *i;
     i = memAllocate(MEM_IPCACHE_ENTRY);
-    i->hash.key = xstrdup(name);
+    i->key = xstrdup(name);
     i->expires = squid_curtime + Config.negativeDnsTtl;
     return i;
 }
@@ -199,7 +200,7 @@
 static void
 ipcacheAddEntry(ipcache_entry * i)
 {
-    hash_link *e = hash_lookup(ip_table, i->hash.key);
+    hash_link *e = hash_lookup(ip_table, i->key);
     if (NULL != e) {
 	/* avoid colission */
 	ipcache_entry *q = (ipcache_entry *) e;
@@ -437,10 +438,17 @@
 #if USE_DNSSERVERS
     dnsSubmit(hashKeyStr(&i->hash), ipcacheHandleReply, c);
 #else
-    idnsALookup(hashKeyStr(&i->hash), ipcacheHandleReply, c);
+    idnsALookup(hashKeyStr(ip_table, &i->hash), ipcacheHandleReply, c);
 #endif
 }
 
+const void *
+ipcache_entry_key(const void *data)
+{
+    const ipcache_entry *e = data;
+    return e->key;
+}
+
 /* initialize the ipcache */
 void
 ipcache_init(void)
@@ -465,7 +473,7 @@
     ipcache_low = (long) (((float) Config.ipcache.size *
 	    (float) Config.ipcache.low) / (float) 100);
     n = hashPrime(ipcache_high / 4);
-    ip_table = hash_create((HASHCMP *) strcmp, n, hash4);
+    ip_table = hash_create(ipcache_entry_key, (HASHCMP *) strcmp, n, hash4);
     cachemgrRegister("ipcache",
 	"IP Cache Stats and Contents",
 	stat_ipcache_get, 0, 1);
@@ -508,7 +516,7 @@
 {
     int k;
     storeAppendPrintf(sentry, " %-32.32s %c%c %6d %6d %2d(%2d)",
-	hashKeyStr(&i->hash),
+	hashKeyStr(ip_table, &i->hash),
 	i->flags.fromhosts ? 'H' : ' ',
 	i->flags.negcached ? 'N' : ' ',
 	(int) (squid_curtime - i->lastref),
@@ -694,7 +702,7 @@
     ipcache_entry *i = data;
     safe_free(i->addrs.in_addrs);
     safe_free(i->addrs.bad_mask);
-    safe_free(i->hash.key);
+    safe_free(i->key);
     safe_free(i->error_message);
     memFree(i, MEM_IPCACHE_ENTRY);
 }
Index: squid/src/neighbors.c
diff -u squid/src/neighbors.c:1.11 squid/src/neighbors.c:1.8.2.4
--- squid/src/neighbors.c:1.11	Fri Apr 13 17:31:02 2001
+++ squid/src/neighbors.c	Sat Apr 14 06:36:18 2001
@@ -422,7 +422,7 @@
     mem->start_ping = current_time;
     mem->ping_reply_callback = callback;
     mem->ircb_data = callback_data;
-    reqnum = icpSetCacheKey(entry->hash.key);
+    reqnum = icpSetCacheKey(entry->key);
     for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
 	if (p == NULL)
 	    p = Config.peers;
@@ -434,7 +434,7 @@
 	    p->host, url);
 	if (p->type == PEER_MULTICAST)
 	    mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
-	debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->hash.key));
+	debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->key));
 	debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum);
 
 #if USE_HTCP
@@ -1136,7 +1136,7 @@
     mem->ircb_data = psstate;
     mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
     p->mcast.id = mem->id;
-    reqnum = icpSetCacheKey(fake->hash.key);
+    reqnum = icpSetCacheKey(fake->key);
     query = icpCreateMessage(ICP_QUERY, 0, url, reqnum, 0);
     icpUdpSend(theOutIcpConnection,
 	&p->in_addr,
Index: squid/src/net_db.c
diff -u squid/src/net_db.c:1.10 squid/src/net_db.c:1.9.2.2
--- squid/src/net_db.c:1.10	Sat Mar  3 02:44:32 2001
+++ squid/src/net_db.c	Sun Mar 11 13:37:27 2001
@@ -81,7 +81,7 @@
 netdbHashInsert(netdbEntry * n, struct in_addr addr)
 {
     xstrncpy(n->network, inet_ntoa(networkFromInaddr(addr)), 16);
-    n->hash.key = n->network;
+    n->key = n->network;
     assert(hash_lookup(addr_table, n->network) == NULL);
     hash_join(addr_table, &n->hash);
 }
@@ -101,7 +101,7 @@
 netdbHostInsert(netdbEntry * n, const char *hostname)
 {
     net_db_name *x = memAllocate(MEM_NET_DB_NAME);
-    x->hash.key = xstrdup(hostname);
+    x->key = xstrdup(hostname);
     x->next = n->hosts;
     n->hosts = x;
     x->net_db_entry = n;
@@ -126,7 +126,7 @@
 	}
     }
     hash_remove_link(host_table, (hash_link *) x);
-    xfree(x->hash.key);
+    xfree(x->key);
     memFree((void *) x, MEM_NET_DB_NAME);
 }
 
@@ -520,7 +520,7 @@
 netdbFreeNameEntry(void *data)
 {
     net_db_name *x = data;
-    xfree(x->hash.key);
+    xfree(x->key);
     memFree(x, MEM_NET_DB_NAME);
 }
 
Index: squid/src/pconn.c
diff -u squid/src/pconn.c:1.6 squid/src/pconn.c:1.5.2.3
--- squid/src/pconn.c:1.6	Fri Apr 13 17:31:02 2001
+++ squid/src/pconn.c	Sat Apr 14 06:36:18 2001
@@ -37,6 +37,7 @@
 
 struct _pconn {
     hash_link hash;		/* must be first */
+    char *key;
     int *fds;
     int nfds_alloc;
     int nfds;
@@ -70,10 +71,10 @@
 pconnNew(const char *key)
 {
     struct _pconn *p = memPoolAlloc(pconn_data_pool);
-    p->hash.key = xstrdup(key);
+    p->key = xstrdup(key);
     p->nfds_alloc = PCONN_FDS_SZ;
     p->fds = memPoolAlloc(pconn_fds_pool);
-    debug(48, 3) ("pconnNew: adding %s\n", hashKeyStr(&p->hash));
+    debug(48, 3) ("pconnNew: adding %s\n", hashKeyStr(table, &p->hash));
     hash_join(table, &p->hash);
     return p;
 }
@@ -81,13 +82,13 @@
 static void
 pconnDelete(struct _pconn *p)
 {
-    debug(48, 3) ("pconnDelete: deleting %s\n", hashKeyStr(&p->hash));
+    debug(48, 3) ("pconnDelete: deleting %s\n", hashKeyStr(table, &p->hash));
     hash_remove_link(table, (hash_link *) p);
     if (p->nfds_alloc == PCONN_FDS_SZ)
 	memPoolFree(pconn_fds_pool, p->fds);
     else
 	xfree(p->fds);
-    xfree(p->hash.key);
+    xfree(p->key);
     memPoolFree(pconn_data_pool, p);
 }
 
@@ -112,7 +113,7 @@
 {
     struct _pconn *p = data;
     assert(table != NULL);
-    debug(48, 3) ("pconnTimeout: FD %d %s\n", fd, hashKeyStr(&p->hash));
+    debug(48, 3) ("pconnTimeout: FD %d %s\n", fd, hashKeyStr(table, &p->hash));
     pconnRemoveFD(p, fd);
     comm_close(fd);
 }
@@ -127,7 +128,7 @@
     statCounter.syscalls.sock.reads++;
     n = FD_READ_METHOD(fd, buf, 256);
     debug(48, 3) ("pconnRead: %d bytes from FD %d, %s\n", n, fd,
-	hashKeyStr(&p->hash));
+	hashKeyStr(table, &p->hash));
     pconnRemoveFD(p, fd);
     comm_close(fd);
 }
@@ -163,13 +164,19 @@
 
 /* ========== PUBLIC FUNCTIONS ============================================ */
 
+const void *
+pconn_key(const void *data)
+{
+    const struct _pconn *p = data;
+    return p->key;
+}
 
 void
 pconnInit(void)
 {
     int i;
     assert(table == NULL);
-    table = hash_create((HASHCMP *) strcmp, 229, hash_string);
+    table = hash_create(pconn_key, (HASHCMP *) strcmp, 229, hash_string);
     for (i = 0; i < PCONN_HIST_SZ; i++) {
 	client_pconn_hist[i] = 0;
 	server_pconn_hist[i] = 0;
Index: squid/src/protos.h
diff -u squid/src/protos.h:1.24 squid/src/protos.h:1.16.2.5
--- squid/src/protos.h:1.24	Fri Apr 13 17:31:02 2001
+++ squid/src/protos.h	Sat Apr 14 06:36:18 2001
@@ -951,9 +951,7 @@
 /*
  * store_key_*.c
  */
-extern cache_key *storeKeyDup(const cache_key *);
 extern cache_key *storeKeyCopy(cache_key *, const cache_key *);
-extern void storeKeyFree(const cache_key *);
 extern const cache_key *storeKeyScan(const char *);
 extern const char *storeKeyText(const cache_key *);
 extern const cache_key *storeKeyPublic(const char *, const method_t);
@@ -1234,8 +1232,6 @@
 extern int delayMostBytesWanted(const MemObject * mem, int max);
 extern delay_id delayMostBytesAllowed(const MemObject * mem);
 extern void delaySetStoreClient(store_client * sc, delay_id delay_id);
-extern void delayRegisterDelayIdPtr(delay_id * loc);
-extern void delayUnregisterDelayIdPtr(delay_id * loc);
 #endif
 
 /* helper.c */
Index: squid/src/ssl.c
diff -u squid/src/ssl.c:1.8 squid/src/ssl.c:1.6.2.3
--- squid/src/ssl.c:1.8	Fri Apr 13 17:31:02 2001
+++ squid/src/ssl.c	Sat Apr 14 06:36:18 2001
@@ -109,9 +109,6 @@
     sslState->host = NULL;
     requestUnlink(sslState->request);
     sslState->request = NULL;
-#if DELAY_POOLS
-    delayUnregisterDelayIdPtr(&sslState->delay_id);
-#endif
     cbdataFree(sslState);
 }
 
@@ -487,7 +484,6 @@
     sslState = cbdataAlloc(SslStateData);
 #if DELAY_POOLS
     sslState->delay_id = delayClient(request);
-    delayRegisterDelayIdPtr(&sslState->delay_id);
 #endif
     sslState->url = xstrdup(url);
     sslState->request = requestLink(request);
@@ -593,7 +589,6 @@
 #if DELAY_POOLS
     /* no point using the delayIsNoDelay stuff since ssl is nice and simple */
     if (g && g->options.no_delay && sslState->delay_id) {
-	delayUnregisterDelayIdPtr(&sslState->delay_id);
 	sslState->delay_id = 0;
     }
 #endif
Index: squid/src/stat.c
diff -u squid/src/stat.c:1.9 squid/src/stat.c:1.7.2.2
--- squid/src/stat.c:1.9	Sat Mar  3 02:44:32 2001
+++ squid/src/stat.c	Sun Mar 11 13:37:27 2001
@@ -260,7 +260,7 @@
     int i;
     struct _store_client *sc;
     dlink_node *node;
-    storeAppendPrintf(s, "KEY %s\n", storeKeyText(e->hash.key));
+    storeAppendPrintf(s, "KEY %s\n", storeKeyText(e->key));
     if (mem)
 	storeAppendPrintf(s, "\t%s %s\n",
 	    RequestMethodStr[mem->method], mem->log_url);
@@ -1427,9 +1427,9 @@
 	    http->out.offset, http->out.size);
 	storeAppendPrintf(s, "req_sz %d\n", http->req_sz);
 	e = http->entry;
-	storeAppendPrintf(s, "entry %p/%s\n", e, e ? storeKeyText(e->hash.key) : "N/A");
+	storeAppendPrintf(s, "entry %p/%s\n", e, e ? storeKeyText(e->key) : "N/A");
 	e = http->old_entry;
-	storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? storeKeyText(e->hash.key) : "N/A");
+	storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? storeKeyText(e->key) : "N/A");
 	storeAppendPrintf(s, "start %d.%06d (%f seconds ago)\n", http->start.tv_sec,
 	    http->start.tv_usec,
 	    tvSubDsec(http->start, current_time));
Index: squid/src/store.c
diff -u squid/src/store.c:1.12 squid/src/store.c:1.9.2.5
--- squid/src/store.c:1.12	Fri Apr 13 17:31:02 2001
+++ squid/src/store.c	Sat Apr 14 06:36:18 2001
@@ -179,7 +179,7 @@
     if (e->mem_obj)
 	destroy_MemObject(e);
     storeHashDelete(e);
-    assert(e->hash.key == NULL);
+    assert(e->key == NULL);
     memFree(e, MEM_STOREENTRY);
 }
 
@@ -190,7 +190,8 @@
 {
     debug(20, 3) ("storeHashInsert: Inserting Entry %p key '%s'\n",
 	e, storeKeyText(key));
-    e->hash.key = storeKeyDup(key);
+    storeKeyCopy(e->key, key);
+    EBIT_SET(e->flags, KEY_SET);
     hash_join(store_table, &e->hash);
 }
 
@@ -198,8 +199,6 @@
 storeHashDelete(StoreEntry * e)
 {
     hash_remove_link(store_table, &e->hash);
-    storeKeyFree(e->hash.key);
-    e->hash.key = NULL;
 }
 
 /* -------------------------------------------------------------------------- */
@@ -213,7 +212,7 @@
     if (e->mem_obj == NULL)
 	return;
     debug(20, 3) ("storePurgeMem: Freeing memory-copy of %s\n",
-	storeKeyText(e->hash.key));
+	storeKeyText(e->key));
     storeSetMemStatus(e, NOT_IN_MEMORY);
     destroy_MemObject(e);
     if (e->swap_status != SWAPOUT_DONE)
@@ -261,7 +260,7 @@
 {
     e->lock_count++;
     debug(20, 3) ("storeLockObject: key '%s' count=%d\n",
-	storeKeyText(e->hash.key), (int) e->lock_count);
+	storeKeyText(e->key), (int) e->lock_count);
     e->lastref = squid_curtime;
     storeEntryReferenced(e);
 }
@@ -271,7 +270,7 @@
 {
     if (EBIT_TEST(e->flags, RELEASE_REQUEST))
 	return;
-    debug(20, 3) ("storeReleaseRequest: '%s'\n", storeKeyText(e->hash.key));
+    debug(20, 3) ("storeReleaseRequest: '%s'\n", storeKeyText(e->key));
     EBIT_SET(e->flags, RELEASE_REQUEST);
     /*
      * Clear cachable flag here because we might get called before
@@ -289,7 +288,7 @@
 {
     e->lock_count--;
     debug(20, 3) ("storeUnlockObject: key '%s' count=%d\n",
-	storeKeyText(e->hash.key), e->lock_count);
+	storeKeyText(e->key), e->lock_count);
     if (e->lock_count)
 	return (int) e->lock_count;
     if (e->store_status == STORE_PENDING)
@@ -356,9 +355,10 @@
 {
     const cache_key *newkey;
     MemObject *mem = e->mem_obj;
-    if (e->hash.key && EBIT_TEST(e->flags, KEY_PRIVATE))
+    if (EBIT_TEST(e->flags, KEY_PRIVATE))
 	return;			/* is already private */
-    if (e->hash.key) {
+
+    if (EBIT_TEST(e->flags, KEY_SET)) {
 	if (e->swap_filen > -1)
 	    storeDirSwapLog(e, SWAP_LOG_DEL);
 	storeHashDelete(e);
@@ -380,7 +380,7 @@
     StoreEntry *e2 = NULL;
     const cache_key *newkey;
     MemObject *mem = e->mem_obj;
-    if (e->hash.key && !EBIT_TEST(e->flags, KEY_PRIVATE))
+    if (e->key && !EBIT_TEST(e->flags, KEY_PRIVATE))
 	return;			/* is already public */
     assert(mem);
     /*
@@ -396,7 +396,7 @@
 #if MORE_DEBUG_OUTPUT
     if (EBIT_TEST(e->flags, RELEASE_REQUEST))
 	debug(20, 1) ("assertion failed: RELEASE key %s, url %s\n",
-	    e->hash.key, mem->url);
+	    e->key, mem->url);
 #endif
     assert(!EBIT_TEST(e->flags, RELEASE_REQUEST));
     if (mem->request) {
@@ -457,7 +457,7 @@
 	else
 	    newkey = storeKeyPublic(mem->url, mem->method);
     }
-    if (e->hash.key)
+    if (e->key)
 	storeHashDelete(e);
     EBIT_CLR(e->flags, KEY_PRIVATE);
     storeHashInsert(e, newkey);
@@ -504,7 +504,7 @@
 void
 storeExpireNow(StoreEntry * e)
 {
-    debug(20, 3) ("storeExpireNow: '%s'\n", storeKeyText(e->hash.key));
+    debug(20, 3) ("storeExpireNow: '%s'\n", storeKeyText(e->key));
     e->expires = squid_curtime;
 }
 
@@ -519,7 +519,7 @@
     if (len) {
 	debug(20, 5) ("storeAppend: appending %d bytes for '%s'\n",
 	    len,
-	    storeKeyText(e->hash.key));
+	    storeKeyText(e->key));
 	storeGetMemSpace(len);
 	stmemAppend(&mem->data_hdr, buf, len);
 	mem->inmem_hi += len;
@@ -697,7 +697,7 @@
 void
 storeComplete(StoreEntry * e)
 {
-    debug(20, 3) ("storeComplete: '%s'\n", storeKeyText(e->hash.key));
+    debug(20, 3) ("storeComplete: '%s'\n", storeKeyText(e->key));
     if (e->store_status != STORE_PENDING) {
 	/*
 	 * if we're not STORE_PENDING, then probably we got aborted
@@ -739,7 +739,7 @@
     MemObject *mem = e->mem_obj;
     assert(e->store_status == STORE_PENDING);
     assert(mem != NULL);
-    debug(20, 6) ("storeAbort: %s\n", storeKeyText(e->hash.key));
+    debug(20, 6) ("storeAbort: %s\n", storeKeyText(e->key));
     storeLockObject(e);		/* lock while aborting */
     storeNegativeCache(e);
     storeReleaseRequest(e);
@@ -842,7 +842,7 @@
 void
 storeRelease(StoreEntry * e)
 {
-    debug(20, 3) ("storeRelease: Releasing: '%s'\n", storeKeyText(e->hash.key));
+    debug(20, 3) ("storeRelease: Releasing: '%s'\n", storeKeyText(e->key));
     /* If, for any reason we can't discard this object because of an
      * outstanding request, mark it for pending release */
     if (storeEntryLocked(e)) {
@@ -936,7 +936,7 @@
     const HttpReply *reply;
     assert(e->mem_obj != NULL);
     reply = e->mem_obj->reply;
-    debug(20, 3) ("storeEntryValidLength: Checking '%s'\n", storeKeyText(e->hash.key));
+    debug(20, 3) ("storeEntryValidLength: Checking '%s'\n", storeKeyText(e->key));
     debug(20, 5) ("storeEntryValidLength:     object_len = %d\n",
 	objectLen(e));
     debug(20, 5) ("storeEntryValidLength:         hdr_sz = %d\n",
@@ -945,17 +945,17 @@
 	reply->content_length);
     if (reply->content_length < 0) {
 	debug(20, 5) ("storeEntryValidLength: Unspecified content length: %s\n",
-	    storeKeyText(e->hash.key));
+	    storeKeyText(e->key));
 	return 1;
     }
     if (reply->hdr_sz == 0) {
 	debug(20, 5) ("storeEntryValidLength: Zero header size: %s\n",
-	    storeKeyText(e->hash.key));
+	    storeKeyText(e->key));
 	return 1;
     }
     if (e->mem_obj->method == METHOD_HEAD) {
 	debug(20, 5) ("storeEntryValidLength: HEAD request: %s\n",
-	    storeKeyText(e->hash.key));
+	    storeKeyText(e->key));
 	return 1;
     }
     if (reply->sline.status == HTTP_NOT_MODIFIED)
@@ -968,7 +968,7 @@
     debug(20, 3) ("storeEntryValidLength: %d bytes too %s; '%s'\n",
 	diff < 0 ? -diff : diff,
 	diff < 0 ? "big" : "small",
-	storeKeyText(e->hash.key));
+	storeKeyText(e->key));
     return 0;
 }
 
@@ -990,12 +990,18 @@
     debug(20, 1) ("Max Swap size: %d KB\n", Config.Swap.maxSize);
 }
 
+const void *storeEntryKey(const void *data)
+{
+    const StoreEntry *e = data;
+    return e->key;
+}
+
 void
 storeInit(void)
 {
     storeKeyInit();
     storeInitHashValues();
-    store_table = hash_create(storeKeyHashCmp,
+    store_table = hash_create(storeEntryKey, storeKeyHashCmp,
 	store_hash_buckets, storeKeyHashHash);
     mem_policy = createRemovalPolicy(Config.memPolicy);
     storeDigestInit();
@@ -1158,7 +1164,7 @@
 void
 storeEntryDump(const StoreEntry * e, int l)
 {
-    debug(20, l) ("StoreEntry->key: %s\n", storeKeyText(e->hash.key));
+    debug(20, l) ("StoreEntry->key: %s\n", storeKeyText(e->key));
     debug(20, l) ("StoreEntry->next: %p\n", e->hash.next);
     debug(20, l) ("StoreEntry->mem_obj: %p\n", e->mem_obj);
     debug(20, l) ("StoreEntry->timestamp: %d\n", (int) e->timestamp);
Index: squid/src/store_client.c
diff -u squid/src/store_client.c:1.8 squid/src/store_client.c:1.6.2.4
--- squid/src/store_client.c:1.8	Fri Apr 13 17:31:02 2001
+++ squid/src/store_client.c	Sat Apr 14 06:36:18 2001
@@ -188,7 +188,7 @@
 {
     assert(!EBIT_TEST(e->flags, ENTRY_ABORTED));
     debug(20, 3) ("storeClientCopy: %s, seen %d, want %d, size %d, cb %p, cbdata %p\n",
-	storeKeyText(e->hash.key),
+	storeKeyText(e->key),
 	(int) seen_offset,
 	(int) copy_offset,
 	(int) size,
@@ -248,7 +248,7 @@
     }
     cbdataLock(sc);		/* ick, prevent sc from getting freed */
     sc->flags.store_copying = 1;
-    debug(20, 3) ("storeClientCopy2: %s\n", storeKeyText(e->hash.key));
+    debug(20, 3) ("storeClientCopy2: %s\n", storeKeyText(e->key));
     assert(sc->callback != NULL);
     /*
      * We used to check for ENTRY_ABORTED here.  But there were some
@@ -409,10 +409,10 @@
 	case STORE_META_KEY:
 	    assert(t->length == MD5_DIGEST_CHARS);
 	    if (!EBIT_TEST(e->flags, KEY_PRIVATE) &&
-		memcmp(t->value, e->hash.key, MD5_DIGEST_CHARS)) {
+		memcmp(t->value, e->key, MD5_DIGEST_CHARS)) {
 		debug(20, 2) ("storeClientReadHeader: swapin MD5 mismatch\n");
 		debug(20, 2) ("\t%s\n", storeKeyText(t->value));
-		debug(20, 2) ("\t%s\n", storeKeyText(e->hash.key));
+		debug(20, 2) ("\t%s\n", storeKeyText(e->key));
 		if (isPowTen(++md5_mismatches))
 		    debug(20, 1) ("WARNING: %d swapin MD5 mismatches\n",
 			md5_mismatches);
@@ -507,7 +507,7 @@
 #endif
     if (mem == NULL)
 	return 0;
-    debug(20, 3) ("storeUnregister: called for '%s'\n", storeKeyText(e->hash.key));
+    debug(20, 3) ("storeUnregister: called for '%s'\n", storeKeyText(e->key));
     if (sc == NULL)
 	return 0;
     if (mem->clients.head == NULL)
@@ -535,9 +535,6 @@
 	    mem->url);
 	storeClientCallback(sc, -1);
     }
-#if DELAY_POOLS
-    delayUnregisterDelayIdPtr(&sc->delay_id);
-#endif
     cbdataUnlock(sc->callback_data);	/* we're done with it now */
     /*assert(!sc->flags.disk_io_pending); */
     cbdataFree(sc);
@@ -582,7 +579,7 @@
     dlink_node *nx = NULL;
     dlink_node *node;
 
-    debug(20, 3) ("InvokeHandlers: %s\n", storeKeyText(e->hash.key));
+    debug(20, 3) ("InvokeHandlers: %s\n", storeKeyText(e->key));
     /* walk the entire list looking for valid callbacks */
     for (node = mem->clients.head; node; node = nx) {
 	sc = node->data;
Index: squid/src/store_digest.c
diff -u squid/src/store_digest.c:1.9 squid/src/store_digest.c:1.7.2.2
--- squid/src/store_digest.c:1.9	Sat Mar  3 02:44:32 2001
+++ squid/src/store_digest.c	Sun Mar 11 13:37:28 2001
@@ -135,17 +135,17 @@
     }
     assert(entry && store_digest);
     debug(71, 6) ("storeDigestDel: checking entry, key: %s\n",
-	storeKeyText(entry->hash.key));
+	storeKeyText(entry->key));
     if (!EBIT_TEST(entry->flags, KEY_PRIVATE)) {
-	if (!cacheDigestTest(store_digest, entry->hash.key)) {
+	if (!cacheDigestTest(store_digest, entry->key)) {
 	    sd_stats.del_lost_count++;
 	    debug(71, 6) ("storeDigestDel: lost entry, key: %s url: %s\n",
-		storeKeyText(entry->hash.key), storeUrl(entry));
+		storeKeyText(entry->key), storeUrl(entry));
 	} else {
 	    sd_stats.del_count++;
-	    cacheDigestDel(store_digest, entry->hash.key);
+	    cacheDigestDel(store_digest, entry->key);
 	    debug(71, 6) ("storeDigestDel: deled entry, key: %s\n",
-		storeKeyText(entry->hash.key));
+		storeKeyText(entry->key));
 	}
     }
 #endif
@@ -187,7 +187,7 @@
     /* add some stats! XXX */
 
     debug(71, 6) ("storeDigestAddable: checking entry, key: %s\n",
-	storeKeyText(e->hash.key));
+	storeKeyText(e->key));
 
     /* check various entry flags (mimics storeCheckCachable XXX) */
     if (!EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
@@ -245,14 +245,14 @@
 
     if (storeDigestAddable(entry)) {
 	sd_stats.add_count++;
-	if (cacheDigestTest(store_digest, entry->hash.key))
+	if (cacheDigestTest(store_digest, entry->key))
 	    sd_stats.add_coll_count++;
-	cacheDigestAdd(store_digest, entry->hash.key);
+	cacheDigestAdd(store_digest, entry->key);
 	debug(71, 6) ("storeDigestAdd: added entry, key: %s\n",
-	    storeKeyText(entry->hash.key));
+	    storeKeyText(entry->key));
     } else {
 	sd_stats.rej_count++;
-	if (cacheDigestTest(store_digest, entry->hash.key))
+	if (cacheDigestTest(store_digest, entry->key))
 	    sd_stats.rej_coll_count++;
     }
 }
@@ -354,7 +354,7 @@
     assert(e);
     sd_state.rewrite_lock = cbdataAlloc(generic_cbdata);
     sd_state.rewrite_lock->data = e;
-    debug(71, 3) ("storeDigestRewrite: url: %s key: %s\n", url, storeKeyText(e->hash.key));
+    debug(71, 3) ("storeDigestRewrite: url: %s key: %s\n", url, storeKeyText(e->key));
     e->mem_obj->request = requestLink(urlParse(METHOD_GET, url));
     /* wait for rebuild (if any) to finish */
     if (sd_state.rebuild_lock) {
Index: squid/src/store_dir.c
diff -u squid/src/store_dir.c:1.15 squid/src/store_dir.c:1.11.2.3
--- squid/src/store_dir.c:1.15	Thu Mar 29 01:41:31 2001
+++ squid/src/store_dir.c	Fri Apr 13 13:55:53 2001
@@ -252,7 +252,7 @@
     assert(op > SWAP_LOG_NOP && op < SWAP_LOG_MAX);
     debug(20, 3) ("storeDirSwapLog: %s %s %d %08X\n",
 	swap_log_op_str[op],
-	storeKeyText(e->hash.key),
+	storeKeyText(e->key),
 	e->swap_dirn,
 	e->swap_filen);
     sd = &Config.cacheSwap.swapDirs[e->swap_dirn];
Index: squid/src/store_key_md5.c
diff -u squid/src/store_key_md5.c:1.6 squid/src/store_key_md5.c:1.5.2.2
--- squid/src/store_key_md5.c:1.6	Fri Apr 13 17:31:02 2001
+++ squid/src/store_key_md5.c	Sat Apr 14 06:36:18 2001
@@ -104,6 +104,7 @@
     MD5Update(&M, (unsigned char *) &method, sizeof(method));
     MD5Update(&M, (unsigned char *) url, strlen(url));
     MD5Final(digest, &M);
+    digest[0]|=1;
     return digest;
 }
 
@@ -157,12 +158,6 @@
     return dst;
 }
 
-void
-storeKeyFree(const cache_key * key)
-{
-    memFree((void *) key, MEM_MD5_DIGEST);
-}
-
 int
 storeKeyHashBuckets(int nbuckets)
 {
Index: squid/src/store_log.c
diff -u squid/src/store_log.c:1.6 squid/src/store_log.c:1.5.2.2
--- squid/src/store_log.c:1.6	Sat Feb 17 12:56:22 2001
+++ squid/src/store_log.c	Sun Mar 11 13:37:28 2001
@@ -75,7 +75,7 @@
 	    storeLogTags[tag],
 	    e->swap_dirn,
 	    e->swap_filen,
-	    storeKeyText(e->hash.key),
+	    storeKeyText(e->key),
 	    reply->sline.status,
 	    (int) reply->date,
 	    (int) reply->last_modified,
@@ -93,7 +93,7 @@
 	    storeLogTags[tag],
 	    e->swap_dirn,
 	    e->swap_filen,
-	    storeKeyText(e->hash.key));
+	    storeKeyText(e->key));
     }
 }
 
Index: squid/src/store_swapin.c
diff -u squid/src/store_swapin.c:1.5 squid/src/store_swapin.c:1.5.2.1
--- squid/src/store_swapin.c:1.5	Fri Jan 12 00:20:33 2001
+++ squid/src/store_swapin.c	Fri Jan 12 17:36:57 2001
@@ -48,7 +48,7 @@
 	return;
     }
     debug(20, 3) ("storeSwapInStart: called for %d %08X %s \n",
-	e->swap_dirn, e->swap_filen, storeKeyText(e->hash.key));
+	e->swap_dirn, e->swap_filen, storeKeyText(e->key));
     if (e->swap_status != SWAPOUT_WRITING && e->swap_status != SWAPOUT_DONE) {
 	debug(20, 1) ("storeSwapInStart: bad swap_status (%s)\n",
 	    swapStatusStr[e->swap_status]);
Index: squid/src/store_swapmeta.c
diff -u squid/src/store_swapmeta.c:1.7 squid/src/store_swapmeta.c:1.5.2.3
--- squid/src/store_swapmeta.c:1.7	Fri Apr 13 17:31:02 2001
+++ squid/src/store_swapmeta.c	Sat Apr 14 06:36:18 2001
@@ -72,7 +72,7 @@
     assert(e->swap_status == SWAPOUT_WRITING);
     url = storeUrl(e);
     debug(20, 3) ("storeSwapMetaBuild: %s\n", url);
-    T = storeSwapTLVAdd(STORE_META_KEY, e->hash.key, MD5_DIGEST_CHARS, T);
+    T = storeSwapTLVAdd(STORE_META_KEY, e->key, MD5_DIGEST_CHARS, T);
     T = storeSwapTLVAdd(STORE_META_STD, &e->timestamp, STORE_HDR_METASIZE, T);
     T = storeSwapTLVAdd(STORE_META_URL, url, strlen(url) + 1, T);
     vary = e->mem_obj->vary_headers;
Index: squid/src/store_swapout.c
diff -u squid/src/store_swapout.c:1.7 squid/src/store_swapout.c:1.6.2.2
--- squid/src/store_swapout.c:1.7	Sat Mar  3 02:44:32 2001
+++ squid/src/store_swapout.c	Sun Mar 11 13:37:28 2001
@@ -263,7 +263,7 @@
 {
     MemObject *mem = e->mem_obj;
     assert(mem != NULL);
-    debug(20, 3) ("storeSwapOutFileClose: %s\n", storeKeyText(e->hash.key));
+    debug(20, 3) ("storeSwapOutFileClose: %s\n", storeKeyText(e->key));
     debug(20, 3) ("storeSwapOutFileClose: sio = %p\n", mem->swapout.sio);
     if (mem->swapout.sio == NULL)
 	return;
Index: squid/src/structs.h
diff -u squid/src/structs.h:1.30 squid/src/structs.h:1.21.2.7
--- squid/src/structs.h:1.30	Fri Apr 13 17:31:02 2001
+++ squid/src/structs.h	Sat Apr 14 06:36:18 2001
@@ -33,6 +33,7 @@
 
 #include "config.h"
 #include "splay.h"
+#include "heap.h"
 
 struct _dlink_node {
     void *data;
@@ -80,9 +81,7 @@
 };
 
 struct _auth_user_hash_pointer {
-    /* first two items must be same as hash_link */
-    char *key;
-    auth_user_hash_pointer *next;
+    hash_link hash;		/* must be first */
     auth_user_t *auth_user;
     dlink_node link;		/* other hash entries that point to the same auth_user */
 };
@@ -1389,8 +1388,10 @@
 
 /* Removal policies */
 
-struct _RemovalPolicyNode {
+union _RemovalPolicyNode {
     void *data;
+    dlink_node dlink;
+    heap_node heap;
 };
 
 struct _RemovalPolicy {
@@ -1457,6 +1458,7 @@
 
 struct _StoreEntry {
     hash_link hash;		/* must be first */
+    unsigned char key[MD5_DIGEST_CHARS];
     MemObject *mem_obj;
     RemovalPolicyNode repl;
     time_t timestamp;
Index: squid/src/typedefs.h
diff -u squid/src/typedefs.h:1.18 squid/src/typedefs.h:1.13.2.4
--- squid/src/typedefs.h:1.18	Fri Apr 13 17:31:02 2001
+++ squid/src/typedefs.h	Sat Apr 14 06:36:18 2001
@@ -185,7 +185,7 @@
 typedef struct _RemovalPolicy RemovalPolicy;
 typedef struct _RemovalPolicyWalker RemovalPolicyWalker;
 typedef struct _RemovalPurgeWalker RemovalPurgeWalker;
-typedef struct _RemovalPolicyNode RemovalPolicyNode;
+typedef union _RemovalPolicyNode RemovalPolicyNode;
 typedef struct _RemovalPolicySettings RemovalPolicySettings;
 
 typedef struct _http_version_t http_version_t;
Index: squid/src/auth/basic/auth_basic.c
diff -u squid/src/auth/basic/auth_basic.c:1.11 squid/src/auth/basic/auth_basic.c:1.5.2.4
--- squid/src/auth/basic/auth_basic.c:1.11	Wed Mar 21 15:43:33 2001
+++ squid/src/auth/basic/auth_basic.c	Fri Apr 13 13:55:53 2001
@@ -389,8 +389,8 @@
     debug(29, 9) ("authBasicAuthUserFindUsername: Looking for user '%s'\n", username);
     if (username && (usernamehash = hash_lookup(proxy_auth_username_cache, username))) {
 	while ((usernamehash->auth_user->auth_type != AUTH_BASIC) &&
-	    (usernamehash->next))
-	    usernamehash = usernamehash->next;
+	    (usernamehash->hash.next))
+	    usernamehash = (auth_user_hash_pointer *)usernamehash->hash.next;
 	auth_user = NULL;
 	if (usernamehash->auth_user->auth_type == AUTH_BASIC) {
 	    auth_user = usernamehash->auth_user;
Index: squid/src/auth/basic/helpers/NCSA/ncsa_auth.c
diff -u squid/src/auth/basic/helpers/NCSA/ncsa_auth.c:1.2 squid/src/auth/basic/helpers/NCSA/ncsa_auth.c:1.2.12.1
--- squid/src/auth/basic/helpers/NCSA/ncsa_auth.c:1.2	Sun Jan  7 16:02:37 2001
+++ squid/src/auth/basic/helpers/NCSA/ncsa_auth.c	Fri Jan 12 17:32:06 2001
@@ -47,9 +47,8 @@
 static HASHFREE my_free;
 
 typedef struct _user_data {
-    /* first two items must be same as hash_link */
+    hash_link hash;		/* must be first */
     char *user;
-    struct _user_data *next;
     char *passwd;
 } user_data;
 
@@ -62,6 +61,12 @@
     xfree(u);
 }
 
+const void *user_data_key(const void *data)
+{
+    const user_data *user = data;
+    return user->user;
+}
+
 static void
 read_passwd_file(const char *passwdfile)
 {
@@ -74,7 +79,7 @@
 	hashFreeItems(hash, my_free);
     }
     /* initial setup */
-    hash = hash_create((HASHCMP *) strcmp, 7921, hash_string);
+    hash = hash_create(user_data_key, (HASHCMP *) strcmp, 7921, hash_string);
     if (NULL == hash) {
 	fprintf(stderr, "ncsa_auth: cannot create hash table\n");
 	exit(1);
@@ -90,7 +95,7 @@
 	    u = xmalloc(sizeof(*u));
 	    u->user = xstrdup(user);
 	    u->passwd = xstrdup(passwd);
-	    hash_join(hash, (hash_link *) u);
+	    hash_join(hash, &u->hash);
 	}
     }
     fclose(f);
Index: squid/src/auth/ntlm/auth_ntlm.c
diff -u squid/src/auth/ntlm/auth_ntlm.c:1.9 squid/src/auth/ntlm/auth_ntlm.c:1.6.2.3
--- squid/src/auth/ntlm/auth_ntlm.c:1.9	Fri Mar  9 16:58:00 2001
+++ squid/src/auth/ntlm/auth_ntlm.c	Sun Mar 11 13:37:28 2001
@@ -75,6 +75,8 @@
 
 static statefulhelper *ntlmauthenticators = NULL;
 
+static MemPool *ntlm_hash_pool;
+
 CBDATA_TYPE(authenticateStateData);
 
 static int authntlm_initialised = 0;
@@ -84,7 +86,7 @@
 MemPool *ntlm_request_pool = NULL;
 static auth_ntlm_config *ntlmConfig = NULL;
 
-static hash_table *proxy_auth_cache = NULL;
+static hash_table *proxy_auth_ntlm_hash_cache = NULL;
 
 /*
  *
@@ -205,6 +207,13 @@
     authscheme->decodeauth = authenticateDecodeNTLMAuth;
     authscheme->donefunc = authNTLMDone;
     authscheme->oncloseconnection = authenticateNTLMOnCloseConnection;
+    ntlm_hash_pool = memPoolCreate("ntlm_user_hash", sizeof(ntlm_hash_user_pointer));
+}
+
+const void *ntlm_hash_user_pointer_key(const void *data)
+{
+    const ntlm_hash_user_pointer *ntlm_hash = data;
+    return ntlm_hash->ntlmhash;
 }
 
 /* Initialize helpers and the like for this auth scheme. Called AFTER parsing the
@@ -223,9 +232,9 @@
 	authntlm_initialised = 1;
 	if (ntlmauthenticators == NULL)
 	    ntlmauthenticators = helperStatefulCreate("ntlmauthenticator");
-	if (!proxy_auth_cache)
-	    proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
-	assert(proxy_auth_cache);
+	if (!proxy_auth_ntlm_hash_cache)
+	    proxy_auth_ntlm_hash_cache = hash_create(ntlm_hash_user_pointer_key, (HASHCMP *) strcmp, 7921, hash_string);
+	assert(proxy_auth_ntlm_hash_cache);
 	ntlmauthenticators->cmdline = ntlmConfig->authenticate;
 	ntlmauthenticators->n_to_start = ntlmConfig->authenticateChildren;
 	ntlmauthenticators->ipc_type = IPC_TCP_SOCKET;
@@ -355,7 +364,7 @@
 {
     dlink_node *link, *tmplink;
     ntlm_user_t *ntlm_user = auth_user->scheme_data;
-    auth_user_hash_pointer *proxy_auth_hash;
+    ntlm_hash_user_pointer *ntlm_hash;
 
     debug(29, 5) ("authenticateNTLMFreeUser: Clearing NTLM scheme data\n");
     if (ntlm_user->username)
@@ -364,14 +373,14 @@
     link = ntlm_user->proxy_auth_list.head;
     while (link) {
 	debug(29, 9) ("authenticateFreeProxyAuthUser: removing proxy_auth hash entry '%d'\n", link->data);
-	proxy_auth_hash = link->data;
+	ntlm_hash = link->data;
 	tmplink = link;
 	link = link->next;
 	dlinkDelete(tmplink, &ntlm_user->proxy_auth_list);
-	hash_remove_link(proxy_auth_cache, (hash_link *) proxy_auth_hash);
+	hash_remove_link(proxy_auth_ntlm_hash_cache, (hash_link *) ntlm_hash);
 	/* free the key (usually the proxy_auth header) */
-	xfree(proxy_auth_hash->key);
-	memFree(proxy_auth_hash, MEM_AUTH_USER_HASH);
+	xfree(ntlm_hash->ntlmhash);
+	memPoolFree(ntlm_hash_pool, ntlm_hash);
     }
     memPoolFree(ntlm_user_pool, ntlm_user);
     auth_user->scheme_data = NULL;
@@ -853,11 +862,11 @@
 void
 authenticateProxyAuthCacheAddLink(const char *key, auth_user_t * auth_user)
 {
-    auth_user_hash_pointer *proxy_auth_hash;
+    ntlm_hash_user_pointer *ntlm_hash;
     ntlm_user_t *ntlm_user;
-    proxy_auth_hash = memAllocate(MEM_AUTH_USER_HASH);
-    proxy_auth_hash->key = xstrdup(key);
-    proxy_auth_hash->auth_user = auth_user;
+    ntlm_hash = memPoolAlloc(ntlm_hash_pool);
+    ntlm_hash->key = xstrdup(key);
+    ntlm_hash->auth_user = auth_user;
     ntlm_user = auth_user->scheme_data;
     dlinkAddTail(proxy_auth_hash, &proxy_auth_hash->link, &ntlm_user->proxy_auth_list);
     hash_join(proxy_auth_cache, (hash_link *) proxy_auth_hash);
@@ -878,7 +887,8 @@
 authenticateNTLMAuthenticateUser(auth_user_request_t * auth_user_request, request_t * request, ConnStateData * conn, http_hdr_type type)
 {
     const char *proxy_auth;
-    auth_user_hash_pointer *usernamehash, *proxy_auth_hash = NULL;
+    auth_user_hash_pointer *usernamehash;
+    ntlm_hash_user_pointer *ntlm_hash;
     auth_user_t *auth_user;
     ntlm_request_t *ntlm_request;
     ntlm_user_t *ntlm_user;
@@ -933,9 +943,9 @@
 	    ntlm_request->authchallenge);
 	/* see if we already know this user's authenticate */
 	debug(29, 9) ("aclMatchProxyAuth: cache lookup with key '%s'\n", ntlmhash);
-	assert(proxy_auth_cache != NULL);
-	proxy_auth_hash = hash_lookup(proxy_auth_cache, ntlmhash);
-	if (!proxy_auth_hash) {	/* not in the hash table */
+	assert(proxy_auth_ntlm_hash_cache != NULL);
+	ntlm_hash = hash_lookup(proxy_auth_ntlm_hash_cache, ntlmhash);
+	if (!ntlm_hash) {	/* not in the hash table */
 	    debug(29, 4) ("authenticateNTLMAuthenticateUser: proxy-auth cache miss.\n");
 	    ntlm_request->auth_state = AUTHENTICATE_STATE_RESPONSE;
 	    /* verify with the ntlm helper */
@@ -943,8 +953,8 @@
 	    debug(29, 4) ("authenticateNTLMAuthenticateUser: ntlm proxy-auth cache hit\n");
 	    /* throw away the temporary entry */
 	    authenticateNTLMReleasehelper(auth_user_request);
-	    authenticateAuthUserMerge(auth_user, proxy_auth_hash->auth_user);
-	    auth_user = proxy_auth_hash->auth_user;
+	    authenticateAuthUserMerge(auth_user, ntlm_hash->auth_user);
+	    auth_user = ntlm_hash->auth_user;
 	    auth_user_request->auth_user = auth_user;
 	    ntlm_request->auth_state = AUTHENTICATE_STATE_DONE;
 	    /* we found one */
@@ -983,7 +993,6 @@
 		/*
 		 * add another link from the new proxy_auth to the
 		 * auth_user structure and update the information */
-		assert(proxy_auth_hash == NULL);
 		authenticateProxyAuthCacheAddLink(ntlmhash, usernamehash->auth_user);
 		/* we can't seamlessly recheck the username due to the 
 		 * challenge nature of the protocol. Just free the 
Index: squid/src/auth/ntlm/auth_ntlm.h
diff -u squid/src/auth/ntlm/auth_ntlm.h:1.3 squid/src/auth/ntlm/auth_ntlm.h:1.3.2.1
--- squid/src/auth/ntlm/auth_ntlm.h:1.3	Wed Jan 10 16:05:18 2001
+++ squid/src/auth/ntlm/auth_ntlm.h	Sat Jan 13 14:10:55 2001
@@ -9,6 +9,12 @@
 #define DefaultAuthenticateChildrenMax  32	/* 32 processes */
 
 /* Generic */
+typedef struct _ntlm_user ntlm_user_t;
+typedef struct _ntlm_hash_user_pointer ntlm_hash_user_pointer;
+typedef struct _ntlm_request ntlm_request_t;
+typedef struct _ntlm_helper_state_t ntlm_helper_state_t;
+typedef struct _auth_ntlm_config auth_ntlm_config;
+
 typedef struct {
     void *data;
     auth_user_request_t *auth_user_request;
@@ -21,6 +27,13 @@
     dlink_list proxy_auth_list;
 };
 
+struct _ntlm_hash_user_pointer {
+    hash_link hash;	/* must be first */
+    char *ntlmhash;	/* the NTLM hash key */
+    auth_user_t *auth_user;	/* User for this hash */
+    dlink_node link;	/* other NTLM hashes for this user */
+};
+
 struct _ntlm_request {
     /* what negotiate string did the client use? */
     char *ntlmnegotiate;
@@ -49,11 +62,6 @@
     time_t challengelifetime;
 };
 
-typedef struct _ntlm_user ntlm_user_t;
-typedef struct _ntlm_request ntlm_request_t;
-typedef struct _ntlm_helper_state_t ntlm_helper_state_t;
-typedef struct _auth_ntlm_config auth_ntlm_config;
-
 extern MemPool *ntlm_helper_state_pool;
 extern MemPool *ntlm_user_pool;
 extern MemPool *ntlm_request_pool;
Index: squid/src/fs/aufs/store_dir_aufs.c
diff -u squid/src/fs/aufs/store_dir_aufs.c:1.17 squid/src/fs/aufs/store_dir_aufs.c:1.11.2.3
--- squid/src/fs/aufs/store_dir_aufs.c:1.17	Sat Mar 17 05:42:03 2001
+++ squid/src/fs/aufs/store_dir_aufs.c	Fri Apr 13 13:55:54 2001
@@ -466,7 +466,7 @@
 	    storeAufsDirUnlinkFile(SD, sfileno);
 	    continue;
 	}
-	tmpe.hash.key = key;
+	xmemcpy(tmpe.key, key, MD5_DIGEST_CHARS);
 	/* check sizes */
 	if (tmpe.swap_file_sz == 0) {
 	    tmpe.swap_file_sz = sb.st_size;
@@ -1018,7 +1018,7 @@
     s.swap_file_sz = e->swap_file_sz;
     s.refcount = e->refcount;
     s.flags = e->flags;
-    xmemcpy(&s.key, e->hash.key, MD5_DIGEST_CHARS);
+    xmemcpy(&s.key, e->key, MD5_DIGEST_CHARS);
     xmemcpy(state->outbuf + state->outbuf_offset, &s, ss);
     state->outbuf_offset += ss;
     /* buffered write */
@@ -1115,7 +1115,7 @@
     s->swap_file_sz = e->swap_file_sz;
     s->refcount = e->refcount;
     s->flags = e->flags;
-    xmemcpy(s->key, e->hash.key, MD5_DIGEST_CHARS);
+    xmemcpy(s->key, e->key, MD5_DIGEST_CHARS);
     file_write(aioinfo->swaplog_fd,
 	-1,
 	s,
Index: squid/src/fs/coss/store_dir_coss.c
diff -u squid/src/fs/coss/store_dir_coss.c:1.11 squid/src/fs/coss/store_dir_coss.c:1.8.2.2
--- squid/src/fs/coss/store_dir_coss.c:1.11	Sat Mar  3 02:44:33 2001
+++ squid/src/fs/coss/store_dir_coss.c	Sun Mar 11 13:37:28 2001
@@ -533,7 +533,7 @@
     s.swap_file_sz = e->swap_file_sz;
     s.refcount = e->refcount;
     s.flags = e->flags;
-    xmemcpy(&s.key, e->hash.key, MD5_DIGEST_CHARS);
+    xmemcpy(&s.key, e->key, MD5_DIGEST_CHARS);
     xmemcpy(state->outbuf + state->outbuf_offset, &s, ss);
     state->outbuf_offset += ss;
     /* buffered write */
@@ -626,7 +626,7 @@
     s->swap_file_sz = e->swap_file_sz;
     s->refcount = e->refcount;
     s->flags = e->flags;
-    xmemcpy(s->key, e->hash.key, MD5_DIGEST_CHARS);
+    xmemcpy(s->key, e->key, MD5_DIGEST_CHARS);
     file_write(cs->swaplog_fd,
 	-1,
 	s,
Index: squid/src/fs/diskd/diskd.c
diff -u squid/src/fs/diskd/diskd.c:1.6 squid/src/fs/diskd/diskd.c:1.5.2.2
--- squid/src/fs/diskd/diskd.c:1.6	Wed Feb  7 11:11:49 2001
+++ squid/src/fs/diskd/diskd.c	Sun Mar 11 13:37:28 2001
@@ -50,8 +50,7 @@
 typedef struct _file_state file_state;
 
 struct _file_state {
-    void *key;
-    file_state *next;
+    hash_link hash;	/* must be first */
     int id;
     int fd;
     off_t offset;
@@ -80,9 +79,8 @@
     }
     fs = xcalloc(1, sizeof(*fs));
     fs->id = r->id;
-    fs->key = &fs->id;		/* gack */
     fs->fd = fd;
-    hash_join(hash, (hash_link *) fs);
+    hash_join(hash, &fs->hash);
     DEBUG(2)
 	fprintf(stderr, "%d OPEN  id %d, FD %d, fs %p\n",
 	(int) mypid,
@@ -264,6 +262,13 @@
     return (*k & (--n));
 }
 
+const void *
+fsKey(const void *data)
+{
+    const file_state *fs = data;
+    return &fs->id;
+}
+
 static void
 alarm_handler(int sig)
 {
@@ -309,7 +314,7 @@
 	perror("shmat");
 	return 1;
     }
-    hash = hash_create(fsCmp, 1 << 4, fsHash);
+    hash = hash_create(fsKey, fsCmp, 1 << 4, fsHash);
     assert(hash);
     fcntl(0, F_SETFL, SQUID_NONBLOCK);
     memset(&sa, '\0', sizeof(sa));
Index: squid/src/fs/diskd/store_dir_diskd.c
diff -u squid/src/fs/diskd/store_dir_diskd.c:1.22 squid/src/fs/diskd/store_dir_diskd.c:1.10.2.4
--- squid/src/fs/diskd/store_dir_diskd.c:1.22	Tue Apr  3 23:45:09 2001
+++ squid/src/fs/diskd/store_dir_diskd.c	Fri Apr 13 13:55:54 2001
@@ -633,7 +633,7 @@
 	    storeDiskdDirUnlinkFile(SD, sfileno);
 	    continue;
 	}
-	tmpe.hash.key = key;
+	xmemcpy(tmpe.key, key, MD5_DIGEST_CHARS);
 	/* check sizes */
 	if (tmpe.swap_file_sz == 0) {
 	    tmpe.swap_file_sz = sb.st_size;
@@ -1207,7 +1207,7 @@
     s.swap_file_sz = e->swap_file_sz;
     s.refcount = e->refcount;
     s.flags = e->flags;
-    xmemcpy(&s.key, e->hash.key, MD5_DIGEST_CHARS);
+    xmemcpy(&s.key, e->key, MD5_DIGEST_CHARS);
     xmemcpy(state->outbuf + state->outbuf_offset, &s, ss);
     state->outbuf_offset += ss;
     /* buffered write */
@@ -1301,7 +1301,7 @@
     s->swap_file_sz = e->swap_file_sz;
     s->refcount = e->refcount;
     s->flags = e->flags;
-    xmemcpy(s->key, e->hash.key, MD5_DIGEST_CHARS);
+    xmemcpy(s->key, e->key, MD5_DIGEST_CHARS);
     file_write(diskdinfo->swaplog_fd,
 	-1,
 	s,
Index: squid/src/fs/ufs/store_dir_ufs.c
diff -u squid/src/fs/ufs/store_dir_ufs.c:1.16 squid/src/fs/ufs/store_dir_ufs.c:1.10.2.3
--- squid/src/fs/ufs/store_dir_ufs.c:1.16	Fri Mar 16 09:22:14 2001
+++ squid/src/fs/ufs/store_dir_ufs.c	Fri Apr 13 13:55:54 2001
@@ -463,7 +463,7 @@
 	    storeUfsDirUnlinkFile(SD, sfileno);
 	    continue;
 	}
-	tmpe.hash.key = key;
+	xmemcpy(tmpe.key, key, MD5_DIGEST_CHARS);
 	/* check sizes */
 	if (tmpe.swap_file_sz == 0) {
 	    tmpe.swap_file_sz = sb.st_size;
@@ -1014,7 +1014,7 @@
     s.swap_file_sz = e->swap_file_sz;
     s.refcount = e->refcount;
     s.flags = e->flags;
-    xmemcpy(&s.key, e->hash.key, MD5_DIGEST_CHARS);
+    xmemcpy(&s.key, e->key, MD5_DIGEST_CHARS);
     xmemcpy(state->outbuf + state->outbuf_offset, &s, ss);
     state->outbuf_offset += ss;
     /* buffered write */
@@ -1111,7 +1111,7 @@
     s->swap_file_sz = e->swap_file_sz;
     s->refcount = e->refcount;
     s->flags = e->flags;
-    xmemcpy(s->key, e->hash.key, MD5_DIGEST_CHARS);
+    xmemcpy(s->key, e->key, MD5_DIGEST_CHARS);
     file_write(ufsinfo->swaplog_fd,
 	-1,
 	s,
Index: squid/src/repl/heap/store_heap_replacement.c
diff -u squid/src/repl/heap/store_heap_replacement.c:1.6 squid/src/repl/heap/store_heap_replacement.c:1.5.2.2
--- squid/src/repl/heap/store_heap_replacement.c:1.6	Wed Feb  7 11:11:50 2001
+++ squid/src/repl/heap/store_heap_replacement.c	Sun Mar 11 13:37:29 2001
@@ -79,7 +79,7 @@
 	tie = 1.0 - exp((double) (e->lastref - squid_curtime) / 86400.0);
     key = age + (double) e->refcount - tie;
     debug(81, 3) ("HeapKeyGen_StoreEntry_LFUDA: %s refcnt=%ld lastref=%ld age=%f tie=%f -> %f\n",
-	storeKeyText(e->hash.key), e->refcount, e->lastref, age, tie, key);
+	storeKeyText(e->key), e->refcount, e->lastref, age, tie, key);
     if (e->mem_obj && e->mem_obj->url)
 	debug(81, 3) ("HeapKeyGen_StoreEntry_LFUDA: url=%s\n",
 	    e->mem_obj->url);
@@ -115,7 +115,7 @@
     double tie = (e->lastref > 1) ? (1.0 / e->lastref) : 1.0;
     key = age + ((double) e->refcount / size) - tie;
     debug(81, 3) ("HeapKeyGen_StoreEntry_GDSF: %s size=%f refcnt=%ld lastref=%ld age=%f tie=%f -> %f\n",
-	storeKeyText(e->hash.key), size, e->refcount, e->lastref, age, tie, key);
+	storeKeyText(e->key), size, e->refcount, e->lastref, age, tie, key);
     if (e->mem_obj && e->mem_obj->url)
 	debug(81, 3) ("HeapKeyGen_StoreEntry_GDSF: url=%s\n",
 	    e->mem_obj->url);
@@ -134,7 +134,7 @@
 {
     StoreEntry *e = entry;
     debug(81, 3) ("HeapKeyGen_StoreEntry_LRU: %s age=%f lastref=%f\n",
-	storeKeyText(e->hash.key), age, (double) e->lastref);
+	storeKeyText(e->key), age, (double) e->lastref);
     if (e->mem_obj && e->mem_obj->url)
 	debug(81, 3) ("HeapKeyGen_StoreEntry_LRU: url=%s\n",
 	    e->mem_obj->url);
Index: squid/src/repl/heap/store_repl_heap.c
diff -u squid/src/repl/heap/store_repl_heap.c:1.8 squid/src/repl/heap/store_repl_heap.c:1.5.2.3
--- squid/src/repl/heap/store_repl_heap.c:1.8	Fri Mar 16 09:22:14 2001
+++ squid/src/repl/heap/store_repl_heap.c	Fri Apr 13 13:55:54 2001
@@ -48,42 +48,17 @@
     heap_key_func *keyfunc;
     int count;
     int nwalkers;
-    enum heap_entry_type {
-	TYPE_UNKNOWN = 0, TYPE_STORE_ENTRY, TYPE_STORE_MEM
-    } type;
 };
 
-/* Hack to avoid having to remember the RemovalPolicyNode location.
- * Needed by the purge walker.
- */
-static enum heap_entry_type
-heap_guessType(StoreEntry * entry, RemovalPolicyNode * node)
-{
-    if (node == &entry->repl)
-	return TYPE_STORE_ENTRY;
-    if (entry->mem_obj && node == &entry->mem_obj->repl)
-	return TYPE_STORE_MEM;
-    fatal("Heap Replacement: Unknown StoreEntry node type");
-    return TYPE_UNKNOWN;
-}
-#define SET_POLICY_NODE(entry,value) \
-    switch(heap->type) { \
-    case TYPE_STORE_ENTRY: entry->repl.data = value; break ; \
-    case TYPE_STORE_MEM: entry->mem_obj->repl.data = value ; break ; \
-    default: break; \
-    }
-
 static void
 heap_add(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
 {
     HeapPolicyData *heap = policy->_data;
-    assert(!node->data);
+    assert(!node->heap.data);
     if (EBIT_TEST(entry->flags, ENTRY_SPECIAL))
 	return;			/* We won't manage these.. they messes things up */
-    node->data = heap_insert(heap->heap, entry);
+    heap_insert(heap->heap, &node->heap, entry);
     heap->count += 1;
-    if (!heap->type)
-	heap->type = heap_guessType(entry, node);
     /* Add a little more variance to the aging factor */
     heap->heap->age += heap->heap->age / 100000000;
 }
@@ -93,11 +68,11 @@
     RemovalPolicyNode * node)
 {
     HeapPolicyData *heap = policy->_data;
-    heap_node *hnode = node->data;
-    if (!hnode)
+    heap_node *hnode = &node->heap;
+    if (!hnode->data)
 	return;
     heap_delete(heap->heap, hnode);
-    node->data = NULL;
+    hnode->data = NULL;
     heap->count -= 1;
 }
 
@@ -106,7 +81,7 @@
     RemovalPolicyNode * node)
 {
     HeapPolicyData *heap = policy->_data;
-    heap_node *hnode = node->data;
+    heap_node *hnode = &node->heap;
     if (!hnode)
 	return;
     heap_update(heap->heap, hnode, (StoreEntry *) entry);
@@ -176,18 +151,19 @@
     RemovalPolicy *policy = walker->_policy;
     HeapPolicyData *heap = policy->_data;
     StoreEntry *entry;
+    heap_node *node;
     heap_key age;
   try_again:
     if (!heap_nodes(heap->heap) > 0)
 	return NULL;		/* done */
     age = heap_peepminkey(heap->heap);
-    entry = heap_extractmin(heap->heap);
+    node = heap_extractmin_node(heap->heap);
+    entry = node->data;
     if (storeEntryLocked(entry)) {
-	linklistPush(&heap_walker->locked_entries, entry);
+	linklistPush(&heap_walker->locked_entries, node);
 	goto try_again;
     }
     heap_walker->min_age = age;
-    SET_POLICY_NODE(entry, NULL);
     return entry;
 }
 
@@ -197,7 +173,7 @@
     HeapPurgeData *heap_walker = walker->_data;
     RemovalPolicy *policy = walker->_policy;
     HeapPolicyData *heap = policy->_data;
-    StoreEntry *entry;
+    heap_node *node;
     assert(strcmp(policy->_type, "heap") == 0);
     assert(heap->nwalkers > 0);
     heap->nwalkers -= 1;
@@ -209,9 +185,8 @@
     /*
      * Reinsert the locked entries
      */
-    while ((entry = linklistShift(&heap_walker->locked_entries))) {
-	heap_node *node = heap_insert(heap->heap, entry);
-	SET_POLICY_NODE(entry, node);
+    while ((node = linklistShift(&heap_walker->locked_entries))) {
+	heap_insert(heap->heap, node->data, node);
     }
     safe_free(walker->_data);
     cbdataFree(walker);
Index: squid/src/repl/lru/store_repl_lru.c
diff -u squid/src/repl/lru/store_repl_lru.c:1.7 squid/src/repl/lru/store_repl_lru.c:1.5.2.3
--- squid/src/repl/lru/store_repl_lru.c:1.7	Sat Mar  3 02:44:34 2001
+++ squid/src/repl/lru/store_repl_lru.c	Sun Mar 11 13:37:29 2001
@@ -43,73 +43,31 @@
     dlink_list list;
     int count;
     int nwalkers;
-    enum heap_entry_type {
-	TYPE_UNKNOWN = 0, TYPE_STORE_ENTRY, TYPE_STORE_MEM
-    } type;
 };
 
-/* Hack to avoid having to remember the RemovalPolicyNode location.
- * Needed by the purge walker to clear the policy information
- */
-static enum heap_entry_type
-repl_guessType(StoreEntry * entry, RemovalPolicyNode * node)
-{
-    if (node == &entry->repl)
-	return TYPE_STORE_ENTRY;
-    if (entry->mem_obj && node == &entry->mem_obj->repl)
-	return TYPE_STORE_MEM;
-    fatal("Heap Replacement: Unknown StoreEntry node type");
-    return TYPE_UNKNOWN;
-}
-#define SET_POLICY_NODE(entry,value) \
-    switch(lru->type) { \
-    case TYPE_STORE_ENTRY: entry->repl.data = value; break ; \
-    case TYPE_STORE_MEM: entry->mem_obj->repl.data = value ; break ; \
-    default: break; \
-    }
-
-typedef struct _LruNode LruNode;
-struct _LruNode {
-    /* Note: the dlink_node MUST be the first member of the LruNode
-     * structure. This member is later pointer typecasted to LruNode *.
-     */
-    dlink_node node;
-};
-
-static MemPool *lru_node_pool = NULL;
 static int nr_lru_policies = 0;
 
 static void
 lru_add(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
 {
     LruPolicyData *lru = policy->_data;
-    LruNode *lru_node;
-    assert(!node->data);
-    node->data = lru_node = memPoolAlloc(lru_node_pool);
-    dlinkAddTail(entry, &lru_node->node, &lru->list);
+    dlinkAddTail(entry, &node->dlink, &lru->list);
     lru->count += 1;
-    if (!lru->type)
-	lru->type = repl_guessType(entry, node);
 }
 
 static void
 lru_remove(RemovalPolicy * policy, StoreEntry * entry, RemovalPolicyNode * node)
 {
     LruPolicyData *lru = policy->_data;
-    LruNode *lru_node = node->data;
-    if (!lru_node)
-	return;
     /*
      * It seems to be possible for an entry to exist in the hash
      * but not be in the LRU list, so check for that case rather
      * than suffer a NULL pointer access.
      */
-    if (NULL == lru_node->node.data)
+    if (NULL == node->dlink.data)
 	return;
-    assert(lru_node->node.data == entry);
-    node->data = NULL;
-    dlinkDelete(&lru_node->node, &lru->list);
-    memPoolFree(lru_node_pool, lru_node);
+    dlinkDelete(&node->dlink, &lru->list);
+    node->dlink.data = NULL;
     lru->count -= 1;
 }
 
@@ -118,29 +76,27 @@
     RemovalPolicyNode * node)
 {
     LruPolicyData *lru = policy->_data;
-    LruNode *lru_node = node->data;
-    if (!lru_node)
-	return;
-    dlinkDelete(&lru_node->node, &lru->list);
-    dlinkAddTail((void *) entry, &lru_node->node, &lru->list);
+    if (node->dlink.data)
+	dlinkDelete(&node->dlink, &lru->list);
+    dlinkAddTail((void *) entry, &node->dlink, &lru->list);
 }
 
 /** RemovalPolicyWalker **/
 
 typedef struct _LruWalkData LruWalkData;
 struct _LruWalkData {
-    LruNode *current;
+    dlink_node *current;
 };
 
 static const StoreEntry *
 lru_walkNext(RemovalPolicyWalker * walker)
 {
     LruWalkData *lru_walk = walker->_data;
-    LruNode *lru_node = lru_walk->current;
-    if (!lru_node)
+    dlink_node *node = lru_walk->current;
+    if (!node)
 	return NULL;
-    lru_walk->current = (LruNode *) lru_node->node.next;
-    return (StoreEntry *) lru_node->node.data;
+    lru_walk->current = node->next;
+    return (StoreEntry *) node->data;
 }
 
 static void
@@ -168,7 +124,7 @@
     walker->_data = lru_walk;
     walker->Next = lru_walkNext;
     walker->Done = lru_walkDone;
-    lru_walk->current = (LruNode *) lru->list.head;
+    lru_walk->current = lru->list.head;
     return walker;
 }
 
@@ -176,8 +132,8 @@
 
 typedef struct _LruPurgeData LruPurgeData;
 struct _LruPurgeData {
-    LruNode *current;
-    LruNode *start;
+    dlink_node *current;
+    dlink_node *start;
 };
 
 static StoreEntry *
@@ -186,29 +142,28 @@
     LruPurgeData *lru_walker = walker->_data;
     RemovalPolicy *policy = walker->_policy;
     LruPolicyData *lru = policy->_data;
-    LruNode *lru_node;
+    dlink_node *node;
     StoreEntry *entry;
   try_again:
-    lru_node = lru_walker->current;
-    if (!lru_node || walker->scanned >= walker->max_scan)
+    node = lru_walker->current;
+    if (!node || walker->scanned >= walker->max_scan)
 	return NULL;
     walker->scanned += 1;
-    lru_walker->current = (LruNode *) lru_node->node.next;
+    lru_walker->current = node->next;
     if (lru_walker->current == lru_walker->start) {
 	/* Last node found */
 	lru_walker->current = NULL;
     }
-    entry = (StoreEntry *) lru_node->node.data;
-    dlinkDelete(&lru_node->node, &lru->list);
+    entry = (StoreEntry *) node->data;
+    dlinkDelete(node, &lru->list);
+    node->data = NULL;
     if (storeEntryLocked(entry)) {
 	/* Shit, it is locked. we can't return this one */
 	walker->locked++;
-	dlinkAddTail(entry, &lru_node->node, &lru->list);
+	dlinkAddTail(entry, node, &lru->list);
 	goto try_again;
     }
-    memPoolFree(lru_node_pool, lru_node);
     lru->count -= 1;
-    SET_POLICY_NODE(entry, NULL);
     return entry;
 }
 
@@ -238,7 +193,7 @@
     walker->max_scan = max_scan;
     walker->Next = lru_purgeNext;
     walker->Done = lru_purgeDone;
-    lru_walk->start = lru_walk->current = (LruNode *) lru->list.head;
+    lru_walk->start = lru_walk->current = lru->list.head;
     return walker;
 }
 
@@ -263,9 +218,6 @@
     LruPolicyData *lru_data;
     /* no arguments expected or understood */
     assert(!args);
-    /* Initialize */
-    if (!lru_node_pool)
-	lru_node_pool = memPoolCreate("LRU policy node", sizeof(LruNode));
     /* Allocate the needed structures */
     lru_data = xcalloc(1, sizeof(*lru_data));
     policy = cbdataAlloc(RemovalPolicy);