--------------------- PatchSet 821 Date: 2000/11/10 18:44:50 Author: hno Branch: bugless-2_2 Tag: (none) Log: Imported a long lost megapatch from Stephen R. van den Berg (AKA BuGless). What it does: What it does: - Uses a partially memory mapped store metadata. - Because of this, it allows instant restarts after a crash or termination of squid. - It allows immediate proxying operation without having problems with stale URLs pointing to the wrong (newer) swapfile. - Instant termination without needing to write out the swaplog metadata. - Memory pools that never shrink. - Memory pools that reuse other pools with the same object size. - Vastly reduced overall memory footprint. - Integrates the recent HPL_REPL heap replacement strategies (a few bugs fixed and optimised relative to the posted version). - More aggressive and fair loadbalancing across several spindles (especially important when adding an empty drive to several other full drives). - Perform swap-in consistency checks to avoid handing out the wrong cached file in *any* case (not that it catches anything currently, but it helps prevent disasters while hacking :-). - Support for the cuciwhirl redirector (i.e. terminate redirect URLs with double newlines to improve speed). - Some minor bugfixes here and there. - I browsed through Henrik's patch section, and included these: squid-2.2.STABLE2.to_large_objects-2.patch squid-2.2.STABLE3.CONNECT_hierarchy_tag_and_memory_leak.patch squid-2.2.STABLE3.FD_SETSIZE_poll.patch squid-2.2.STABLE3.ftp_abort_assert.patch squid-2.2.STABLE3.persistent_connection_timeout.patch - All published memory leak patches. - Some other semi-fatal patches from Duane's page. - Even more graceful shutdown code. - Support for javascript-closeme.html redirector support. - The cuciwhirl v1.6 includes samples for the tiny.gif and closeme.html files. - Cuciwhirl 1.6 includes support to auto-close popupwindows. Note, for people wanting to try this out: * The content of the swap is compatible. * The content of the swaplog files is *not* compatible (the format can be converted from and to the old by the provided conv.c file). * I.e. without prior conversion, the swaplogfile needs to be emptied first. * The redirector code as supplied here differs from the standard 2.2S3 format in two ways: - Every line sent to the redirector is terminated with a double newline (this allows for speedier parsing). - The order of the arguments has been rearranged (in order to speed up the decision process). Due to the special memory allocation handling (which, in the end, conserves memory), the patch requires memory pools to be turned on without limits. Why not modify the patch such that it gracefully handles the no-memory-pools option, you might ask? Well, because the notion here is that if the patch gets adopted, one would probably completely throw out the code that made memory pools optional. Due to time constraints I have not had the time to backcheck what happens if the MMAPSTORE, NEVERFREE and HPL_REPL macros are turned off. I tried to make things backward compatible, but didn't explicitly verify its sanity. So if you encounter problems compiling the source with those macros turned off, don't be surprised. If someone has time to sanitise the patch to get it into mainstream squid, be my guest. Members: makefile.in:1.1.1.2->1.1.1.2.12.1 icons/Makefile.in:1.1.1.2->1.1.1.2.12.1 include/hash.h:1.1.1.1->1.1.1.1.38.1 include/heap.h:1.3->1.3.6.1 lib/Makefile.in:1.1.1.1->1.1.1.1.10.1 lib/hash.c:1.1.1.2->1.1.1.2.12.1 lib/heap.c:1.3->1.3.6.1 src/HttpHdrRange.c:1.1.1.2->1.1.1.2.12.1 src/MemPool.c:1.1.1.2->1.1.1.2.12.1 src/aiops.c:1.1.1.2->1.1.1.2.10.1 src/asn.c:1.1.1.2->1.1.1.2.10.1 src/async_io.c:1.1.1.2->1.1.1.2.10.1 src/cache_cf.c:1.1.1.2->1.1.1.2.10.1 src/cache_manager.c:1.1.1.2->1.1.1.2.28.1 src/cachemgr.c:1.1.1.2->1.1.1.2.12.1 src/cf.data.pre:1.1.1.2->1.1.1.2.10.1 src/client_side.c:1.1.1.2->1.1.1.2.10.1 src/comm.c:1.1.1.2->1.1.1.2.10.1 src/defines.h:1.1.1.2->1.1.1.2.10.1 src/disk.c:1.1.1.2->1.1.1.2.10.1 src/enums.h:1.1.1.2->1.1.1.2.10.1 src/errorpage.c:1.1.1.2->1.1.1.2.10.1 src/filemap.c:1.1.1.1->1.1.1.1.12.1 src/ftp.c:1.1.1.2->1.1.1.2.10.1 src/globals.h:1.1.1.2->1.1.1.2.12.1 src/gopher.c:1.1.1.2->1.1.1.2.10.1 src/helper.c:1.1.1.2->1.1.1.2.10.1 src/http.c:1.1.1.2->1.1.1.2.10.1 src/main.c:1.1.1.2->1.1.1.2.10.1 src/mem.c:1.1.1.2->1.1.1.2.12.1 src/mime.c:1.1.1.2->1.1.1.2.12.1 src/mime.conf:1.1.1.2->1.1.1.2.12.1 src/neighbors.c:1.1.1.2->1.1.1.2.10.1 src/net_db.c:1.1.1.2->1.1.1.2.10.1 src/pconn.c:1.1.1.2->1.1.1.2.28.1 src/peer_digest.c:1.1.1.2->1.1.1.2.10.1 src/peer_select.c:1.1.1.2->1.1.1.2.10.1 src/protos.h:1.1.1.2->1.1.1.2.10.1 src/pump.c:1.1.1.2->1.1.1.2.10.1 src/redirect.c:1.1.1.2->1.1.1.2.10.1 src/refresh.c:1.1.1.2->1.1.1.2.12.1 src/snmp_agent.c:1.1.1.2->1.1.1.2.12.1 src/squid.h:1.1.1.2->1.1.1.2.10.1 src/stat.c:1.1.1.2->1.1.1.2.10.1 src/store.c:1.1.1.2->1.1.1.2.10.1 src/store_client.c:1.1.1.2->1.1.1.2.10.1 src/store_digest.c:1.1.1.2->1.1.1.2.12.1 src/store_dir.c:1.1.1.2->1.1.1.2.10.1 src/store_log.c:1.1.1.1->1.1.1.1.10.1 src/store_rebuild.c:1.1.1.2->1.1.1.2.10.1 src/store_swapin.c:1.1.1.2->1.1.1.2.12.1 src/store_swapmeta.c:1.1.1.1->1.1.1.1.12.1 src/store_swapout.c:1.1.1.2->1.1.1.2.12.1 src/structs.h:1.1.1.2->1.1.1.2.10.1 src/tools.c:1.1.1.2->1.1.1.2.10.1 src/url.c:1.1.1.2->1.1.1.2.10.1 src/urn.c:1.1.1.2->1.1.1.2.10.1 src/wais.c:1.1.1.2->1.1.1.2.28.1 Index: squid/makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/Attic/makefile.in,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.12.1 diff -u -r1.1.1.2 -r1.1.1.2.12.1 --- squid/makefile.in 26 Jan 2000 03:23:09 -0000 1.1.1.2 +++ squid/makefile.in 10 Nov 2000 18:44:50 -0000 1.1.1.2.12.1 @@ -1,4 +1,4 @@ -# $Id: makefile.in,v 1.1.1.2 2000/01/26 03:23:09 hno Exp $ +# $Id: makefile.in,v 1.1.1.2.12.1 2000/11/10 18:44:50 hno Exp $ # srcdir = @srcdir@ @@ -8,6 +8,7 @@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ +CFLAGS = @CFLAGS@ -DHPL_REPL SHELL = /bin/sh # Where to install Index: squid/icons/Makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/icons/Attic/Makefile.in,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.12.1 diff -u -r1.1.1.2 -r1.1.1.2.12.1 --- squid/icons/Makefile.in 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/icons/Makefile.in 10 Nov 2000 18:44:51 -0000 1.1.1.2.12.1 @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ +# $Id: Makefile.in,v 1.1.1.2.12.1 2000/11/10 18:44:51 hno Exp $ # prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -43,7 +43,9 @@ anthony-text.gif \ anthony-unknown.gif \ anthony-xbm.gif \ - anthony-xpm.gif + anthony-xpm.gif \ + closeme.html \ + tiny.gif all: Index: squid/include/hash.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/hash.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.38.1 diff -u -r1.1.1.1 -r1.1.1.1.38.1 --- squid/include/hash.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/include/hash.h 10 Nov 2000 18:44:51 -0000 1.1.1.1.38.1 @@ -1,5 +1,5 @@ /* - * $Id: hash.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: hash.h,v 1.1.1.1.38.1 2000/11/10 18:44:51 hno Exp $ */ typedef void HASHFREE(void *); @@ -24,8 +24,8 @@ }; extern hash_table *hash_create(HASHCMP *, int, HASHHASH *); -extern void hash_join(hash_table *, hash_link *); -extern void hash_remove_link(hash_table *, hash_link *); +extern unsigned hash_join(hash_table *, hash_link *); +extern unsigned hash_remove_link(hash_table *, hash_link *); extern int hashPrime(int n); extern void *hash_lookup(hash_table *, const void *); extern void hash_first(hash_table *); Index: squid/include/heap.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/heap.h,v retrieving revision 1.3 retrieving revision 1.3.6.1 diff -u -r1.3 -r1.3.6.1 --- squid/include/heap.h 23 Oct 2000 15:04:18 -0000 1.3 +++ squid/include/heap.h 10 Nov 2000 18:44:51 -0000 1.3.6.1 @@ -1,35 +1,4 @@ -/* - * $Id: heap.h,v 1.3 2000/10/23 15:04:18 hno Exp $ - * - * AUTHOR: John Dilley, Hewlett Packard - * - * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ - * -------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from the - * Internet community. Development is led by Duane Wessels of the - * National Laboratory for Applied Network Research and funded by - * the National Science Foundation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - /**************************************************************************** - * Copyright (C) 1999 by Hewlett Packard - * * Heap data structure. Used to store objects for cache replacement. The * heap is implemented as a contiguous array in memory. Heap sort and heap * update are done in-place. The heap is ordered with the smallest value at @@ -40,16 +9,26 @@ #ifndef _heap_h_INCLUDED #define _heap_h_INCLUDED +/* + * Typdefs for non-synchronized heap implementation. + */ +typedef unsigned long mutex_t; +# define mutex_lock(m) (void)0 +# define mutex_unlock(m) (void)0 +# define mutex_trylock(m) (void)0 +# define mutex_init(m) ((m)=123456) + /* * Function for generating heap keys. The first argument will typically be * a dws_md_p passed in as a void *. Should find a way to get type safety * without having heap know all about metadata objects... The second arg is * the current aging factor for the heap. */ -typedef unsigned long heap_mutex_t; -typedef void *heap_t; -typedef double heap_key; -typedef heap_key heap_key_func(heap_t, heap_key); +# define _HEAPTYPE void * +# define _HEAPKEY double +# define _HEAPKEYSTORED float /* no need to store doubles */ + +typedef _HEAPKEY (*key_func) (_HEAPTYPE, _HEAPKEY); /* @@ -58,10 +37,9 @@ * key_func can generate a key from. */ typedef struct _heap_node { - heap_key key; - unsigned long id; - heap_t data; -} heap_node; + _HEAPKEYSTORED key; + long id; +} heap_node, *heap_node_p; /* @@ -70,28 +48,32 @@ * function. Also stores aging factor for this heap. */ typedef struct _heap { - heap_mutex_t lock; - unsigned long size; - unsigned long last; - heap_key_func *gen_key; /* key generator for heap */ - heap_key age; /* aging factor for heap */ - heap_node **nodes; -} heap; + mutex_t lock; + unsigned long size; + unsigned long last; + size_t nodeoffset; /* offset from start of data to node struct */ + key_func gen_key; /* key generator for heap */ + _HEAPKEY age; /* aging factor for heap */ + heap_node ** nodes; +} heap, *heap_p; /**************************************************************************** * Public functions ****************************************************************************/ +#define heap_DATA(hp,elm) ((_HEAPTYPE)((char*)(elm)-(hp)->nodeoffset)) +#define heap_ELM(hp,data) ((heap_node_p)((char*)(data)+(hp)->nodeoffset)) + /* * Create and initialize a new heap. */ -extern heap *new_heap(int init_size, heap_key_func gen_key); +extern heap_p new_heap(int init_size, key_func gen_key, size_t nodeoffset); /* * Delete a heap and clean up its memory. Does not delete what the heap * nodes are pointing to! */ -extern void delete_heap(heap *); +extern void delete_heap(heap_p); /* * Insert a new node into a heap, returning a pointer to it. The heap_node @@ -99,13 +81,13 @@ * 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_p heap_insert(heap_p, _HEAPTYPE dat); /* * Delete a node out of a heap. Returns the heap data from the deleted * node. The caller is responsible for freeing this data. */ -extern heap_t heap_delete(heap *, heap_node * elm); +extern _HEAPTYPE heap_delete(heap_p, heap_node_p elm); /* * The semantics of this routine is the same as the followings: @@ -114,16 +96,16 @@ * Returns the old data object from elm (the one being replaced). The * caller must free this as necessary. */ -extern heap_t heap_update(heap *, heap_node * elm, heap_t dat); +extern void heap_update(heap_p, heap_node* elm); /* * Generate a heap key for a given data object. Alternative macro form: */ #ifdef MACRO_DEBUG -extern heap_key heap_gen_key(heap * hp, heap_t dat); +extern _HEAPKEY heap_gen_key(heap_p hp, _HEAPTYPE dat); #else -#define heap_gen_key(hp,md) ((hp)->gen_key((md),(hp)->age)) -#endif /* MACRO_DEBUG */ +# define heap_gen_key(hp,md) ((hp)->gen_key((md),(hp)->age)) +#endif /* MACRO_DEBUG */ /* @@ -131,7 +113,7 @@ * Returns the data pointed to by the root node, which the caller must * free as necessary. */ -extern heap_t heap_extractmin(heap *); +extern _HEAPTYPE heap_extractmin(heap_p); /* * Extract the last leaf node (does not change the heap property). @@ -140,35 +122,35 @@ * parent, but may not be less than any of the other (leaf or parent) notes * in the tree. This operation is fast but imprecise. */ -extern heap_t heap_extractlast(heap * hp); +extern _HEAPTYPE heap_extractlast(heap_p hp); /* * Get the root key, the nth key, the root (smallest) element, or the nth * element. None of these operations modify the heap. */ -extern heap_key heap_peepminkey(heap *); -extern heap_key heap_peepkey(heap *, int n); +extern _HEAPKEY heap_peepminkey(heap_p); +extern _HEAPKEY heap_peepkey(heap_p, int n); -extern heap_t heap_peepmin(heap *); -extern heap_t heap_peep(heap *, int n); +extern _HEAPTYPE heap_peepmin(heap_p); +extern _HEAPTYPE heap_peep(heap_p, int n); /* * Is the heap empty? How many nodes (data objects) are in it? */ #ifdef MACRO_DEBUG -extern int heap_empty(heap *); -extern int heap_nodes(heap *); -#else /* MACRO_DEBUG */ -#define heap_nodes(heap) ((heap)->last) -#define heap_empty(heap) (((heap)->last <= 0) ? 1 : 0) -#endif /* MACRO_DEBUG */ +extern int heap_empty(heap_p); +extern int heap_nodes(heap_p); +#else /* MACRO_DEBUG */ +# define heap_nodes(heap) ((heap)->last) +# define heap_empty(heap) (((heap)->last <= 0) ? 1 : 0) +#endif /* MACRO_DEBUG */ /* * Print the heap or a node in the heap. */ -extern void heap_print(heap *); -extern void heap_printnode(char *msg, heap_node * elm); +extern void heap_print(heap_p); +extern void heap_printnode(char *msg, heap_node_p elm); -extern int verify_heap_property(heap *); +extern int verify_heap_property(heap_p); -#endif /* _heap_h_INCLUDED */ +#endif /* _heap_h_INCLUDED */ Index: squid/lib/Makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/Attic/Makefile.in,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.10.1 diff -u -r1.1.1.1 -r1.1.1.1.10.1 --- squid/lib/Makefile.in 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/lib/Makefile.in 10 Nov 2000 18:44:51 -0000 1.1.1.1.10.1 @@ -1,5 +1,5 @@ # -# $Id: Makefile.in,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ +# $Id: Makefile.in,v 1.1.1.1.10.1 2000/11/10 18:44:51 hno Exp $ # prefix = @prefix@ top_srcdir = @top_srcdir@ @@ -37,6 +37,7 @@ Array.o \ Stack.o \ hash.o \ + heap.o \ $(LIBOBJS) REGEXOBJS = GNUregex.o DLMALLOCOBJS = dlmalloc.o Index: squid/lib/hash.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/hash.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.12.1 diff -u -r1.1.1.2 -r1.1.1.2.12.1 --- squid/lib/hash.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/lib/hash.c 10 Nov 2000 18:44:51 -0000 1.1.1.2.12.1 @@ -1,6 +1,6 @@ /* - * $Id: hash.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ + * $Id: hash.c,v 1.1.1.2.12.1 2000/11/10 18:44:51 hno Exp $ * * DEBUG: section 0 Hash Tables * AUTHOR: Harvest Derived @@ -163,14 +163,23 @@ * * It does not copy any data into the hash table, only links pointers. */ -void +unsigned hash_join(hash_table * hid, hash_link * lnk) { int i; i = hid->hash(lnk->key, hid->size); +#if 1 + { /* srb */ + hash_link * ol; + for (ol = hid->buckets[i]; ol; ol = ol->next) + if (ol == lnk) + return 1; + } +#endif lnk->next = hid->buckets[i]; hid->buckets[i] = lnk; hid->count++; + return 0; } /* @@ -252,7 +261,7 @@ * On success, it returns 0 and deletes the link; otherwise, * returns non-zero on error. */ -void +unsigned hash_remove_link(hash_table * hid, hash_link * hl) { hash_link **P; @@ -269,9 +278,12 @@ hash_next_bucket(hid); } hid->count--; - return; + return 0; } +#if 0 /* srb */ assert(0); +#endif + return 1; } /* Index: squid/lib/heap.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/heap.c,v retrieving revision 1.3 retrieving revision 1.3.6.1 diff -u -r1.3 -r1.3.6.1 --- squid/lib/heap.c 23 Oct 2000 15:04:19 -0000 1.3 +++ squid/lib/heap.c 10 Nov 2000 18:44:51 -0000 1.3.6.1 @@ -1,85 +1,33 @@ - -/* - * $Id: heap.c,v 1.3 2000/10/23 15:04:19 hno Exp $ - * - * AUTHOR: John Dilley, Hewlett Packard - * - * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from the - * Internet community. Development is led by Duane Wessels of the - * National Laboratory for Applied Network Research and funded by the - * National Science Foundation. Squid is Copyrighted (C) 1998 by - * the Regents of the University of California. Please see the - * COPYRIGHT file for full details. Squid incorporates software - * developed and/or copyrighted by other sources. Please see the - * CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - +#define HPL_REPL 1 /**************************************************************************** * Heap implementation - * Copyright (C) 1999 by Hewlett Packard ****************************************************************************/ -#include "config.h" - -#if HAVE_STDLIB_H #include -#endif -#if HAVE_ASSERT_H +#include "malloc.h" #include -#endif -#if HAVE_STRING_H #include -#endif -#if HAVE_STDIO_H #include -#endif #include "heap.h" -#include "util.h" - -/* - * Hacks for non-synchronized heap implementation. - */ -#define mutex_lock(m) (void)0 -#define mutex_unlock(m) (void)0 -#define mutex_trylock(m) (void)0 -#define mutex_init(m) ((m)=123456) /* * Private function prototypes. */ -static void _heap_ify_up(heap * hp, heap_node * elm); -static void _heap_ify_down(heap * hp, heap_node * elm); -static int _heap_should_grow(heap * hp); -static void _heap_grow(heap * hp); -static void _heap_swap_element(heap * hp, heap_node * elm1, heap_node * elm2); -static int _heap_node_exist(heap * hp, int id); +static void _heap_ify_up(heap_p hp, heap_node_p elm); +static void _heap_ify_down(heap_p hp, heap_node_p elm); +static int _heap_should_grow(heap_p hp); +static void _heap_grow(heap_p hp); +static void _heap_swap_element(heap_p hp, heap_node_p elm1, heap_node_p elm2); +static unsigned _heap_node_exist(heap_p hp, int id); #ifdef HEAP_DEBUG -void _heap_print_tree(heap * hp, heap_node * node); -#endif /* HEAP_DEBUG */ +void _heap_print_tree(heap_p hp, heap_node_p node); +#endif /* HEAP_DEBUG */ -#define Left(x) (2 * (x) + 1) -#define Right(x) (2 * (x) + 2) -#define Parent(x) ((int)((x)-1)/2) +#define Left(x) (2 * (size_t)(x) + 1) +#define Right(x) (2 * (size_t)(x) + 2) +#define Parent(x) (((size_t)(x)-1)/2) #define Threshold 10000 #define NormalRate 2 @@ -93,23 +41,25 @@ /* * Return a newly created heap. INITSIZE is the initial size of the heap. */ -heap * -new_heap(int initSize, heap_key_func gen_key) +heap_p +new_heap(int initSize, key_func gen_key, size_t nodeoffset) { - heap *hp = xmalloc(sizeof(*hp)); - assert(hp != NULL); + heap_p hp = (heap_p) malloc(sizeof(heap)); + assert(hp != NULL); - if (initSize <= 0) - initSize = MinSize; - hp->nodes = xcalloc(initSize, sizeof(heap_node *)); - assert(hp->nodes != NULL); - - hp->size = initSize; - hp->last = 0; - hp->gen_key = gen_key; - hp->age = 0; + if (initSize <= 0) + initSize = MinSize; - return hp; + hp->nodes = (heap_node_p *)calloc(initSize, sizeof(heap_node_p)); + assert(hp->nodes != NULL); + + hp->size = initSize; + hp->last = 0; + hp->gen_key = gen_key; + hp->nodeoffset = nodeoffset; + hp->age = 0; + + return hp; } @@ -118,77 +68,103 @@ * heap nodes, only the heap's internal memory. */ void -delete_heap(heap * hp) +delete_heap(heap_p hp) { - int i; - assert(hp); - for (i = 0; i < hp->last; i++) { - xfree(hp->nodes[i]); - } - xfree(hp->nodes); - xfree(hp); + int i; + assert(hp); + free(hp->nodes); + free(hp); +} + +/* + * True if a node with ID exists in HP. + */ +static unsigned +_heap_node_exist(heap_p hp, int id) +{ + if ((id >= hp->last) || (id < 0) || (hp->nodes[(size_t)id] == NULL) || + hp->nodes[(size_t)id]->id != id) + return 0; + return 1; } /* - * Insert DAT based on KY into HP maintaining the heap property. - * Return the newly inserted heap node. The fields of ELM other - * than ID are never changed until ELM is deleted from HP, i.e. - * caller can assume that the heap node always exist at the same - * place in memory unless heap_delete or heap_extractmin is called - * on that node. This function exposes the heap's internal data - * structure to the caller. This is required in order to do O(lgN) - * deletion. + * Insert DAT based on KY into HP maintaining the heap property. Return the + * newly inserted heap node. The fields of ELM other than ID are never + * changed until ELM is deleted from HP, i.e. caller can assume that the + * heap node always exist at the same place in memory unless heap_delete or + * heap_extractmin is called on that node. This function exposes the heap's + * internal data structure to the caller. This is required in order to do + * O(lgN) deletion. */ -heap_node * -heap_insert(heap * hp, void *dat) +heap_node_p +heap_insert(heap_p hp, void * dat) { - heap_node *elm = xmalloc(sizeof(*elm)); + heap_node* elm = heap_ELM(hp, dat); + + elm->key = heap_gen_key(hp, dat); - elm->key = heap_gen_key(hp, dat); - elm->data = dat; + if (_heap_should_grow(hp)) + _heap_grow(hp); - if (_heap_should_grow(hp)) - _heap_grow(hp); + hp->nodes[(size_t)hp->last] = elm; + elm->id = hp->last++; - hp->nodes[hp->last] = elm; - elm->id = hp->last; - hp->last += 1; + _heap_ify_up(hp, elm); - _heap_ify_up(hp, elm); + /* + * Set the pointer in the metadata to point to this heap node. + */ + #ifdef HPL_REPL + /* The following must be done immediately upon return! */ + #else /* HPL_REPL */ + md_set_node(dat, elm); + #endif /* HPL_REPL */ - return elm; + return elm; } +static +void _heap_order(heap_p hp, heap_node_p elm) +{ + if (elm->id > 0 && + elm->key < hp->nodes[Parent(elm->id)]->key) + _heap_ify_up(hp, elm); /* COOL! */ + _heap_ify_down(hp, elm); +} /* * Delete ELM while maintaining the heap property. ELM may be modified. * Assumes that ELM is not NULL and frees it. Returns the data pointed to * in, which the caller must free if necessary. */ -heap_t -heap_delete(heap * hp, heap_node * elm) +_HEAPTYPE +heap_delete(heap_p hp, heap_node_p elm) { - heap_node *lastNode; - heap_t data = elm->data; + heap_node_p lastNode; + _HEAPTYPE data = heap_DATA(hp, elm); - assert(_heap_node_exist(hp, hp->last - 1)); + assert(_heap_node_exist(hp, hp->last-1)); - lastNode = hp->nodes[hp->last - 1]; - _heap_swap_element(hp, lastNode, elm); - heap_extractlast(hp); - - if (elm == lastNode) { - /* - * lastNode just got freed, so don't access it in the next - * block. - */ - (void) 0; - } else if (hp->last > 0) { - if (lastNode->key < hp->nodes[Parent(lastNode->id)]->key) - _heap_ify_up(hp, lastNode); /* COOL! */ - _heap_ify_down(hp, lastNode); - } - return data; + if (elm->id != --hp->last) { + lastNode = hp->nodes[(size_t)hp->last]; + hp->nodes[(size_t)elm->id] = lastNode; + lastNode->id = elm->id; + + _heap_order(hp, lastNode); + } + + /* + * Remove the pointer back to the heap from the metadata. + * Then free the element that was just deleted. + */ + #ifdef HPL_REPL + /* The following must be done immediately upon return! */ + #else /* HPL_REPL */ + md_set_node(data, NULL); + #endif /* HPL_REPL */ + + return data; } /* @@ -200,34 +176,25 @@ /* * Function to generate keys. See macro definition in heap.h. */ -heap_key -heap_gen_key(heap * hp, heap_t dat) +_HEAPKEY +heap_gen_key(heap_p hp, _HEAPTYPE dat) { - return hp->gen_key(dat, hp->age); + return hp->gen_key(dat, hp->age); } -#endif /* heap_gen_key */ +#endif /* heap_gen_key */ /* * Returns the data of the node with the largest KEY value and removes that * node from the heap. Returns NULL if the heap was empty. */ -heap_t -heap_extractmin(heap * hp) +_HEAPTYPE +heap_extractmin(heap_p hp) { - heap_t data; - - if (hp->last <= 0) - return NULL; - - mutex_lock(hp->lock); - - data = hp->nodes[0]->data; - heap_delete(hp, hp->nodes[0]); /* Delete the root */ + if (hp->last <= 0) + return NULL; - mutex_unlock(hp->lock); - - return data; + return heap_delete(hp, hp->nodes[0]); /* Delete the root */ } @@ -235,15 +202,13 @@ * Remove the last node in HP. Frees the heap internal structure and * returns the data pointes to by the last node. */ -heap_t -heap_extractlast(heap * hp) +_HEAPTYPE +heap_extractlast(heap_p hp) { - heap_t data; - assert(_heap_node_exist(hp, hp->last - 1)); - hp->last -= 1; - data = hp->nodes[hp->last]->data; - xfree(hp->nodes[hp->last]); - return data; + _HEAPTYPE data; + assert (_heap_node_exist(hp, hp->last-1)); + data = heap_DATA(hp, hp->nodes[(size_t)--hp->last]); + return data; } @@ -254,42 +219,38 @@ * Returns the old data object from elm (the one being replaced). The * caller must free this as necessary. */ -heap_t -heap_update(heap * hp, heap_node * elm, void *dat) +void +heap_update(heap_p hp, heap_node* elm) { - heap_t old = elm->data; - heap_key ky = heap_gen_key(hp, dat); + _HEAPTYPE dat = heap_DATA(hp, elm); + _HEAPKEY ky = heap_gen_key(hp, dat); + assert (_heap_node_exist(hp, elm->id)); - elm->key = ky; - elm->data = dat; + elm->key = ky; - if (elm->key < hp->nodes[Parent(elm->id)]->key) - _heap_ify_up(hp, elm); - _heap_ify_down(hp, elm); - - return old; + _heap_order(hp, elm); } /* * A pointer to the root node's DATA. */ -void * -heap_peepmin(heap * hp) +void* +heap_peepmin(heap_p hp) { - assert(_heap_node_exist(hp, 0)); - return hp->nodes[0]->data; + assert(_heap_node_exist(hp, 0)); + return heap_DATA(hp, hp->nodes[0]); } /* * The KEY of the root node. */ -heap_key -heap_peepminkey(heap * hp) +_HEAPKEY +heap_peepminkey(heap_p hp) { - assert(_heap_node_exist(hp, 0)); - return hp->nodes[0]->key; + assert(_heap_node_exist(hp, 0)); + return hp->nodes[0]->key; } @@ -297,11 +258,11 @@ * Same as heap_peep except that this return the KEY of the node. * Only meant for iteration. */ -heap_key -heap_peepkey(heap * hp, int n) +_HEAPKEY +heap_peepkey(heap_p hp, int n) { - assert(_heap_node_exist(hp, n)); - return hp->nodes[n]->key; + assert(_heap_node_exist(hp, n)); + return hp->nodes[(size_t)n]->key; } @@ -311,13 +272,11 @@ * for(i = 0; i < heap_nodes(hp); i++) * data = heap_peep(hp, i); */ -void * -heap_peep(heap * hp, int n) +void* +heap_peep(heap_p hp, int n) { - void *data; - assert(_heap_node_exist(hp, n)); - data = hp->nodes[n]->data; - return data; + assert(_heap_node_exist(hp, n)); + return heap_DATA(hp, hp->nodes[(size_t)n]); } @@ -326,11 +285,11 @@ * Current number of nodes in HP. */ int -heap_nodes(heap * hp) +heap_nodes(heap_p hp) { - return hp->last; + return hp->last; } -#endif /* heap_nodes */ +#endif /* heap_nodes */ #ifndef heap_empty @@ -339,11 +298,11 @@ * otherwise. */ int -heap_empty(heap * hp) +heap_empty(heap_p hp) { - return (hp->last <= 0) ? 1 : 0; + return (hp->last <= 0) ? 1 : 0; } -#endif /* heap_empty */ +#endif /* heap_empty */ /****************** Private Functions *******************/ @@ -352,33 +311,31 @@ * may only be violated at ELM downwards. Assumes caller has locked the heap. */ static void -_heap_ify_down(heap * hp, heap_node * elm) +_heap_ify_down(heap_p hp, heap_node_p elm) { - heap_node *kid; - int left = 0, right = 0; - int true = 1; - while (true) { - left = Left(elm->id); - right = Right(elm->id); - if (!_heap_node_exist(hp, left)) { - /* At the bottom of the heap (no child). */ - - assert(!_heap_node_exist(hp, right)); - break; - } else if (!_heap_node_exist(hp, right)) - /* Only left child exists. */ - - kid = hp->nodes[left]; - else { - if (hp->nodes[right]->key < hp->nodes[left]->key) - kid = hp->nodes[right]; - else - kid = hp->nodes[left]; - } - if (elm->key <= kid->key) - break; - _heap_swap_element(hp, kid, elm); + heap_node* kid; + int left, right; + for(;;) { + assert(_heap_node_exist(hp, elm->id)); + left = Left(elm->id); + right = Right(elm->id); + if (hp->last <= left) // At the bottom of the heap (no child). + break; + else if (hp->last <= right) { // Only left child exists. + assert(_heap_node_exist(hp, left)); + kid = hp->nodes[(size_t)left]; + } else { + assert(_heap_node_exist(hp, left)); + assert(_heap_node_exist(hp, right)); + if (hp->nodes[(size_t)right]->key < hp->nodes[(size_t)left]->key) + kid = hp->nodes[(size_t)right]; + else + kid = hp->nodes[(size_t)left]; } + if (elm->key <= kid->key) + break; + _heap_swap_element(hp, kid, elm); + } } @@ -386,15 +343,18 @@ * Maintain the heap property above ELM. Caller has locked the heap. */ static void -_heap_ify_up(heap * hp, heap_node * elm) +_heap_ify_up(heap_p hp, heap_node_p elm) { - heap_node *parentNode; - while (elm->id > 0) { - parentNode = hp->nodes[Parent(elm->id)]; - if (parentNode->key <= elm->key) - break; - _heap_swap_element(hp, parentNode, elm); /* Demote the parent. */ - } + heap_node_p parentNode; + assert(_heap_node_exist(hp, elm->id)); + while (elm->id > 0) { + assert(_heap_node_exist(hp, elm->id)); + parentNode = hp->nodes[Parent(elm->id)]; + assert(_heap_node_exist(hp, parentNode->id)); + if (parentNode->key <= elm->key) + break; + _heap_swap_element(hp, parentNode, elm); /* Demote the parent. */ + } } @@ -403,13 +363,13 @@ * swapped. */ static void -_heap_swap_element(heap * hp, heap_node * elm1, heap_node * elm2) +_heap_swap_element(heap_p hp, heap_node_p elm1, heap_node_p elm2) { - int elm1Id = elm1->id; - elm1->id = elm2->id; - elm2->id = elm1Id; - hp->nodes[elm1->id] = elm1; - hp->nodes[elm2->id] = elm2; + int elm1Id = elm1->id; + elm1->id = elm2->id; + elm2->id = elm1Id; + hp->nodes[(size_t)elm1->id] = elm1; + hp->nodes[(size_t)elm2->id] = elm2; } @@ -419,24 +379,22 @@ * Copy KEY and DATA fields of SRC to DEST. ID field is NOT copied. */ static void -_heap_copy_element(heap_node * src, heap_node * dest) +_heap_copy_element(heap_node_p src, heap_node_p dest) { - dest->key = src->key; - dest->data = src->data; + dest->key = src->key; } - -#endif /* NOTDEF */ +#endif /* NOTDEF */ /* * True if HP needs to be grown in size. */ static int -_heap_should_grow(heap * hp) +_heap_should_grow(heap_p hp) { - if (hp->size <= hp->last) - return 1; - return 0; + if (hp->size <= hp->last) + return 1; + return 0; } @@ -444,37 +402,25 @@ * Grow HP. */ static void -_heap_grow(heap * hp) +_heap_grow(heap_p hp) { - int newSize; + int newSize; + //heap_node_p * newNodes; - if (hp->size > Threshold) - newSize = hp->size * SlowRate; - else - 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; + if (hp->size > Threshold) + newSize = hp->size * SlowRate; + else + newSize = hp->size * NormalRate; + + hp->nodes = (heap_node_p *)realloc(hp->nodes, newSize * sizeof(heap_node_p)); + //for(i = 0; i < hp->size; i++) + //newNodes[i] = hp->nodes[i]; + //free(hp->nodes); + //hp->nodes = newNodes; + hp->size = newSize; } -/* - * True if a node with ID exists in HP. - */ -static int -_heap_node_exist(heap * hp, int id) -{ - if ((id >= hp->last) || (id < 0) || (hp->nodes[id] == NULL)) - return 0; - return 1; -} - /**************************************************************************** * Printing and debug functions ****************************************************************************/ @@ -483,37 +429,37 @@ * Print the heap in element order, id..last. */ void -heap_print_inorder(heap * hp, int id) +heap_print_inorder(heap_p hp, int id) { - while (id < hp->last) { - printf("%d\tKey = %.04f\n", id, hp->nodes[id]->key); - id++; - } + while (id < hp->last) { + printf("%d <- %d -> %d\tKey = %.04f\n", Parent(id), id, Left(id), hp->nodes[id]->key); + id++; + } } /* * Returns 1 if HP maintians the heap property and 0 otherwise. */ int -verify_heap_property(heap * hp) +verify_heap_property(heap_p hp) { - int i = 0; - int correct = 1; - for (i = 0; i < hp->last / 2; i++) { - correct = 1; - if (_heap_node_exist(hp, Left(i))) - if (hp->nodes[i]->key > hp->nodes[Left(i)]->key) - correct = 0; - if (_heap_node_exist(hp, Right(i))) - if (hp->nodes[i]->key > hp->nodes[Right(i)]->key) - correct = 0; - if (!correct) { - printf("verifyHeap: violated at %d", i); - heap_print_inorder(hp, 0); - break; - } + int i = 0; + int correct = 1; + for(i = 0; i < hp->last / 2; i++) { + correct = 1; + if (_heap_node_exist(hp, Left(i))) + if (hp->nodes[i]->key > hp->nodes[Left(i)]->key) + correct = 0; + if (_heap_node_exist(hp, Right(i))) + if (hp->nodes[i]->key > hp->nodes[Right(i)]->key) + correct = 0; + if (!correct) { + printf("verifyHeap: violated at %d", i); + heap_print_inorder(hp, 0); + break; } - return correct; + } + return correct; } #ifdef MEASURE_HEAP_SKEW @@ -522,16 +468,16 @@ * Heap skew computation ****************************************************************************/ -int -compare_heap_keys(const void *a, const void *b) +int +compare_heap_keys(const void * a, const void * b) { - heap_node **an = (heap_node **) a; - heap_node **bn = (heap_node **) b; - float cmp = (*an)->key - (*bn)->key; - if (cmp < 0) - return -1; - else - return 1; + heap_node ** an = (heap_node**)a; + heap_node ** bn = (heap_node**)b; + float cmp = (*an)->key - (*bn)->key; + if (cmp < 0) + return -1; + else + return 1; } /* @@ -545,83 +491,85 @@ * sorted heap. It is faster not to replace. */ float -calc_heap_skew(heap * heap, int replace) +calc_heap_skew(heap_p heap, int replace) { - heap_node **nodes; - long id, diff, skew = 0; -#ifdef HEAP_DEBUG_SKEW - long skewsq = 0; -#endif /* HEAP_DEBUG_SKEW */ - float norm = 0; - unsigned long max; + heap_node ** nodes; + long id, diff, skew = 0; + #ifdef HEAP_DEBUG_SKEW + long skewsq = 0; + #endif /* HEAP_DEBUG_SKEW */ + float norm = 0; + unsigned long max; + + /* + * Lock the heap to copy it. If replacing it need to keep the heap locked + * until we are all done. + */ + mutex_lock(hp->lock); + + max = heap_nodes(heap); + + /* + * Copy the heap nodes to a new storage area for offline sorting. + */ + nodes = (heap_node **)malloc(max * sizeof(heap_node *)); + memcpy(nodes, heap->nodes, max * sizeof(heap_node *)); + if (replace == 0) { /* - * Lock the heap to copy it. If replacing it need to keep the heap locked - * until we are all done. + * Unlock the heap to allow updates from other threads before the sort. + * This allows other heap operations to proceed concurrently with the + * heap skew computation on the heap at the time of the call ... */ - mutex_lock(hp->lock); + mutex_unlock(hp->lock); + } + + qsort(nodes, max, sizeof(heap_node *), compare_heap_keys); - max = heap_nodes(heap); + for (id=0; id < max; id++) { + diff = id - nodes[id]->id; + skew += abs(diff); + + #ifdef HEAP_DEBUG_SKEW + skewsq += diff*diff; + #ifdef HEAP_DEBUG_ALL + printf("%d\tKey = %f, diff = %d\n", id, nodes[id]->key, diff); + #endif /* HEAP_DEBUG */ + #endif /* HEAP_DEBUG_SKEW */ + } + if (replace != 0) { /* - * Copy the heap nodes to a new storage area for offline sorting. + * Replace the original heap with the newly sorted heap and let it + * continue. Then compute the skew using the copy of the previous heap + * which we maintain as private data. */ - nodes = xmalloc(max * sizeof(heap_node *)); - memcpy(nodes, heap->nodes, max * sizeof(heap_node *)); - - if (replace == 0) { - /* - * Unlock the heap to allow updates from other threads before the sort. - * This allows other heap operations to proceed concurrently with the - * heap skew computation on the heap at the time of the call ... - */ - mutex_unlock(hp->lock); - } - qsort(nodes, max, sizeof(heap_node *), compare_heap_keys); + memcpy(heap->nodes, nodes, max * sizeof(heap_node *)); for (id = 0; id < max; id++) { - diff = id - nodes[id]->id; - skew += abs(diff); - -#ifdef HEAP_DEBUG_SKEW - skewsq += diff * diff; -#ifdef HEAP_DEBUG_ALL - printf("%d\tKey = %f, diff = %d\n", id, nodes[id]->key, diff); -#endif /* HEAP_DEBUG */ -#endif /* HEAP_DEBUG_SKEW */ + /* + * Fix up all the ID values in the copied nodes. + */ + heap->nodes[id]->id = id; } - if (replace != 0) { - /* - * Replace the original heap with the newly sorted heap and let it - * continue. Then compute the skew using the copy of the previous heap - * which we maintain as private data. - */ - memcpy(heap->nodes, nodes, max * sizeof(heap_node *)); - - for (id = 0; id < max; id++) { - /* - * Fix up all the ID values in the copied nodes. - */ - heap->nodes[id]->id = id; - } - - mutex_unlock(hp->lock); - } - /* - * The skew value is normalized to a range of [0..1]; the distribution - * appears to be a skewed Gaussian distribution. For random insertions - * into a heap the normalized skew will be slightly less than 0.5. The - * maximum value of skew/N^2 (for any value of N) is about 0.39 and is - * fairly stable. - */ - norm = skew * 2.56 / (max * max); + mutex_unlock(hp->lock); + } - /* - * Free the nodes array; note this is just an array of pointers, not data! - */ - xfree(nodes); - return norm; + /* + * The skew value is normalized to a range of [0..1]; the distribution + * appears to be a skewed Gaussian distribution. For random insertions + * into a heap the normalized skew will be slightly less than 0.5. The + * maximum value of skew/N^2 (for any value of N) is about 0.39 and is + * fairly stable. + */ + norm = skew*2.56/(max*max); + + /* + * Free the nodes array; note this is just an array of pointers, not data! + */ + free(nodes); + return norm; } -#endif /* MEASURE_HEAP_SKEW */ +#endif /* MEASURE_HEAP_SKEW */ Index: squid/src/HttpHdrRange.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpHdrRange.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.12.1 diff -u -r1.1.1.2 -r1.1.1.2.12.1 --- squid/src/HttpHdrRange.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/src/HttpHdrRange.c 10 Nov 2000 18:44:52 -0000 1.1.1.2.12.1 @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrRange.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ + * $Id: HttpHdrRange.c,v 1.1.1.2.12.1 2000/11/10 18:44:52 hno Exp $ * * DEBUG: section 64 HTTP Range Header * AUTHOR: Alex Rousskov @@ -462,7 +462,7 @@ assert(http); stringAppend(&b, full_appname_string, strlen(full_appname_string)); stringAppend(&b, ":", 1); - key = storeKeyText(http->entry->key); + key = storeKeyText(http->entry->Skey); stringAppend(&b, key, strlen(key)); return b; } Index: squid/src/MemPool.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/MemPool.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.12.1 diff -u -r1.1.1.2 -r1.1.1.2.12.1 --- squid/src/MemPool.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/src/MemPool.c 10 Nov 2000 18:44:52 -0000 1.1.1.2.12.1 @@ -1,6 +1,6 @@ /* - * $Id: MemPool.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ + * $Id: MemPool.c,v 1.1.1.2.12.1 2000/11/10 18:44:52 hno Exp $ * * DEBUG: section 63 Low Level Memory Pool Management * AUTHOR: Alex Rousskov @@ -204,7 +204,20 @@ assert(label && obj_size); pool->label = label; pool->obj_size = obj_size; - stackInit(&pool->pstack); + pool->pstack = 0; + pool->ss = pool; +#ifdef SSPOOLS + { + unsigned i; + for (i = 0; i < Pools.count; i++) { + MemPool *np = Pools.items[i]; + if (np->obj_size == pool->obj_size && pool != np) { + pool->ss = np; + break; + } + } + } +#endif /* other members are set to 0 */ stackPush(&Pools, pool); return pool; @@ -218,56 +231,83 @@ memPoolDestroy(MemPool * pool) { assert(pool); - stackClean(&pool->pstack); xfree(pool); } void * memPoolAlloc(MemPool * pool) { + void *obj; assert(pool); memMeterInc(pool->meter.inuse); gb_inc(&pool->meter.total, 1); gb_inc(&TheMeter.total, pool->obj_size); memMeterAdd(TheMeter.inuse, pool->obj_size); gb_inc(&mem_traffic_volume, pool->obj_size); +#ifdef NEVERFREE + if (!(obj = pool->ss->pstack)) { + unsigned step = pool->meter.alloc.level/4+1; /* 25% growth */ + if (step*pool->obj_size>256*1024) + step = 256*1024/pool->obj_size; /* but at most 256KB at a time */ + obj = xmalloc(step*pool->obj_size); + memMeterAdd(pool->meter.alloc, step); + memMeterAdd(TheMeter.alloc, step*pool->obj_size); + while(--step) { + memPoolFree(pool, obj); + obj=(char*)obj+pool->obj_size; + memMeterInc(pool->meter.inuse); + memMeterAdd(TheMeter.inuse, pool->obj_size); + } +#else if (pool->pstack.count) { - assert(pool->meter.idle.level); - memMeterDec(pool->meter.idle); + assert(!pool->meter.idle.level); + return xcalloc(1, pool->obj_size); +#endif + } else { + memMeterDec(pool->ss->meter.idle); + memMeterDec(pool->ss->meter.alloc); + memMeterInc(pool->meter.alloc); memMeterDel(TheMeter.idle, pool->obj_size); gb_inc(&pool->meter.saved, 1); gb_inc(&TheMeter.saved, pool->obj_size); - return stackPop(&pool->pstack); - } else { - assert(!pool->meter.idle.level); - memMeterInc(pool->meter.alloc); - memMeterAdd(TheMeter.alloc, pool->obj_size); - return xcalloc(1, pool->obj_size); + pool->ss->pstack = *(void**)obj; } + memset(obj, 0, pool->obj_size); + return obj; } void memPoolFree(MemPool * pool, void *obj) { assert(pool && obj); + assert(pool->obj_size >= sizeof pool->pstack); memMeterDec(pool->meter.inuse); + memMeterDec(pool->meter.alloc); + memMeterInc(pool->ss->meter.alloc); memMeterDel(TheMeter.inuse, pool->obj_size); +#ifdef NEVERFREE + if (1) { +#else if (TheMeter.idle.level + pool->obj_size <= mem_idle_limit) { - memMeterInc(pool->meter.idle); +#endif + memMeterInc(pool->ss->meter.idle); memMeterAdd(TheMeter.idle, pool->obj_size); - memset(obj, 0, pool->obj_size); - stackPush(&pool->pstack, obj); + *(void**)obj = pool->ss->pstack; + pool->ss->pstack = obj; } else { memMeterDec(pool->meter.alloc); memMeterDel(TheMeter.alloc, pool->obj_size); xfree(obj); } +#if 0 /* bogus assertion? srb */ assert(pool->meter.idle.level <= pool->meter.alloc.level); +#endif } static void memPoolShrink(MemPool * pool, size_t new_limit) { +#ifndef NEVERFREE assert(pool); assert(new_limit >= 0); while (pool->meter.idle.level > new_limit && pool->pstack.count > 0) { @@ -278,13 +318,15 @@ xfree(stackPop(&pool->pstack)); } assert(pool->meter.idle.level <= new_limit); /* paranoid */ +#endif } int memPoolWasUsed(const MemPool * pool) { assert(pool); - return pool->meter.alloc.hwater_level > 0; + return pool->meter.inuse.hwater_level > 0 || + pool->meter.idle.hwater_level > 0; } int @@ -358,8 +400,7 @@ idle_count += pool->meter.idle.level; } overhd_size += sizeof(MemPool) + sizeof(MemPool *) + - strlen(pool->label) + 1 + - pool->pstack.capacity * sizeof(void *); + strlen(pool->label) + 1; } overhd_size += sizeof(Pools) + Pools.capacity * sizeof(MemPool *); /* totals */ Index: squid/src/aiops.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/aiops.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.10.1 diff -u -r1.1.1.2 -r1.1.1.2.10.1 --- squid/src/aiops.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/src/aiops.c 10 Nov 2000 18:44:52 -0000 1.1.1.2.10.1 @@ -1,5 +1,5 @@ /* - * $Id: aiops.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ + * $Id: aiops.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $ * * DEBUG: section 43 AIOPS * AUTHOR: Stewart Forster @@ -385,9 +385,14 @@ high_start = 0; } if (request_queue_len > RIDICULOUS_LENGTH) { + static unsigned warned; + if (!warned) debug(43, 0) ("aio_queue_request: Async request queue growing uncontrollably!\n"); + warned=1; +#if 0 debug(43, 0) ("aio_queue_request: Possible infinite loop somewhere in squid. Restarting...\n"); abort(); +#endif } } /* aio_queue_request */ @@ -577,7 +582,9 @@ aio_do_read(aio_request_t * requestp) { lseek(requestp->fd, requestp->offset, requestp->whence); - requestp->ret = read(requestp->fd, requestp->tmpbufp, requestp->buflen); + while((requestp->ret = + read(requestp->fd, requestp->tmpbufp, requestp->buflen)) < 0 && + errno == EAGAIN); requestp->err = errno; } @@ -615,7 +622,9 @@ static void aio_do_write(aio_request_t * requestp) { - requestp->ret = write(requestp->fd, requestp->tmpbufp, requestp->buflen); + while((requestp->ret = + write(requestp->fd, requestp->tmpbufp, requestp->buflen)) < 0 && + errno == EAGAIN); requestp->err = errno; } @@ -644,7 +653,10 @@ static void aio_do_close(aio_request_t * requestp) { - requestp->ret = close(requestp->fd); + if((requestp->ret = close(requestp->fd))<0) { + debug(43, 0) ("aio_do_close: FD %d, errno %d\n", requestp->fd, errno); + close(requestp->fd); + } requestp->err = errno; } Index: squid/src/asn.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/asn.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.10.1 diff -u -r1.1.1.2 -r1.1.1.2.10.1 --- squid/src/asn.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/src/asn.c 10 Nov 2000 18:44:52 -0000 1.1.1.2.10.1 @@ -1,5 +1,5 @@ /* - * $Id: asn.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ + * $Id: asn.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $ * * DEBUG: section 53 AS Number handling * AUTHOR: Duane Wessels, Kostas Anagnostakis @@ -221,7 +221,7 @@ char *s; char *t; debug(53, 3) ("asHandleReply: Called with size=%d\n", size); - if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { + if (EBIT_TEST(e->Sflag, ENTRY_ABORTED)) { memFree(buf, MEM_4K_BUF); asStateFree(asState); return; Index: squid/src/async_io.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/async_io.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.10.1 diff -u -r1.1.1.2 -r1.1.1.2.10.1 --- squid/src/async_io.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/src/async_io.c 10 Nov 2000 18:44:52 -0000 1.1.1.2.10.1 @@ -1,6 +1,6 @@ /* - * $Id: async_io.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ + * $Id: async_io.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $ * * DEBUG: section 32 Asynchronous Disk I/O * AUTHOR: Pete Bentley @@ -132,7 +132,8 @@ ctrlp->done_handler_data = NULL; ctrlp->operation = _AIO_CLOSE; if (aio_close(fd, &(ctrlp->result)) < 0) { - close(fd); /* Can't create thread - do a normal close */ + if(close(fd)) /* Can't create thread - do a normal close */ + debug(0,0) ("aioClose: FD %d, errno %d\n", fd, errno), close(fd); memPoolFree(aio_ctrl_pool, ctrlp); fd_was_closed(fd); return; Index: squid/src/cache_cf.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cache_cf.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.10.1 diff -u -r1.1.1.2 -r1.1.1.2.10.1 --- squid/src/cache_cf.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/src/cache_cf.c 10 Nov 2000 18:44:52 -0000 1.1.1.2.10.1 @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ + * $Id: cache_cf.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -222,7 +222,7 @@ /* calculate Config.Swap.maxSize */ storeDirConfigure(); if (Config.Swap.maxSize < (Config.memMaxSize >> 10)) - fatal("cache_swap is lower than cache_mem"); + debug(3, 0) ("configDoConfigure: cache_swap is lower than cache_mem"); if (Config.Announce.period > 0) { Config.onoff.announce = 1; } else if (Config.Announce.period < 1) { @@ -303,10 +303,14 @@ debug(3, 0) ("WARNING: resetting 'maximum_single_addr_tries to 1\n"); Config.retry.maxtries = 1; } + #ifdef HPL_REPL + /* The non-LRU policies do not use referenceAge */ + #else /* HPL_REPL */ if (Config.referenceAge < 300) { debug(3, 0) ("WARNING: resetting 'reference_age' to 1 week\n"); Config.referenceAge = 86400 * 7; } + #endif /* HPL_REPL */ requirePathnameExists("MIME Config Table", Config.mimeTablePathname); requirePathnameExists("cache_dns_program", Config.Program.dnsserver); requirePathnameExists("unlinkd_program", Config.Program.unlinkd); @@ -837,6 +841,9 @@ tmp->l2 = l2; tmp->flags.read_only = read_only; tmp->swaplog_fd = -1; +#ifdef MMAPSTORE + tmp->mi = 0; +#endif swap->n_configured++; } @@ -856,6 +863,7 @@ } xfree(s->path); filemapFreeMemory(s->map); + delete_heap(s->heap); } safe_free(swap->swapDirs); swap->swapDirs = NULL; Index: squid/src/cache_manager.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cache_manager.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.28.1 diff -u -r1.1.1.2 -r1.1.1.2.28.1 --- squid/src/cache_manager.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/src/cache_manager.c 10 Nov 2000 18:44:52 -0000 1.1.1.2.28.1 @@ -1,6 +1,6 @@ /* - * $Id: cache_manager.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ + * $Id: cache_manager.c,v 1.1.1.2.28.1 2000/11/10 18:44:52 hno Exp $ * * DEBUG: section 16 Cache Manager Objects * AUTHOR: Duane Wessels @@ -201,12 +201,12 @@ err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND); err->url = xstrdup(storeUrl(entry)); errorAppendEntry(entry, err); - entry->expires = squid_curtime; + entry->Sexpires = squid_curtime; return; } mgr->entry = entry; storeLockObject(entry); - entry->expires = squid_curtime; + entry->Sexpires = squid_curtime; debug(16, 5) ("CACHEMGR: %s requesting '%s'\n", fd_table[fd].ipaddr, mgr->action); /* get additional info from request headers */ @@ -238,7 +238,7 @@ httpReplyAbsorb(entry->mem_obj->reply, rep); /* store the reply */ httpReplySwapOut(entry->mem_obj->reply, entry); - entry->expires = squid_curtime; + entry->Sexpires = squid_curtime; storeComplete(entry); cachemgrStateFree(mgr); return; Index: squid/src/cachemgr.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/cachemgr.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.2.12.1 diff -u -r1.1.1.2 -r1.1.1.2.12.1 --- squid/src/cachemgr.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 +++ squid/src/cachemgr.c 10 Nov 2000 18:44:52 -0000 1.1.1.2.12.1 @@ -1,6 +1,6 @@ /* - * $Id: cachemgr.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ + * $Id: cachemgr.c,v 1.1.1.2.12.1 2000/11/10 18:44:52 hno Exp $ * * DEBUG: section 0 CGI Cache Manager * AUTHOR: Duane Wessels @@ -344,7 +344,7 @@ { static const char *ttags[] = {"td", "th"}; - static char html[4096]; + static char html[4096*4]; static int table_line_num = 0; static int next_is_header = 0; int is_header = 0; @@ -358,7 +358,7 @@ snprintf(html, sizeof(html), "%s%s", table_line_num ? "\n
" : "", buf);
 	table_line_num = 0;
-	return html;
+	goto ret;
     }
     /* start html table */
     if (!table_line_num) {
@@ -391,6 +391,37 @@
     l += snprintf(html + l, sizeof(html) - l, "\n");
     next_is_header = is_header && strstr(buf, "\t\t");
     table_line_num++;
+ret:
+    {
+#define STRLEN(x)	(sizeof(x)-1)
+	char*pok, *found;
+	for(pok = html; pok = strstr(pok+4, "://"); )
+#define CHECKFOR(str)	(!memcmp(found=pok-STRLEN(str),str,STRLEN(str)))
+	    if(CHECKFOR("http")||CHECKFOR("ftp")||
+		CHECKFOR("gopher")||CHECKFOR("wais")) {
+		static const char prefix[]="",
+		    postfix[]="";
+		size_t len,restlen;
+		for(;;) {
+		    switch(*++pok) {
+			default:
+			    continue;
+			case ' ':case '\t':case '\n':case '\0':
+			    break;
+		    }
+		    break;
+		}
+		len=pok-found; restlen=strlen(pok)+1;
+		memmove(found+STRLEN(prefix)+len+STRLEN(interfix)+len+
+		    STRLEN(postfix),found+len,restlen);
+		memmove(found+STRLEN(prefix),found,len);
+		memcpy(found,prefix,STRLEN(prefix));
+		memcpy(pok = found+STRLEN(prefix)+len,
+		    interfix,STRLEN(interfix));
+		memcpy(pok += STRLEN(interfix),found+STRLEN(prefix),len);
+		memcpy(pok += len, postfix,STRLEN(postfix));
+	    }
+    }
     return html;
 }
 
@@ -440,6 +471,7 @@
 	case isHeaders:
 	    /* forward header field */
 	    if (!strcmp(buf, "\r\n")) {		/* end of headers */
+		fputs("Cache-Control: max-age=4\r\n", stdout);	/* add our type */
 		fputs("Content-Type: text/html\r\n", stdout);	/* add our type */
 		istate = isBodyStart;
 	    }
Index: squid/src/cf.data.pre
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/cf.data.pre,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/cf.data.pre	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/cf.data.pre	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+# $Id: cf.data.pre,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
 #
 #
 # SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -69,6 +69,17 @@
 http_port 3128
 DOC_END
 
+NAME: bhttp_port ascii_port
+TYPE: ushort
+DEFAULT: none
+LOC: Config.Port.bhttp
+DOC_START
+	The port number where Squid uses the cuciwhirl junkfilter.
+	Note that you need another http_port directive to actually
+	bind the port.
+
+bhttp_port 3129
+DOC_END
 
 NAME: icp_port udp_port
 TYPE: ushort
@@ -494,12 +505,17 @@
 DEFAULT: 95
 LOC: Config.Swap.highWaterMark
 DOC_START
-	The low- and high-water marks for cache LRU replacement.  LRU
-	replacement begins when the high-water mark is reached and ends
-	when enough objects have been removed and the low-water mark is
-	reached. Defaults are 90% and 95%. If you have a large cache, 5%
-	could be hundreds of MB. If this is the case you may wish to
-	set these numbers closer together.
+
+	The low- and high-water marks for cache object replacement.
+	Replacement begins when the swap (disk) usage is above the
+	low-water mark and attempts to maintain utilization near the
+	low-water mark.  As swap utilization gets close to high-water
+	mark object eviction becomes more aggressive.  If utilization is
+	close to the low-water mark less replacement is done each time.
+	
+	Defaults are 90% and 95%. If you have a large cache, 5% could be
+	hundreds of MB. If this is the case you may wish to set these
+	numbers closer together.
 
 cache_swap_low  90
 cache_swap_high 95
@@ -518,6 +534,10 @@
 	hits).  If you wish to increase speed more than your want to
 	save bandwidth you should leave this low.
 
+	NOTE: if using the LFUDA replacement policy you should increase
+	this value to maximize the byte hit rate improvement of LFUDA!
+	See replacement_policy below for a discussion of this policy.
+
 maximum_object_size 4096 KB
 DOC_END
 
@@ -1092,6 +1112,49 @@
 DOC_END
 
 
+NAME: replacement_policy
+TYPE: string
+LOC: Config.replPolicy
+DEFAULT: LFUDA
+IFDEF: HPL_REPL
+DOC_START
+	The cache replacement policy parameter determines which objects
+	are evicted (replaced) when disk space is needed.  Squid used to
+	have only a single replacement policy, LRU.  But when built with
+	-DHPL_REPL you can choose between two new, enhanced policies:
+
+		   GDSF: Greedy-Dual Size Frequency
+		   LFUDA: Least Frequently Used with Dynamic Aging
+
+	Both of these policies are frequency based rather than recency
+	based, and perform better than LRU.
+
+	The GDSF policy optimizes object hit rate by keeping smaller
+	popular objects in cache so it has a better chance of getting a
+	hit.  It achieves a lower byte hit rate than LFUDA though since
+	it evicts larger (possibly popular) objects.
+
+	The LFUDA policy keeps popular objects in cache regardless of
+	their size and thus optimizes byte hit rate at the expense of
+	hit rate since one large, popular object will prevent many
+	smaller, slightly less popular objects from being cached.
+
+	Both policies utilize a dynamic aging mechanism that prevents
+	cache pollution that can otherwise occur with frequency-based
+	replacement policies.
+
+	NOTE: if using the LFUDA replacement policy you should increase
+	the value of maximum_object_size above its default of 4096 KB to
+	to maximize the potential byte hit rate improvement of LFUDA.  
+
+	For more information about these cache replacement policies see
+	http://www.hpl.hp.com/personal/John_Dilley/caching/wcw.html and
+	http://fog.hpl.external.hp.com/techreports/98/HPL-98-173.html.
+
+replacement_policy LFUDA
+DOC_END
+
+
 NAME: reference_age
 TYPE: time_t
 LOC: Config.referenceAge
@@ -1114,6 +1177,9 @@
 		4 months
 		2.2 hours
 
+	NOTE: this parameter is not used when using the enhanced
+	replacement policies, GDSH or LFUDA.
+
 reference_age 1 month
 DOC_END
 
Index: squid/src/client_side.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/client_side.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/client_side.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: client_side.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -58,6 +58,9 @@
 #endif
 #endif
 
+#ifdef	HPL_REPL
+#include "heap.h"
+#endif	/* HPL_REPL */
 
 
 #if LINGERING_CLOSE
@@ -284,6 +287,9 @@
 	    new_request->body_sz = old_request->body_sz;
 	}
 	requestUnlink(old_request);
+	if (!*new_request->host)
+	    xstrncpy(new_request->host, internalHostname(),
+		SQUIDHOSTNAMELEN);
 	http->request = requestLink(new_request);
     }
     clientInterpretRequestHeaders(http);
@@ -298,7 +304,7 @@
     char *url = http->uri;
     StoreEntry *entry = NULL;
     debug(33, 3) ("clientProcessExpired: '%s'\n", http->uri);
-    assert(http->entry->lastmod >= 0);
+    assert(http->entry->Slastmod >= 0);
     /*
      * check if we are allowed to contact other servers
      * @?@: Instead of a 504 (Gateway Timeout) reply, we may want to return 
@@ -326,15 +332,26 @@
     /* delay_id is already set on original store client */
     delaySetStoreClient(entry, http, delayClient(http->request));
 #endif
-    entry->lastmod = http->old_entry->lastmod;
-    debug(33, 5) ("clientProcessExpired: lastmod %d\n", (int) entry->lastmod);
-    entry->refcount++;		/* EXPIRED CASE */
+    entry->Slastmod = http->old_entry->Slastmod;
+    debug(33, 5) ("clientProcessExpired: lastmod %d\n", (int) entry->Slastmod);
+    entry->Srefcount++;		/* EXPIRED CASE */
+#ifdef	HPL_REPL
+    /* 
+     * Update the position of this object in the store heap and memory
+     * heap.  The cache replacement policy uses refcount to determie the
+     * priority value of the object.
+     */
+    if (entry->n.ode.id >= 0)
+      heap_update(Store_Heap(entry), &entry->n.ode);
+    if (entry->mem_obj->n.ode.id >= 0)
+      heap_update(inmem_heap, &entry->mem_obj->n.ode);
+#endif	/* HPL_REPL */
     http->entry = entry;
     http->out.offset = 0;
     fwdStart(http->conn->fd, http->entry, http->request,
 	http->conn->peer.sin_addr, http->conn->me.sin_addr);
     /* Register with storage manager to receive updates when data comes in. */
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED))
+    if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED))
 	debug(33, 0) ("clientProcessExpired: found ENTRY_ABORTED object\n");
     storeClientCopy(entry,
 	http->out.offset,
@@ -399,13 +416,13 @@
 	memFree(buf, MEM_CLIENT_SOCK_BUF);
 	return;
     }
-    if (size < 0 && !EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+    if (size < 0 && !EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	memFree(buf, MEM_CLIENT_SOCK_BUF);
 	return;
     }
     mem = entry->mem_obj;
     status = mem->reply->sline.status;
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	debug(33, 3) ("clientHandleIMSReply: ABORTED '%s'\n", url);
 	/* We have an existing entry, but failed to validate it */
 	/* Its okay to send the old one anyway */
@@ -413,7 +430,14 @@
 	storeUnregister(entry, http);
 	storeUnlockObject(entry);
 	entry = http->entry = http->old_entry;
-	entry->refcount++;
+	entry->Srefcount++;
+#ifdef	HPL_REPL
+	/* Update the position of this object in the store and memory heaps. */
+	if (entry->n.ode.id >= 0)
+	  heap_update(Store_Heap(entry), &entry->n.ode);
+	if (entry->mem_obj->n.ode.id >= 0)
+	  heap_update(inmem_heap, &entry->mem_obj->n.ode);
+#endif	/* HPL_REPL */
     } else if (STORE_PENDING == entry->store_status && 0 == status) {
 	debug(33, 3) ("clientHandleIMSReply: Incomplete headers for '%s'\n", url);
 	if (size >= CLIENT_SOCK_SZ) {
@@ -424,7 +448,14 @@
 	    storeUnregister(entry, http);
 	    storeUnlockObject(entry);
 	    entry = http->entry = http->old_entry;
-	    entry->refcount++;
+	    entry->Srefcount++;
+#ifdef	HPL_REPL
+	    /* Update the position of this object in the store and memory heaps. */
+	    if (entry->n.ode.id >= 0)
+	      heap_update(Store_Heap(entry), &entry->n.ode);
+	    if (entry->mem_obj->n.ode.id >= 0)
+	      heap_update(inmem_heap, &entry->mem_obj->n.ode);
+#endif	/* HPL_REPL */
 	    /* continue */
 	} else {
 	    storeClientCopy(entry,
@@ -455,7 +486,7 @@
 	storeUnregister(entry, http);
 	storeUnlockObject(entry);
 	entry = http->entry = oldentry;
-	entry->timestamp = squid_curtime;
+	entry->Stimestamp = squid_curtime;
 	if (unlink_request) {
 	    requestUnlink(entry->mem_obj->request);
 	    entry->mem_obj->request = NULL;
@@ -464,8 +495,15 @@
 	/* the client can handle this reply, whatever it is */
 	http->log_type = LOG_TCP_REFRESH_MISS;
 	if (HTTP_NOT_MODIFIED == mem->reply->sline.status) {
-	    http->old_entry->timestamp = squid_curtime;
-	    http->old_entry->refcount++;
+	    http->old_entry->Stimestamp = squid_curtime;
+	    http->old_entry->Srefcount++;
+#ifdef	HPL_REPL
+	    /* Update the position of this object in the store and memory heaps. */
+	    if (http->old_entry->n.ode.id >= 0)
+	      heap_update(Store_Heap(http->old_entry), &http->old_entry->n.ode);
+	    if (http->old_entry->mem_obj->n.ode.id >= 0)
+	      heap_update(inmem_heap, &http->old_entry->mem_obj->n.ode);
+#endif	/* HPL_REPL */
 	    http->log_type = LOG_TCP_REFRESH_HIT;
 	}
 	storeUnregister(http->old_entry, http);
@@ -473,7 +511,7 @@
 	recopy = 0;
     }
     http->old_entry = NULL;	/* done with old_entry */
-    assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED));
+    assert(!EBIT_TEST(entry->Sflag, ENTRY_ABORTED));
     if (recopy) {
 	storeClientCopy(entry,
 	    http->out.offset,
@@ -492,10 +530,10 @@
 {
     int object_length;
     MemObject *mem = entry->mem_obj;
-    time_t mod_time = entry->lastmod;
+    time_t mod_time = entry->Slastmod;
     debug(33, 3) ("modifiedSince: '%s'\n", storeUrl(entry));
     if (mod_time < 0)
-	mod_time = entry->timestamp;
+      mod_time = entry->Stimestamp;
     debug(33, 3) ("modifiedSince: mod_time = %d\n", (int) mod_time);
     if (mod_time < 0)
 	return 1;
@@ -560,9 +598,9 @@
 int
 checkNegativeHit(StoreEntry * e)
 {
-    if (!EBIT_TEST(e->flags, ENTRY_NEGCACHED))
+    if (!EBIT_TEST(e->Sflag, ENTRY_NEGCACHED))
 	return 0;
-    if (e->expires <= squid_curtime)
+    if (e->Sexpires <= squid_curtime)
 	return 0;
     if (e->store_status != STORE_OK)
 	return 0;
@@ -989,7 +1027,7 @@
     }
     /* got modification time? */
     if (spec.time >= 0) {
-	return http->entry->lastmod <= spec.time;
+	return http->entry->Slastmod <= spec.time;
     }
     assert(0);			/* should not happen */
     return 0;
@@ -1108,7 +1146,7 @@
      * Add Age header, not that our header must replace Age headers
      * from other caches if any
      */
-    if (http->entry->timestamp > 0) {
+    if (http->entry->Stimestamp > 0) {
 	httpHeaderDelById(hdr, HDR_AGE);
 	/*
 	 * we do not follow HTTP/1.1 precisely here becuase we rely
@@ -1117,8 +1155,8 @@
 	 * or if it is out of sync
 	 */
 	httpHeaderPutInt(hdr, HDR_AGE,
-	    http->entry->timestamp <= squid_curtime ?
-	    squid_curtime - http->entry->timestamp : 0);
+	    http->entry->Stimestamp <= squid_curtime ?
+	    squid_curtime - http->entry->Stimestamp : 0);
     }
     /* Append X-Cache */
     httpHeaderPutStrf(hdr, HDR_X_CACHE, "%s from %s",
@@ -1193,7 +1231,7 @@
 	memFree(buf, MEM_CLIENT_SOCK_BUF);
 	debug(33, 3) ("clientCacheHit: request aborted\n");
 	return;
-    } else if (size < 0) {
+    } else if (size <= 0) {
 	/* swap in failure */
 	memFree(buf, MEM_CLIENT_SOCK_BUF);
 	debug(33, 3) ("clientCacheHit: swapin failure for %s\n", http->uri);
@@ -1206,9 +1244,8 @@
 	clientProcessMiss(http);
 	return;
     }
-    assert(size > 0);
     mem = e->mem_obj;
-    assert(!EBIT_TEST(e->flags, ENTRY_ABORTED));
+    assert(!EBIT_TEST(e->Sflag, ENTRY_ABORTED));
     if (mem->reply->sline.status == 0) {
 	/*
 	 * we don't have full reply headers yet; either wait for more or
@@ -1261,7 +1298,7 @@
 	 * both have a stale version of the object.
 	 */
 	r->flags.need_validation = 1;
-	if (e->lastmod < 0) {
+	if (e->Slastmod < 0) {
 	    /*
 	     * Previous reply didn't have a Last-Modified header,
 	     * we cannot revalidate it.
@@ -1479,7 +1516,7 @@
 	debug(33, 1) ("clientSendMoreData: Deferring %s\n", storeUrl(entry));
 	memFree(buf, MEM_CLIENT_SOCK_BUF);
 	return;
-    } else if (entry && EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+    } else if (entry && EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	/* call clientWriteComplete so the client socket gets closed */
 	clientWriteComplete(fd, NULL, 0, COMM_OK, http);
 	memFree(buf, MEM_CLIENT_SOCK_BUF);
@@ -1591,12 +1628,12 @@
 	/*
 	 * Set the timeout BEFORE calling clientReadRequest().
 	 */
-	commSetTimeout(conn->fd, 15, requestTimeout, conn);
+	commSetTimeout(conn->fd, Config.Timeout.request, requestTimeout, conn);
 	clientReadRequest(conn->fd, conn);	/* Read next request */
 	/*
 	 * Note, the FD may be closed at this point.
 	 */
-    } else if ((entry = http->entry) == NULL) {
+    } else if (!(entry = http->entry)) {
 	/*
 	 * this request is in progress, maybe doing an ACL or a redirect,
 	 * execution will resume after the operation completes.
@@ -1604,9 +1641,8 @@
     } else {
 	debug(33, 1) ("clientKeepaliveNextRequest: FD %d Sending next\n",
 	    conn->fd);
-	assert(entry);
 	if (0 == storeClientCopyPending(entry, http)) {
-	    if (EBIT_TEST(entry->flags, ENTRY_ABORTED))
+	    if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED))
 		debug(33, 0) ("clientKeepaliveNextRequest: ENTRY_ABORTED\n");
 	    storeClientCopy(entry,
 		http->out.offset,
@@ -1640,7 +1676,7 @@
 	comm_close(fd);
     } else if (NULL == entry) {
 	comm_close(fd);		/* yuk */
-    } else if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+    } else if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	comm_close(fd);
     } else if ((done = clientCheckTransferDone(http)) != 0 || size == 0) {
 	debug(33, 5) ("clientWriteComplete: FD %d transfer is DONE\n", fd);
@@ -1663,7 +1699,7 @@
     } else {
 	/* More data will be coming from primary server; register with 
 	 * storage manager. */
-	if (EBIT_TEST(entry->flags, ENTRY_ABORTED))
+	if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED))
 	    debug(33, 0) ("clientWriteComplete 2: ENTRY_ABORTED\n");
 	storeClientCopy(entry,
 	    http->out.offset,
@@ -1729,7 +1765,7 @@
 	http->entry = NULL;
 	return LOG_TCP_MISS;
     }
-    if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
+    if (EBIT_TEST(e->Sflag, ENTRY_SPECIAL)) {
 	/* Special entries are always hits, no matter what the client says */
 	debug(33, 3) ("clientProcessRequest2: ENTRY_SPECIAL HIT\n");
 	http->entry = e;
@@ -1824,7 +1860,14 @@
 #if DELAY_POOLS
 	delaySetStoreClient(http->entry, http, delayClient(r));
 #endif
-	http->entry->refcount++;
+	http->entry->Srefcount++;
+#ifdef	HPL_REPL
+	/* Update the position of this object in the store and memory heaps. */
+	if (http->entry->n.ode.id >= 0)
+	  heap_update(Store_Heap(http->entry), &http->entry->n.ode);
+	if (http->entry->mem_obj->n.ode.id >= 0)
+	  heap_update(inmem_heap, &http->entry->mem_obj->n.ode);
+#endif	/* HPL_REPL */
 	storeClientCopy(http->entry,
 	    http->out.offset,
 	    http->out.offset,
@@ -1855,7 +1898,7 @@
      * or IMS request.
      */
     if (http->entry) {
-	if (EBIT_TEST(http->entry->flags, ENTRY_SPECIAL))
+	if (EBIT_TEST(http->entry->Sflag, ENTRY_SPECIAL))
 	    debug(33, 0) ("clientProcessMiss: miss on a special object (%s).\n", url);
 	storeUnregister(http->entry, http);
 	storeUnlockObject(http->entry);
@@ -1879,7 +1922,14 @@
     }
     assert(http->out.offset == 0);
     http->entry = clientCreateStoreEntry(http, r->method, r->flags);
-    http->entry->refcount++;
+    http->entry->Srefcount++;
+#ifdef	HPL_REPL
+    /* Update the position of this object in the store and memory heaps. */
+    if (http->entry->n.ode.id >= 0)
+      heap_update(Store_Heap(http->entry), &http->entry->n.ode);
+    if (http->entry->mem_obj->n.ode.id >= 0)
+      heap_update(inmem_heap, &http->entry->mem_obj->n.ode);
+#endif	/* HPL_REPL */
     if (http->redirect.status) {
 	HttpReply *rep = httpReplyCreate();
 	storeReleaseRequest(http->entry);
@@ -2087,14 +2137,16 @@
 	    if (natfd < 0) {
 		debug(50, 1) ("parseHttpRequest: NAT open failed: %s\n",
 		    xstrerror());
-		return parseHttpRequestAbort(conn, "error:nat-open-failed");
+		http = parseHttpRequestAbort(conn, "error:nat-open-failed");
+		goto ret;
 	    }
 	    if (ioctl(natfd, SIOCGNATL, &natLookup) < 0) {
 		if (errno != ESRCH) {
 		    debug(50, 1) ("parseHttpRequest: NAT lookup failed: ioctl(SIOCGNATL)\n");
 		    close(natfd);
 		    natfd = -1;
-		    return parseHttpRequestAbort(conn, "error:nat-lookup-failed");
+		    http = parseHttpRequestAbort(conn, "error:nat-lookup-failed");
+		    goto ret;
 		} else
 		    snprintf(http->uri, url_sz, "http://%s:%d%s",
 			inet_ntoa(http->conn->me.sin_addr),
@@ -2133,8 +2185,9 @@
     debug(33, 5) ("parseHttpRequest: Complete request received\n");
     if (free_request)
 	safe_free(url);
-    xfree(inbuf);
     *status = 1;
+ret:
+    xfree(inbuf);
     return http;
 }
 
@@ -2249,7 +2302,7 @@
 	    conn->nrequests++;
 	    commSetTimeout(fd, Config.Timeout.lifetime, NULL, NULL);
 	    if (parser_return_code < 0) {
-		debug(33, 1) ("clientReadRequest: FD %d Invalid Request\n", fd);
+		debug(33, 1) ("clientReadRequest: FD %d Indecent proposal\n", fd);
 		err = errorCon(ERR_INVALID_REQ, HTTP_BAD_REQUEST);
 		err->request_hdrs = xstrdup(conn->in.buf);
 		http->entry = clientCreateStoreEntry(http, method, null_request_flags);
Index: squid/src/comm.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/comm.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/comm.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/comm.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: comm.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: comm.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 5     Socket Functions
  * AUTHOR: Harvest Derived
@@ -597,7 +597,8 @@
      * michael@metal.iinet.net.au sez close() on
      * network sockets never blocks.
      */
-    close(fd);
+    if(close(fd))
+	debug(50, 0) ("comm_close: FD %d, %s\n", fd, xstrerror()), close(fd);
 #elif USE_ASYNC_IO
     if (doaioclose)
 	aioClose(fd);
Index: squid/src/defines.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/defines.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/defines.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/defines.h	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: defines.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: defines.h,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -87,7 +87,7 @@
 
 #define DNS_INBUF_SZ 4096
 
-#define FD_DESC_SZ		64
+#define FD_DESC_SZ		128
 
 #define FQDN_LOOKUP_IF_MISS	0x01
 #define FQDN_MAX_NAMES 5
@@ -208,6 +208,15 @@
 #define STORE_SWAP_BUF		DISK_PAGE_SIZE
 #define VM_WINDOW_SZ		DISK_PAGE_SIZE
 
+#define SWAP_DIR_SHIFT 24
+#define SWAP_FILE_MASK ((1<Sswap_file_number>=0),getswapdir((e)->Sswap_file_number)->heap)
+
 #define SKIP_BASIC_SZ ((size_t) 6)
 
 #define PINGER_PAYLOAD_SZ 8192
Index: squid/src/disk.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/disk.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/disk.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/disk.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,7 +1,7 @@
 
 
 /*
- * $Id: disk.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: disk.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 6     Disk I/O Routines
  * AUTHOR: Harvest Derived
@@ -242,6 +242,12 @@
 #endif
     debug(6, 3) ("diskHandleWrite: FD %d\n", fd);
     assert(fdd->write_q != NULL);
+    if (fdd->write_q->len == fdd->write_q->buf_offset) {
+        debug(6, 0) ("diskHandleWrite: nothing to write FD %d offset %d\n",
+		fd, fdd->write_q->buf_offset);
+	diskHandleWriteComplete(fd, fdd->write_q, 0, 0);
+	return;
+    }
     assert(fdd->write_q->len > fdd->write_q->buf_offset);
 #if USE_ASYNC_IO
     aioWrite(fd,
@@ -296,7 +302,7 @@
     }
 #endif
     if (q == NULL)		/* Someone aborted then write completed */
-	return;
+	goto ret;
 
     if (len == -2 && errcode == -2) {	/* Write cancelled - cleanup */
 	do {
@@ -333,6 +339,8 @@
 	     * repeated write failures for the same FD because of
 	     * the queued data.
 	     */
+	    if (data == q)
+		data = 0;
 	    do {
 		fdd->write_q = q->next;
 		if (q->free_func)
@@ -354,6 +362,8 @@
 	    fdd->write_q = q->next;
 	    if (q->free_func)
 		(q->free_func) (q->buf);
+	    if (data == q)
+		data = 0;
 	    safe_free(q);
 	}
     }
@@ -390,11 +400,13 @@
 #ifdef OPTIMISTIC_IO
 	    F->flags.calling_io_handler = 0;
 #endif
-	    return;
+	    goto ret;
 	}
     }
     if (do_close)
 	file_close(fd);
+ret:
+    safe_free(data);
 }
 
 
Index: squid/src/enums.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/enums.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/enums.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/enums.h	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: enums.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: enums.h,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -535,6 +535,7 @@
     MEM_MEM_NODE,
     MEM_NETDBENTRY,
     MEM_NET_DB_NAME,
+    MEM_STORESWAPLOGDATA,
     MEM_NET_DB_PEER,
     MEM_PEER,
 #if USE_CACHE_DIGESTS
Index: squid/src/errorpage.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/errorpage.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/errorpage.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/errorpage.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: errorpage.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: errorpage.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 4     Error Generation
  * AUTHOR: Duane Wessels
@@ -270,7 +270,7 @@
 	 * care about it, and we don't need to generate an
 	 * error message
 	 */
-	assert(EBIT_TEST(entry->flags, ENTRY_ABORTED));
+	assert(EBIT_TEST(entry->Sflag, ENTRY_ABORTED));
 	assert(mem->nclients == 0);
 	errorStateFree(err);
 	return;
@@ -298,7 +298,7 @@
     httpReplyDestroy(rep);
     mem->reply->sline.status = err->http_status;
     mem->reply->content_length = -1;
-    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
+    EBIT_CLR(entry->Sflag, ENTRY_FWD_HDR_WAIT);
     storeBufferFlush(entry);
     storeComplete(entry);
     storeNegativeCache(entry);
@@ -599,6 +599,9 @@
     }
     if (*m)
 	memBufPrintf(&content, "%s", m);	/* copy tail */
-    assert(content.size == strlen(content.buf));
+    if (content.size != strlen(content.buf)) {
+	debug(4,0) ("errorBuildContent: %d, %d != %d\n", err->page_id,
+		content.size, strlen(content.buf));
+    }
     return content;
 }
Index: squid/src/filemap.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/filemap.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.12.1
diff -u -r1.1.1.1 -r1.1.1.1.12.1
--- squid/src/filemap.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/filemap.c	10 Nov 2000 18:44:52 -0000	1.1.1.1.12.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: filemap.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: filemap.c,v 1.1.1.1.12.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 8     Swap File Bitmap
  * AUTHOR: Harvest Derived
@@ -115,7 +115,8 @@
     for (count = 0; count < fm->nwords; count++) {
 	if (fm->file_map[word] != ALL_ONES)
 	    break;
-	word = (word + 1) % fm->nwords;
+	if (++word == fm->nwords)
+	    word = 0;
     }
     for (bit = 0; bit < BITS_IN_A_LONG; bit++) {
 	suggestion = ((unsigned long) word << LONG_BIT_SHIFT) | bit;
Index: squid/src/ftp.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/ftp.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/ftp.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/ftp.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ftp.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: ftp.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 9     File Transfer Protocol (FTP)
  * AUTHOR: Harvest Derived
@@ -306,6 +306,7 @@
 static void
 ftpLoginParser(const char *login, FtpStateData * ftpState, int escaped)
 {
+    static unsigned long counter;
     char *s = NULL;
     xstrncpy(ftpState->user, login, MAX_URL);
     if ((s = strchr(ftpState->user, ':'))) {
@@ -320,8 +321,10 @@
 	rfc1738_unescape(ftpState->user);
     if (ftpState->user[0] || ftpState->password[0])
 	return;
+
     xstrncpy(ftpState->user, "anonymous", MAX_URL);
-    xstrncpy(ftpState->password, Config.Ftp.anon_user, MAX_URL);
+    snprintf(ftpState->password, MAX_URL, "%lx.%s", counter++,
+	Config.Ftp.anon_user);
 }
 
 static void
@@ -863,7 +866,7 @@
     delay_id delay_id = delayMostBytesAllowed(mem);
 #endif
     assert(fd == ftpState->data.fd);
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	comm_close(ftpState->ctrl.fd);
 	return;
     }
@@ -1216,6 +1219,10 @@
     int len;
     ErrorState *err;
     debug(9, 5) ("ftpReadControlReply\n");
+    if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
+	comm_close(ftpState->ctrl.fd);
+	return;
+    }
     assert(ftpState->ctrl.offset < ftpState->ctrl.size);
     Counter.syscalls.sock.reads++;
     len = read(fd,
@@ -1297,7 +1304,8 @@
     for (W = &ftpState->ctrl.message; (*W)->next; W = &(*W)->next);
     safe_free(ftpState->ctrl.last_reply);
     ftpState->ctrl.last_reply = (*W)->key;
-    safe_free(*W);
+    memFree(*W, MEM_WORDLIST);
+    *W = 0;
     debug(9, 8) ("ftpReadControlReply: state=%d, code=%d\n", ftpState->state,
 	ftpState->ctrl.replycode);
     FTP_SM_FUNCS[ftpState->state] (ftpState);
@@ -1467,7 +1475,7 @@
     w = ftpState->pathcomps;
     ftpState->filepath = w->key;
     ftpState->pathcomps = w->next;
-    xfree(w);
+    memFree(w, MEM_WORDLIST);
     /* Check if we are to CWD or RETR */
     if (ftpState->pathcomps != NULL || ftpState->flags.isdir) {
 	ftpSendCwd(ftpState);
@@ -2371,7 +2379,7 @@
 	return;
     ftpState->flags.http_header_sent = 1;
     assert(e->mem_obj->inmem_hi == 0);
-    EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT);
+    EBIT_CLR(e->Sflag, ENTRY_FWD_HDR_WAIT);
     filename = (t = strRChr(urlpath, '/')) ? t + 1 : strBuf(urlpath);
     if (ftpState->flags.isdir) {
 	mime_type = "text/html";
@@ -2422,7 +2430,7 @@
 	if (pe)
 	    storeRelease(pe);
 	storeRelease(e);
-    } else if (EBIT_TEST(e->flags, ENTRY_CACHABLE) && !ftpState->restarted_offset) {
+    } else if (EBIT_TEST(e->Sflag, ENTRY_CACHABLE) && !ftpState->restarted_offset) {
 	storeSetPublicKey(e);
     } else {
 	storeRelease(e);
Index: squid/src/globals.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/globals.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.12.1
diff -u -r1.1.1.2 -r1.1.1.2.12.1
--- squid/src/globals.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/globals.h	10 Nov 2000 18:44:52 -0000	1.1.1.2.12.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: globals.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: globals.h,v 1.1.1.2.12.1 2000/11/10 18:44:52 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -30,6 +30,9 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  *
  */
+#ifdef	HPL_REPL
+#include "heap.h"
+#endif	/* HPL_REPL */
 
 extern FILE *debug_log;		/* NULL */
 extern FILE *cache_useragent_log;	/* NULL */
@@ -53,8 +56,8 @@
 extern const char *const dash_str;	/* "-" */
 extern const char *const localhost;	/* "127.0.0.1" */
 extern const char *const null_string;	/* "" */
-extern const char *const version_string;	/* SQUID_VERSION */
-extern const char *const full_appname_string;	/* "Squid/" SQUID_VERSION */
+extern const char *const version_string;	/* SQUID_VERSION "BuGless" */
+extern const char *const full_appname_string;	/* "Squid/" SQUID_VERSION "BuGless"*/
 extern const char *const w_space;	/* " \t\n\r" */
 extern const char *fdTypeStr[];
 extern const char *hier_strings[];
@@ -124,7 +127,13 @@
 extern double current_dtime;
 extern int store_hash_buckets;	/* 0 */
 extern hash_table *store_table;	/* NULL */
+#ifdef	HPL_REPL
+extern heap_p store_heap;
+extern heap_p inmem_heap;
+extern key_func store_policy;
+#else	/* HPL_REPL */
 extern dlink_list store_list;
+#endif	/* HPL_REPL */
 extern dlink_list ClientActiveRequests;
 extern const String StringNull;	/* { 0, 0, NULL } */
 extern const MemBuf MemBufNull;	/* MemBufNULL */
Index: squid/src/gopher.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/gopher.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/gopher.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/gopher.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,7 +1,7 @@
 
 
 /*
- * $Id: gopher.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: gopher.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 10    Gopher
  * AUTHOR: Harvest Derived
@@ -187,7 +187,7 @@
 	break;
     }
     memBufPrintf(&mb, "\r\n");
-    EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT);
+    EBIT_CLR(gopherState->entry->Sflag, ENTRY_FWD_HDR_WAIT);
     storeAppend(gopherState->entry, mb.buf, mb.size);
     memBufClean(&mb);
 }
@@ -600,7 +600,7 @@
 #if DELAY_POOLS
     delay_id delay_id = delayMostBytesAllowed(entry->mem_obj);
 #endif
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	comm_close(fd);
 	return;
     }
@@ -761,7 +761,7 @@
 	gopherSendComplete,
 	data,
 	memFree4K);
-    if (EBIT_TEST(gopherState->entry->flags, ENTRY_CACHABLE))
+    if (EBIT_TEST(gopherState->entry->Sflag, ENTRY_CACHABLE))
 	storeSetPublicKey(gopherState->entry);	/* Make it public */
 }
 
Index: squid/src/helper.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/helper.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/helper.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/helper.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -255,8 +255,11 @@
     debug(29, 5) ("helperHandleRead: %d bytes from %s #%d.\n",
 	len, hlp->id_name, srv->index + 1);
     if (len <= 0) {
-	if (len < 0)
+	if (len < 0) {
+	    if (errno == EAGAIN)
+		goto again;
 	    debug(50, 1) ("helperHandleRead: FD %d read: %s\n", fd, xstrerror());
+	}
 	comm_close(fd);
 	return;
     }
@@ -288,7 +291,7 @@
 	else
 	    helperKickQueue(hlp);
     } else {
-	commSetSelect(srv->rfd, COMM_SELECT_READ, helperHandleRead, srv, 0);
+again:	commSetSelect(srv->rfd, COMM_SELECT_READ, helperHandleRead, srv, 0);
     }
 }
 
@@ -308,7 +311,7 @@
     debug(14, 0) ("WARNING: All %s processes are busy.\n", hlp->id_name);
     debug(14, 0) ("WARNING: %d pending requests queued\n", hlp->stats.queue_size);
     if (hlp->stats.queue_size > hlp->n_running * 2)
-	fatalf("Too many queued %s requests", hlp->id_name);
+	debug(14, 0) ("Too many queued %s requests", hlp->id_name);
     debug(14, 1) ("Consider increasing the number of %s processes in your config file.\n", hlp->id_name);
 }
 
Index: squid/src/http.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/http.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/http.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/http.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: http.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -106,7 +106,7 @@
 static void
 httpMakePublic(StoreEntry * entry)
 {
-    if (EBIT_TEST(entry->flags, ENTRY_CACHABLE))
+    if (EBIT_TEST(entry->Sflag, ENTRY_CACHABLE))
 	storeSetPublicKey(entry);
 }
 
@@ -124,7 +124,7 @@
 httpCacheNegatively(StoreEntry * entry)
 {
     storeNegativeCache(entry);
-    if (EBIT_TEST(entry->flags, ENTRY_CACHABLE))
+    if (EBIT_TEST(entry->Sflag, ENTRY_CACHABLE))
 	storeSetPublicKey(entry);
 }
 
@@ -133,7 +133,7 @@
 {
     int remove = 0;
     StoreEntry *pe;
-    if (!EBIT_TEST(e->flags, KEY_PRIVATE))
+    if (!EBIT_TEST(e->Sflag, KEY_PRIVATE))
 	return;
     switch (status) {
     case HTTP_OK:
@@ -294,7 +294,7 @@
     int hdr_len;
     HttpReply *reply = entry->mem_obj->reply;
     debug(11, 3) ("httpProcessReplyHeader: key '%s'\n",
-	storeKeyText(entry->key));
+	storeKeyText(entry->Skey));
     if (httpState->reply_hdr == NULL)
 	httpState->reply_hdr = memAllocate(MEM_8K_BUF);
     if (httpState->reply_hdr_state == 0) {
@@ -348,9 +348,9 @@
 	}
 	if (reply->cache_control) {
 	    if (EBIT_TEST(reply->cache_control->mask, CC_PROXY_REVALIDATE))
-		EBIT_SET(entry->flags, ENTRY_REVALIDATE);
+		EBIT_SET(entry->Sflag, ENTRY_REVALIDATE);
 	    else if (EBIT_TEST(reply->cache_control->mask, CC_MUST_REVALIDATE))
-		EBIT_SET(entry->flags, ENTRY_REVALIDATE);
+		EBIT_SET(entry->Sflag, ENTRY_REVALIDATE);
 	}
 	if (httpState->flags.keepalive)
 	    if (httpState->peer)
@@ -456,7 +456,7 @@
     else
 	delay_id = delayMostBytesAllowed(entry->mem_obj);
 #endif
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	comm_close(fd);
 	return;
     }
@@ -536,11 +536,11 @@
 		 * allow the client to get it.
 		 */
 		if (!fwdReforwardableStatus(s))
-		    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
+		    EBIT_CLR(entry->Sflag, ENTRY_FWD_HDR_WAIT);
 	    }
 	}
 	storeAppend(entry, buf, len);
-	if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+	if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	    /*
 	     * the above storeAppend() call could ABORT this entry,
 	     * in that case, the server FD should already be closed.
@@ -631,8 +631,8 @@
     HttpHeaderPos pos = HttpHeaderInitPos;
     httpHeaderInit(hdr_out, hoRequest);
     /* append our IMS header */
-    if (entry && entry->lastmod > -1 && request->method == METHOD_GET)
-	httpHeaderPutTime(hdr_out, HDR_IF_MODIFIED_SINCE, entry->lastmod);
+    if (entry && entry->Slastmod > -1 && request->method == METHOD_GET)
+	httpHeaderPutTime(hdr_out, HDR_IF_MODIFIED_SINCE, entry->Slastmod);
 
     /* decide if we want to do Ranges ourselves 
      * (and fetch the whole object now)
@@ -935,7 +935,7 @@
 	comm_close(fd);
 	return;
     }
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	comm_close(fd);
 	return;
     }
Index: squid/src/main.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/main.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/main.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/main.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: main.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: main.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 1     Startup and Main Loop
  * AUTHOR: Harvest Derived
@@ -516,8 +516,10 @@
     time_t loop_delay;
 
     debug_log = stderr;
+#if !HAVE_POLL
     if (FD_SETSIZE < Squid_MaxFD)
 	Squid_MaxFD = FD_SETSIZE;
+#endif
 
     /* call mallopt() before anything else */
 #if HAVE_MALLOPT
@@ -691,6 +693,7 @@
     if (*(argv[0]) == '(')
 	return;
     openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
+    if (getppid() != 1)
     if ((pid = fork()) < 0)
 	syslog(LOG_ALERT, "fork failed: %s", xstrerror());
     else if (pid > 0)
@@ -741,9 +744,12 @@
 	    failcount++;
 	else
 	    failcount = 0;
-	if (failcount == 5) {
-	    syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
-	    exit(1);
+	if (failcount >= 5) {
+	    extern char **environ;
+	    if (failcount == 5)
+		syslog(LOG_ALERT, "Repeated frequent failures!");
+	    sleep(1);
+	    execve(argv[0], argv, environ);
 	}
 	if (WIFEXITED(status))
 	    if (WEXITSTATUS(status) == 0)
@@ -806,6 +812,7 @@
     if (opt_no_daemon) {
 	file_close(0);
 	file_close(1);
+	if (opt_debug_stderr < 0)
 	file_close(2);
     }
 #endif
Index: squid/src/mem.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/mem.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.12.1
diff -u -r1.1.1.2 -r1.1.1.2.12.1
--- squid/src/mem.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/mem.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.12.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: mem.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: mem.c,v 1.1.1.2.12.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 13    High Level Memory Pool Management
  * AUTHOR: Harvest Derived
@@ -280,6 +280,8 @@
     memDataInit(MEM_STMEM_BUF, "Store Mem Buffer", SM_PAGE_SIZE,
 	Config.memMaxSize / SM_PAGE_SIZE);
     memDataInit(MEM_STOREENTRY, "StoreEntry", sizeof(StoreEntry), 0);
+    memDataInit(MEM_STORESWAPLOGDATA, "storeSwapLogData",
+	sizeof(storeSwapLogData), 0);
     memDataInit(MEM_STORE_CLIENT, "store_client", sizeof(store_client), 0);
     memDataInit(MEM_SWAPDIR, "SwapDir", sizeof(SwapDir), 0);
     memDataInit(MEM_USHORTLIST, "ushort_list", sizeof(ushortlist), 0);
Index: squid/src/mime.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/mime.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.12.1
diff -u -r1.1.1.2 -r1.1.1.2.12.1
--- squid/src/mime.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/mime.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.12.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: mime.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: mime.c,v 1.1.1.2.12.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 25    MIME Parsing
  * AUTHOR: Harvest Derived
@@ -431,9 +431,9 @@
     while ((n = read(fd, buf, 4096)) > 0)
 	storeAppend(e, buf, n);
     file_close(fd);
+    EBIT_SET(e->Sflag, ENTRY_SPECIAL);
     storeComplete(e);
     storeTimestampsSet(e);
-    EBIT_SET(e->flags, ENTRY_SPECIAL);
     debug(25, 3) ("Loaded icon %s\n", url);
     storeUnlockObject(e);
     memFree(buf, MEM_4K_BUF);
Index: squid/src/mime.conf
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/Attic/mime.conf,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.12.1
diff -u -r1.1.1.2 -r1.1.1.2.12.1
--- squid/src/mime.conf	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/mime.conf	10 Nov 2000 18:44:52 -0000	1.1.1.2.12.1
@@ -30,6 +30,8 @@
 ^internal-unknown$	-			anthony-unknown.gif	-	ascii
 ^internal-view$		-			anthony-text.gif	-	ascii
 ^internal-download$	-			anthony-box.gif		-	ascii
+^internal-closeme$	-			closeme.html		-	ascii
+^internal-tiny$		-			tiny.gif		-	ascii
 \.bin$		application/macbinary		anthony-unknown.gif		-		image
 \.oda$		application/oda			anthony-unknown.gif		-		image
 \.exe$		application/octet-stream	anthony-unknown.gif		-		image
Index: squid/src/neighbors.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/neighbors.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/neighbors.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/neighbors.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: neighbors.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: neighbors.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 15    Neighbor Routines
  * AUTHOR: Harvest Derived
@@ -381,7 +381,7 @@
     mem->ping_reply_callback = callback;
     mem->ircb_data = callback_data;
     *timeout = 0.0;
-    reqnum = icpSetCacheKey(entry->key);
+    reqnum = icpSetCacheKey(entry->Skey);
     for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
 	if (p == NULL)
 	    p = Config.peers;
@@ -393,7 +393,7 @@
 	    p->host, url);
 	if (p->type == PEER_MULTICAST)
 	    mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
-	debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->key));
+	debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->Skey));
 	debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum);
 
 #if USE_HTCP
@@ -551,7 +551,8 @@
 #endif
     return LOOKUP_NONE;
 }
-
+    if (!request->flags.hierarchical)
+	return NULL;
 /* select best peer based on cache digests */
 peer *
 neighborsDigestSelect(request_t * request, StoreEntry * entry)
@@ -578,8 +579,10 @@
 	if (lookup == LOOKUP_NONE)
 	    continue;
 	choice_count++;
-	if (lookup == LOOKUP_MISS)
+	if (lookup == LOOKUP_MISS) {
+	    cacheDigestGuessStatsUpdate(&p->digest->stats.guess, 0, 0);
 	    continue;
+	}
 	p_rtt = netdbHostRtt(p->host);
 	debug(15, 5) ("neighborsDigestSelect: peer %s rtt: %d\n",
 	    p->host, p_rtt);
@@ -760,7 +763,7 @@
 	return;
     }
     /* check if someone is already fetching it */
-    if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED)) {
+    if (EBIT_TEST(entry->Sflag, ENTRY_DISPATCHED)) {
 	debug(15, 3) ("neighborsUdpAck: '%s' already being fetched.\n",
 	    storeKeyText(key));
 	neighborCountIgnored(p);
@@ -1067,7 +1070,7 @@
     mem->ircb_data = psstate;
     mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
     p->mcast.id = mem->id;
-    reqnum = icpSetCacheKey(fake->key);
+    reqnum = icpSetCacheKey(fake->Skey);
     query = icpCreateMessage(ICP_QUERY, 0, url, reqnum, 0);
     icpUdpSend(theOutIcpConnection,
 	&p->in_addr,
@@ -1100,7 +1103,7 @@
 	p->mcast.avg_n_members,
 	p->stats.rtt);
     p->mcast.n_replies_expected = (int) p->mcast.avg_n_members;
-    EBIT_SET(fake->flags, ENTRY_ABORTED);
+    EBIT_SET(fake->Sflag, ENTRY_ABORTED);
     requestUnlink(fake->mem_obj->request);
     fake->mem_obj->request = NULL;
     storeReleaseRequest(fake);
Index: squid/src/net_db.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/net_db.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/net_db.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/net_db.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: net_db.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: net_db.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 38    Network Measurement Database
  * AUTHOR: Duane Wessels
@@ -587,7 +587,7 @@
     debug(38, 3) ("netdbExchangeHandleReply: used %d entries, (x %d bytes) == %d bytes total\n",
 	nused, rec_sz, nused * rec_sz);
     debug(38, 3) ("netdbExchangeHandleReply: seen %d, used %d\n", ex->seen, ex->used);
-    if (EBIT_TEST(ex->e->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(ex->e->Sflag, ENTRY_ABORTED)) {
 	debug(38, 3) ("netdbExchangeHandleReply: ENTRY_ABORTED\n");
 	netdbExchangeDone(ex);
     } else if (ex->e->store_status == STORE_PENDING) {
Index: squid/src/pconn.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/pconn.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.28.1
diff -u -r1.1.1.2 -r1.1.1.2.28.1
--- squid/src/pconn.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/pconn.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.28.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: pconn.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: pconn.c,v 1.1.1.2.28.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 48    Persistent Connections
  * AUTHOR: Duane Wessels
@@ -205,7 +205,7 @@
     p->fds[p->nfds++] = fd;
     commSetSelect(fd, COMM_SELECT_READ, pconnRead, p, 0);
     commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p);
-    snprintf(desc, FD_DESC_SZ, "%s idle connection", host);
+    snprintf(desc, FD_DESC_SZ, "http://%s/ idle connection", host);
     fd_note(fd, desc);
     debug(48, 3) ("pconnPush: pushed FD %d for %s\n", fd, key);
 }
Index: squid/src/peer_digest.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/peer_digest.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/peer_digest.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/peer_digest.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: peer_digest.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: peer_digest.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 72    Peer Digest Routines
  * AUTHOR: Alex Rousskov
@@ -179,8 +179,8 @@
 peerDigestNewDelay(const StoreEntry * e)
 {
     assert(e);
-    if (e->expires > 0)
-	return e->expires + PeerDigestReqMinGap - squid_curtime;
+    if (e->Sexpires > 0)
+	return e->Sexpires + PeerDigestReqMinGap - squid_curtime;
     return PeerDigestReqMinGap;
 }
 
@@ -309,11 +309,11 @@
 	storeClientListAdd(old_e, fetch);
     }
     e = fetch->entry = storeCreateEntry(url, url, req->flags, req->method);
-    assert(EBIT_TEST(e->flags, KEY_PRIVATE));
+    assert(EBIT_TEST(e->Sflag, KEY_PRIVATE));
     storeClientListAdd(e, fetch);
     /* set lastmod to trigger IMS request if possible */
     if (old_e)
-	e->lastmod = old_e->lastmod;
+	e->Slastmod = old_e->Slastmod;
 
     /* push towards peer cache */
     debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n");
@@ -540,7 +540,7 @@
 	    reason = "swap failure";
 	else if (!fetch->entry)
 	    reason = "swap aborted?!";
-	else if (EBIT_TEST(fetch->entry->flags, ENTRY_ABORTED))
+	else if (EBIT_TEST(fetch->entry->Sflag, ENTRY_ABORTED))
 	    reason = "swap aborted";
     }
     /* continue checking (maybe-successful eof case) */
@@ -715,14 +715,14 @@
     fetch->recv.bytes = fetch->entry->store_status == STORE_PENDING ?
 	mem->inmem_hi : mem->object_sz;
     fetch->sent.msg = fetch->recv.msg = 1;
-    fetch->expires = fetch->entry->expires;
+    fetch->expires = fetch->entry->Sexpires;
     fetch->resp_time = squid_curtime - fetch->start_time;
 
     debug(72, 3) ("peerDigestFetchFinish: recv %d bytes in %d secs\n",
 	fetch->recv.bytes, fetch->resp_time);
     debug(72, 3) ("peerDigestFetchFinish: expires: %d (%+d), lmt: %d (%+d)\n",
 	fetch->expires, fetch->expires - squid_curtime,
-	fetch->entry->lastmod, fetch->entry->lastmod - squid_curtime);
+	fetch->entry->Slastmod, fetch->entry->Slastmod - squid_curtime);
 }
 
 
Index: squid/src/peer_select.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/peer_select.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/peer_select.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/peer_select.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: peer_select.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: peer_select.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 44    Peer Selection Algorithm
  * AUTHOR: Duane Wessels
@@ -117,7 +117,7 @@
     debug(44, 3) ("peerSelectIcpPing: %s\n", storeUrl(entry));
     if (!request->flags.hierarchical && direct != DIRECT_NO)
 	return 0;
-    if (EBIT_TEST(entry->flags, KEY_PRIVATE) && !neighbors_do_private_keys)
+    if (EBIT_TEST(entry->Sflag, KEY_PRIVATE) && !neighbors_do_private_keys)
 	if (direct != DIRECT_NO)
 	    return 0;
     n = neighborsCount(request);
@@ -609,3 +609,22 @@
 	FS = &(*FS)->next;
     *FS = fs;
 }
+
+void
+freeFwdServer(FwdServer *fs)
+{
+    if (fs->peer)
+	cbdataUnlock(fs->peer);
+    memFree(fs, MEM_FWD_SERVER);
+}
+
+void
+freeFwdServers(FwdServer ** FS)
+{
+    FwdServer *fs;
+    while ((fs = *FS)) {
+	*FS = fs->next;
+	freeFwdServer(fs);
+    }
+}
+
Index: squid/src/protos.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/protos.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/protos.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/protos.h	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: protos.h,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -620,6 +620,8 @@
 #if USE_HTCP
 extern void neighborsHtcpReply(const cache_key *, htcpReplyData *, const struct sockaddr_in *);
 #endif
+extern void freeFwdServer(FwdServer *);
+extern void freeFwdServers(FwdServer **);
 
 extern void netdbInit(void);
 extern void netdbHandlePingReply(const struct sockaddr_in *from, int hops, int rtt);
@@ -773,6 +775,7 @@
  */
 extern StoreEntry *new_StoreEntry(int, const char *, const char *);
 extern StoreEntry *storeGet(const cache_key *);
+extern void storeHashDelete(StoreEntry *);
 extern StoreEntry *storeGetPublic(const char *uri, const method_t method);
 extern StoreEntry *storeCreateEntry(const char *, const char *, request_flags, method_t);
 extern void storeSetPublicKey(StoreEntry *);
@@ -826,7 +829,7 @@
 extern void storeAppendVPrintf(StoreEntry *, const char *, va_list ap);
 extern int storeCheckCachable(StoreEntry * e);
 extern void storeUnlinkFileno(int fileno);
-extern void storeSetPrivateKey(StoreEntry *);
+extern void storeSetPrivateKey(StoreEntry *, unsigned);
 extern int objectLen(const StoreEntry * e);
 extern int contentLen(const StoreEntry * e);
 extern HttpReply *storeEntryReply(StoreEntry *);
@@ -873,6 +876,7 @@
 /*
  * store_dir.c
  */
+extern SwapDir*getswapdir(int);
 extern char *storeSwapFullPath(int, char *);
 extern char *storeSwapSubSubDir(int, char *);
 extern int storeVerifySwapDirs(void);
@@ -886,8 +890,8 @@
 extern void storeDirCloseTmpSwapLog(int dirn);
 extern void storeDirOpenSwapLogs(void);
 extern void storeDirCloseSwapLogs(void);
-extern char *storeDirSwapLogFile(int, const char *);
-extern void storeDirSwapLog(const StoreEntry *, int op);
+extern void storeDirSwapLog(StoreEntry *, int op);
+extern storeSwapLogData *storeSwapAppendList(SwapDir*, storeSwapLogData*);
 extern int storeDirNumber(int fileno);
 extern void storeDirUpdateSwapSize(int fn, size_t size, int sign);
 extern int storeDirProperFileno(int dirn, int fn);
Index: squid/src/pump.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/Attic/pump.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/pump.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/pump.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,5 +1,5 @@
 /*
- * $Id: pump.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: pump.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 61    PUMP handler
  * AUTHOR: Kostas Anagnostakis
@@ -120,7 +120,7 @@
     request_t *r = fwd->request;
     size_t copy_sz;
     debug(61, 3) ("pumpStart: FD %d, key %s\n",
-	s_fd, storeKeyText(fwd->entry->key));
+	s_fd, storeKeyText(fwd->entry->Skey));
     /*
      * find state data generated by pumpInit in linked list
      */
@@ -205,7 +205,7 @@
 	pumpClose(p);
 	return;
     }
-    if (EBIT_TEST(p->request_entry->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(p->request_entry->Sflag, ENTRY_ABORTED)) {
 	debug(61, 5) ("pumpServerCopyComplete: ENTRY_ABORTED\n");
 	pumpClose(p);
 	return;
Index: squid/src/redirect.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/redirect.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/redirect.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/redirect.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: redirect.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: redirect.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 29    Redirector
  * AUTHOR: Duane Wessels
@@ -103,7 +103,9 @@
     cbdataAdd(r, cbdataXfree, 0);
     r->orig_url = xstrdup(http->uri);
     r->client_addr = conn->log_addr;
-    if (conn->ident == NULL || *conn->ident == '\0') {
+    if (ntohs(conn->me.sin_port) == Config.Port.bhttp) {
+	r->client_ident = "B";
+    } else if (conn->ident == NULL || *conn->ident == '\0') {
 	r->client_ident = dash_str;
     } else {
 	r->client_ident = conn->ident;
@@ -114,11 +116,11 @@
     cbdataLock(r->data);
     if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL)
 	fqdn = dash_str;
-    snprintf(buf, 8192, "%s %s/%s %s %s\n",
+    snprintf(buf, 8192, "%s %s %s/%s %s\n\n",
+	r->client_ident,
 	r->orig_url,
 	inet_ntoa(r->client_addr),
 	fqdn,
-	r->client_ident,
 	r->method_s);
     helperSubmit(redirectors, buf, redirectHandleReply, r);
 }
Index: squid/src/refresh.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/refresh.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.12.1
diff -u -r1.1.1.2 -r1.1.1.2.12.1
--- squid/src/refresh.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/refresh.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.12.1
@@ -1,7 +1,7 @@
 
 
 /*
- * $Id: refresh.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: refresh.c,v 1.1.1.2.12.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 22    Refresh Calculation
  * AUTHOR: Harvest Derived
@@ -133,7 +133,7 @@
 
     debug(22, 3) ("refreshCheck(%s): '%s'\n", rc->proto, uri ? uri : "");
     rc->total++;
-    if (EBIT_TEST(entry->flags, ENTRY_REVALIDATE)) {
+    if (EBIT_TEST(entry->Sflag, ENTRY_REVALIDATE)) {
 	debug(22, 3) ("refreshCheck: YES: Required Authorization\n");
 	rc->revalidate_stale++;
 	return 1;
@@ -156,10 +156,10 @@
 #endif
     debug(22, 3) ("refreshCheck: Matched '%s %d %d%% %d'\n",
 	pattern, (int) min, (int) (100.0 * pct), (int) max);
-    age = check_time - entry->timestamp;
+    age = check_time - entry->Stimestamp;
     debug(22, 3) ("refreshCheck: age = %d\n", (int) age);
     debug(22, 3) ("\tcheck_time:\t%s\n", mkrfc1123(check_time));
-    debug(22, 3) ("\tentry->timestamp:\t%s\n", mkrfc1123(entry->timestamp));
+    debug(22, 3) ("\tentry->Stimestamp:\t%s\n", mkrfc1123(entry->Stimestamp));
     /* request-specific checks */
     if (request) {
 #if HTTP_VIOLATIONS
@@ -202,8 +202,8 @@
 	return 0;
     }
 #endif
-    if (entry->expires > -1) {
-	if (entry->expires <= check_time) {
+    if (entry->Sexpires > -1) {
+	if (entry->Sexpires <= check_time) {
 	    debug(22, 3) ("refreshCheck: YES: expires <= curtime\n");
 	    rc->response_expires_stale++;
 	    return 1;
@@ -225,8 +225,8 @@
 	return 0;
     }
 #endif
-    if (entry->lastmod > -1 && entry->timestamp > entry->lastmod) {
-	factor = (double) age / (double) (entry->timestamp - entry->lastmod);
+    if (entry->Slastmod > -1 && entry->Stimestamp > entry->Slastmod) {
+	factor = (double) age / (double) (entry->Stimestamp - entry->Slastmod);
 	debug(22, 3) ("refreshCheck: factor = %f\n", factor);
 	if (factor < pct) {
 	    debug(22, 3) ("refreshCheck: NO: factor < pct\n");
@@ -237,11 +237,11 @@
 	    rc->last_modified_factor_stale++;
 	    return 1;
 	}
-    } else if (entry->lastmod > -1 && entry->timestamp == entry->lastmod) {
+    } else if (entry->Slastmod > -1 && entry->Stimestamp == entry->Slastmod) {
 	debug(22, 3) ("refreshCheck: YES: last-modified 'now'\n");
 	rc->response_lmt_now_stale++;
 	return 1;
-    } else if (entry->lastmod > -1 && entry->timestamp < entry->lastmod) {
+    } else if (entry->Slastmod > -1 && entry->Stimestamp < entry->Slastmod) {
 	debug(22, 3) ("refreshCheck: MAYBE: last-modified in the future\n");
 	rc->response_lmt_future_maybe++;
     }
@@ -267,7 +267,7 @@
     if (!refreshCheck(entry, NULL, 60, &refreshCounts[rcStore]))
 	/* Does not need refresh. This is certainly cachable */
 	return 1;
-    if (entry->lastmod < 0)
+    if (entry->Slastmod < 0)
 	/* Last modified is needed to do a refresh */
 	return 0;
     if (entry->mem_obj == NULL)
Index: squid/src/snmp_agent.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/snmp_agent.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.12.1
diff -u -r1.1.1.2 -r1.1.1.2.12.1
--- squid/src/snmp_agent.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/snmp_agent.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.12.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: snmp_agent.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: snmp_agent.c,v 1.1.1.2.12.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 49     SNMP Interface
  * AUTHOR: Kostas Anagnostakis
@@ -312,7 +312,11 @@
 	break;
     case PERF_SYS_CURLRUEXP:
 	Answer->type = SMI_TIMETICKS;
+#if HPL_REPL
+	*(Answer->val.integer) = 0;
+#else
 	*(Answer->val.integer) = (snint) (storeExpiredReferenceAge() * 100);
+#endif
 	break;
     case PERF_SYS_CURUNLREQ:
 	*(Answer->val.integer) = (snint) Counter.unlink.requests;
Index: squid/src/squid.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/squid.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/squid.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/squid.h	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: squid.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: squid.h,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * AUTHOR: Duane Wessels
  *
@@ -82,6 +82,9 @@
 #if HAVE_STDLIB_H
 #include 
 #endif
+#if HAVE_STDDEF_H
+#include 
+#endif
 #if HAVE_STDIO_H
 #include 
 #endif
Index: squid/src/stat.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/stat.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/stat.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/stat.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: stat.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: stat.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 18    Cache Manager Statistics
  * AUTHOR: Harvest Derived
@@ -201,7 +201,7 @@
 storeEntryFlags(const StoreEntry * entry)
 {
     LOCAL_ARRAY(char, buf, 256);
-    int flags = (int) entry->flags;
+    int flags = (int) entry->Sflag;
     char *t;
     buf[0] = '\0';
     if (EBIT_TEST(flags, ENTRY_SPECIAL))
@@ -240,10 +240,10 @@
 {
     LOCAL_ARRAY(char, buf, 256);
     snprintf(buf, 256, "LV:%-9d LU:%-9d LM:%-9d EX:%-9d",
-	(int) entry->timestamp,
-	(int) entry->lastref,
-	(int) entry->lastmod,
-	(int) entry->expires);
+	(int) entry->Stimestamp,
+	(int) entry->Slastref,
+	(int) entry->Slastmod,
+	(int) entry->Sexpires);
     return buf;
 }
 
@@ -253,7 +253,7 @@
     MemObject *mem = e->mem_obj;
     int i;
     struct _store_client *sc;
-    storeAppendPrintf(s, "KEY %s\n", storeKeyText(e->key));
+    storeAppendPrintf(s, "KEY %s\n", storeKeyText(e->Skey));
     if (mem)
 	storeAppendPrintf(s, "\t%s %s\n",
 	    RequestMethodStr[mem->method], mem->log_url);
@@ -263,9 +263,9 @@
     storeAppendPrintf(s, "\t%d locks, %d clients, %d refs\n",
 	(int) e->lock_count,
 	storePendingNClients(e),
-	(int) e->refcount);
+	(int) e->Srefcount);
     storeAppendPrintf(s, "\tSwap File %#08X\n",
-	e->swap_file_number);
+	e->Sswap_file_number);
     if (mem != NULL) {
 	storeAppendPrintf(s, "\tinmem_lo: %d\n", (int) mem->inmem_lo);
 	storeAppendPrintf(s, "\tinmem_hi: %d\n", (int) mem->inmem_hi);
@@ -311,7 +311,7 @@
 	storeUnlockObject(state->sentry);
 	cbdataFree(state);
 	return;
-    } else if (EBIT_TEST(state->sentry->flags, ENTRY_ABORTED)) {
+    } else if (EBIT_TEST(state->sentry->Sflag, ENTRY_ABORTED)) {
 	storeUnlockObject(state->sentry);
 	cbdataFree(state);
 	return;
@@ -489,8 +489,12 @@
 	store_swap_size);
     storeAppendPrintf(sentry, "\tStorage Mem size:\t%d KB\n",
 	(int) (store_mem_size >> 10));
+    #ifdef	HPL_REPL
+    /* The non-LRU policies do not use referenceAge */
+    #else	/* HPL_REPL */
     storeAppendPrintf(sentry, "\tStorage LRU Expiration Age:\t%6.2f days\n",
 	(double) storeExpiredReferenceAge() / 86400.0);
+    #endif	/* HPL_REPL */
     storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n",
 	n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0);
     storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%d\n",
@@ -603,6 +607,8 @@
 	memInUse(MEM_STOREENTRY));
     storeAppendPrintf(sentry, "\t%6d StoreEntries with MemObjects\n",
 	memInUse(MEM_MEMOBJECT));
+    storeAppendPrintf(sentry, "\t%6d storeSwapLogData temporaries\n",
+	memInUse(MEM_STORESWAPLOGDATA));
     storeAppendPrintf(sentry, "\t%6d Hot Object Cache Items\n",
 	hot_obj_count);
     storeAppendPrintf(sentry, "\t%6d Filemap bits set\n",
@@ -824,9 +830,11 @@
     cachemgrRegister("filedescriptors",
 	"Process Filedescriptor Allocation",
 	statFiledescriptors, 0, 1);
+#ifdef DEBUG_ALLOBJECTS
     cachemgrRegister("objects",
 	"All Cache Objects",
 	stat_objects_get, 0, 0);
+#endif
     cachemgrRegister("vm_objects",
 	"In-Memory and In-Transit Objects",
 	stat_vmobjects_get, 0, 0);
@@ -1336,9 +1344,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->key) : "N/A");
+	storeAppendPrintf(s, "entry %p/%s\n", e, e ? storeKeyText(e->Skey) : "N/A");
 	e = http->old_entry;
-	storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? storeKeyText(e->key) : "N/A");
+	storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? storeKeyText(e->Skey) : "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
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/store.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/store.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: store.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 20    Storage Manager
  * AUTHOR: Harvest Derived
@@ -35,6 +35,10 @@
 
 #include "squid.h"
 
+#ifdef	HPL_REPL
+#include "heap.h"
+#endif	/* HPL_REPL */
+
 #define REBUILD_TIMESTAMP_DELTA_MAX 2
 
 #define STORE_IN_MEM_BUCKETS		(229)
@@ -79,7 +83,6 @@
 static int storeEntryLocked(const StoreEntry *);
 static int storeEntryValidLength(const StoreEntry *);
 static void storeGetMemSpace(int);
-static void storeHashDelete(StoreEntry *);
 static MemObject *new_MemObject(const char *, const char *);
 static void destroy_MemObject(StoreEntry *);
 static FREE destroy_StoreEntry;
@@ -92,7 +95,14 @@
 /*
  * local variables
  */
+#ifdef	HPL_REPL
+/*
+ * The heap equivalent of inmem_list, inmem_heap, is in globals.c so other
+ * modules can access it when updating object metadata (e.g., refcount)
+ */
+#else	/* HPL_REPL */
 static dlink_list inmem_list;
+#endif	/* HPL_REPL */
 static int store_pages_max = 0;
 static int store_swap_high = 0;
 static int store_swap_low = 0;
@@ -110,6 +120,9 @@
     mem->swapout.fd = -1;
     mem->object_sz = -1;
     mem->fd = -1;
+#if HPL_REPL
+    mem->n.ode.id = -1;
+#endif
     /* XXX account log_url */
     debug(20, 3) ("new_MemObject: returning %p\n", mem);
     return mem;
@@ -120,10 +133,18 @@
 {
     StoreEntry *e = NULL;
     e = memAllocate(MEM_STOREENTRY);
-    if (mem_obj_flag)
+    if (mem_obj_flag) {
 	e->mem_obj = new_MemObject(url, log_url);
+#if HPL_REPL
+	e->mem_obj->entry = e;
+#endif
+        e->s = memAllocate(MEM_STORESWAPLOGDATA);
+        e->Sexpires = e->Slastmod = e->Slastref = e->Stimestamp = -1;
+    }
+#if HPL_REPL
+    e->n.ode.id = -1;
+#endif
     debug(20, 3) ("new_StoreEntry: returning %p\n", e);
-    e->expires = e->lastmod = e->lastref = e->timestamp = -1;
     return e;
 }
 
@@ -132,7 +153,7 @@
 {
     MemObject *mem = e->mem_obj;
     const Ctx ctx = ctx_enter(mem->url);
-    debug(20, 3) ("destroy_MemObject: destroying %p\n", mem);
+    debug(20, 4) ("destroy_MemObject: destroying %p\n", mem);
     e->mem_obj = NULL;
     if (!shutting_down)
 	assert(mem->swapout.fd == -1);
@@ -161,12 +182,16 @@
 destroy_StoreEntry(void *data)
 {
     StoreEntry *e = data;
-    debug(20, 3) ("destroy_StoreEntry: destroying %p\n", e);
+    debug(20, 4) ("destroy_StoreEntry: destroying %p\n", e);
     assert(e != NULL);
     if (e->mem_obj)
 	destroy_MemObject(e);
     storeHashDelete(e);
-    assert(e->key == NULL);
+    if (e->s)
+	destroy_storeSwapLogData(e->s);
+#ifndef MMAPSTORE
+    assert(e->Skey == NULL);
+#endif
     memFree(e, MEM_STOREENTRY);
 }
 
@@ -177,18 +202,33 @@
 {
     debug(20, 3) ("storeHashInsert: Inserting Entry %p key '%s'\n",
 	e, storeKeyText(key));
-    e->key = storeKeyDup(key);
-    hash_join(store_table, (hash_link *) e);
+#ifdef MMAPSTORE
+    if (key != e->s->key)
+	xmemcpy(e->s->key, key, MD5_DIGEST_CHARS);
+#else
+    e->Skey = storeKeyDup(key);
+#endif
+    if(hash_join(store_table, (hash_link *) e))
+	debug(20, 0) ("storeHashInsert: duplicate entry %p %s\n",e,storeUrl(e));
+    if (e->Sswap_file_number < 0)
+	return;
+    #if	!HPL_REPL
     dlinkAdd(e, &e->lru, &store_list);
+    #endif	/* HPL_REPL */
 }
 
-static void
+void
 storeHashDelete(StoreEntry * e)
 {
-    hash_remove_link(store_table, (hash_link *) e);
+    if(hash_remove_link(store_table, (hash_link *) e))
+	debug(20, 2) ("storeHashDelete: missing entry %p %s\n",e,storeUrl(e));
+    #if	!HPL_REPL
     dlinkDelete(&e->lru, &store_list);
-    storeKeyFree(e->key);
-    e->key = NULL;
+    #endif	/* HPL_REPL */
+#ifndef MMAPSTORE
+    storeKeyFree(e->Skey);
+    e->Skey = NULL;
+#endif
 }
 
 /* -------------------------------------------------------------------------- */
@@ -202,7 +242,7 @@
     if (e->mem_obj == NULL)
 	return;
     debug(20, 3) ("storePurgeMem: Freeing memory-copy of %s\n",
-	storeKeyText(e->key));
+	storeKeyText(e->Skey));
     storeSetMemStatus(e, NOT_IN_MEMORY);
     destroy_MemObject(e);
     if (e->swap_status != SWAPOUT_DONE)
@@ -213,28 +253,37 @@
 storeLockObject(StoreEntry * e)
 {
     if (e->lock_count++ == 0) {
+      #ifdef	HPL_REPL
+      /* there is no reason to take any action here.
+	 Squid by default is moving locked objects to the end of the LRU
+	 list to keep them from getting bumped into by the replacement
+	 algorithm.  We can't do that so we will just have to handle them.
+      */
+      debug(20, 4) ("storeLockObject: just locked node %d\n", e->n.ode.id);
+      #else	/* HPL_REPL */
 	dlinkDelete(&e->lru, &store_list);
 	dlinkAdd(e, &e->lru, &store_list);
+      #endif	/* HPL_REPL */
     }
-    debug(20, 3) ("storeLockObject: key '%s' count=%d\n",
-	storeKeyText(e->key), (int) e->lock_count);
-    e->lastref = squid_curtime;
+    debug(20, 4) ("storeLockObject: key '%s' count=%d\n",
+	storeKeyText(e->Skey), (int) e->lock_count);
+    e->Slastref = squid_curtime;
 }
 
 void
 storeReleaseRequest(StoreEntry * e)
 {
-    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
+    if (EBIT_TEST(e->Sflag, RELEASE_REQUEST))
 	return;
-    debug(20, 3) ("storeReleaseRequest: '%s'\n", storeKeyText(e->key));
-    EBIT_SET(e->flags, RELEASE_REQUEST);
+    debug(20, 3) ("storeReleaseRequest: '%s'\n", storeKeyText(e->Skey));
+    EBIT_SET(e->Sflag, RELEASE_REQUEST);
     /*
      * Clear cachable flag here because we might get called before
      * anyone else even looks at the cachability flag.  Also, this
      * prevents httpMakePublic from really setting a public key.
      */
-    EBIT_CLR(e->flags, ENTRY_CACHABLE);
-    storeSetPrivateKey(e);
+    EBIT_CLR(e->Sflag, ENTRY_CACHABLE);
+    storeSetPrivateKey(e, 1);
 }
 
 /* unlock object, return -1 if object get released after unlock
@@ -244,13 +293,13 @@
 {
     e->lock_count--;
     debug(20, 3) ("storeUnlockObject: key '%s' count=%d\n",
-	storeKeyText(e->key), e->lock_count);
+	storeKeyText(e->Skey), e->lock_count);
     if (e->lock_count)
 	return (int) e->lock_count;
     if (e->store_status == STORE_PENDING)
-	EBIT_SET(e->flags, RELEASE_REQUEST);
+	EBIT_SET(e->Sflag, RELEASE_REQUEST);
     assert(storePendingNClients(e) == 0);
-    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
+    if (EBIT_TEST(e->Sflag, RELEASE_REQUEST))
 	storeRelease(e);
     else if (storeKeepInMemory(e)) {
 	storeSetMemStatus(e, IN_MEMORY);
@@ -258,9 +307,17 @@
 	e->mem_obj->request = NULL;
     } else {
 	storePurgeMem(e);
-	if (EBIT_TEST(e->flags, KEY_PRIVATE)) {
+	if (EBIT_TEST(e->Sflag, KEY_PRIVATE)) {
+        #ifdef	HPL_REPL
+        /*
+         * Squid/LRU is moving things around in the linked list in order
+         * to keep from bumping into them when purging from the LRU list.
+         */
+        debug(20, 4) ("storeUnlockObject: purged private node %d\n", e->n.ode.id);
+        #else	/* HPL_REPL */
 	    dlinkDelete(&e->lru, &store_list);
 	    dlinkAddTail(e, &e->lru, &store_list);
+        #endif	/* HPL_REPL */
 	}
     }
     return 0;
@@ -291,17 +348,16 @@
 }
 
 void
-storeSetPrivateKey(StoreEntry * e)
+storeSetPrivateKey(StoreEntry * e, unsigned hashed)
 {
     const cache_key *newkey;
     MemObject *mem = e->mem_obj;
-    if (e->key && EBIT_TEST(e->flags, KEY_PRIVATE))
+    if (EBIT_TEST(e->Sflag, KEY_PRIVATE))
 	return;			/* is already private */
-    if (e->key) {
-	if (e->swap_file_number > -1)
+    if (e->Sswap_file_number > -1)
 	    storeDirSwapLog(e, SWAP_LOG_DEL);
+    if (hashed)
 	storeHashDelete(e);
-    }
     if (mem != NULL) {
 	mem->id = getKeyCounter();
 	newkey = storeKeyPrivate(mem->url, mem->method, mem->id);
@@ -309,7 +365,7 @@
 	newkey = storeKeyPrivate("JUNK", METHOD_NONE, getKeyCounter());
     }
     assert(hash_lookup(store_table, newkey) == NULL);
-    EBIT_SET(e->flags, KEY_PRIVATE);
+    EBIT_SET(e->Sflag, KEY_PRIVATE);
     storeHashInsert(e, newkey);
 }
 
@@ -319,7 +375,7 @@
     StoreEntry *e2 = NULL;
     const cache_key *newkey;
     MemObject *mem = e->mem_obj;
-    if (e->key && !EBIT_TEST(e->flags, KEY_PRIVATE))
+    if (!EBIT_TEST(e->Sflag, KEY_PRIVATE))
 	return;			/* is already public */
     assert(mem);
     /*
@@ -332,19 +388,22 @@
      * If RELEASE_REQUEST is set, then ENTRY_CACHABLE should not
      * be set, and storeSetPublicKey() should not be called.
      */
-    assert(!EBIT_TEST(e->flags, RELEASE_REQUEST));
+#ifdef	HPL_REPL_DEBUG
+    if (EBIT_TEST(e->Sflag, RELEASE_REQUEST))
+	    debug(20, 1) ("assertion failed: RELEASE key %s, url %s\n", e->Skey, mem->url);
+#endif	/* HPL_REPL */
+    assert(!EBIT_TEST(e->Sflag, RELEASE_REQUEST));
     newkey = storeKeyPublic(mem->url, mem->method);
     if ((e2 = (StoreEntry *) hash_lookup(store_table, newkey))) {
 	debug(20, 3) ("storeSetPublicKey: Making old '%s' private.\n", mem->url);
-	storeSetPrivateKey(e2);
+	storeSetPrivateKey(e2, 1);
 	storeRelease(e2);
 	newkey = storeKeyPublic(mem->url, mem->method);
     }
-    if (e->key)
 	storeHashDelete(e);
-    EBIT_CLR(e->flags, KEY_PRIVATE);
+    EBIT_CLR(e->Sflag, KEY_PRIVATE);
     storeHashInsert(e, newkey);
-    if (e->swap_file_number > -1)
+    if (e->Sswap_file_number > -1)
 	storeDirSwapLog(e, SWAP_LOG_ADD);
 }
 
@@ -359,26 +418,26 @@
     e->lock_count = 1;		/* Note lock here w/o calling storeLock() */
     mem = e->mem_obj;
     mem->method = method;
+    e->Sswap_file_number = -1;
     if (neighbors_do_private_keys || !flags.hierarchical)
-	storeSetPrivateKey(e);
+	storeSetPrivateKey(e, 0);
     else
 	storeSetPublicKey(e);
     if (flags.cachable) {
-	EBIT_SET(e->flags, ENTRY_CACHABLE);
-	EBIT_CLR(e->flags, RELEASE_REQUEST);
+	EBIT_SET(e->Sflag, ENTRY_CACHABLE);
+	EBIT_CLR(e->Sflag, RELEASE_REQUEST);
     } else {
-	EBIT_CLR(e->flags, ENTRY_CACHABLE);
+	EBIT_CLR(e->Sflag, ENTRY_CACHABLE);
 	storeReleaseRequest(e);
     }
     e->store_status = STORE_PENDING;
     storeSetMemStatus(e, NOT_IN_MEMORY);
     e->swap_status = SWAPOUT_NONE;
-    e->swap_file_number = -1;
-    e->refcount = 0;
-    e->lastref = squid_curtime;
-    e->timestamp = 0;		/* set in storeTimestampsSet() */
+    e->Srefcount = 0;
+    e->Slastref = squid_curtime;
+    e->Stimestamp = 0;		/* set in storeTimestampsSet() */
     e->ping_status = PING_NONE;
-    EBIT_SET(e->flags, ENTRY_VALIDATED);
+    EBIT_SET(e->Sflag, ENTRY_VALIDATED);
     return e;
 }
 
@@ -386,8 +445,8 @@
 void
 storeExpireNow(StoreEntry * e)
 {
-    debug(20, 3) ("storeExpireNow: '%s'\n", storeKeyText(e->key));
-    e->expires = squid_curtime;
+    debug(20, 3) ("storeExpireNow: '%s'\n", storeKeyText(e->Skey));
+    e->Sexpires = squid_curtime;
 }
 
 /* Append incoming data from a primary server to an entry. */
@@ -399,14 +458,14 @@
     assert(len >= 0);
     assert(e->store_status == STORE_PENDING);
     if (len) {
-	debug(20, 5) ("storeAppend: appending %d bytes for '%s'\n",
+	debug(20, 6) ("storeAppend: appending %d bytes for '%s'\n",
 	    len,
-	    storeKeyText(e->key));
+	    storeKeyText(e->Skey));
 	storeGetMemSpace(len);
 	stmemAppend(&mem->data_hdr, buf, len);
 	mem->inmem_hi += len;
     }
-    if (EBIT_TEST(e->flags, DELAY_SENDING))
+    if (EBIT_TEST(e->Sflag, DELAY_SENDING))
 	return;
 #ifdef OPTIMISTIC_IO
     storeLockObject(e);
@@ -488,23 +547,25 @@
 	store_check_cachable_hist.no.non_get++;
     } else
 #endif
-    if (!EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
+    if (!EBIT_TEST(e->Sflag, ENTRY_CACHABLE)) {
 	debug(20, 2) ("storeCheckCachable: NO: not cachable\n");
 	store_check_cachable_hist.no.not_entry_cachable++;
-    } else if (EBIT_TEST(e->flags, RELEASE_REQUEST)) {
+    } else if (EBIT_TEST(e->Sflag, RELEASE_REQUEST)) {
 	debug(20, 2) ("storeCheckCachable: NO: release requested\n");
 	store_check_cachable_hist.no.release_request++;
-    } else if (e->store_status == STORE_OK && EBIT_TEST(e->flags, ENTRY_BAD_LENGTH)) {
+    } else if (e->store_status == STORE_OK && EBIT_TEST(e->Sflag, ENTRY_BAD_LENGTH)) {
 	debug(20, 2) ("storeCheckCachable: NO: wrong content-length\n");
 	store_check_cachable_hist.no.wrong_content_length++;
-    } else if (EBIT_TEST(e->flags, ENTRY_NEGCACHED)) {
+    } else if (EBIT_TEST(e->Sflag, ENTRY_NEGCACHED)) {
 	debug(20, 3) ("storeCheckCachable: NO: negative cached\n");
 	store_check_cachable_hist.no.negative_cached++;
 	return 0;		/* avoid release call below */
-    } else if (e->mem_obj->inmem_hi > Config.Store.maxObjectSize) {
+    } else if ((e->mem_obj->reply->content_length > 0 &&
+		e->mem_obj->reply->content_length > Config.Store.maxObjectSize) ||
+		e->mem_obj->inmem_hi > Config.Store.maxObjectSize) {
 	debug(20, 2) ("storeCheckCachable: NO: too big\n");
 	store_check_cachable_hist.no.too_big++;
-    } else if (EBIT_TEST(e->flags, KEY_PRIVATE)) {
+    } else if (EBIT_TEST(e->Sflag, KEY_PRIVATE)) {
 	debug(20, 3) ("storeCheckCachable: NO: private key\n");
 	store_check_cachable_hist.no.private_key++;
     } else if (e->swap_status != SWAPOUT_NONE) {
@@ -515,21 +576,28 @@
 	 */
 	return 1;
     } else if (storeTooManyDiskFilesOpen()) {
-	debug(20, 2) ("storeCheckCachable: NO: too many disk files open\n");
+	debug(20, 3) ("storeCheckCachable: NO: too many disk files open\n");
 	store_check_cachable_hist.no.too_many_open_files++;
     } else if (fdNFree() < RESERVED_FD) {
-	debug(20, 2) ("storeCheckCachable: NO: too many FD's open\n");
+	debug(20, 3) ("storeCheckCachable: NO: too many FD's open\n");
 	store_check_cachable_hist.no.too_many_open_fds++;
+#ifdef	HPL_REPL
+    /*
+     * With the HPL replacement policies a low reference age should not
+     * prevent cacheability of an object.  We do not use LRU age at all.
+     */
+#else	/* HPL_REPL */
     } else if (storeExpiredReferenceAge() < 300) {
-	debug(20, 2) ("storeCheckCachable: NO: LRU Age = %d\n",
+	debug(20, 3) ("storeCheckCachable: NO: LRU Age = %d\n",
 	    storeExpiredReferenceAge());
 	store_check_cachable_hist.no.lru_age_too_low++;
+#endif	/* HPL_REPL */
     } else {
 	store_check_cachable_hist.yes.Default++;
 	return 1;
     }
     storeReleaseRequest(e);
-    EBIT_CLR(e->flags, ENTRY_CACHABLE);
+    EBIT_CLR(e->Sflag, ENTRY_CACHABLE);
     return 0;
 }
 
@@ -566,13 +634,13 @@
 void
 storeComplete(StoreEntry * e)
 {
-    debug(20, 3) ("storeComplete: '%s'\n", storeKeyText(e->key));
+    debug(20, 3) ("storeComplete: '%s'\n", storeKeyText(e->Skey));
     if (e->store_status != STORE_PENDING) {
 	/*
 	 * if we're not STORE_PENDING, then probably we got aborted
 	 * and there should be NO clients on this entry
 	 */
-	assert(EBIT_TEST(e->flags, ENTRY_ABORTED));
+	assert(EBIT_TEST(e->Sflag, ENTRY_ABORTED));
 	assert(e->mem_obj->nclients == 0);
 	return;
     }
@@ -580,7 +648,7 @@
     e->store_status = STORE_OK;
     assert(e->mem_status == NOT_IN_MEMORY);
     if (!storeEntryValidLength(e)) {
-	EBIT_SET(e->flags, ENTRY_BAD_LENGTH);
+	EBIT_SET(e->Sflag, ENTRY_BAD_LENGTH);
 	storeReleaseRequest(e);
     }
 #if USE_CACHE_DIGESTS
@@ -602,11 +670,11 @@
     MemObject *mem = e->mem_obj;
     assert(e->store_status == STORE_PENDING);
     assert(mem != NULL);
-    debug(20, 6) ("storeAbort: %s\n", storeKeyText(e->key));
+    debug(20, 6) ("storeAbort: %s\n", storeKeyText(e->Skey));
     storeLockObject(e);		/* lock while aborting */
     storeNegativeCache(e);
     storeReleaseRequest(e);
-    EBIT_SET(e->flags, ENTRY_ABORTED);
+    EBIT_SET(e->Sflag, ENTRY_ABORTED);
     storeSetMemStatus(e, NOT_IN_MEMORY);
     /* No DISK swap for negative cached object */
     e->swap_status = SWAPOUT_NONE;
@@ -634,7 +702,7 @@
 #if USE_ASYNC_IO
     aioCancel(-1, e);
 #endif
-    if (e->swap_file_number > -1) {
+    if (e->Sswap_file_number > -1) {
 #if USE_ASYNC_IO
 	/* Need to cancel any pending ASYNC writes right now */
 	if (mem->swapout.fd >= 0)
@@ -656,17 +724,63 @@
     static time_t last_check = 0;
     int pages_needed;
     dlink_node *m;
-    dlink_node *head;
     dlink_node *prev = NULL;
+    int locked = 0;
+    #ifdef	HPL_REPL
+    heap_p heap = inmem_heap;
+    _HEAPKEY age, min_age = 0;
+    MemObject *locked_entries = NULL;
+    MemObject *mo;
+    #else	/* HPL_REPL */
+    dlink_node *head;
+    #endif	/* HPL_REPL */
+
     if (squid_curtime == last_check)
 	return;
     last_check = squid_curtime;
     pages_needed = (size / SM_PAGE_SIZE) + 1;
+    debug(20, 3) ("storeGetMemSpace: inuse %d, need %d, have %d\n",
+		  memInUse(MEM_STMEM_BUF), pages_needed, store_pages_max);
     if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max)
 	return;
     if (store_rebuilding)
 	return;
     debug(20, 2) ("storeGetMemSpace: Starting, need %d pages\n", pages_needed);
+    #ifdef	HPL_REPL
+    while (heap_nodes(heap) > 0) {
+        age = heap_peepminkey(heap);
+	mo = heap_extractmin(heap);
+	e = mo->entry;
+	if (storeEntryLocked(e)) {
+	  locked++;
+	  debug(20, 5) ("storeGetMemSpace: locked key %s\n", storeKeyText(e->Skey));
+	  mo->n.ext = locked_entries;
+	  locked_entries = mo;
+	  continue;
+	}
+	mo->n.ode.id = -1;		/* no longer in the heap */
+	released++;
+	debug(20, 3) ("Released memory object with key %f size %d refs %d url %s\n",
+		age, e->Sswap_file_sz, e->Srefcount, e->mem_obj->url);
+	min_age = age;
+	storePurgeMem(e);
+	if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max)
+	    break;
+    }
+    /*
+     * Increase the heap age factor.
+     */
+    if (min_age > 0)
+      heap->age = min_age;
+    /*
+     * Reinsert all bumped locked entries back into heap...
+     */
+    while (mo = locked_entries) {
+      locked_entries = mo->n.ext;
+      heap_insert(heap, mo);
+    }
+
+    #else	/* HPL_REPL */
     head = inmem_list.head;
     for (m = inmem_list.tail; m; m = prev) {
 	if (m == head)
@@ -674,6 +788,7 @@
 	prev = m->prev;
 	e = m->data;
 	if (storeEntryLocked(e)) {
+	    locked++;
 	    dlinkDelete(m, &inmem_list);
 	    dlinkAdd(e, m, &inmem_list);
 	    continue;
@@ -683,9 +798,12 @@
 	if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max)
 	    break;
     }
-    debug(20, 3) ("storeGetMemSpace stats:\n");
-    debug(20, 3) ("  %6d HOT objects\n", hot_obj_count);
-    debug(20, 3) ("  %6d were released\n", released);
+    #endif	/* HPL_REPL */
+    debug(20, 3) ("storeGetMemSpace: released %d/%d locked %d\n",
+		  released, hot_obj_count, locked);
+    debug(20, 4) ("storeGetMemSpace stats:\n");
+    debug(20, 4) ("  %6d HOT objects\n", hot_obj_count);
+    debug(20, 4) ("  %6d were released\n", released);
 }
 
 /* The maximum objects to scan for maintain storage space */
@@ -709,26 +827,150 @@
     int locked = 0;
     int expired = 0;
     int max_scan;
-    int max_remove;
-    double f;
     static time_t last_warn_time = 0;
+    SwapDir *SD;
+    unsigned i;
+    #ifdef	HPL_REPL
+
+    #ifdef	HPL_REPL_DEBUG
+    if (!verify_heap_property(store_heap)) {
+	debug(20, 1) ("Heap property violated!\n");
+    }
+    #endif	/* HPL_REPL_DEBUG */
+    #endif	/* HPL_REPL */
+
     /* We can't delete objects while rebuilding swap */
     if (store_rebuilding) {
 	eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0, 1);
 	return;
     } else {
-	f = (double) (store_swap_size - store_swap_low) / (store_swap_high - store_swap_low);
+        double f;
+	f = ((double) (store_swap_size - store_swap_low) /
+	     (store_swap_high - store_swap_low));
 	f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f;
 	max_scan = (int) (f * 400.0 + 100.0);
-	max_remove = (int) (f * 70.0 + 10.0);
-	eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0 - f, 1);
+	eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 10*(1.0 - f), 1);
+    }
+
+#if 0
+    if (store_swap_size < store_swap_low) {
+        /* Just return since we still have enougy memory */
+        return; 
     }
-    debug(20, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n",
-	f, max_scan, max_remove);
+#endif
+    {
+        int dirmax = -1;
+	unsigned long dirmaxval = 0;
+
+	for (SD = Config.cacheSwap.swapDirs +
+	     (i = Config.cacheSwap.n_configured); i--; ) {
+	    (--SD)->riddance = 0;
+	    if (!SD->flags.read_only && SD->cur_size >= SD->low_size) {
+		unsigned long tval;
+		tval = (SD->cur_size - SD->low_size) / SD->win_size;
+		if (tval > dirmaxval)
+		    dirmaxval = tval, dirmax = i;
+		SD->riddance = (40 * tval) >> STORE_GRAN_ORDER;
+	        debug(20, 4) ("storeMaintainSwapSpace: Remove %d in swapdir %s\n",
+		 SD->riddance, SD->path);
+	    }
+	}
+	if (dirmax >= 0) {
+	    SD[dirmax].riddance += 10;
+	    debug(20, 3) ("storeMaintainSwapSpace: Aggressive reduction for swapdir %s\n",
+		Config.cacheSwap.swapDirs[dirmax].path);
+	}
+    }
+
+    debug(20, 2) ("storeMaintainSwapSpace: Starting, max_scan=%d\n",
+	max_scan);
+
+#ifdef	HPL_REPL
+
+    for (i = Config.cacheSwap.n_configured; i--; SD++) {
+        heap_p heap = SD->heap;
+        _HEAPKEY age, min_age;
+        StoreEntry *locked_entries;
+	if (!SD->riddance)
+	   continue;
+	min_age = 0; locked_entries = 0;
+    while (heap_nodes(heap) > 0) {
+        age = heap_peepminkey(heap);
+	e = heap_extractmin(heap);
+	e->n.ode.id = -1;				/* no longer in the heap */
+	scanned++;
+	if (storeEntryLocked(e)) {
+	    /*
+	     * Entry is in use ... put it in a linked list to ignore it.
+	     */
+#if 0	/* we're never inserting specials, so don't check for it */
+	    if (!EBIT_TEST(e->Sflag, ENTRY_SPECIAL))
+#else
+	    assert(!EBIT_TEST(e->Sflag, ENTRY_SPECIAL));
+#endif
+	    {
+		/*
+		 * If this was a "SPECIAL" do not add it back into the heap.
+		 * It will always be "SPECIAL" and therefore never removed.
+		 */
+		debug(20, 4) ("storeMaintainSwapSpace: locked url %s\n",
+			      (e->mem_obj && e->mem_obj->url) ? e->mem_obj->url : storeKeyText(e->Skey));
+		e->n.ext = locked_entries;
+		locked_entries = e;
+	    }
+	    locked++;
+	    continue;
+	} else if (storeCheckExpired(e)) {
+	    /*
+	     * Note: This will not check the reference age ifdef HPL_REPL,
+	     * but it does some other useful checks...
+	     */
+	    expired++;
+	    debug(20, 3) ("Released store object age %f size %d refs %d key %s\n",
+			  age, e->Sswap_file_sz, e->Srefcount, storeKeyText(e->Skey));
+	    min_age = age;
+	    storeRelease(e);
+	} else {
+	    /*
+	     * Did not expire the object so we need to add it back into the heap!
+	     */
+	    debug(20, 5) ("storeMaintainSwapSpace: non-expired %s\n", storeKeyText(e->Skey));
+	    e->n.ext = locked_entries;
+	    locked_entries = e;
+	    continue;
+	}
+	if (SD->cur_size <= SD->low_size
+	    || expired >= SD->riddance
+	    || scanned >= max_scan)
+	    break;
+    }
+    /*
+     * Bump the heap age factor.
+     */
+    if (min_age > 0)
+	heap->age = min_age;
+
+    /*
+     * Reinsert all bumped locked entries back into heap...
+     */
+    while (e = locked_entries) {
+      locked_entries = e->n.ext;
+      heap_insert(heap, e);
+    }
+    }
+
+#else	/* HPL_REPL */
+
     for (m = store_list.tail; m; m = prev) {
+	unsigned dirn;
 	prev = m->prev;
 	e = m->data;
-	scanned++;
+	dirn = e->Sswap_file_number >> SWAP_DIR_SHIFT;
+	if (dirn == dirmax) {
+	    if (ext_max_scan-- < 0)
+		break;
+	} else if (++scanned >= max_scan)
+	    goto enough;
 	if (storeEntryLocked(e)) {
 	    /*
 	     * If there is a locked entry at the tail of the LRU list,
@@ -743,19 +985,27 @@
 	    }
 	    locked++;
 	} else if (storeCheckExpired(e)) {
+	    if (dirn == dirmax)
+		min_removehigh--;
 	    expired++;
 	    storeRelease(e);
 	}
 	if (expired >= max_remove)
-	    break;
+	    goto enough;
 	if (scanned >= max_scan)
+enough:	   if (min_removehigh <= 0)
 	    break;
     }
-    debug(20, 3) ("storeMaintainSwapSpace stats:\n");
-    debug(20, 3) ("  %6d objects\n", memInUse(MEM_STOREENTRY));
-    debug(20, 3) ("  %6d were scanned\n", scanned);
-    debug(20, 3) ("  %6d were locked\n", locked);
-    debug(20, 3) ("  %6d were expired\n", expired);
+
+#endif	/* HPL_REPL */
+
+    debug(20, (expired?2:3)) ("storeMaintainSwapSpace: scanned %d/%d removed %d locked %d\n",
+		  scanned, max_scan, expired, locked);
+    debug(20, 4) ("storeMaintainSwapSpace stats:\n");
+    debug(20, 4) ("  %6d objects\n", memInUse(MEM_STOREENTRY));
+    debug(20, 4) ("  %6d were scanned\n", scanned);
+    debug(20, 4) ("  %6d were locked\n", locked);
+    debug(20, 4) ("  %6d were expired\n", expired);
     if (store_swap_size < Config.Swap.maxSize)
 	return;
     if (squid_curtime - last_warn_time < 10)
@@ -771,7 +1021,7 @@
 void
 storeRelease(StoreEntry * e)
 {
-    debug(20, 3) ("storeRelease: Releasing: '%s'\n", storeKeyText(e->key));
+    debug(20, 3) ("storeRelease: Releasing: '%s'\n", storeKeyText(e->Skey));
     /* If, for any reason we can't discard this object because of an
      * outstanding request, mark it for pending release */
     if (storeEntryLocked(e)) {
@@ -787,7 +1037,7 @@
     aioCancel(-1, e);
 #endif
     if (store_rebuilding) {
-	storeSetPrivateKey(e);
+	storeSetPrivateKey(e, 1);
 	if (e->mem_obj) {
 	    storeSetMemStatus(e, NOT_IN_MEMORY);
 	    destroy_MemObject(e);
@@ -801,14 +1051,15 @@
 	return;
     }
     storeLog(STORE_LOG_RELEASE, e);
-    if (e->swap_file_number > -1) {
-	storeUnlinkFileno(e->swap_file_number);
-	storeDirMapBitReset(e->swap_file_number);
+    if (e->Sswap_file_number > -1) {
+	storeUnlinkFileno(e->Sswap_file_number);
+	storeDirMapBitReset(e->Sswap_file_number);
 	if (e->swap_status == SWAPOUT_DONE)
-	    if (EBIT_TEST(e->flags, ENTRY_VALIDATED))
-		storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, -1);
-	if (!EBIT_TEST(e->flags, KEY_PRIVATE))
+	    if (EBIT_TEST(e->Sflag, ENTRY_VALIDATED))
+		storeDirUpdateSwapSize(e->Sswap_file_number, e->Sswap_file_sz, -1);
+	if (!EBIT_TEST(e->Sflag, KEY_PRIVATE))
 	    storeDirSwapLog(e, SWAP_LOG_DEL);
+	set_swap_file_number(e, -1);
     }
     storeSetMemStatus(e, NOT_IN_MEMORY);
     destroy_StoreEntry(e);
@@ -852,8 +1103,8 @@
     /*
      * SPECIAL, PUBLIC entries should be "locked"
      */
-    if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
-	if (!EBIT_TEST(e->flags, KEY_PRIVATE))
+    if (EBIT_TEST(e->Sflag, ENTRY_SPECIAL))
+	if (!EBIT_TEST(e->Sflag, KEY_PRIVATE))
 	    return 1;
     return 0;
 }
@@ -865,7 +1116,7 @@
     const HttpReply *reply;
     assert(e->mem_obj != NULL);
     reply = e->mem_obj->reply;
-    debug(20, 3) ("storeEntryValidLength: Checking '%s'\n", storeKeyText(e->key));
+    debug(20, 3) ("storeEntryValidLength: Checking '%s'\n", storeKeyText(e->Skey));
     debug(20, 5) ("storeEntryValidLength:     object_len = %d\n",
 	objectLen(e));
     debug(20, 5) ("storeEntryValidLength:         hdr_sz = %d\n",
@@ -874,17 +1125,17 @@
 	reply->content_length);
     if (reply->content_length < 0) {
 	debug(20, 5) ("storeEntryValidLength: Unspecified content length: %s\n",
-	    storeKeyText(e->key));
+	    storeKeyText(e->Skey));
 	return 1;
     }
     if (reply->hdr_sz == 0) {
 	debug(20, 5) ("storeEntryValidLength: Zero header size: %s\n",
-	    storeKeyText(e->key));
+	    storeKeyText(e->Skey));
 	return 1;
     }
     if (e->mem_obj->method == METHOD_HEAD) {
 	debug(20, 5) ("storeEntryValidLength: HEAD request: %s\n",
-	    storeKeyText(e->key));
+	    storeKeyText(e->Skey));
 	return 1;
     }
     if (reply->sline.status == HTTP_NOT_MODIFIED)
@@ -894,10 +1145,10 @@
     diff = reply->hdr_sz + reply->content_length - objectLen(e);
     if (diff == 0)
 	return 1;
-    debug(20, 3) ("storeEntryValidLength: %d bytes too %s; '%s'\n",
+    debug(20, 4) ("storeEntryValidLength: %d bytes too %s; '%s'\n",
 	diff < 0 ? -diff : diff,
 	diff < 0 ? "big" : "small",
-	storeKeyText(e->key));
+	storeKeyText(e->Skey));
     return 0;
 }
 
@@ -924,6 +1175,72 @@
     debug(20, 1) ("Max Swap size: %d KB\n", Config.Swap.maxSize);
 }
 
+#ifdef	HPL_REPL
+
+/*
+ * For a description of these cache replacement policies see --
+ http://www.hpl.hp.com/personal/John_Dilley/caching/wcw.html
+ */
+
+
+/*
+ * Key generation function to implement the LFU-DA policy (Least Frequently
+ * Used with Dynamic Aging).  Similar to classical LFU but with aging to
+ * handle turnover of the popular document set.  Maximizes byte hit rate by
+ * keeping more currently popular objects in cache regardless of size.
+ * Achieves lower hit rate than GDS because there are more large objects in
+ * cache (so less room for smaller popular objects).
+ * 
+ * This version implements a tie-breaker based upon recency (e->lastref):
+ * for objects that have the same reference count the most recent object
+ * wins (gets a higher key value).
+ */
+double
+HeapKeyGen_StoreEntry_LFUDA(void * entry, double age)
+{
+  StoreEntry * e = entry;
+  /* dangerous arithmetic after the year 2038 */
+  double tie = (e->Slastref>1)?(1.0/e->Slastref):1;
+  return age + e->Srefcount - tie;
+}
+
+
+/*
+ * Key generation function to implement the GDS-Frequency policy.
+ * Similar to Greedy Dual-Size Hits policy, but adds aging of documents to
+ * prevent pollution.  Maximizes object hit rate by keeping more small,
+ * popular objects in cache.  Achieves lower byte hit rate than LFUDA
+ * because there are fewer large objects in cache.
+ * 
+ * This version implements a tie-breaker based upon recency (e->lastref):
+ * for objects that have the same reference count the most recent object
+ * wins (gets a higher key value).
+ */
+double
+HeapKeyGen_StoreEntry_GDSF(void * entry, double age)
+{
+  StoreEntry * e = entry;
+  double size = e->Sswap_file_sz ? e->Sswap_file_sz : 1.0;
+  /* dangerous arithmetic after the year 2038 */
+  double tie = (e->Slastref>1)?(1.0/e->Slastref):1;
+  return age + ((double)e->Srefcount / size) - tie;
+}
+
+/* 
+ * Key generation function to implement the LRU policy.  Normally one would
+ * not do this with a heap -- use the linked list instead.  For testing and
+ * performance characterization it was useful.  Don't use it unless you are
+ * trying to compare performance among heap-based replacement policies...
+ */
+double
+HeapKeyGen_StoreEntry_LRU(void * entry, double age)
+{
+  StoreEntry * e = entry;
+  return e->Slastref;
+}
+
+#endif	/* HPL_REPL */
+
 void
 storeInit(void)
 {
@@ -941,9 +1258,43 @@
 	    ERROR_BUF_SZ);
 	fatal(tmp_error_buf);
     }
-    storeDirOpenSwapLogs();
+    #ifdef	HPL_REPL
+    /*
+     * Create new heaps with cache replacement policies attached to them.
+     * The cache replacement policy is specified as either GDSF or LFUDA in
+     * the squid.conf configuration file.  Note that the replacement policy
+     * applies only to the disk replacement algorithm.  Memory replacement
+     * always uses GDSF since we want to maximize object hit rate.
+     */
+    inmem_heap = new_heap(1000, HeapKeyGen_StoreEntry_GDSF,
+		    offsetof(MemObject, n.ode));
+
+    store_policy = HeapKeyGen_StoreEntry_GDSF;
+
+    if (Config.replPolicy)
+      if (tolower(Config.replPolicy[0]) == 'g')
+	debug(20, 1) ("Using GDSF disk replacement policy\n");
+      else if (tolower(Config.replPolicy[0]) == 'l') {
+	if (tolower(Config.replPolicy[1]) == 'f') {
+	  debug(20, 1) ("Using LFUDA disk replacement policy\n");
+	  store_policy = HeapKeyGen_StoreEntry_LFUDA;
+	} else if (tolower(Config.replPolicy[1]) == 'r') {
+	  debug(20, 1) ("Using LRU heap disk replacement policy\n");
+	  store_policy = HeapKeyGen_StoreEntry_LRU;
+	}
+      } else
+	  debug(20, 1) ("Unrecognized replacement_policy; using GDSF\n");
+    else
+	debug(20, 1) ("Using default disk replacement policy (GDSF)\n");
+
+    #else	/* HPL_REPL */
+
     store_list.head = store_list.tail = NULL;
     inmem_list.head = inmem_list.tail = NULL;
+
+    #endif	/* HPL_REPL */
+
+    storeDirOpenSwapLogs();
     stackInit(&LateReleaseStack);
     eventAdd("storeLateRelease", storeLateRelease, NULL, 1.0, 1);
     storeRebuildStart();
@@ -982,15 +1333,28 @@
 {
     if (storeEntryLocked(e))
 	return 0;
-    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
+    if (EBIT_TEST(e->Sflag, RELEASE_REQUEST))
 	return 1;
-    if (EBIT_TEST(e->flags, ENTRY_NEGCACHED) && squid_curtime >= e->expires)
+    if (EBIT_TEST(e->Sflag, ENTRY_NEGCACHED) && squid_curtime >= e->Sexpires)
 	return 1;
-    if (squid_curtime - e->lastref > storeExpiredReferenceAge())
+#ifdef	HPL_REPL
+    /*
+     * With HPL_REPL we are not using the LRU reference age, the heap
+     * controls the replacement of objects.
+     */
+    return 1;
+#else	/* HPL_REPL */
+    if (squid_curtime - e->Slastref > storeExpiredReferenceAge())
 	return 1;
     return 0;
+#endif	/* HPL_REPL */
 }
 
+#ifdef	HPL_REPL
+/*
+ * The non-LRU cache replacement policies do not use LRU referenceAge
+ */
+#else	/* HPL_REPL */
 /* 
  * storeExpiredReferenceAge
  *
@@ -1018,12 +1382,13 @@
 	age = 31536000;
     return age;
 }
+#endif	/* HPL_REPL */
 
 void
 storeNegativeCache(StoreEntry * e)
 {
-    e->expires = squid_curtime + Config.negativeTtl;
-    EBIT_SET(e->flags, ENTRY_NEGCACHED);
+    e->Sexpires = squid_curtime + Config.negativeTtl;
+    EBIT_SET(e->Sflag, ENTRY_NEGCACHED);
 }
 
 void
@@ -1050,12 +1415,12 @@
 int
 storeEntryValidToSend(StoreEntry * e)
 {
-    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
+    if (EBIT_TEST(e->Sflag, RELEASE_REQUEST))
 	return 0;
-    if (EBIT_TEST(e->flags, ENTRY_NEGCACHED))
-	if (e->expires <= squid_curtime)
+    if (EBIT_TEST(e->Sflag, ENTRY_NEGCACHED))
+	if (e->Sexpires <= squid_curtime)
 	    return 0;
-    if (EBIT_TEST(e->flags, ENTRY_ABORTED))
+    if (EBIT_TEST(e->Sflag, ENTRY_ABORTED))
 	return 0;
     return 1;
 }
@@ -1068,9 +1433,9 @@
     served_date = reply->date;
     if (served_date < 0)
 	served_date = squid_curtime;
-    entry->expires = reply->expires;
-    entry->lastmod = reply->last_modified;
-    entry->timestamp = served_date;
+    entry->Sexpires = reply->expires;
+    entry->Slastmod = reply->last_modified;
+    entry->Stimestamp = served_date;
 }
 
 void
@@ -1125,17 +1490,16 @@
 void
 storeEntryDump(StoreEntry * e, int l)
 {
-    debug(20, l) ("StoreEntry->key: %s\n", storeKeyText(e->key));
-    debug(20, l) ("StoreEntry->next: %p\n", e->next);
+    debug(20, l) ("StoreEntry->key: %s\n", storeKeyText(e->Skey));
     debug(20, l) ("StoreEntry->mem_obj: %p\n", e->mem_obj);
-    debug(20, l) ("StoreEntry->timestamp: %d\n", (int) e->timestamp);
-    debug(20, l) ("StoreEntry->lastref: %d\n", (int) e->lastref);
-    debug(20, l) ("StoreEntry->expires: %d\n", (int) e->expires);
-    debug(20, l) ("StoreEntry->lastmod: %d\n", (int) e->lastmod);
-    debug(20, l) ("StoreEntry->swap_file_sz: %d\n", (int) e->swap_file_sz);
-    debug(20, l) ("StoreEntry->refcount: %d\n", e->refcount);
-    debug(20, l) ("StoreEntry->flags: %s\n", storeEntryFlags(e));
-    debug(20, l) ("StoreEntry->swap_file_number: %d\n", (int) e->swap_file_number);
+    debug(20, l) ("StoreEntry->Stimestamp: %d\n", (int) e->Stimestamp);
+    debug(20, l) ("StoreEntry->Slastref: %d\n", (int) e->Slastref);
+    debug(20, l) ("StoreEntry->Sexpires: %d\n", (int) e->Sexpires);
+    debug(20, l) ("StoreEntry->Slastmod: %d\n", (int) e->Slastmod);
+    debug(20, l) ("StoreEntry->Sswap_file_sz: %d\n", (int) e->Sswap_file_sz);
+    debug(20, l) ("StoreEntry->Srefcount: %d\n", e->Srefcount);
+    debug(20, l) ("StoreEntry->flag: %X %s\n", e->Sflag, storeEntryFlags(e));
+    debug(20, l) ("StoreEntry->Sswap_file_number: %d\n", (int) e->Sswap_file_number);
     debug(20, l) ("StoreEntry->lock_count: %d\n", (int) e->lock_count);
     debug(20, l) ("StoreEntry->mem_status: %d\n", (int) e->mem_status);
     debug(20, l) ("StoreEntry->ping_status: %d\n", (int) e->ping_status);
@@ -1153,10 +1517,33 @@
     assert(mem != NULL);
     if (new_status == IN_MEMORY) {
 	assert(mem->inmem_lo == 0);
+	#ifdef	HPL_REPL
+	if (mem->n.ode.id < 0) {
+	  if (EBIT_TEST(e->Sflag, ENTRY_SPECIAL)) {
+	    debug(20, 4) ("storeSetMemStatus: not inserting special %s\n", mem->url);
+	  } else {
+	    heap_insert(inmem_heap, mem);
+	    debug(20, 4) ("storeSetMemStatus: inserted mem node %d\n", mem->n.ode.id);
+	  }
+	}
+	#else	/* HPL_REPL */
 	dlinkAdd(e, &mem->lru, &inmem_list);
+	#endif	/* HPL_REPL */
 	hot_obj_count++;
     } else {
+      #ifdef	HPL_REPL
+      /*
+       * It's being removed from the memory heap; is it already gone?
+       */
+      if (mem->n.ode.id >= 0) {
+	heap_delete(inmem_heap, &mem->n.ode);
+	debug(20, 4) ("storeSetMemStatus: deleted mem node %d\n",
+		      mem->n.ode.id);
+	mem->n.ode.id = -1;
+      }
+      #else	/* HPL_REPL */
 	dlinkDelete(&mem->lru, &inmem_list);
+      #endif	/* HPL_REPL */
 	hot_obj_count--;
     }
     e->mem_status = new_status;
@@ -1179,20 +1566,23 @@
     if (e->mem_obj)
 	return;
     e->mem_obj = new_MemObject(url, log_url);
+#if HPL_REPL
+    e->mem_obj->entry = e;
+#endif
 }
 
 /* this just sets DELAY_SENDING */
 void
 storeBuffer(StoreEntry * e)
 {
-    EBIT_SET(e->flags, DELAY_SENDING);
+    EBIT_SET(e->Sflag, DELAY_SENDING);
 }
 
 /* this just clears DELAY_SENDING and Invokes the handlers */
 void
 storeBufferFlush(StoreEntry * e)
 {
-    EBIT_CLR(e->flags, DELAY_SENDING);
+    EBIT_CLR(e->Sflag, DELAY_SENDING);
     InvokeHandlers(e);
     storeCheckSwapOut(e);
 }
@@ -1200,7 +1590,7 @@
 void
 storeUnlinkFileno(int fileno)
 {
-    debug(20, 5) ("storeUnlinkFileno: %08X\n", fileno);
+    debug(20, 6) ("storeUnlinkFileno: %08X\n", fileno);
 #if USE_ASYNC_IO
     safeunlink(storeSwapFullPath(fileno, NULL), 1);
 #else
@@ -1237,7 +1627,7 @@
 storeEntryReset(StoreEntry * e)
 {
     MemObject *mem = e->mem_obj;
-    debug(20, 3) ("storeEntryReset: %s\n", storeUrl(e));
+    debug(20, 4) ("storeEntryReset: %s\n", storeUrl(e));
     assert(mem->swapout.fd == -1);
     stmemFree(&mem->data_hdr);
     mem->inmem_hi = mem->inmem_lo = 0;
Index: squid/src/store_client.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_client.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/store_client.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/store_client.c	10 Nov 2000 18:44:52 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_client.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: store_client.c,v 1.1.1.2.10.1 2000/11/10 18:44:52 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Client-Side Interface
  * AUTHOR: Duane Wessels
@@ -81,7 +81,7 @@
     MemObject *mem = e->mem_obj;
     if (mem->inmem_lo)
 	return STORE_DISK_CLIENT;
-    if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(e->Sflag, ENTRY_ABORTED)) {
 	/* I don't think we should be adding clients to aborted entries */
 	debug(20, 1) ("storeClientType: adding to ENTRY_ABORTED entry\n");
 	return STORE_MEM_CLIENT;
@@ -129,7 +129,7 @@
     if (sc->type == STORE_DISK_CLIENT)
 	/* assert we'll be able to get the data we want */
 	/* maybe we should open swapin_fd here */
-	assert(e->swap_file_number > -1 || storeSwapOutAble(e));
+	assert(e->Sswap_file_number > -1 || storeSwapOutAble(e));
     for (T = &mem->clients; *T; T = &(*T)->next);
     *T = sc;
 #if DELAY_POOLS
@@ -141,7 +141,7 @@
 storeClientCopyEvent(void *data)
 {
     store_client *sc = data;
-    debug(20, 3) ("storeClientCopyEvent: Running\n");
+    debug(20, 4) ("storeClientCopyEvent: Running\n");
     sc->flags.copy_event_pending = 0;
     if (!sc->callback)
 	return;
@@ -159,9 +159,9 @@
     void *data)
 {
     store_client *sc;
-    assert(!EBIT_TEST(e->flags, ENTRY_ABORTED));
+    assert(!EBIT_TEST(e->Sflag, ENTRY_ABORTED));
     debug(20, 3) ("storeClientCopy: %s, seen %d, want %d, size %d, cb %p, cbdata %p\n",
-	storeKeyText(e->key),
+	storeKeyText(e->Skey),
 	(int) seen_offset,
 	(int) copy_offset,
 	(int) size,
@@ -209,7 +209,7 @@
     size_t sz;
     if (sc->flags.copy_event_pending)
 	return;
-    if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) {
+    if (EBIT_TEST(e->Sflag, ENTRY_FWD_HDR_WAIT)) {
 	debug(20, 5) ("storeClientCopy2: returning because ENTRY_FWD_HDR_WAIT set\n");
 	return;
     }
@@ -221,7 +221,7 @@
     }
     cbdataLock(sc);		/* ick, prevent sc from getting freed */
     sc->flags.store_copying = 1;
-    debug(20, 3) ("storeClientCopy2: %s\n", storeKeyText(e->key));
+    debug(20, 3) ("storeClientCopy2: %s\n", storeKeyText(e->Skey));
     assert(callback != NULL);
     /*
      * We used to check for ENTRY_ABORTED here.  But there were some
@@ -245,10 +245,10 @@
 	callback(sc->callback_data, sc->copy_buf, 0);
     } else if (e->store_status == STORE_PENDING && sc->seen_offset >= mem->inmem_hi) {
 	/* client has already seen this, wait for more */
-	debug(20, 3) ("storeClientCopy2: Waiting for more\n");
+	debug(20, 4) ("storeClientCopy2: Waiting for more\n");
     } else if (sc->copy_offset >= mem->inmem_lo && sc->copy_offset < mem->inmem_hi) {
 	/* What the client wants is in memory */
-	debug(20, 3) ("storeClientCopy2: Copying from memory\n");
+	debug(20, 4) ("storeClientCopy2: Copying from memory\n");
 	sz = stmemCopy(&mem->data_hdr, sc->copy_offset, sc->copy_buf, sc->copy_size);
 #if USE_ASYNC_IO
 	if (sc->flags.disk_io_pending) {
@@ -262,7 +262,7 @@
 	sc->callback = NULL;
 	callback(sc->callback_data, sc->copy_buf, sz);
     } else if (sc->swapin_fd < 0) {
-	debug(20, 3) ("storeClientCopy2: Need to open swap in file\n");
+	debug(20, 4) ("storeClientCopy2: Need to open swap in file\n");
 	assert(sc->type == STORE_DISK_CLIENT);
 	/* gotta open the swapin file */
 	if (storeTooManyDiskFilesOpen()) {
@@ -276,7 +276,7 @@
 	    debug(20, 2) ("storeClientCopy2: Averted multiple fd operation\n");
 	}
     } else {
-	debug(20, 3) ("storeClientCopy: reading from disk FD %d\n",
+	debug(20, 4) ("storeClientCopy: reading from disk FD %d\n",
 	    sc->swapin_fd);
 	assert(sc->type == STORE_DISK_CLIENT);
 	if (!sc->flags.disk_io_pending) {
@@ -295,7 +295,7 @@
     store_client *sc = data;
     STCB *callback = sc->callback;
     if (fd < 0) {
-	debug(20, 3) ("storeClientFileOpened: failed\n");
+	debug(20, 4) ("storeClientFileOpened: failed\n");
 	sc->flags.disk_io_pending = 0;
 	sc->callback = NULL;
 	callback(sc->callback_data, sc->copy_buf, -1);
@@ -344,7 +344,7 @@
     assert(sc->flags.disk_io_pending);
     sc->flags.disk_io_pending = 0;
     assert(sc->callback != NULL);
-    debug(20, 3) ("storeClientReadBody: FD %d, len %d\n", fd, len);
+    debug(20, 4) ("storeClientReadBody: FD %d, len %d\n", fd, len);
     if (sc->copy_offset == 0 && len > 0 && mem->reply->sline.status == 0)
 	httpReplyParse(mem->reply, sc->copy_buf);
     sc->callback = NULL;
@@ -365,9 +365,9 @@
     assert(sc->flags.disk_io_pending);
     sc->flags.disk_io_pending = 0;
     assert(sc->callback != NULL);
-    debug(20, 3) ("storeClientReadHeader: FD %d, len %d\n", fd, len);
+    debug(20, 4) ("storeClientReadHeader: FD %d, len %d\n", fd, len);
     if (len < 0) {
-	debug(20, 3) ("storeClientReadHeader: FD %d: %s\n", fd, xstrerror());
+	debug(20, 4) ("storeClientReadHeader: FD %d: %s\n", fd, xstrerror());
 	sc->callback = NULL;
 	callback(sc->callback_data, sc->copy_buf, len);
 	return;
@@ -380,12 +380,44 @@
 	return;
     }
     /*
-     * XXX Here we should check the meta data and make sure we got
+     * Check the meta data and make sure we got
      * the right object.
      */
+    {
+	tlv *tlv_cur;
+	char *skey = 0;
+	for (tlv_cur = tlv_list; tlv_cur; tlv_cur = tlv_cur->next)
+	    switch (tlv_cur->type)
+	    {
+		case STORE_META_KEY:
+		    if (memcmp(e->Skey, skey = (char*)tlv_cur->value, MD5_DIGEST_CHARS))
+		    {
+			debug(20, 0) ("storeClientReadHeader: MD5 mismatch %x %s\n",
+			    e->Sswap_file_number, storeUrl(e));
+badstore:		debug(20, 0) ("storeClientReadHeader: MD5 match? %x %s %s\n",
+			    e->Sswap_file_number,
+			    skey ? storeKeyText(skey) : "-", storeKeyText(e->Skey));
+			storeSwapTLVFree(tlv_list);
+			sc->callback = NULL;
+			callback(sc->callback_data, sc->copy_buf, -1);
+			return;
+		    }
+#if 0				/* optimisation possible */
+		    tlv_cur = 0;
+#endif
+		    break;
+		case STORE_META_URL:
+		    if (memcmp((char*)tlv_cur->value, storeUrl(e), tlv_cur->length))
+		    {
+			debug(20, 0) ("storeClientReadHeader: URL mismatch %x %s %s\n",
+			    e->Sswap_file_number, (char*)tlv_cur->value, storeUrl(e));
+			goto badstore;
+		    }
+	    }
+    }
     storeSwapTLVFree(tlv_list);
     mem->swap_hdr_sz = swap_hdr_sz;
-    mem->object_sz = e->swap_file_sz - swap_hdr_sz;
+    mem->object_sz = e->Sswap_file_sz - swap_hdr_sz;
     /*
      * If our last read got some data the client wants, then give
      * it to them, otherwise schedule another read.
@@ -396,7 +428,7 @@
 	 * we have (part of) what they want
 	 */
 	copy_sz = XMIN(sc->copy_size, body_sz);
-	debug(20, 3) ("storeClientReadHeader: copying %d bytes of body\n",
+	debug(20, 4) ("storeClientReadHeader: copying %d bytes of body\n",
 	    copy_sz);
 	xmemmove(sc->copy_buf, sc->copy_buf + swap_hdr_sz, copy_sz);
 	if (sc->copy_offset == 0 && len > 0 && mem->reply->sline.status == 0)
@@ -433,7 +465,7 @@
     STCB *callback;
     if (mem == NULL)
 	return 0;
-    debug(20, 3) ("storeUnregister: called for '%s'\n", storeKeyText(e->key));
+    debug(20, 3) ("storeUnregister: called for '%s'\n", storeKeyText(e->Skey));
     for (S = &mem->clients; (sc = *S) != NULL; S = &(*S)->next) {
 	if (sc->callback_data == data)
 	    break;
@@ -462,7 +494,7 @@
 #endif
     if ((callback = sc->callback) != NULL) {
 	/* callback with ssize = -1 to indicate unexpected termination */
-	debug(20, 3) ("storeUnregister: store_client for %s has a callback\n",
+	debug(20, 4) ("storeUnregister: store_client for %s has a callback\n",
 	    mem->url);
 	sc->callback = NULL;
 	callback(sc->callback_data, sc->copy_buf, -1);
@@ -505,7 +537,7 @@
     store_client *sc;
     store_client *nx = NULL;
     assert(mem->clients != NULL || mem->nclients == 0);
-    debug(20, 3) ("InvokeHandlers: %s\n", storeKeyText(e->key));
+    debug(20, 3) ("InvokeHandlers: %s\n", storeKeyText(e->Skey));
     /* walk the entire list looking for valid callbacks */
     for (sc = mem->clients; sc; sc = nx) {
 	nx = sc->next;
@@ -523,7 +555,7 @@
 {
     MemObject *mem = e->mem_obj;
     int npend = NULL == mem ? 0 : mem->nclients;
-    debug(20, 3) ("storePendingNClients: returning %d\n", npend);
+    debug(20, 4) ("storePendingNClients: returning %d\n", npend);
     return npend;
 }
 
@@ -541,7 +573,7 @@
 	debug(20, 3) ("CheckQuickAbort2: YES !mem->request->flags.cachable\n");
 	return 1;
     }
-    if (EBIT_TEST(entry->flags, KEY_PRIVATE)) {
+    if (EBIT_TEST(entry->Sflag, KEY_PRIVATE)) {
 	debug(20, 3) ("CheckQuickAbort2: YES KEY_PRIVATE\n");
 	return 1;
     }
@@ -585,7 +617,7 @@
 	return;
     if (entry->store_status != STORE_PENDING)
 	return;
-    if (EBIT_TEST(entry->flags, ENTRY_SPECIAL))
+    if (EBIT_TEST(entry->Sflag, ENTRY_SPECIAL))
 	return;
     if (CheckQuickAbort2(entry) == 0)
 	return;
Index: squid/src/store_digest.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_digest.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.12.1
diff -u -r1.1.1.2 -r1.1.1.2.12.1
--- squid/src/store_digest.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/store_digest.c	10 Nov 2000 18:44:53 -0000	1.1.1.2.12.1
@@ -1,5 +1,5 @@
 /*
- * $Id: store_digest.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: store_digest.c,v 1.1.1.2.12.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 71    Store Digest Manager
  * AUTHOR: Alex Rousskov
@@ -138,17 +138,17 @@
 #if USE_CACHE_DIGESTS
     assert(entry && store_digest);
     debug(71, 6) ("storeDigestDel: checking entry, key: %s\n",
-	storeKeyText(entry->key));
-    if (!EBIT_TEST(entry->flags, KEY_PRIVATE)) {
-	if (!cacheDigestTest(store_digest, entry->key)) {
+	storeKeyText(entry->Skey));
+    if (!EBIT_TEST(entry->Sflag, KEY_PRIVATE)) {
+	if (!cacheDigestTest(store_digest, entry->Skey)) {
 	    sd_stats.del_lost_count++;
 	    debug(71, 6) ("storeDigestDel: lost entry, key: %s url: %s\n",
-		storeKeyText(entry->key), storeUrl(entry));
+		storeKeyText(entry->Skey), storeUrl(entry));
 	} else {
 	    sd_stats.del_count++;
-	    cacheDigestDel(store_digest, entry->key);
+	    cacheDigestDel(store_digest, entry->Skey);
 	    debug(71, 6) ("storeDigestDel: deled entry, key: %s\n",
-		storeKeyText(entry->key));
+		storeKeyText(entry->Skey));
 	}
     }
 #endif
@@ -187,31 +187,31 @@
     /* add some stats! XXX */
 
     debug(71, 6) ("storeDigestAddable: checking entry, key: %s\n",
-	storeKeyText(e->key));
+	storeKeyText(e->Skey));
 
     /* check various entry flags (mimics storeCheckCachable XXX) */
-    if (!EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
+    if (!EBIT_TEST(e->Sflag, ENTRY_CACHABLE)) {
 	debug(71, 6) ("storeDigestAddable: NO: not cachable\n");
 	return 0;
     }
-    if (EBIT_TEST(e->flags, KEY_PRIVATE)) {
+    if (EBIT_TEST(e->Sflag, KEY_PRIVATE)) {
 	debug(71, 6) ("storeDigestAddable: NO: private key\n");
 	return 0;
     }
-    if (EBIT_TEST(e->flags, ENTRY_NEGCACHED)) {
+    if (EBIT_TEST(e->Sflag, ENTRY_NEGCACHED)) {
 	debug(71, 6) ("storeDigestAddable: NO: negative cached\n");
 	return 0;
     }
-    if (EBIT_TEST(e->flags, RELEASE_REQUEST)) {
+    if (EBIT_TEST(e->Sflag, RELEASE_REQUEST)) {
 	debug(71, 6) ("storeDigestAddable: NO: release requested\n");
 	return 0;
     }
-    if (e->store_status == STORE_OK && EBIT_TEST(e->flags, ENTRY_BAD_LENGTH)) {
+    if (e->store_status == STORE_OK && EBIT_TEST(e->Sflag, ENTRY_BAD_LENGTH)) {
 	debug(71, 6) ("storeDigestAddable: NO: wrong content-length\n");
 	return 0;
     }
     /* do not digest huge objects */
-    if (e->swap_file_sz > Config.Store.maxObjectSize) {
+    if (e->Sswap_file_sz > Config.Store.maxObjectSize) {
 	debug(71, 6) ("storeDigestAddable: NO: too big\n");
 	return 0;
     }
@@ -235,14 +235,14 @@
 
     if (storeDigestAddable(entry)) {
 	sd_stats.add_count++;
-	if (cacheDigestTest(store_digest, entry->key))
+	if (cacheDigestTest(store_digest, entry->Skey))
 	    sd_stats.add_coll_count++;
-	cacheDigestAdd(store_digest, entry->key);
+	cacheDigestAdd(store_digest, entry->Skey);
 	debug(71, 6) ("storeDigestAdd: added entry, key: %s\n",
-	    storeKeyText(entry->key));
+	    storeKeyText(entry->Skey));
     } else {
 	sd_stats.rej_count++;
-	if (cacheDigestTest(store_digest, entry->key))
+	if (cacheDigestTest(store_digest, entry->Skey))
 	    sd_stats.rej_coll_count++;
     }
 }
@@ -341,7 +341,7 @@
     sd_state.rewrite_lock = e = storeCreateEntry(url, url, flags, METHOD_GET);
     assert(sd_state.rewrite_lock);
     cbdataAdd(sd_state.rewrite_lock, NULL, 0);
-    debug(71, 3) ("storeDigestRewrite: url: %s key: %s\n", url, storeKeyText(e->key));
+    debug(71, 3) ("storeDigestRewrite: url: %s key: %s\n", url, storeKeyText(e->Skey));
     e->mem_obj->request = requestLink(urlParse(METHOD_GET, url));
     /* wait for rebuild (if any) to finish */
     if (sd_state.rebuild_lock) {
@@ -359,7 +359,7 @@
     assert(sd_state.rewrite_lock);
     assert(!sd_state.rebuild_lock);
     sd_state.rewrite_offset = 0;
-    EBIT_SET(e->flags, ENTRY_SPECIAL);
+    EBIT_SET(e->Sflag, ENTRY_SPECIAL);
     /* setting public key will purge old digest entry if any */
     storeSetPublicKey(e);
     /* fake reply */
@@ -384,7 +384,7 @@
     storeComplete(e);
     storeTimestampsSet(e);
     debug(71, 2) ("storeDigestRewriteFinish: digest expires at %d (%+d)\n",
-	e->expires, e->expires - squid_curtime);
+	e->Sexpires, e->Sexpires - squid_curtime);
     /* is this the write order? @?@ */
     requestUnlink(e->mem_obj->request);
     e->mem_obj->request = NULL;
Index: squid/src/store_dir.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_dir.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/store_dir.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/store_dir.c	10 Nov 2000 18:44:53 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_dir.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: store_dir.c,v 1.1.1.2.10.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 47    Store Directory Routines
  * AUTHOR: Duane Wessels
@@ -39,9 +39,10 @@
 #include 
 #endif
 #endif
+#ifdef MMAPSTORE
+#include 
+#endif
 
-#define SWAP_DIR_SHIFT 24
-#define SWAP_FILE_MASK 0x00FFFFFF
 #define DefaultLevelOneDirs     16
 #define DefaultLevelTwoDirs     256
 
@@ -232,16 +233,20 @@
 static int
 storeDirSelectSwapDir(void)
 {
-    double least_used = 1.0;
-    double high = (double) Config.Swap.highWaterMark / 100.0;
-    double u;
-    int dirn;
     int i, j;
-    SwapDir *SD;
-    static int nleast = 0;
-    static int nconf = 0;
+    static unsigned nleast = 0;
+    static unsigned returnlast = 0;
+    static unsigned nconf = 0;
+    static unsigned lastdirn;
+    static unsigned relstoremax;
     static int *dirq = NULL;
-    static double *diru = NULL;
+    static unsigned long *diru = NULL;
+    unsigned long least_used;
+    /*
+     * Scan for a non-negative dirn in the dirq array and return that one
+     */
+    if (returnlast)
+	return dirq[--returnlast];
     /*
      * Handle simplest case of a single swap directory immediately
      */
@@ -256,45 +261,28 @@
 	safe_free(dirq);
 	dirq = (int *) xmalloc(sizeof(int) * nleast);
 	safe_free(diru);
-	diru = (double *) xmalloc(sizeof(double) * nconf);
+	diru = xmalloc(sizeof*diru * nconf);
 	for (j = 0; j < nleast; j++)
 	    dirq[j] = -1;
+	relstoremax = ((unsigned)Config.Swap.highWaterMark*2 + 1) *
+	 STORE_GRAN_MAX / 200 + 1;
     }
     /*
-     * Scan for a non-negative dirn in the dirq array and return that one
-     */
-    dirn = -1;
-    for (j = 0; j < nleast; j++) {
-	dirn = dirq[j];
-	if (dirn < 0)
-	    continue;
-	dirq[j] = -1;
-	break;
-    }
-    /*
-     * If we found a valid dirn return it
-     */
-    if (dirn >= 0)
-	return dirn;
-    /*
      * Now for the real guts of the algorithm - building the dirq array
      */
     for (i = 0; i < nconf; i++) {
-	diru[i] = 1.1;
-	SD = &Config.cacheSwap.swapDirs[i];
+        SwapDir *SD = &Config.cacheSwap.swapDirs[i];
+	diru[i] = STORE_GRAN_MAX+STORE_GRAN_MAX/2;
 	SD->flags.selected = 0;
 	if (SD->flags.read_only)
 	    continue;
-	u = (double) SD->cur_size / SD->max_size;
-	if (u > high)
-	    continue;
-	diru[i] = u;
+	diru[i] = SD->cur_size/
+	 (((unsigned long)SD->max_size+STORE_GRAN_MAX-1)>>STORE_GRAN_ORDER);
     }
     for (j = 0; j < nleast; j++) {
-	dirq[j] = -1;
-	least_used = 1.0;
-	dirn = -1;
-	for (i = 0; i < nconf; i++) {
+        int dirn = -1;
+	least_used = relstoremax;
+	for (i = lastdirn; (i = (i+1)%nconf) != lastdirn; ) {
 	    if (diru[i] < least_used) {
 		least_used = diru[i];
 		dirn = i;
@@ -302,19 +290,25 @@
 	}
 	if (dirn < 0)
 	    break;
-	dirq[j] = dirn;
-	diru[dirn] = 1.1;
+	dirq[j] = lastdirn = dirn;
+	diru[dirn] = STORE_GRAN_MAX+2;
 	/* set selected flag for debugging/cachemgr only */
 	Config.cacheSwap.swapDirs[dirn].flags.selected = 1;
     }
+    if (!j)
+	for (i = nconf; i--;)
+	    if (diru[i] == least_used) {
+		dirq[j] = i;
+		Config.cacheSwap.swapDirs[i].flags.selected = 1;
+		if (++j == nleast)
+		    break;
+    }
     /*
      * Setup default return of 0 if no least found
      */
-    if (dirq[0] < 0)
-	dirq[0] = 0;
-    dirn = dirq[0];
-    dirq[0] = -1;
-    return dirn;
+    if (!j)
+	return 0;
+    return dirq[returnlast = j-1];
 }
 
 int
@@ -386,6 +380,185 @@
     return (dirn << SWAP_DIR_SHIFT) | (fn & SWAP_FILE_MASK);
 }
 
+static struct mmapinfo *allmi;
+
+static void
+mapfdswap(SwapDir *sd)
+{
+#ifdef MMAPSTORE
+    struct stat stbuf;
+    struct mmapinfo *mi = sd->mi;
+    if (!mi) {
+	const char *path = sd->path;
+	for (mi = allmi; ; mi = mi->next) {
+	    if (!mi) {
+		mi = xmalloc(sizeof *mi);
+		mi->next = allmi;
+		allmi = mi;
+		mi->path = xstrdup(path);
+		mi->mmapbase = mi->mmapfreelist = 0;
+		break;
+	    }
+	    if (!strcmp(mi->path, path))
+		break;
+	}
+	sd->mi = mi;
+    }
+    if(mi->mmapbase)
+	munmap(mi->mmapbase, (char*)mi->mmapmax-(char*)mi->mmapbase);
+    if(!fstat(sd->swaplog_fd,&stbuf)) {
+	storeSwapLogData*oldbase = mi->mmapbase, *oldend = mi->mmapend;
+	size_t max=(((size_t)stbuf.st_size/16*17+32768)/sizeof*mi->mmapbase+1)*
+	    sizeof*mi->mmapbase;
+	if(MAP_FAILED != (mi->mmapbase = mmap(0, max, PROT_READ|PROT_WRITE,
+	    MAP_SHARED, sd->swaplog_fd, 0))) {
+	    mi->mmapend = mi->mmapbase + stbuf.st_size/sizeof*mi->mmapbase;
+	    mi->mmapmax = (storeSwapLogData*)((char*)mi->mmapbase + max);
+	    if (oldbase) {
+	        ptrdiff_t fix = (char*)mi->mmapbase-(char*)oldbase;
+#ifdef	HPL_REPL
+		int node;
+	        for (node=0; node < heap_nodes(sd->heap); node++) {
+	            StoreEntry *e = (StoreEntry*)heap_peep(sd->heap, node);
+#else	/* HPL_REPL */
+		dlink_node *m;
+	        for (m = store_list.tail; m; m = m->prev) {
+	            StoreEntry *e = m->data;
+	            if (oldbase <= e->s && e->s s = (storeSwapLogData*)((char*)e->s+fix);
+	        }
+		if(mi->mmapfreelist)
+		    mi->mmapfreelist =
+			(storeSwapLogData*)((char*)mi->mmapfreelist+fix);
+	    }
+	    return;
+	}
+    } else
+	sd->mi = 0;
+    fatal_dump("mapfdswap: Couldn't mmap() the store swap logfiles\n");
+    return;
+#endif
+}
+
+void storeSwapToFreeList(SwapDir*sd, storeSwapLogData *s)
+{
+    struct mmapinfo *mi = sd->mi;
+    s->swap_file_number = -1;
+    if (mi->mmapend != s+1) {
+	s->swap_file_sz = mi->mmapfreelist ? mi->mmapfreelist - s : 0 ;
+	mi->mmapfreelist = s;
+    } else {
+	int ret;
+	ret = ftruncate (sd->swaplog_fd, (char*)s - (char*)mi->mmapbase);
+	lseek (sd->swaplog_fd, 0L, SEEK_END);
+	assert(!ret);
+	mi->mmapend--;
+    }
+}
+
+storeSwapLogData*storeSwapAppendList(SwapDir*sd, storeSwapLogData*s)
+{
+    struct mmapinfo *mi = sd->mi;
+    {
+        storeSwapLogData*ns;
+        if (ns = mi->mmapfreelist) {
+	    mi->mmapfreelist = ns->swap_file_sz ?
+		ns + (int)ns->swap_file_sz : 0;
+	    *ns = *s;
+	    return ns;
+        }
+    }
+    if(mi->mmapend == mi->mmapmax)
+	mapfdswap(sd);
+    {
+	int ret, todo=sizeof*s;
+	char*p = (char*)s;
+	do
+	    ret = write(sd->swaplog_fd, p, todo);
+	while (ret < 0 && (errno == EAGAIN || errno == EINTR) ||
+	    (p += ret, todo -= ret));
+	if ( ret <= 0 )
+            debug(20, 0) ("storeSwapAppendList: %d %d\n", ret, errno);
+	assert(ret > 0);
+    }
+    return mi->mmapend++;
+}
+
+SwapDir*
+getswapdir(int swapfilenumber)
+{
+    unsigned dirn = (swapfilenumber >> SWAP_DIR_SHIFT);
+    assert(dirn < Config.cacheSwap.n_configured);
+    return Config.cacheSwap.swapDirs + dirn;
+}
+
+void
+destroy_storeSwapLogData(storeSwapLogData*s)
+{
+#ifdef MMAPSTORE
+    int swf = s->swap_file_number;
+    if (swf < 0)
+#endif
+	memFree(s, MEM_STORESWAPLOGDATA);
+#ifdef MMAPSTORE
+    else
+	storeSwapToFreeList(getswapdir(swf), s);
+#endif
+}
+
+void
+set_swap_file_number(StoreEntry*e, int swf)
+{
+#ifdef MMAPSTORE
+    storeSwapLogData*s = e->s;
+    int oswf = s->swap_file_number;
+    if (oswf == swf)
+	return;
+    if (shutting_down) {
+	if (oswf >= 0) {
+            storeSwapLogData *ns = memAllocate(MEM_STORESWAPLOGDATA);
+	    *ns = *s;
+	    e->s = ns;
+	}
+        s->swap_file_number = swf;
+	return;
+    }
+    s->swap_file_number = swf;
+    if (EBIT_TEST(e->Sflag, ENTRY_SPECIAL))
+	return;
+    if (oswf < 0) {
+        SwapDir*sd = getswapdir(swf);
+	e->s = storeSwapAppendList(sd, s);
+	memFree(s, MEM_STORESWAPLOGDATA);
+#if HPL_REPL
+	assert(e->n.ode.id < 0);
+	heap_insert(sd->heap, e);
+#endif
+    } else {
+        SwapDir*sd,*osd = getswapdir(oswf);
+        if (swf < 0) {
+            storeSwapLogData *ns = memAllocate(MEM_STORESWAPLOGDATA);
+	    *ns = *s;
+	    e->s = ns;
+	    goto takeout;
+        }
+	sd = getswapdir(swf);
+	if (sd != osd) {
+	    e->s = storeSwapAppendList(sd, s);
+takeout:
+#if HPL_REPL
+	    if (e->n.ode.id >= 0) {
+		heap_delete(osd->heap, &e->n.ode);
+		e->n.ode.id = -1;
+	    }
+#endif
+	    storeSwapToFreeList(osd, s);
+	}
+    }
+#endif
+}
+
 /*
  * An entry written to the swap log MUST have the following
  * properties.
@@ -396,42 +569,48 @@
  *   2.  It MUST have a valid (> -1) swap_file_number.
  */
 void
-storeDirSwapLog(const StoreEntry * e, int op)
+storeDirSwapLog(StoreEntry * e, int op)
 {
+#ifdef MMAPSTORE
+    return;
+#else
     storeSwapLogData *s;
     int dirn;
-    dirn = e->swap_file_number >> SWAP_DIR_SHIFT;
+    SwapDir*sd;
+    dirn = e->Sswap_file_number >> SWAP_DIR_SHIFT;
     assert(dirn < Config.cacheSwap.n_configured);
-    assert(!EBIT_TEST(e->flags, KEY_PRIVATE));
-    assert(e->swap_file_number >= 0);
+    assert(!EBIT_TEST(e->Sflag, KEY_PRIVATE));
+    assert(e->Sswap_file_number >= 0);
+    sd = &Config.cacheSwap.swapDirs[dirn];
     /*
      * icons and such; don't write them to the swap log
      */
-    if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
+    if (EBIT_TEST(e->Sflag, ENTRY_SPECIAL))
 	return;
     assert(op > SWAP_LOG_NOP && op < SWAP_LOG_MAX);
     debug(20, 3) ("storeDirSwapLog: %s %s %08X\n",
 	swap_log_op_str[op],
-	storeKeyText(e->key),
-	e->swap_file_number);
+	storeKeyText(e->Skey),
+	e->Sswap_file_number);
     s = xcalloc(1, sizeof(storeSwapLogData));
     s->op = (char) op;
-    s->swap_file_number = e->swap_file_number;
-    s->timestamp = e->timestamp;
-    s->lastref = e->lastref;
-    s->expires = e->expires;
-    s->lastmod = e->lastmod;
-    s->swap_file_sz = e->swap_file_sz;
-    s->refcount = e->refcount;
-    s->flags = e->flags;
+    s->timestamp = e->Stimestamp;
+    s->lastref = e->Slastref;
+    s->expires = e->Sexpires;
+    s->lastmod = e->Slastmod;
+    s->swap_file_sz = e->Sswap_file_sz;
+    s->refcount = e->Srefcount;
+    s->flags = e->Sflag;
     xmemcpy(s->key, e->key, MD5_DIGEST_CHARS);
-    file_write(Config.cacheSwap.swapDirs[dirn].swaplog_fd,
+    s->swap_file_number = e->Sswap_file_number;
+    file_write(sd->swaplog_fd,
 	-1,
 	s,
 	sizeof(storeSwapLogData),
 	NULL,
 	NULL,
 	xfree);
+#endif
 }
 
 char *
@@ -463,14 +642,88 @@
     for (i = 0; i < Config.cacheSwap.n_configured; i++) {
 	SD = &Config.cacheSwap.swapDirs[i];
 	path = storeDirSwapLogFile(i, NULL);
-	fd = file_open(path, O_WRONLY | O_CREAT, NULL, NULL, NULL);
+	fd = file_open(path, O_RDWR | O_CREAT, NULL, NULL, NULL);
 	if (fd < 0) {
 	    debug(50, 1) ("%s: %s\n", path, xstrerror());
 	    fatal("storeDirOpenSwapLogs: Failed to open swap log.");
+#ifdef MMAPSTORE
+	    SD->mi = 0;
+#endif
 	}
 	debug(47, 3) ("Cache Dir #%d log opened on FD %d\n", i, fd);
 	SD->swaplog_fd = fd;
+	lseek(fd, 0L, SEEK_END);
+	mapfdswap(SD);
+#if HPL_REPL
+	if (!SD->heap)
+	    SD->heap = new_heap(SD->max_size / Config.Store.avgObjectSize,
+			    store_policy,
+			    offsetof(StoreEntry, n.ode));
+#endif
     }
+#ifdef MMAPSTORE
+    {
+	struct mmapinfo *mi, **pmi;
+	for (pmi=&allmi; mi = *pmi; ) {
+	    for (i = 0; i < Config.cacheSwap.n_configured; i++) {
+		SD = &Config.cacheSwap.swapDirs[i];
+		if (SD->swaplog_fd < 0)	/* not open */
+		    continue;
+		if (SD->mi == mi) {
+		    pmi = &mi->next;
+		    goto next;
+		}
+	    }
+	    xfree(mi->path);
+	    *pmi = mi->next;
+	    {
+		storeSwapLogData*oldbase = mi->mmapbase, *oldend = mi->mmapend;
+#ifdef	HPL_REPL
+#if 1
+		assert(0); /* delete_heap, filebitmap */
+#else
+		heap_node_p tobefreed = 0;
+		int node;
+	        for (node=0; node < heap_nodes(store_heap); ) {
+	            StoreEntry *e = (StoreEntry*)heap_peep(store_heap, node);
+	            if (oldbase <= e->s && e->s n.ode;
+			e->n.ode = tp;		/* collect'm */
+			continue;
+		    }
+		    node++;
+	        }
+		while (tobefreed) {		/* delete'm */
+		    heap_node_p next;
+		    StoreEntry *e;
+		    e = tobefreed->data;
+		    next = e->n.ode;
+		    e->n.ode = tobefreed;	/* put back node value */
+		    storeHashDelete(e);
+		    tobefreed = next;
+		}
+#endif
+#else	/* HPL_REPL */
+		dlink_node *m;
+	        for (m = store_list.tail; m; ) {
+	            StoreEntry *e = m->data;
+		    m = m->prev;
+	            if (oldbase <= e->s && e->s mmapbase, (char*)mi->mmapmax-(char*)mi->mmapbase);
+	    xfree(mi);
+next:;
+	}
+    }
+#endif
+
 }
 
 void
@@ -482,6 +735,13 @@
 	SD = &Config.cacheSwap.swapDirs[i];
 	if (SD->swaplog_fd < 0)	/* not open */
 	    continue;
+#ifdef MMAPSTORE
+	{
+	    struct mmapinfo *mi = SD->mi;
+	    msync(mi->mmapbase, (char*)mi->mmapend-(char*)mi-> mmapbase, MS_ASYNC);
+	}
+	SD->mi = 0;
+#endif
 	file_close(SD->swaplog_fd);
 	debug(47, 3) ("Cache Dir #%d log closed on FD %d\n", i, SD->swaplog_fd);
 	SD->swaplog_fd = -1;
@@ -491,6 +751,10 @@
 FILE *
 storeDirOpenTmpSwapLog(int dirn, int *clean_flag, int *zero_flag)
 {
+#ifdef MMAPSTORE
+    *clean_flag = 1; *zero_flag = 0;
+    return stderr;
+#else
     char *swaplog_path = xstrdup(storeDirSwapLogFile(dirn, NULL));
     char *clean_path = xstrdup(storeDirSwapLogFile(dirn, ".last-clean"));
     char *new_path = xstrdup(storeDirSwapLogFile(dirn, ".new"));
@@ -535,11 +799,13 @@
     safe_free(clean_path);
     safe_free(new_path);
     return fp;
+#endif
 }
 
 void
 storeDirCloseTmpSwapLog(int dirn)
 {
+#ifndef MMAPSTORE
     char *swaplog_path = xstrdup(storeDirSwapLogFile(dirn, NULL));
     char *new_path = xstrdup(storeDirSwapLogFile(dirn, ".new"));
     SwapDir *SD = &Config.cacheSwap.swapDirs[dirn];
@@ -564,6 +830,7 @@
     safe_free(new_path);
     SD->swaplog_fd = fd;
     debug(47, 3) ("Cache Dir #%d log opened on FD %d\n", dirn, fd);
+#endif
 }
 
 void
@@ -600,13 +867,23 @@
     for (i = 0; i < Config.cacheSwap.n_configured; i++) {
 	SD = &Config.cacheSwap.swapDirs[i];
 	storeAppendPrintf(sentry, "\n");
-	storeAppendPrintf(sentry, "Store Directory #%d: %s\n", i, SD->path);
-	storeAppendPrintf(sentry, "First level subdirectories: %d\n", SD->l1);
-	storeAppendPrintf(sentry, "Second level subdirectories: %d\n", SD->l2);
-	storeAppendPrintf(sentry, "Maximum Size: %d KB\n", SD->max_size);
-	storeAppendPrintf(sentry, "Current Size: %d KB\n", SD->cur_size);
-	storeAppendPrintf(sentry, "Percent Used: %0.2f%%\n",
-	    100.0 * SD->cur_size / SD->max_size);
+	storeAppendPrintf(sentry, "Store Directory #%d: %s [%d][%d]\n",
+	    i, SD->path, SD->l1, SD->l2);
+	storeAppendPrintf(sentry, "Size: %d < %d < %d KB of %d MB (%.2f%%)\n",
+	    SD->low_size, SD->cur_size, SD->low_size + SD->win_size*STORE_GRAN_MAX,
+	    SD->max_size / 1024, 100.0 * SD->cur_size / SD->max_size);
+#ifdef MMAPSTORE
+	{
+	    struct mmapinfo *mi = SD->mi;
+	    storeAppendPrintf(sentry,
+		"Swapfile: %.1f < %.1f < %.1f MB (%.2f%% efficiency)\n",
+		SD->heap->last * sizeof(storeSwapLogData) / (1024*1024.),
+		((char*)mi->mmapend-(char*)mi->mmapbase) / (1024*1024.),
+		((char*)mi->mmapmax-(char*)mi->mmapbase) / (1024*1024.),
+		100. * (SD->heap->last * sizeof(storeSwapLogData)) /
+		  ((char*)mi->mmapend-(char*)mi->mmapbase));
+	}
+#endif
 	storeAppendPrintf(sentry, "Filemap bits in use: %d of %d (%d%%)\n",
 	    SD->map->n_files_in_map, SD->map->max_n_files,
 	    percent(SD->map->n_files_in_map, SD->map->max_n_files));
@@ -643,6 +920,50 @@
     return n;
 }
 
+
+void
+storeDirConfigure(void)
+{
+    SwapDir *SD;
+    int n;
+    int i;
+    fileMap *fm;
+    Config.Swap.maxSize = 0;
+    for (i = 0; i < Config.cacheSwap.n_configured; i++) {
+	SD = &Config.cacheSwap.swapDirs[i];
+	Config.Swap.maxSize += SD->max_size;
+	SD->low_size = (double) SD->max_size * Config.Swap.lowWaterMark /100;
+	SD->win_size = (double) SD->max_size *
+		(Config.Swap.highWaterMark - Config.Swap.lowWaterMark) /100
+		/STORE_GRAN_MAX;
+	if (!SD->win_size)
+	    SD->win_size = 1;
+	n = SD->max_size / Config.Store.avgObjectSize * 3 / 2;
+	if (NULL == SD->map) {
+	    /* first time */
+	    SD->map = file_map_create(n);
+	    SD->heap = 0;
+	} else if (n > SD->map->max_n_files) {
+	    /* it grew, need to expand */
+	    fm = file_map_create(n);
+	    filemapCopy(SD->map, fm);
+	    filemapFreeMemory(SD->map);
+	    SD->map = fm;
+	}
+	/* else it shrunk, and we leave the old one in place */
+    }
+}
+
+void
+storeDirDiskFull(int fn)
+{
+    int dirn = fn >> SWAP_DIR_SHIFT;
+    SwapDir *SD = &Config.cacheSwap.swapDirs[dirn];
+    assert(0 <= dirn && dirn < Config.cacheSwap.n_configured);
+    SD->max_size = SD->cur_size;
+    debug(20, 1) ("WARNING: Shrinking cache_dir #%d to %d KB\n",
+	dirn, SD->cur_size);
+}
 /*
  *  storeDirWriteCleanLogs
  * 
@@ -652,6 +973,9 @@
 int
 storeDirWriteCleanLogs(int reopen)
 {
+#ifdef MMAPSTORE
+    return 0;
+#else
     StoreEntry *e = NULL;
     int *fd;
     int n = 0;
@@ -662,11 +986,16 @@
     char **cln;
     int dirn;
     int N = Config.cacheSwap.n_configured;
-    dlink_node *m;
     char **outbuf;
     off_t *outbufoffset;
     storeSwapLogData s;
     size_t ss = sizeof(storeSwapLogData);
+    #ifdef	HPL_REPL
+    int node;
+    #else	/* HPL_REPL */
+    dlink_node *m;
+    #endif	/* HPL_REPL */
+
     if (store_rebuilding) {
 	debug(20, 1) ("Not currently OK to rewrite swap log.\n");
 	debug(20, 1) ("storeDirWriteCleanLogs: Operation aborted.\n");
@@ -707,34 +1036,43 @@
 	outbuf[dirn] = xcalloc(CLEAN_BUF_SZ, 1);
 	outbufoffset[dirn] = 0;
     }
-    for (m = store_list.tail; m; m = m->prev) {
+    #ifdef	HPL_REPL
+    for (node=0; node < heap_nodes(store_heap); node++)
+    #else	/* HPL_REPL */
+    for (m = store_list.tail; m; m = m->prev)
+    #endif	/* HPL_REPL */
+      {
+	#ifdef	HPL_REPL
+	e = (StoreEntry*)heap_peep(store_heap, node);
+	#else	/* HPL_REPL */
 	e = m->data;
-	if (e->swap_file_number < 0)
+	#endif	/* HPL_REPL */
+	if (e->Sswap_file_number < 0)
 	    continue;
 	if (e->swap_status != SWAPOUT_DONE)
 	    continue;
-	if (e->swap_file_sz <= 0)
+	if (e->Sswap_file_sz <= 0)
 	    continue;
-	if (EBIT_TEST(e->flags, RELEASE_REQUEST))
+	if (EBIT_TEST(e->Sflag, RELEASE_REQUEST))
 	    continue;
-	if (EBIT_TEST(e->flags, KEY_PRIVATE))
+	if (EBIT_TEST(e->Sflag, KEY_PRIVATE))
 	    continue;
-	if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
+	if (EBIT_TEST(e->Sflag, ENTRY_SPECIAL))
 	    continue;
-	dirn = storeDirNumber(e->swap_file_number);
+	dirn = storeDirNumber(e->Sswap_file_number);
 	assert(dirn < N);
 	if (fd[dirn] < 0)
 	    continue;
 	memset(&s, '\0', ss);
 	s.op = (char) SWAP_LOG_ADD;
-	s.swap_file_number = e->swap_file_number;
-	s.timestamp = e->timestamp;
-	s.lastref = e->lastref;
-	s.expires = e->expires;
-	s.lastmod = e->lastmod;
-	s.swap_file_sz = e->swap_file_sz;
-	s.refcount = e->refcount;
-	s.flags = e->flags;
+	s.swap_file_number = e->Sswap_file_number;
+	s.timestamp = e->Stimestamp;
+	s.lastref = e->Slastref;
+	s.expires = e->Sexpires;
+	s.lastmod = e->Slastmod;
+	s.swap_file_sz = e->Sswap_file_sz;
+	s.refcount = e->Srefcount;
+	s.flags = e->Sflag;
 	xmemcpy(&s.key, e->key, MD5_DIGEST_CHARS);
 	xmemcpy(outbuf[dirn] + outbufoffset[dirn], &s, ss);
 	outbufoffset[dirn] += ss;
@@ -828,42 +1166,6 @@
     safe_free(cln);
     safe_free(fd);
     return n;
+#endif
 }
 #undef CLEAN_BUF_SZ
-
-void
-storeDirConfigure(void)
-{
-    SwapDir *SD;
-    int n;
-    int i;
-    fileMap *fm;
-    Config.Swap.maxSize = 0;
-    for (i = 0; i < Config.cacheSwap.n_configured; i++) {
-	SD = &Config.cacheSwap.swapDirs[i];;
-	Config.Swap.maxSize += SD->max_size;
-	n = 2 * SD->max_size / Config.Store.avgObjectSize;
-	if (NULL == SD->map) {
-	    /* first time */
-	    SD->map = file_map_create(n);
-	} else if (n > SD->map->max_n_files) {
-	    /* it grew, need to expand */
-	    fm = file_map_create(n);
-	    filemapCopy(SD->map, fm);
-	    filemapFreeMemory(SD->map);
-	    SD->map = fm;
-	}
-	/* else it shrunk, and we leave the old one in place */
-    }
-}
-
-void
-storeDirDiskFull(int fn)
-{
-    int dirn = fn >> SWAP_DIR_SHIFT;
-    SwapDir *SD = &Config.cacheSwap.swapDirs[dirn];
-    assert(0 <= dirn && dirn < Config.cacheSwap.n_configured);
-    SD->max_size = SD->cur_size;
-    debug(20, 1) ("WARNING: Shrinking cache_dir #%d to %d KB\n",
-	dirn, SD->cur_size);
-}
Index: squid/src/store_log.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_log.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.10.1
diff -u -r1.1.1.1 -r1.1.1.1.10.1
--- squid/src/store_log.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_log.c	10 Nov 2000 18:44:53 -0000	1.1.1.1.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_log.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_log.c,v 1.1.1.1.10.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Logging Functions
  * AUTHOR: Duane Wessels
@@ -66,7 +66,7 @@
 	(int) current_time.tv_sec,
 	(int) current_time.tv_usec / 1000,
 	storeLogTags[tag],
-	e->swap_file_number,
+	e->Sswap_file_number,
 	reply->sline.status,
 	(int) reply->date,
 	(int) reply->last_modified,
Index: squid/src/store_rebuild.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_rebuild.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/store_rebuild.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/store_rebuild.c	10 Nov 2000 18:44:53 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_rebuild.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: store_rebuild.c,v 1.1.1.2.10.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 20    Store Rebuild Routines
  * AUTHOR: Duane Wessels
@@ -91,8 +91,10 @@
 static void storeRebuildComplete(void);
 static EVH storeRebuildADirectory;
 static int storeGetNextFile(rebuild_dir *, int *sfileno, int *size);
-static StoreEntry *storeAddDiskRestore(const cache_key * key,
-    int file_number,
+#ifdef MMAPSTORE
+static StoreEntry *storeAddDiskRestore(storeSwapLogData*s);
+#else
+static StoreEntry *storeAddDiskRestore(int file_number,
     size_t swap_file_sz,
     time_t expires,
     time_t timestamp,
@@ -101,6 +103,7 @@
     u_num32 refcount,
     u_short flags,
     int clean);
+#endif
 static AIOCB storeValidateComplete;
 
 static int
@@ -109,7 +112,13 @@
     LOCAL_ARRAY(char, hdr_buf, DISK_PAGE_SIZE);
     StoreEntry *e = NULL;
     StoreEntry tmpe;
+#ifdef MMAPSTORE
+    storeSwapLogData tmps;
+    SwapDir *sd = Config.cacheSwap.swapDirs + d->dirn;
+    cache_key*key;
+#else
     cache_key key[MD5_DIGEST_CHARS];
+#endif
     int sfileno = 0;
     int count;
     int size;
@@ -119,7 +128,7 @@
     tlv *tlv_list;
     tlv *t;
     assert(d != NULL);
-    debug(20, 3) ("storeRebuildFromDirectory: DIR #%d\n", d->dirn);
+    debug(20, 2) ("storeRebuildFromDirectory: DIR #%d\n", d->dirn);
     for (count = 0; count < d->speed; count++) {
 	assert(fd == -1);
 	fd = storeGetNextFile(d, &sfileno, &size);
@@ -169,8 +178,14 @@
 	    continue;
 	}
 	debug(20, 3) ("storeRebuildFromDirectory: successful swap meta unpacking\n");
-	memset(key, '\0', MD5_DIGEST_CHARS);
 	memset(&tmpe, '\0', sizeof(StoreEntry));
+#ifdef MMAPSTORE
+	tmpe.s=&tmps;
+	memset(&tmps, '\0', sizeof(StoreEntry));
+	key = tmps.key;
+#else
+	memset(key, '\0', MD5_DIGEST_CHARS);
+#endif
 	for (t = tlv_list; t; t = t->next) {
 	    switch (t->type) {
 	    case STORE_META_KEY:
@@ -179,7 +194,7 @@
 		break;
 	    case STORE_META_STD:
 		assert(t->length == STORE_HDR_METASIZE);
-		xmemcpy(&tmpe.timestamp, t->value, STORE_HDR_METASIZE);
+		xmemcpy(&tmpe.Stimestamp, t->value, STORE_HDR_METASIZE);
 		break;
 	    default:
 		break;
@@ -192,25 +207,27 @@
 	    storeUnlinkFileno(sfileno);
 	    continue;
 	}
+#ifndef MMAPSTORE
 	tmpe.key = key;
+#endif
 	/* check sizes */
-	if (tmpe.swap_file_sz == 0) {
-	    tmpe.swap_file_sz = sb.st_size;
-	} else if (tmpe.swap_file_sz == sb.st_size - swap_hdr_len) {
-	    tmpe.swap_file_sz = sb.st_size;
-	} else if (tmpe.swap_file_sz != sb.st_size) {
+	if (tmpe.Sswap_file_sz == 0) {
+	    tmpe.Sswap_file_sz = sb.st_size;
+	} else if (tmpe.Sswap_file_sz == sb.st_size - swap_hdr_len) {
+	    tmpe.Sswap_file_sz = sb.st_size;
+	} else if (tmpe.Sswap_file_sz != sb.st_size) {
 	    debug(20, 1) ("storeRebuildFromDirectory: SIZE MISMATCH %d!=%d\n",
-		tmpe.swap_file_sz, (int) sb.st_size);
+		tmpe.Sswap_file_sz, (int) sb.st_size);
 	    storeUnlinkFileno(sfileno);
 	    continue;
 	}
-	if (EBIT_TEST(tmpe.flags, KEY_PRIVATE)) {
+	if (EBIT_TEST(tmpe.Sflag, KEY_PRIVATE)) {
 	    storeUnlinkFileno(sfileno);
 	    RebuildState.badflags++;
 	    continue;
 	}
 	e = storeGet(key);
-	if (e && e->lastref >= tmpe.lastref) {
+	if (e && e->Slastref >= tmpe.Slastref) {
 	    /* key already exists, current entry is newer */
 	    /* keep old, ignore new */
 	    RebuildState.dupcount++;
@@ -218,21 +235,34 @@
 	} else if (NULL != e) {
 	    /* URL already exists, this swapfile not being used */
 	    /* junk old, load new */
-	    storeRelease(e);	/* release old entry */
+	    storeLockObject(e);
+	    storeReleaseRequest(e);	/* release old entry */
+	    e->lock_count--;
 	    RebuildState.dupcount++;
 	}
 	RebuildState.objcount++;
 	storeEntryDump(&tmpe, 5);
+#ifdef MMAPSTORE
+	{
+	    storeSwapLogData *ns = memAllocate(MEM_STORESWAPLOGDATA);
+            *ns = tmps;
+	    ns->swap_file_number = -1;
+	    set_swap_file_number(ns, sfileno);
+	    e = storeAddDiskRestore(storeSwapAppendList(sd, ns));
+	}
+	storeDirSwapLog(e, SWAP_LOG_ADD);
+#else
 	e = storeAddDiskRestore(key,
 	    sfileno,
-	    tmpe.swap_file_sz,
-	    tmpe.expires,
-	    tmpe.timestamp,
-	    tmpe.lastref,
-	    tmpe.lastmod,
-	    tmpe.refcount,	/* refcount */
-	    tmpe.flags,		/* flags */
+	    tmpe.Sswap_file_sz,
+	    tmpe.Sexpires,
+	    tmpe.Stimestamp,
+	    tmpe.Slastref,
+	    tmpe.Slastmod,
+	    tmpe.Srefcount,	/* refcount */
+	    tmpe.Sflag,		/* flags */
 	    d->clean);
+#endif
     }
     return count;
 }
@@ -241,16 +271,28 @@
 storeRebuildFromSwapLog(rebuild_dir * d)
 {
     StoreEntry *e = NULL;
-    storeSwapLogData s;
+    storeSwapLogData ts,*s;
     size_t ss = sizeof(storeSwapLogData);
     int count;
     int used;			/* is swapfile already in use? */
     int disk_entry_newer;	/* is the log entry newer than current entry? */
     double x;
-    assert(d != NULL);
     /* load a number of objects per invocation */
+#ifdef MMAPSTORE
+    SwapDir *sd = Config.cacheSwap.swapDirs + d->dirn;
+    struct mmapinfo *mi = sd->mi;
+    for (s=mi->mmapbase, count = 0;; s++, count++) {
+	if (s - mi->mmapend >= 0) {
+	    debug(20, 1) ("Done reading Cache Dir #%d swaplog (%d entries)\n",
+		d->dirn, d->n_read);
+	    d->log = 0;
+	    return -1;
+	}
+#else
+    assert(d != NULL);
+    s = &ts;
     for (count = 0; count < d->speed; count++) {
-	if (fread(&s, ss, 1, d->log) != 1) {
+	if (fread(s, ss, 1, d->log) != 1) {
 	    debug(20, 1) ("Done reading Cache Dir #%d swaplog (%d entries)\n",
 		d->dirn, d->n_read);
 	    fclose(d->log);
@@ -258,20 +300,28 @@
 	    storeDirCloseTmpSwapLog(d->dirn);
 	    return -1;
 	}
+#endif
 	d->n_read++;
-	if (s.op <= SWAP_LOG_NOP)
+#ifdef MMAPSTORE
+	if (s->swap_file_number<0) {
+	    goto delit;
+	}
+#else
+	if (s->op <= SWAP_LOG_NOP)
 	    continue;
-	if (s.op >= SWAP_LOG_MAX)
+	if (s->op >= SWAP_LOG_MAX)
 	    continue;
-	s.swap_file_number = storeDirProperFileno(d->dirn, s.swap_file_number);
+#endif
+	s->swap_file_number = storeDirProperFileno(d->dirn, s->swap_file_number);
+#ifndef MMAPSTORE
 	debug(20, 3) ("storeRebuildFromSwapLog: %s %s %08X\n",
-	    swap_log_op_str[(int) s.op],
-	    storeKeyText(s.key),
-	    s.swap_file_number);
-	if (s.op == SWAP_LOG_ADD) {
+	    swap_log_op_str[(int) s->op],
+	    storeKeyText(s->key),
+	    s->swap_file_number);
+	if (s->op == SWAP_LOG_ADD) {
 	    (void) 0;
-	} else if (s.op == SWAP_LOG_DEL) {
-	    if ((e = storeGet(s.key)) != NULL) {
+	} else if (s->op == SWAP_LOG_DEL) {
+	    if ((e = storeGet(s->key)) != NULL) {
 		/*
 		 * Make sure we don't unlink the file, it might be
 		 * in use by a subsequent entry.  Also note that
@@ -281,9 +331,9 @@
 		 */
 		storeExpireNow(e);
 		storeReleaseRequest(e);
-		if (e->swap_file_number > -1) {
-		    storeDirMapBitReset(e->swap_file_number);
-		    e->swap_file_number = -1;
+		if (e->Sswap_file_number > -1) {
+		    storeDirMapBitReset(e->Sswap_file_number);
+		    e->Sswap_file_number = -1;
 		}
 		RebuildState.objcount--;
 		RebuildState.cancelcount++;
@@ -297,49 +347,60 @@
 	    RebuildState.invalid++;
 	    continue;
 	}
+#endif
 	if ((++RebuildState.linecount & 0xFFFF) == 0)
 	    debug(20, 1) ("  %7d Entries read so far.\n",
 		RebuildState.linecount);
-	if (!storeDirValidFileno(s.swap_file_number)) {
+	if (!storeDirValidFileno(s->swap_file_number)) {
 	    RebuildState.invalid++;
-	    continue;
+	    goto remswap;
 	}
-	if (EBIT_TEST(s.flags, KEY_PRIVATE)) {
+	used = storeDirMapBitTest(s->swap_file_number);
+	if (EBIT_TEST(s->flags, KEY_PRIVATE)) {
 	    RebuildState.badflags++;
-	    continue;
+	    if (!used)
+	       goto remswap;
+	    goto delit;
 	}
-	e = storeGet(s.key);
-	used = storeDirMapBitTest(s.swap_file_number);
+	e = storeGet(s->key);
 	/* If this URL already exists in the cache, does the swap log
 	 * appear to have a newer entry?  Compare 'lastref' from the
-	 * swap log to e->lastref. */
-	disk_entry_newer = e ? (s.lastref > e->lastref ? 1 : 0) : 0;
+	 * swap log to e->Slastref. */
+	disk_entry_newer = e ? (s->lastref > e->Slastref ? 1 : 0) : 0;
 	if (used && !disk_entry_newer) {
 	    /* log entry is old, ignore it */
 	    RebuildState.clashcount++;
-	    continue;
-	} else if (used && e && e->swap_file_number == s.swap_file_number) {
+	    goto delit;
+	} else if (used && e && e->Sswap_file_number == s->swap_file_number) {
 	    /* swapfile taken, same URL, newer, update meta */
 	    if (e->store_status == STORE_OK) {
-		e->lastref = s.timestamp;
-		e->timestamp = s.timestamp;
-		e->expires = s.expires;
-		e->lastmod = s.lastmod;
-		e->flags = s.flags;
-		e->refcount += s.refcount;
+		e->Slastref = s->timestamp;
+		e->Stimestamp = s->timestamp;
+		e->Sexpires = s->expires;
+		e->Slastmod = s->lastmod;
+		e->Sflag = s->flags;
+		e->Srefcount += s->refcount;
+#ifdef	HPL_REPL
+		/* Update the position of this object in the store and memory heaps. */
+		assert(e->n.ode.id >= 0);
+		heap_update(sd->heap, &e->n.ode);
+		if (e->mem_obj)
+		  heap_update(inmem_heap, &e->mem_obj->n.ode);
+#endif	/* HPL_REPL */
+
 	    } else {
 		debug_trap("storeRebuildFromSwapLog: bad condition");
 		debug(20, 1) ("\tSee %s:%d\n", __FILE__, __LINE__);
 	    }
-	    continue;
+	    goto delit;
 	} else if (used) {
 	    /* swapfile in use, not by this URL, log entry is newer */
 	    /* This is sorta bad: the log entry should NOT be newer at this
 	     * point.  If the log is dirty, the filesize check should have
-	     * caught this.  If the log is clean, there should never be a
+	     * caught this->  If the log is clean, there should never be a
 	     * newer entry. */
 	    debug(20, 1) ("WARNING: newer swaplog entry for fileno %08X\n",
-		s.swap_file_number);
+		s->swap_file_number);
 	    /* I'm tempted to remove the swapfile here just to be safe,
 	     * but there is a bad race condition in the NOVM version if
 	     * the swapfile has recently been opened for writing, but
@@ -349,24 +410,32 @@
 	    /* We'll assume the existing entry is valid, probably because
 	     * were in a slow rebuild and the the swap file number got taken
 	     * and the validation procedure hasn't run. */
+#ifndef MMAPSTORE
 	    assert(RebuildState.need_to_validate);
+#endif
 	    RebuildState.clashcount++;
-	    continue;
+	    goto delit;
 	} else if (e && !disk_entry_newer) {
 	    /* key already exists, current entry is newer */
 	    /* keep old, ignore new */
 	    RebuildState.dupcount++;
+remswap:
+#ifdef MMAPSTORE
+	    storeUnlinkFileno(s->swap_file_number);
+erasit:	    storeDirMapBitReset(s->swap_file_number);
+delit:	    storeSwapToFreeList(sd, s);
+#else
+delit:;
+#endif
 	    continue;
 	} else if (e) {
 	    /* key already exists, this swapfile not being used */
 	    /* junk old, load new */
 	    storeExpireNow(e);
 	    storeReleaseRequest(e);
-	    if (e->swap_file_number > -1) {
-		storeDirMapBitReset(e->swap_file_number);
-		e->swap_file_number = -1;
-	    }
 	    RebuildState.dupcount++;
+	    if (e->Sswap_file_number > -1)
+		goto erasit;
 	} else {
 	    /* URL doesnt exist, swapfile not in use */
 	    /* load new */
@@ -374,17 +443,24 @@
 	}
 	/* update store_swap_size */
 	RebuildState.objcount++;
-	e = storeAddDiskRestore(s.key,
-	    s.swap_file_number,
-	    s.swap_file_sz,
-	    s.expires,
-	    s.timestamp,
-	    s.lastref,
-	    s.lastmod,
-	    s.refcount,
-	    s.flags,
+#ifdef MMAPSTORE
+	e = storeAddDiskRestore(s);
+#else
+	e = storeAddDiskRestore(s->key,
+	    s->swap_file_number,
+	    s->swap_file_sz,
+	    s->expires,
+	    s->timestamp,
+	    s->lastref,
+	    s->lastmod,
+	    s->refcount,
+	    s->flags,
 	    d->clean);
 	storeDirSwapLog(e, SWAP_LOG_ADD);
+#endif
+#if HPL_REPL
+	heap_insert(sd->heap, e);
+#endif
     }
     return count;
 }
@@ -395,6 +471,7 @@
     int count;
     rebuild_dir *d;
     rebuild_dir **D;
+loop:
     if ((d = RebuildState.rebuild_dir) == NULL) {
 	storeRebuildComplete();
 	return;
@@ -409,7 +486,7 @@
 	d->next = NULL;
     }
     if (opt_foreground_rebuild)
-	storeRebuildADirectory(NULL);
+	goto loop;
     else
 	eventAdd("storeRebuild", storeRebuildADirectory, NULL, 0.0, 1);
 }
@@ -435,7 +512,7 @@
     tlv *tlv_list;
     StoreEntry e;
     e.key = key;
-    e.swap_file_sz = swap_file_sz;
+    e.Sswap_file_sz = swap_file_sz;
     e.expires = expires;
     e.lastref = lastref;
     e.refcount = refcount;
@@ -543,6 +620,9 @@
 /* Add a new object to the cache with empty memory copy and pointer to disk
  * use to rebuild store from disk. */
 static StoreEntry *
+#ifdef MMAPSTORE
+storeAddDiskRestore(storeSwapLogData*s)
+#else
 storeAddDiskRestore(const cache_key * key,
     int file_number,
     size_t swap_file_sz,
@@ -553,32 +633,39 @@
     u_num32 refcount,
     u_short flags,
     int clean)
+#endif
 {
     StoreEntry *e = NULL;
+#ifndef MMAPSTORE
     debug(20, 5) ("StoreAddDiskRestore: %s, fileno=%08X\n", storeKeyText(key), file_number);
+#endif
     /* if you call this you'd better be sure file_number is not 
      * already in use! */
     e = new_StoreEntry(STORE_ENTRY_WITHOUT_MEMOBJ, NULL, NULL);
     e->store_status = STORE_OK;
     storeSetMemStatus(e, NOT_IN_MEMORY);
     e->swap_status = SWAPOUT_DONE;
-    e->swap_file_number = file_number;
-    e->swap_file_sz = swap_file_sz;
     e->lock_count = 0;
-    e->refcount = 0;
-    e->lastref = lastref;
-    e->timestamp = timestamp;
-    e->expires = expires;
-    e->lastmod = lastmod;
-    e->refcount = refcount;
-    e->flags = flags;
-    EBIT_SET(e->flags, ENTRY_CACHABLE);
-    EBIT_CLR(e->flags, RELEASE_REQUEST);
-    EBIT_CLR(e->flags, KEY_PRIVATE);
     e->ping_status = PING_NONE;
-    EBIT_CLR(e->flags, ENTRY_VALIDATED);
-    storeDirMapBitSet(e->swap_file_number);
-    storeHashInsert(e, key);	/* do it after we clear KEY_PRIVATE */
+#ifdef MMAPSTORE
+    e->s = s;
+#else
+    e->key = key;
+    e->Sswap_file_number = file_number;
+    e->Sswap_file_sz = swap_file_sz;
+    e->Slastref = lastref;
+    e->Stimestamp = timestamp;
+    e->Sexpires = expires;
+    e->Slastmod = lastmod;
+    e->Srefcount = refcount;
+    e->Sflag = flags;
+#endif
+    EBIT_SET(e->Sflag, ENTRY_CACHABLE);
+    EBIT_CLR(e->Sflag, RELEASE_REQUEST);
+    EBIT_CLR(e->Sflag, KEY_PRIVATE);
+    EBIT_CLR(e->Sflag, ENTRY_VALIDATED);
+    storeDirMapBitSet(e->Sswap_file_number);
+    storeHashInsert(e, e->Skey);	/* do it after we clear KEY_PRIVATE */
     return e;
 }
 
@@ -591,13 +678,18 @@
     StoreEntry *e;
     hash_link *link_ptr = NULL;
     hash_link *link_next = NULL;
+    time_t force_doublecheck = RebuildState.start - 1024;
     if (++bucketnum >= store_hash_buckets) {
 	debug(20, 1) ("  Completed Validation Procedure\n");
 	debug(20, 1) ("  Validated %d Entries\n", validnum);
 	debug(20, 1) ("  store_swap_size = %dk\n", store_swap_size);
 	store_rebuilding = 0;
-	if (opt_store_doublecheck)
+	if (opt_store_doublecheck) {
+#if 0	/* bogus assertion srb */
 	    assert(store_errors == 0);
+#endif
+	    opt_store_doublecheck = 0;	/* only do this once */
+	}
 	if (store_digest)
 	    storeDigestNoteStoreReady();
 	return;
@@ -606,41 +698,57 @@
     while (NULL != (link_ptr = link_next)) {
 	link_next = link_ptr->next;
 	e = (StoreEntry *) link_ptr;
-	if (EBIT_TEST(e->flags, ENTRY_VALIDATED))
+	if (EBIT_TEST(e->Sflag, ENTRY_VALIDATED))
 	    continue;
+	if (e->Sswap_file_number < 0)
+	    continue;
+	if (EBIT_TEST(e->Sflag, RELEASE_REQUEST)) {
 	/*
 	 * Calling storeRelease() has no effect because we're
 	 * still in 'store_rebuilding' state
 	 */
-	if (e->swap_file_number < 0)
+relit:	    storeLockObject(e);
+	    storeReleaseRequest(e);	/* release entry */
+	    e->lock_count--;
 	    continue;
-	if (opt_store_doublecheck) {
+	}
+  	if (e->Sswap_file_number < 0)
+  	    continue;
+	if (opt_store_doublecheck ||
+		!e->Sswap_file_sz ||
+		e->Slastref > force_doublecheck) {
 	    struct stat sb;
-	    if (stat(storeSwapFullPath(e->swap_file_number, NULL), &sb) < 0) {
+	    if (stat(storeSwapFullPath(e->Sswap_file_number, NULL), &sb) < 0) {
+	        static unsigned vleft = 1024;
 		store_errors++;
-		debug(20, 0) ("storeCleanup: MISSING SWAP FILE\n");
-		debug(20, 0) ("storeCleanup: FILENO %08X\n", e->swap_file_number);
-		debug(20, 0) ("storeCleanup: PATH %s\n",
-		    storeSwapFullPath(e->swap_file_number, NULL));
-		storeEntryDump(e, 0);
-		continue;
+	        if (vleft) {
+		    if (!--vleft)
+			debug (20, 0) ("storeCleanup: Too many missing "
+			    "swapfiles, suppressing logging\n");
+		    debug(20, 1) ("storeCleanup: MISSING SWAP FILE\n");
+		    debug(20, 1) ("storeCleanup: FILENO %08X\n",
+			e->Sswap_file_number);
+		    debug(20, 1) ("storeCleanup: PATH %s\n",
+		        storeSwapFullPath(e->Sswap_file_number, NULL));
+dumpit:		    storeEntryDump(e, 1);
+	    }
+		goto relit;
 	    }
-	    if (e->swap_file_sz != sb.st_size) {
+	    if (e->Sswap_file_sz != sb.st_size) {
 		store_errors++;
-		debug(20, 0) ("storeCleanup: SIZE MISMATCH\n");
-		debug(20, 0) ("storeCleanup: FILENO %08X\n", e->swap_file_number);
-		debug(20, 0) ("storeCleanup: PATH %s\n",
-		    storeSwapFullPath(e->swap_file_number, NULL));
-		debug(20, 0) ("storeCleanup: ENTRY SIZE: %d, FILE SIZE: %d\n",
-		    e->swap_file_sz, (int) sb.st_size);
-		storeEntryDump(e, 0);
-		continue;
+		debug(20, 1) ("storeCleanup: SIZE MISMATCH\n");
+		debug(20, 1) ("storeCleanup: FILENO %08X\n", e->Sswap_file_number);
+		debug(20, 1) ("storeCleanup: PATH %s\n",
+		    storeSwapFullPath(e->Sswap_file_number, NULL));
+		debug(20, 1) ("storeCleanup: ENTRY SIZE: %d, FILE SIZE: %d\n",
+		    e->Sswap_file_sz, (int) sb.st_size);
+		goto dumpit;
 	    }
 	}
-	EBIT_SET(e->flags, ENTRY_VALIDATED);
+	EBIT_SET(e->Sflag, ENTRY_VALIDATED);
 	/* Only set the file bit if we know its a valid entry */
 	/* otherwise, set it in the validation procedure */
-	storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, 1);
+	storeDirUpdateSwapSize(e->Sswap_file_number, e->Sswap_file_sz, 1);
 	if ((++validnum & 0xFFFF) == 0)
 	    debug(20, 1) ("  %7d Entries Validated so far.\n", validnum);
     }
@@ -656,13 +764,13 @@
 #if !USE_ASYNC_IO
     int x;
 #endif
-    assert(!EBIT_TEST(e->flags, ENTRY_VALIDATED));
-    if (e->swap_file_number < 0) {
-	EBIT_CLR(e->flags, ENTRY_VALIDATED);
+    assert(!EBIT_TEST(e->Sflag, ENTRY_VALIDATED));
+    if (e->Sswap_file_number < 0) {
+	EBIT_CLR(e->Sflag, ENTRY_VALIDATED);
 	callback(callback_data, 0, 0);
 	return;
     }
-    path = storeSwapFullPath(e->swap_file_number, NULL);
+    path = storeSwapFullPath(e->Sswap_file_number, NULL);
     sb = xmalloc(sizeof(struct stat));
     ctrlp = xmalloc(sizeof(valid_ctrl_t));
     ctrlp->sb = sb;
@@ -698,14 +806,14 @@
 	return;
     }
     if (retcode < 0 && errcode == EWOULDBLOCK) {
-	path = storeSwapFullPath(e->swap_file_number, NULL);
+	path = storeSwapFullPath(e->Sswap_file_number, NULL);
 	retcode = stat(path, sb);
     }
-    if (retcode < 0 || sb->st_size == 0 || sb->st_size != e->swap_file_sz) {
-	EBIT_CLR(e->flags, ENTRY_VALIDATED);
+    if (retcode < 0 || sb->st_size == 0 || sb->st_size != e->Sswap_file_sz) {
+	EBIT_CLR(e->Sflag, ENTRY_VALIDATED);
     } else {
-	EBIT_SET(e->flags, ENTRY_VALIDATED);
-	storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, 1);
+	EBIT_SET(e->Sflag, ENTRY_VALIDATED);
+	storeDirUpdateSwapSize(e->Sswap_file_number, e->Sswap_file_sz, 1);
     }
     errno = errcode;
     ctrlp->callback(ctrlp->callback_data, retcode, errcode);
@@ -750,6 +858,7 @@
     int i;
     memset(&RebuildState, '\0', sizeof(RebuildState));
     RebuildState.start = squid_curtime;
+    store_swap_size = 0;
     for (i = 0; i < Config.cacheSwap.n_configured; i++) {
 	d = xcalloc(1, sizeof(rebuild_dir));
 	d->dirn = i;
Index: squid/src/store_swapin.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_swapin.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.12.1
diff -u -r1.1.1.2 -r1.1.1.2.12.1
--- squid/src/store_swapin.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/store_swapin.c	10 Nov 2000 18:44:53 -0000	1.1.1.2.12.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_swapin.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: store_swapin.c,v 1.1.1.2.12.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Swapin Functions
  * AUTHOR: Duane Wessels
@@ -50,21 +50,21 @@
 {
     swapin_ctrl_t *ctrlp;
     assert(e->mem_status == NOT_IN_MEMORY);
-    if (!EBIT_TEST(e->flags, ENTRY_VALIDATED)) {
+    if (!EBIT_TEST(e->Sflag, ENTRY_VALIDATED)) {
 	/* We're still reloading and haven't validated this entry yet */
 	callback(-1, callback_data);
 	return;
     }
     debug(20, 3) ("storeSwapInStart: called for %08X %s \n",
-	e->swap_file_number, storeKeyText(e->key));
+	e->Sswap_file_number, storeKeyText(e->Skey));
     assert(e->swap_status == SWAPOUT_WRITING || e->swap_status == SWAPOUT_DONE);
-    assert(e->swap_file_number >= 0);
+    assert(e->Sswap_file_number >= 0);
     assert(e->mem_obj != NULL);
     ctrlp = xmalloc(sizeof(swapin_ctrl_t));
     ctrlp->e = e;
     ctrlp->callback = callback;
     ctrlp->callback_data = callback_data;
-    if (EBIT_TEST(e->flags, ENTRY_VALIDATED))
+    if (EBIT_TEST(e->Sflag, ENTRY_VALIDATED))
 	storeSwapInValidateComplete(ctrlp, 0, 0);
     else
 	storeValidate(e, storeSwapInValidateComplete, ctrlp, callback_data);
@@ -81,13 +81,13 @@
     }
     e = ctrlp->e;
     assert(e->mem_status == NOT_IN_MEMORY);
-    if (!EBIT_TEST(e->flags, ENTRY_VALIDATED)) {
+    if (!EBIT_TEST(e->Sflag, ENTRY_VALIDATED)) {
 	/* Invoke a store abort that should free the memory object */
 	(ctrlp->callback) (-1, ctrlp->callback_data);
 	xfree(ctrlp);
 	return;
     }
-    ctrlp->path = xstrdup(storeSwapFullPath(e->swap_file_number, NULL));
+    ctrlp->path = xstrdup(storeSwapFullPath(e->Sswap_file_number, NULL));
     debug(20, 3) ("storeSwapInValidateComplete: Opening %s\n", ctrlp->path);
     store_open_disk_fd++;
     file_open(ctrlp->path,
@@ -126,8 +126,8 @@
 	file_close(fd);
 	store_open_disk_fd--;
 	fd = -1;
-    } else if (sb.st_size == 0 || sb.st_size != e->swap_file_sz) {
-	debug(20, 1) ("storeSwapInFileOpened: %s: Size mismatch: %d(fstat) != %d(object)\n", ctrlp->path, (int) sb.st_size, e->swap_file_sz);
+    } else if (sb.st_size == 0 || sb.st_size != e->Sswap_file_sz) {
+	debug(20, 1) ("storeSwapInFileOpened: %s: Size mismatch: %d(fstat) != %d(object)\n", ctrlp->path, (int) sb.st_size, e->Sswap_file_sz);
 	file_close(fd);
 	store_open_disk_fd--;
 	fd = -1;
Index: squid/src/store_swapmeta.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_swapmeta.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.12.1
diff -u -r1.1.1.1 -r1.1.1.1.12.1
--- squid/src/store_swapmeta.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_swapmeta.c	10 Nov 2000 18:44:53 -0000	1.1.1.1.12.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_swapmeta.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_swapmeta.c,v 1.1.1.1.12.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Swapfile Metadata
  * AUTHOR: Kostas Anagnostakis
@@ -72,8 +72,8 @@
     assert(e->swap_status == SWAPOUT_WRITING);
     url = storeUrl(e);
     debug(20, 3) ("storeSwapMetaBuild: %s\n", url);
-    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_KEY, e->Skey, MD5_DIGEST_CHARS, T);
+    T = storeSwapTLVAdd(STORE_META_STD, &e->Stimestamp, STORE_HDR_METASIZE, T);
     T = storeSwapTLVAdd(STORE_META_URL, url, strlen(url) + 1, T);
     return TLV;
 }
Index: squid/src/store_swapout.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_swapout.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.12.1
diff -u -r1.1.1.2 -r1.1.1.2.12.1
--- squid/src/store_swapout.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/store_swapout.c	10 Nov 2000 18:44:53 -0000	1.1.1.2.12.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_swapout.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: store_swapout.c,v 1.1.1.2.12.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Swapout Functions
  * AUTHOR: Duane Wessels
@@ -54,8 +54,8 @@
     assert(e->mem_obj);
     cbdataAdd(ctrlp, cbdataXfree, 0);
     storeLockObject(e);
-    e->swap_file_number = storeDirMapAllocate();
-    ctrlp->swapfilename = xstrdup(storeSwapFullPath(e->swap_file_number, NULL));
+    set_swap_file_number(e, storeDirMapAllocate());
+    ctrlp->swapfilename = xstrdup(storeSwapFullPath(e->Sswap_file_number, NULL));
     ctrlp->e = e;
     ctrlp->oldswapstatus = e->swap_status;
     e->swap_status = SWAPOUT_OPENING;
@@ -74,20 +74,20 @@
     swapout_ctrl_t *ctrlp = data;
     StoreEntry *e = ctrlp->e;
     MemObject *mem = e->mem_obj;
-    debug(20, 3) ("storeSwapOutHandle: '%s', len=%d\n", storeKeyText(e->key), (int) len);
+    debug(20, 3) ("storeSwapOutHandle: '%s', len=%d\n", storeKeyText(e->Skey), (int) len);
     if (flag < 0) {
 	debug(20, 1) ("storeSwapOutHandle: SwapOut failure (err code = %d).\n",
 	    flag);
 	e->swap_status = SWAPOUT_NONE;
-	if (e->swap_file_number > -1) {
-	    storeUnlinkFileno(e->swap_file_number);
-	    storeDirMapBitReset(e->swap_file_number);
+	if (e->Sswap_file_number > -1) {
+	    storeUnlinkFileno(e->Sswap_file_number);
+	    storeDirMapBitReset(e->Sswap_file_number);
 	    if (flag == DISK_NO_SPACE_LEFT) {
-		storeDirDiskFull(e->swap_file_number);
+		storeDirDiskFull(e->Sswap_file_number);
 		storeDirConfigure();
 		storeConfigure();
 	    }
-	    e->swap_file_number = -1;
+	    set_swap_file_number(e, -1);
 	}
 	storeReleaseRequest(e);
 	storeSwapOutFileClose(e);
@@ -112,10 +112,17 @@
     }
     /* swapping complete */
     debug(20, 5) ("storeSwapOutHandle: SwapOut complete: '%s' to %s.\n",
-	storeUrl(e), storeSwapFullPath(e->swap_file_number, NULL));
-    e->swap_file_sz = objectLen(e) + mem->swap_hdr_sz;
+	storeUrl(e), storeSwapFullPath(e->Sswap_file_number, NULL));
+    e->Sswap_file_sz = objectLen(e) + mem->swap_hdr_sz;
+#ifdef	HPL_REPL
+    /* Update the position of this object in the store and memory heaps. */
+    if (e->n.ode.id >= 0)
+        heap_update(Store_Heap(e), &e->n.ode);
+    if (mem->n.ode.id >= 0)
+        heap_update(inmem_heap, &mem->n.ode);
+#endif	/* HPL_REPL */
     e->swap_status = SWAPOUT_DONE;
-    storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, 1);
+    storeDirUpdateSwapSize(e->Sswap_file_number, e->Sswap_file_sz, 1);
     if (storeCheckCachable(e)) {
 	storeLog(STORE_LOG_SWAPOUT, e);
 	storeDirSwapLog(e, SWAP_LOG_ADD);
@@ -142,8 +149,8 @@
     debug(20, 7) ("storeCheckSwapOut: %s\n", storeUrl(e));
     debug(20, 7) ("storeCheckSwapOut: store_status = %s\n",
 	storeStatusStr[e->store_status]);
-    if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
-	assert(EBIT_TEST(e->flags, RELEASE_REQUEST));
+    if (EBIT_TEST(e->Sflag, ENTRY_ABORTED)) {
+	assert(EBIT_TEST(e->Sflag, RELEASE_REQUEST));
 	storeSwapOutFileClose(e);
 	return;
     }
@@ -158,7 +165,7 @@
 #if USE_ASYNC_IO
     if (mem->inmem_hi < mem->swapout.queue_offset) {
 	storeAbort(e);
-	assert(EBIT_TEST(e->flags, RELEASE_REQUEST));
+	assert(EBIT_TEST(e->Sflag, RELEASE_REQUEST));
 	storeSwapOutFileClose(e);
 	return;
     }
@@ -191,10 +198,10 @@
     if (swapout_size == 0) {
 	if (e->store_status == STORE_OK && !storeSwapOutWriteQueued(mem)) {
 	    debug(20, 7) ("storeCheckSwapOut: nothing to write for STORE_OK\n");
-	    if (e->swap_file_number > -1) {
-		storeUnlinkFileno(e->swap_file_number);
-		storeDirMapBitReset(e->swap_file_number);
-		e->swap_file_number = -1;
+	    if (e->Sswap_file_number > -1) {
+		storeUnlinkFileno(e->Sswap_file_number);
+		storeDirMapBitReset(e->Sswap_file_number);
+	        set_swap_file_number(e, -1);
 	    }
 	    e->swap_status = SWAPOUT_NONE;
 	    storeReleaseRequest(e);
@@ -234,11 +241,12 @@
 	swap_buf,
 	swapout_size);
     if (swap_buf_len < 0) {
-	debug(20, 1) ("stmemCopy returned %d for '%s'\n", swap_buf_len, storeKeyText(e->key));
-	storeUnlinkFileno(e->swap_file_number);
-	storeDirMapBitReset(e->swap_file_number);
-	e->swap_file_number = -1;
+	debug(20, 1) ("stmemCopy returned %d for '%s'\n", swap_buf_len, storeKeyText(e->Skey));
+	storeUnlinkFileno(e->Sswap_file_number);
+	storeDirMapBitReset(e->Sswap_file_number);
 	e->swap_status = SWAPOUT_NONE;
+	storeDirSwapLog(e, SWAP_LOG_DEL);
+	set_swap_file_number(e, -1);
 	memFree(swap_buf, MEM_DISK_BUF);
 	storeReleaseRequest(e);
 	storeSwapOutFileClose(e);
@@ -264,7 +272,7 @@
     MemObject *mem = e->mem_obj;
     swapout_ctrl_t *ctrlp;
     assert(mem != NULL);
-    debug(20, 3) ("storeSwapOutFileClose: %s\n", storeKeyText(e->key));
+    debug(20, 3) ("storeSwapOutFileClose: %s\n", storeKeyText(e->Skey));
     if (mem->swapout.fd < 0) {
 #if USE_ASYNC_IO
 	aioCancel(-1, e);	/* Make doubly certain pending ops are gone */
@@ -306,8 +314,8 @@
 	 * we don't try re-using it over and over
 	 */
 	if (errno != EPERM)
-	    storeDirMapBitReset(e->swap_file_number);
-	e->swap_file_number = -1;
+	    storeDirMapBitReset(e->Sswap_file_number);
+	set_swap_file_number(e, -1);
 	e->swap_status = ctrlp->oldswapstatus;
 	xfree(ctrlp->swapfilename);
 	cbdataFree(ctrlp);
@@ -319,7 +327,7 @@
     e->swap_status = SWAPOUT_WRITING;
     debug(20, 5) ("storeSwapOutFileOpened: Begin SwapOut '%s' to FD %d '%s'\n",
 	storeUrl(e), fd, ctrlp->swapfilename);
-    debug(20, 5) ("swap_file_number=%08X\n", e->swap_file_number);
+    debug(20, 5) ("swap_file_number=%08X\n", e->Sswap_file_number);
     tlv_list = storeSwapMetaBuild(e);
     buf = storeSwapMetaPack(tlv_list, &swap_hdr_sz);
     storeSwapTLVFree(tlv_list);
@@ -399,5 +407,5 @@
     for (sc = e->mem_obj->clients; sc; sc = sc->next)
 	if (sc->type == STORE_DISK_CLIENT)
 	    return 1;
-    return EBIT_TEST(e->flags, ENTRY_CACHABLE);
+    return EBIT_TEST(e->Sflag, ENTRY_CACHABLE);
 }
Index: squid/src/structs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/structs.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/structs.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/structs.h	10 Nov 2000 18:44:53 -0000	1.1.1.2.10.1
@@ -1,6 +1,9 @@
-
+#define MMAPSTORE	/*srb*/
+#define NEVERFREE
+#define SSPOOLS
+#define HPL_REPL	1
 /*
- * $Id: structs.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: structs.h,v 1.1.1.2.10.1 2000/11/10 18:44:53 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -231,6 +234,13 @@
 	int pct;
 	size_t max;
     } quickAbort;
+#ifdef	HPL_REPL
+    char * replPolicy;
+#endif	/* HPL_REPL */
+    /* 
+     * Note: the non-LRU policies do not use referenceAge, but we cannot
+     * remove it until we find out how to implement #else for cf_parser.c
+     */
     time_t referenceAge;
     time_t negativeTtl;
     time_t negativeDnsTtl;
@@ -253,6 +263,7 @@
     size_t maxRequestSize;
     struct {
 	ushortlist *http;
+	ushort bhttp;
 	u_short icp;
 #if USE_HTCP
 	u_short htcp;
@@ -1195,15 +1206,30 @@
 #endif
 };
 
+#ifdef	HPL_REPL
+#include "heap.h"
+#endif	/* HPL_REPL */
 
 /* This structure can be freed while object is purged out from memory */
 struct _MemObject {
-    method_t method;
     char *url;
+    store_client *clients;
+#if HPL_REPL
+    /* 
+     * A MemObject knows where it is in the in-memory heap.
+     */
+    union {
+     heap_node ode;
+     struct _MemObject *ext;
+    } n;
+    StoreEntry *entry;
+#else	/* HPL_REPL */
+    dlink_node lru;
+#endif	/* HPL_REPL */
+    method_t method;
     mem_hdr data_hdr;
     off_t inmem_hi;
     off_t inmem_lo;
-    store_client *clients;
     int nclients;
     struct {
 	off_t queue_offset;	/* relative to in-mem data */
@@ -1222,17 +1248,51 @@
 	void *data;
     } abort;
     char *log_url;
-    dlink_node lru;
     int id;
     ssize_t object_sz;
     size_t swap_hdr_sz;
 };
 
+#ifdef MMAPSTORE
+#define Skey			s->key
+#define Stimestamp		s->timestamp
+#define Slastref		s->lastref
+#define Sexpires		s->expires
+#define Slastmod		s->lastmod
+#define Sswap_file_sz		s->swap_file_sz
+#define Srefcount		s->refcount
+#define Sflag			s->flags
+#define Sswap_file_number	s->swap_file_number
+#else
+#define Skey			key
+#define Stimestamp		timestamp
+#define Slastref		lastref
+#define Sexpires		expires
+#define Slastmod		lastmod
+#define Sswap_file_sz		swap_file_sz
+#define Srefcount		refcount
+#define Sflag			flags
+#define Sswap_file_number	swap_file_number
+#endif
+
 struct _StoreEntry {
     /* first two items must be same as hash_link */
+#ifdef MMAPSTORE
+    storeSwapLogData *s;
+#else
     const cache_key *key;
-    StoreEntry *next;
+#endif
+    StoreEntry *next;		/* for the hash table */
+#ifdef	HPL_REPL
+    union {
+     heap_node ode;
+     StoreEntry *ext;
+    } n;
+#else	/* HPL_REPL */
+    dlink_node lru;
+#endif	/* HPL_REPL */
     MemObject *mem_obj;
+#ifndef MMAPSTORE
     time_t timestamp;
     time_t lastref;
     time_t expires;
@@ -1241,7 +1301,7 @@
     u_short refcount;
     u_short flags;
     int swap_file_number;
-    dlink_node lru;
+#endif
     u_short lock_count;		/* Assume < 65536! */
     mem_status_t mem_status:3;
     ping_status_t ping_status:3;
@@ -1249,14 +1309,31 @@
     swap_status_t swap_status:3;
 };
 
+#ifdef MMAPSTORE
+struct mmapinfo {
+    storeSwapLogData*mmapbase,*mmapend,*mmapmax,*mmapfreelist;
+    char*path;
+    struct mmapinfo*next;
+};
+#endif
+
 struct _SwapDir {
+#ifdef MMAPSTORE
+    struct mmapinfo*mi;
+#endif
     char *path;
     int l1;
     int l2;
+    int low_size;
     int cur_size;
+    int win_size;
     int max_size;
     int suggest;
     fileMap *map;
+#if HPL_REPL
+    heap_p heap;
+    unsigned riddance;
+#endif
     int swaplog_fd;
     struct {
 	unsigned int selected:1;
@@ -1518,16 +1595,18 @@
 };
 
 struct _storeSwapLogData {
-    char op;
-    int swap_file_number;
+    unsigned char key[MD5_DIGEST_CHARS];
+    size_t swap_file_sz;
     time_t timestamp;
     time_t lastref;
     time_t expires;
     time_t lastmod;
-    size_t swap_file_sz;
     u_short refcount;
     u_short flags;
-    unsigned char key[MD5_DIGEST_CHARS];
+#ifndef MMAPSTORE
+    char op;
+#endif
+    int swap_file_number;
 };
 
 /* object to track per-action memory usage (e.g. #idle objects) */
@@ -1550,7 +1629,8 @@
 struct _MemPool {
     const char *label;
     size_t obj_size;
-    Stack pstack;		/* stack for free pointers */
+    void*pstack;		/* stack for free pointers */
+    struct _MemPool *ss;	/* same size free pool */
     MemPoolMeter meter;
 };
 
Index: squid/src/tools.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/tools.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/tools.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/tools.c	10 Nov 2000 18:44:53 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: tools.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: tools.c,v 1.1.1.2.10.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 21    Misc Functions
  * AUTHOR: Harvest Derived
@@ -216,7 +216,10 @@
 {
     struct rusage rusage;
     squid_getrusage(&rusage);
-    fprintf(debug_log, "CPU Usage: %.3f seconds\n", rusage_cputime(&rusage));
+    fprintf(debug_log, "CPU Usage: %.3f seconds = %.3f user + %.3f sys\n",
+	    rusage_cputime(&rusage), 
+	    rusage.ru_utime.tv_sec + ((double) rusage.ru_utime.tv_usec / 1000000.0),
+	    rusage.ru_stime.tv_sec + ((double) rusage.ru_stime.tv_usec / 1000000.0));
     fprintf(debug_log, "Maximum Resident Size: %d KB\n",
 	rusage_maxrss(&rusage));
     fprintf(debug_log, "Page faults with physical i/o: %d\n",
@@ -262,7 +265,9 @@
     releaseServerSockets();
     storeDirWriteCleanLogs(0);
     PrintRusage();
+#if 0 /* srb prevent deadlocks */
     dumpMallocStats();
+#endif
     if (squid_curtime - SQUID_RELEASE_TIME < 864000) {
 	/* skip if more than 10 days old */
 	if (Config.adminEmail)
Index: squid/src/url.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/url.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/url.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/url.c	10 Nov 2000 18:44:53 -0000	1.1.1.2.10.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: url.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: url.c,v 1.1.1.2.10.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 23    URL Parsing
  * AUTHOR: Duane Wessels
@@ -241,7 +241,7 @@
     /* remove trailing dots from hostnames */
     while ((l = strlen(host)) > 0 && host[--l] == '.')
 	host[l] = '\0';
-    if (Config.appendDomain && !strchr(host, '.'))
+    if (Config.appendDomain && *host && !strchr(host, '.'))
 	strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN);
     if (port == 0) {
 	debug(23, 3) ("urlParse: Invalid port == 0\n");
Index: squid/src/urn.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/urn.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.10.1
diff -u -r1.1.1.2 -r1.1.1.2.10.1
--- squid/src/urn.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/urn.c	10 Nov 2000 18:44:53 -0000	1.1.1.2.10.1
@@ -1,7 +1,7 @@
 
 /*
  *
- * $Id: urn.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: urn.c,v 1.1.1.2.10.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 52    URN Parsing
  * AUTHOR: Kostas Anagnostakis
@@ -187,7 +187,7 @@
     int urlcnt = 0;
 
     debug(52, 3) ("urnHandleReply: Called with size=%d.\n", size);
-    if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(urlres_e->Sflag, ENTRY_ABORTED)) {
 	memFree(buf, MEM_4K_BUF);
 	return;
     }
Index: squid/src/wais.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/wais.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.28.1
diff -u -r1.1.1.2 -r1.1.1.2.28.1
--- squid/src/wais.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
+++ squid/src/wais.c	10 Nov 2000 18:44:53 -0000	1.1.1.2.28.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: wais.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
+ * $Id: wais.c,v 1.1.1.2.28.1 2000/11/10 18:44:53 hno Exp $
  *
  * DEBUG: section 24    WAIS Relay
  * AUTHOR: Harvest Derived
@@ -93,7 +93,7 @@
 #if DELAY_POOLS
     delay_id delay_id = delayMostBytesAllowed(entry->mem_obj);
 #endif
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+    if (EBIT_TEST(entry->Sflag, ENTRY_ABORTED)) {
 	comm_close(fd);
 	return;
     }
@@ -130,7 +130,7 @@
 		waisReadReply, waisState, 0);
 	} else {
 	    ErrorState *err;
-	    EBIT_CLR(entry->flags, ENTRY_CACHABLE);
+	    EBIT_CLR(entry->Sflag, ENTRY_CACHABLE);
 	    storeReleaseRequest(entry);
 	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
 	    err->xerrno = errno;
@@ -147,7 +147,7 @@
 	comm_close(fd);
     } else if (len == 0) {
 	/* Connection closed; retrieval done. */
-	entry->expires = squid_curtime;
+	entry->Sexpires = squid_curtime;
 	fwdComplete(waisState->fwd);
 	comm_close(fd);
     } else {
@@ -211,9 +211,9 @@
     memBufPrintf(&mb, "\r\n");
     debug(24, 6) ("waisSendRequest: buf: %s\n", mb.buf);
     comm_write_mbuf(fd, mb, waisSendComplete, waisState);
-    if (EBIT_TEST(waisState->entry->flags, ENTRY_CACHABLE))
+    if (EBIT_TEST(waisState->entry->Sflag, ENTRY_CACHABLE))
 	storeSetPublicKey(waisState->entry);	/* Make it public */
-    EBIT_CLR(waisState->entry->flags, ENTRY_FWD_HDR_WAIT);
+    EBIT_CLR(waisState->entry->Sflag, ENTRY_FWD_HDR_WAIT);
 }
 
 void