# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: henrik@henriknordstrom.net-20100529013101-\
#   wsx8ra6jggw9nibl
# target_branch: http://www.squid-cache.org/bzr/squid3/trunk/
# testament_sha1: 97dccb4964a9a07345462887b7dbc0c52274b136
# timestamp: 2010-05-29 03:32:22 +0200
# base_revision_id: henrik@henriknordstrom.net-20100528215627-\
#   agkq7l8rn7lertwg
# 
# Begin patch
=== modified file 'configure.in'
--- configure.in	2010-05-28 14:15:11 +0000
+++ configure.in	2010-05-29 01:31:01 +0000
@@ -1953,19 +1953,18 @@
 ])
 
 dnl Disable "memPools" code
-AC_ARG_ENABLE(mempools,
-  AS_HELP_STRING([--disable-mempools],
-                 [Disable memPools. Note that this option now simply sets the
-                  default behaviour. Specific classes can override this 
+AC_ARG_ENABLE(chunkedmempools,
+  AS_HELP_STRING([--enable-chunkedmempools],
+                 [Enable experimental chunked memPools. Note that this option
+		  simply sets the default behaviour. Specific classes can override this 
                   at runtime, and only lib/MemPool.c needs to be altered 
                   to change the squid-wide default for all classes.]), [ 
 SQUID_YESNO([$enableval],
-            [--disable-mempools option takes no arguments])
+            [--enable-chunkedmempools option takes no arguments])
 ])
-# notice: the definition's value meaning is INVERTED
-SQUID_DEFINE_BOOL(USE_MEMPOOLS,${enable_mempools:=no},
-   [Enable internal Memory Pools support (experimental)])
-AC_MSG_NOTICE([MemPools enabled: $enable_mempools])
+SQUID_DEFINE_BOOL(USE_CHUNKEDMEMPOOLS,${enable_chunkedmempools:=no},
+   [Enable chunked Memory Pools support (experimental)])
+AC_MSG_NOTICE([Chunked MemPools enabled: $enable_chunkedmempools])
 
 dnl Enable WIN32 Service compile mode
 AC_ARG_ENABLE(win32-service,

=== modified file 'include/MemPool.h'
--- include/MemPool.h	2010-03-21 03:08:26 +0000
+++ include/MemPool.h	2010-05-29 00:59:35 +0000
@@ -1,5 +1,5 @@
-#ifndef _MEM_POOLS_H_
-#define _MEM_POOLS_H_
+#ifndef _MEM_POOL_H_
+#define _MEM_POOL_H_
 
 /**
  \defgroup MemPoolsAPI  Memory Management (Memory Pool Allocator)
@@ -63,7 +63,6 @@
 #define MEM_MAX_FREE  65535	/* ushort is max number of items per chunk */
 
 class MemImplementingAllocator;
-class MemChunk;
 class MemPoolStats;
 
 /// \ingroup MemPoolsAPI
@@ -97,17 +96,20 @@
 class MemPoolMeter
 {
 public:
+    MemPoolMeter();
     void flush();
     MemMeter alloc;
     MemMeter inuse;
     MemMeter idle;
 
-    /** account Allocations */
+
+    /** history Allocations */
+    mgb_t gb_allocated;
+    mgb_t gb_oallocated;
+
+    /** account Saved Allocations */
     mgb_t gb_saved;
 
-    /** history Allocations */
-    mgb_t gb_osaved;
-
     /** account Free calls */
     mgb_t gb_freed;
 };
@@ -130,13 +132,6 @@
     MemImplementingAllocator * create(const char *label, size_t obj_size);
 
     /**
-     \param label	Name for the pool. Displayed in stats.
-     \param obj_size	Size of elements in MemPool.
-     \param chunked	??
-     */
-    MemImplementingAllocator * create(const char *label, size_t obj_size, bool const chunked);
-
-    /**
      * Sets upper limit in bytes to amount of free ram kept in pools. This is
      * not strict upper limit, but a hint. When MemPools are over this limit,
      * totally free chunks are immediately considered for release. Otherwise
@@ -197,7 +192,7 @@
      \param stats	Object to be filled with statistical data about pool.
      \retval		Number of objects in use, ie. allocated.
      */
-    virtual int getStats(MemPoolStats * stats) = 0;
+    virtual int getStats(MemPoolStats * stats, int accumulate = 0) = 0;
 
     virtual MemPoolMeter const &getMeter() const = 0;
 
@@ -325,6 +320,7 @@
 {
 public:
     MemImplementingAllocator(char const *aLabel, size_t aSize);
+    virtual ~MemImplementingAllocator();
     virtual MemPoolMeter const &getMeter() const;
     virtual MemPoolMeter &getMeter();
     virtual void flushMetersFull();
@@ -342,111 +338,23 @@
 
     virtual bool idleTrigger(int shift) const = 0;
     virtual void clean(time_t maxage) = 0;
-    /** Hint to the allocator - may be ignored */
-    virtual void setChunkSize(size_t chunksize) {}
     virtual size_t objectSize() const;
     virtual int getInUseCount() = 0;
 protected:
     virtual void *allocate() = 0;
-    virtual void deallocate(void *) = 0;
-private:
+    virtual void deallocate(void *, bool aggressive) = 0;
     MemPoolMeter meter;
+    int memPID;
 public:
     MemImplementingAllocator *next;
 public:
     size_t alloc_calls;
     size_t free_calls;
+    size_t saved_calls;
     size_t obj_size;
 };
 
 /// \ingroup MemPoolsAPI
-class MemPool : public MemImplementingAllocator
-{
-public:
-    friend class MemChunk;
-    MemPool(const char *label, size_t obj_size);
-    ~MemPool();
-    void convertFreeCacheToChunkFreeCache();
-    virtual void clean(time_t maxage);
-
-    /**
-     \param stats	Object to be filled with statistical data about pool.
-     \retval		Number of objects in use, ie. allocated.
-     */
-    virtual int getStats(MemPoolStats * stats);
-
-    void createChunk();
-    void *get();
-    void push(void *obj);
-    virtual int getInUseCount();
-protected:
-    virtual void *allocate();
-    virtual void deallocate(void *);
-public:
-    /**
-     * Allows you tune chunk size of pooling. Objects are allocated in chunks
-     * instead of individually. This conserves memory, reduces fragmentation.
-     * Because of that memory can be freed also only in chunks. Therefore
-     * there is tradeoff between memory conservation due to chunking and free
-     * memory fragmentation.
-     *
-     \note  As a general guideline, increase chunk size only for pools that keep
-     *      very many items for relatively long time.
-     */
-    virtual void setChunkSize(size_t chunksize);
-
-    virtual bool idleTrigger(int shift) const;
-
-    size_t chunk_size;
-    int chunk_capacity;
-    int memPID;
-    int chunkCount;
-    size_t inuse;
-    size_t idle;
-    void *freeCache;
-    MemChunk *nextFreeChunk;
-    MemChunk *Chunks;
-    Splay<MemChunk *> allChunks;
-};
-
-/// \ingroup MemPoolsAPI
-class MemMalloc : public MemImplementingAllocator
-{
-public:
-    MemMalloc(char const *label, size_t aSize);
-    virtual bool idleTrigger(int shift) const;
-    virtual void clean(time_t maxage);
-
-    /**
-     \param stats	Object to be filled with statistical data about pool.
-     \retval		Number of objects in use, ie. allocated.
-     */
-    virtual int getStats(MemPoolStats * stats);
-
-    virtual int getInUseCount();
-protected:
-    virtual void *allocate();
-    virtual void deallocate(void *);
-private:
-    int inuse;
-};
-
-/// \ingroup MemPoolsAPI
-class MemChunk
-{
-public:
-    MemChunk(MemPool *pool);
-    ~MemChunk();
-    void *freeList;
-    void *objCache;
-    int inuse_count;
-    MemChunk *nextFreeChunk;
-    MemChunk *next;
-    time_t lastref;
-    MemPool *pool;
-};
-
-/// \ingroup MemPoolsAPI
 class MemPoolStats
 {
 public:
@@ -536,4 +444,4 @@
 }
 
 
-#endif /* _MEM_POOLS_H_ */
+#endif /* _MEM_POOL_H_ */

=== added file 'include/MemPoolChunked.h'
--- include/MemPoolChunked.h	1970-01-01 00:00:00 +0000
+++ include/MemPoolChunked.h	2010-05-29 00:59:35 +0000
@@ -0,0 +1,82 @@
+#ifndef _MEM_POOL_CHUNKED_H_
+#define _MEM_POOL_CHUNKED_H_
+
+#include "MemPool.h"
+
+/// \ingroup MemPoolsAPI
+#define MEM_PAGE_SIZE 4096
+/// \ingroup MemPoolsAPI
+#define MEM_CHUNK_SIZE 4096 * 4
+/// \ingroup MemPoolsAPI
+#define MEM_CHUNK_MAX_SIZE  256 * 1024	/* 2MB */
+/// \ingroup MemPoolsAPI
+#define MEM_MIN_FREE  32
+/// \ingroup MemPoolsAPI
+#define MEM_MAX_FREE  65535	/* ushort is max number of items per chunk */
+
+class MemChunk;
+
+/// \ingroup MemPoolsAPI
+class MemPoolChunked : public MemImplementingAllocator
+{
+public:
+    friend class MemChunk;
+    MemPoolChunked(const char *label, size_t obj_size);
+    ~MemPoolChunked();
+    void convertFreeCacheToChunkFreeCache();
+    virtual void clean(time_t maxage);
+
+    /**
+     \param stats	Object to be filled with statistical data about pool.
+     \retval		Number of objects in use, ie. allocated.
+     */
+    virtual int getStats(MemPoolStats * stats, int accumulate);
+
+    void createChunk();
+    void *get();
+    void push(void *obj);
+    virtual int getInUseCount();
+protected:
+    virtual void *allocate();
+    virtual void deallocate(void *, bool aggressive);
+public:
+    /**
+     * Allows you tune chunk size of pooling. Objects are allocated in chunks
+     * instead of individually. This conserves memory, reduces fragmentation.
+     * Because of that memory can be freed also only in chunks. Therefore
+     * there is tradeoff between memory conservation due to chunking and free
+     * memory fragmentation.
+     *
+     \note  As a general guideline, increase chunk size only for pools that keep
+     *      very many items for relatively long time.
+     */
+    virtual void setChunkSize(size_t chunksize);
+
+    virtual bool idleTrigger(int shift) const;
+
+    size_t chunk_size;
+    int chunk_capacity;
+    int memPID;
+    int chunkCount;
+    void *freeCache;
+    MemChunk *nextFreeChunk;
+    MemChunk *Chunks;
+    Splay<MemChunk *> allChunks;
+};
+
+/// \ingroup MemPoolsAPI
+class MemChunk
+{
+public:
+    MemChunk(MemPoolChunked *pool);
+    ~MemChunk();
+    void *freeList;
+    void *objCache;
+    int inuse_count;
+    MemChunk *nextFreeChunk;
+    MemChunk *next;
+    time_t lastref;
+    MemPoolChunked *pool;
+};
+
+#endif /* _MEM_POOL_CHUNKED_H_ */

=== added file 'include/MemPoolMalloc.h'
--- include/MemPoolMalloc.h	1970-01-01 00:00:00 +0000
+++ include/MemPoolMalloc.h	2010-05-29 00:59:35 +0000
@@ -0,0 +1,49 @@
+#ifndef _MEM_POOL_MALLOC_H_
+#define _MEM_POOL_MALLOC_H_
+
+/**
+ \defgroup MemPoolsAPI  Memory Management (Memory Pool Allocator)
+ \ingroup Components
+ *
+ *\par
+ *  MemPools are a pooled memory allocator running on top of malloc(). It's
+ *  purpose is to reduce memory fragmentation and provide detailed statistics
+ *  on memory consumption.
+ *
+ \par
+ *  Preferably all memory allocations in Squid should be done using MemPools
+ *  or one of the types built on top of it (i.e. cbdata).
+ *
+ \note Usually it is better to use cbdata types as these gives you additional
+ *     safeguards in references and typechecking. However, for high usage pools where
+ *     the cbdata functionality of cbdata is not required directly using a MemPool
+ *     might be the way to go.
+ */
+
+#include "MemPool.h"
+
+/// \ingroup MemPoolsAPI
+class MemPoolMalloc : public MemImplementingAllocator
+{
+public:
+    MemPoolMalloc(char const *label, size_t aSize);
+    ~MemPoolMalloc();
+    virtual bool idleTrigger(int shift) const;
+    virtual void clean(time_t maxage);
+
+    /**
+     \param stats	Object to be filled with statistical data about pool.
+     \retval		Number of objects in use, ie. allocated.
+     */
+    virtual int getStats(MemPoolStats * stats, int accumulate);
+
+    virtual int getInUseCount();
+protected:
+    virtual void *allocate();
+    virtual void deallocate(void *, bool aggressive);
+private:
+    Stack<void *> freelist;
+};
+
+
+#endif /* _MEM_POOL_MALLOC_H_ */

=== modified file 'lib/Makefile.am'
--- lib/Makefile.am	2009-12-19 11:56:02 +0000
+++ lib/Makefile.am	2010-05-28 21:53:06 +0000
@@ -49,6 +49,8 @@
 	win32lib.c
 libmiscutil_a_SOURCES = \
 	MemPool.cc \
+	MemPoolChunked.cc \
+	MemPoolMalloc.cc \
 	base64.c \
 	charset.c \
 	getfullhostname.c \

=== modified file 'lib/MemPool.cc'
--- lib/MemPool.cc	2010-04-14 21:04:28 +0000
+++ lib/MemPool.cc	2010-05-29 01:31:01 +0000
@@ -33,63 +33,16 @@
  *
  */
 
-/*
- * Old way:
- *   xmalloc each item separately, upon free stack into idle pool array.
- *   each item is individually malloc()ed from system, imposing libmalloc
- *   overhead, and additionally we add our overhead of pointer size per item
- *   as we keep a list of pointer to free items.
- *
- * Chunking:
- *   xmalloc Chunk that fits at least MEM_MIN_FREE (32) items in an array, but
- *   limit Chunk size to MEM_CHUNK_MAX_SIZE (256K). Chunk size is rounded up to
- *   MEM_PAGE_SIZE (4K), trying to have chunks in multiples of VM_PAGE size.
- *   Minimum Chunk size is MEM_CHUNK_SIZE (16K).
- *   A number of items fits into a single chunk, depending on item size.
- *   Maximum number of items per chunk is limited to MEM_MAX_FREE (65535).
- *
- *   We populate Chunk with a linkedlist, each node at first word of item,
- *   and pointing at next free item. Chunk->FreeList is pointing at first
- *   free node. Thus we stuff free housekeeping into the Chunk itself, and
- *   omit pointer overhead per item.
- *
- *   Chunks are created on demand, and new chunks are inserted into linklist
- *   of chunks so that Chunks with smaller pointer value are placed closer
- *   to the linklist head. Head is a hotspot, servicing most of requests, so
- *   slow sorting occurs and Chunks in highest memory tend to become idle
- *   and freeable.
- *
- *   event is registered that runs every 15 secs and checks reference time
- *   of each idle chunk. If a chunk is not referenced for 15 secs, it is
- *   released.
- *
- *   [If mem_idle_limit is exceeded with pools, every chunk that becomes
- *   idle is immediately considered for release, unless this is the only
- *   chunk with free items in it.] (not implemented)
- *
- *   In cachemgr output, there are new columns for chunking. Special item,
- *   Frag, is shown to estimate approximately fragmentation of chunked
- *   pools. Fragmentation is calculated by taking amount of items in use,
- *   calculating needed amount of chunks to fit all, and then comparing to
- *   actual amount of chunks in use. Frag number, in percent, is showing
- *   how many percent of chunks are in use excessively. 100% meaning that
- *   twice the needed amount of chunks are in use.
- *   "part" item shows number of chunks partially filled. This shows how
- *   badly fragmentation is spread across all chunks.
- *
- *   Andres Kroonmaa.
- *   Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
- */
-
 #include "config.h"
 #if HAVE_ASSERT_H
 #include <assert.h>
 #endif
 
 #include "MemPool.h"
+#include "MemPoolChunked.h"
+#include "MemPoolMalloc.h"
 
 #define FLUSH_LIMIT 1000	/* Flush memPool counters to memMeters after flush limit calls */
-#define MEM_MAX_MMAP_CHUNKS 2048
 
 #if HAVE_STRING_H
 #include <string.h>
@@ -107,10 +60,6 @@
 
 static int Pool_id_counter = 0;
 
-/* local prototypes */
-static int memCompChunks(MemChunk * const &, MemChunk * const &);
-static int memCompObjChunks(void * const &, MemChunk * const &);
-
 MemPools &
 MemPools::GetInstance()
 {
@@ -165,253 +114,26 @@
     return mem_idle_limit;
 }
 
-/* Compare chunks */
-static int
-memCompChunks(MemChunk * const &chunkA, MemChunk * const &chunkB)
-{
-    if (chunkA->objCache > chunkB->objCache)
-        return 1;
-    else if (chunkA->objCache < chunkB->objCache)
-        return -1;
-    else
-        return 0;
-}
-
-/* Compare object to chunk */
-static int
-memCompObjChunks(void *const &obj, MemChunk * const &chunk)
-{
-    /* object is lower in memory than the chunks arena */
-    if (obj < chunk->objCache)
-        return -1;
-    /* object is within the pool */
-    if (obj < (void *) ((char *) chunk->objCache + chunk->pool->chunk_size))
-        return 0;
-    /* object is above the pool */
-    return 1;
-}
-
-MemChunk::MemChunk(MemPool *aPool)
-{
-    /* should have a pool for this too -
-     * note that this requres:
-     * allocate one chunk for the pool of chunks's first chunk
-     * allocate a chunk from that pool
-     * move the contents of one chunk into the other
-     * free the first chunk.
-     */
-    inuse_count = 0;
-    next = NULL;
-    pool = aPool;
-
-    objCache = xcalloc(1, pool->chunk_size);
-    freeList = objCache;
-    void **Free = (void **)freeList;
-
-    for (int i = 1; i < pool->chunk_capacity; i++) {
-        *Free = (void *) ((char *) Free + pool->obj_size);
-        void **nextFree = (void **)*Free;
-        (void) VALGRIND_MAKE_MEM_NOACCESS(Free, pool->obj_size);
-        Free = nextFree;
-    }
-    nextFreeChunk = pool->nextFreeChunk;
-    pool->nextFreeChunk = this;
-
-    memMeterAdd(pool->getMeter().alloc, pool->chunk_capacity);
-    memMeterAdd(pool->getMeter().idle, pool->chunk_capacity);
-    pool->idle += pool->chunk_capacity;
-    pool->chunkCount++;
-    lastref = squid_curtime;
-    pool->allChunks.insert(this, memCompChunks);
-}
-
-MemPool::MemPool(const char *aLabel, size_t aSize) : MemImplementingAllocator(aLabel, aSize)
-{
-    chunk_size = 0;
-    chunk_capacity = 0;
-    memPID = 0;
-    chunkCount = 0;
-    inuse = 0;
-    idle = 0;
-    freeCache = 0;
-    nextFreeChunk = 0;
-    Chunks = 0;
-    next = 0;
-    MemImplementingAllocator *last_pool;
-
-    assert(aLabel != NULL && aSize);
-
-    setChunkSize(MEM_CHUNK_SIZE);
-
-    /* Append as Last */
-    for (last_pool = MemPools::GetInstance().pools; last_pool && last_pool->next;)
-        last_pool = last_pool->next;
-    if (last_pool)
-        last_pool->next = this;
-    else
-        MemPools::GetInstance().pools = this;
-
-    memPID = ++Pool_id_counter;
-}
-
-MemChunk::~MemChunk()
-{
-    memMeterDel(pool->getMeter().alloc, pool->chunk_capacity);
-    memMeterDel(pool->getMeter().idle, pool->chunk_capacity);
-    pool->idle -= pool->chunk_capacity;
-    pool->chunkCount--;
-    pool->allChunks.remove(this, memCompChunks);
-    xfree(objCache);
-}
-
-void
-MemPool::push(void *obj)
-{
-    void **Free;
-    /* XXX We should figure out a sane way of avoiding having to clear
-     * all buffers. For example data buffers such as used by MemBuf do
-     * not really need to be cleared.. There was a condition based on
-     * the object size here, but such condition is not safe.
-     */
-    if (doZeroOnPush)
-        memset(obj, 0, obj_size);
-    Free = (void **)obj;
-    *Free = freeCache;
-    freeCache = obj;
-    (void) VALGRIND_MAKE_MEM_NOACCESS(obj, obj_size);
-}
-
-/*
- * Find a chunk with a free item.
- * Create new chunk on demand if no chunk with frees found.
- * Insert new chunk in front of lowest ram chunk, making it preferred in future,
- * and resulting slow compaction towards lowest ram area.
- */
-void *
-MemPool::get()
-{
-    void **Free;
-
-    /* first, try cache */
-    if (freeCache) {
-        Free = (void **)freeCache;
-        (void) VALGRIND_MAKE_MEM_DEFINED(Free, obj_size);
-        freeCache = *Free;
-        *Free = NULL;
-        return Free;
-    }
-    /* then try perchunk freelist chain */
-    if (nextFreeChunk == NULL) {
-        /* no chunk with frees, so create new one */
-        createChunk();
-    }
-    /* now we have some in perchunk freelist chain */
-    MemChunk *chunk = nextFreeChunk;
-
-    Free = (void **)chunk->freeList;
-    chunk->freeList = *Free;
-    *Free = NULL;
-    chunk->inuse_count++;
-    chunk->lastref = squid_curtime;
-
-    if (chunk->freeList == NULL) {
-        /* last free in this chunk, so remove us from perchunk freelist chain */
-        nextFreeChunk = chunk->nextFreeChunk;
-    }
-    (void) VALGRIND_MAKE_MEM_DEFINED(Free, obj_size);
-    return Free;
-}
-
-/* just create a new chunk and place it into a good spot in the chunk chain */
-void
-MemPool::createChunk()
-{
-    MemChunk *chunk, *newChunk;
-
-    newChunk = new MemChunk(this);
-
-    chunk = Chunks;
-    if (chunk == NULL) {	/* first chunk in pool */
-        Chunks = newChunk;
-        return;
-    }
-    if (newChunk->objCache < chunk->objCache) {
-        /* we are lowest ram chunk, insert as first chunk */
-        newChunk->next = chunk;
-        Chunks = newChunk;
-        return;
-    }
-    while (chunk->next) {
-        if (newChunk->objCache < chunk->next->objCache) {
-            /* new chunk is in lower ram, insert here */
-            newChunk->next = chunk->next;
-            chunk->next = newChunk;
-            return;
-        }
-        chunk = chunk->next;
-    }
-    /* we are the worst chunk in chain, add as last */
-    chunk->next = newChunk;
-}
-
 /* Change the default calue of defaultIsChunked to override
  * all pools - including those used before main() starts where
  * MemPools::GetInstance().setDefaultPoolChunking() can be called.
  */
 MemPools::MemPools() : pools(NULL), mem_idle_limit(2 * MB),
-        poolCount (0), defaultIsChunked (USE_MEMPOOLS && !RUNNING_ON_VALGRIND)
+        poolCount (0), defaultIsChunked (USE_CHUNKEDMEMPOOLS && !RUNNING_ON_VALGRIND)
 {
     char *cfg = getenv("MEMPOOLS");
     if (cfg)
         defaultIsChunked = atoi(cfg);
-#if HAVE_MALLOPT && M_MMAP_MAX
-    mallopt(M_MMAP_MAX, MEM_MAX_MMAP_CHUNKS);
-#endif
-}
-
-void
-MemPool::setChunkSize(size_t chunksize)
-{
-    int cap;
-    size_t csize = chunksize;
-
-    if (Chunks)		/* unsafe to tamper */
-        return;
-
-    csize = ((csize + MEM_PAGE_SIZE - 1) / MEM_PAGE_SIZE) * MEM_PAGE_SIZE;	/* round up to page size */
-    cap = csize / obj_size;
-
-    if (cap < MEM_MIN_FREE)
-        cap = MEM_MIN_FREE;
-    if (cap * obj_size > MEM_CHUNK_MAX_SIZE)
-        cap = MEM_CHUNK_MAX_SIZE / obj_size;
-    if (cap > MEM_MAX_FREE)
-        cap = MEM_MAX_FREE;
-    if (cap < 1)
-        cap = 1;
-
-    csize = cap * obj_size;
-    csize = ((csize + MEM_PAGE_SIZE - 1) / MEM_PAGE_SIZE) * MEM_PAGE_SIZE;	/* round up to page size */
-    cap = csize / obj_size;
-
-    chunk_capacity = cap;
-    chunk_size = csize;
 }
 
 MemImplementingAllocator *
 MemPools::create(const char *label, size_t obj_size)
 {
-    return create (label, obj_size, defaultIsChunked);
-}
-
-MemImplementingAllocator *
-MemPools::create(const char *label, size_t obj_size, bool const chunked)
-{
     ++poolCount;
-    if (chunked)
-        return new MemPool (label, obj_size);
+    if (defaultIsChunked)
+        return new MemPoolChunked (label, obj_size);
     else
-        return new MemMalloc (label, obj_size);
+        return new MemPoolMalloc (label, obj_size);
 }
 
 void
@@ -420,40 +142,6 @@
     defaultIsChunked = aBool;
 }
 
-/*
- * warning: we do not clean this entry from Pools assuming destruction
- * is used at the end of the program only
- */
-MemPool::~MemPool()
-{
-    MemChunk *chunk, *fchunk;
-    MemImplementingAllocator *find_pool, *prev_pool;
-
-    flushMetersFull();
-    clean(0);
-    assert(inuse == 0 && "While trying to destroy pool");
-
-    chunk = Chunks;
-    while ( (fchunk = chunk) != NULL) {
-        chunk = chunk->next;
-        delete fchunk;
-    }
-    /* TODO we should be doing something about the original Chunks pointer here. */
-
-    assert(MemPools::GetInstance().pools != NULL && "Called MemPool::~MemPool, but no pool exists!");
-
-    /* Pool clean, remove it from List and free */
-    for (find_pool = MemPools::GetInstance().pools, prev_pool = NULL; (find_pool && this != find_pool); find_pool = find_pool->next)
-        prev_pool = find_pool;
-    assert(find_pool != NULL && "pool to destroy not found");
-
-    if (prev_pool)
-        prev_pool->next = next;
-    else
-        MemPools::GetInstance().pools = next;
-    --MemPools::GetInstance().poolCount;
-}
-
 char const *
 MemAllocator::objectType() const
 {
@@ -473,17 +161,18 @@
 
     calls = free_calls;
     if (calls) {
-        getMeter().gb_freed.count += calls;
-        memMeterDel(getMeter().inuse, calls);
-        memMeterAdd(getMeter().idle, calls);
+        meter.gb_freed.count += calls;
         free_calls = 0;
     }
     calls = alloc_calls;
     if (calls) {
+        meter.gb_allocated.count += calls;
+        alloc_calls = 0;
+    }
+    calls = saved_calls;
+    if (calls) {
         meter.gb_saved.count += calls;
-        memMeterAdd(meter.inuse, calls);
-        memMeterDel(meter.idle, calls);
-        alloc_calls = 0;
+        saved_calls = 0;
     }
 }
 
@@ -491,6 +180,7 @@
 MemImplementingAllocator::flushMetersFull()
 {
     flushMeters();
+    getMeter().gb_allocated.bytes = getMeter().gb_allocated.count * obj_size;
     getMeter().gb_saved.bytes = getMeter().gb_saved.count * obj_size;
     getMeter().gb_freed.bytes = getMeter().gb_freed.count * obj_size;
 }
@@ -501,11 +191,21 @@
     alloc.level = 0;
     inuse.level = 0;
     idle.level = 0;
+    gb_allocated.count = 0;
+    gb_allocated.bytes = 0;
+    gb_oallocated.count = 0;
+    gb_oallocated.bytes = 0;
     gb_saved.count = 0;
     gb_saved.bytes = 0;
     gb_freed.count = 0;
     gb_freed.bytes = 0;
 }
+
+MemPoolMeter::MemPoolMeter()
+{
+    flush();
+}
+
 /*
  * Updates all pool counters, and recreates TheMeter totals from all pools
  */
@@ -523,8 +223,10 @@
         memMeterAdd(TheMeter.alloc, pool->getMeter().alloc.level * pool->obj_size);
         memMeterAdd(TheMeter.inuse, pool->getMeter().inuse.level * pool->obj_size);
         memMeterAdd(TheMeter.idle, pool->getMeter().idle.level * pool->obj_size);
+        TheMeter.gb_allocated.count += pool->getMeter().gb_allocated.count;
         TheMeter.gb_saved.count += pool->getMeter().gb_saved.count;
         TheMeter.gb_freed.count += pool->getMeter().gb_freed.count;
+        TheMeter.gb_allocated.bytes += pool->getMeter().gb_allocated.bytes;
         TheMeter.gb_saved.bytes += pool->getMeter().gb_saved.bytes;
         TheMeter.gb_freed.bytes += pool->getMeter().gb_freed.bytes;
     }
@@ -532,20 +234,6 @@
 }
 
 void *
-MemMalloc::allocate()
-{
-    inuse++;
-    return xcalloc(1, obj_size);
-}
-
-void
-MemMalloc::deallocate(void *obj)
-{
-    inuse--;
-    xfree(obj);
-}
-
-void *
 MemImplementingAllocator::alloc()
 {
     if (++alloc_calls == FLUSH_LIMIT)
@@ -559,127 +247,10 @@
 {
     assert(obj != NULL);
     (void) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(obj, obj_size);
-    deallocate(obj);
+    deallocate(obj, MemPools::GetInstance().mem_idle_limit == 0);
     ++free_calls;
 }
 
-int
-MemPool::getInUseCount()
-{
-    return inuse;
-}
-
-void *
-MemPool::allocate()
-{
-    void *p = get();
-    assert(idle);
-    --idle;
-    ++inuse;
-    return p;
-}
-
-void
-MemPool::deallocate(void *obj)
-{
-    push(obj);
-    assert(inuse);
-    --inuse;
-    ++idle;
-}
-
-void
-MemPool::convertFreeCacheToChunkFreeCache()
-{
-    void *Free;
-    /*
-     * OK, so we have to go through all the global freeCache and find the Chunk
-     * any given Free belongs to, and stuff it into that Chunk's freelist
-     */
-
-    while ((Free = freeCache) != NULL) {
-        MemChunk *chunk = NULL;
-        chunk = const_cast<MemChunk *>(*allChunks.find(Free, memCompObjChunks));
-        assert(splayLastResult == 0);
-        assert(chunk->inuse_count > 0);
-        chunk->inuse_count--;
-        (void) VALGRIND_MAKE_MEM_DEFINED(Free, sizeof(void *));
-        freeCache = *(void **)Free;	/* remove from global cache */
-        *(void **)Free = chunk->freeList;	/* stuff into chunks freelist */
-        (void) VALGRIND_MAKE_MEM_NOACCESS(Free, sizeof(void *));
-        chunk->freeList = Free;
-        chunk->lastref = squid_curtime;
-    }
-
-}
-
-/* removes empty Chunks from pool */
-void
-MemPool::clean(time_t maxage)
-{
-    MemChunk *chunk, *freechunk, *listTail;
-    time_t age;
-
-    if (!this)
-        return;
-    if (!Chunks)
-        return;
-
-    flushMetersFull();
-    convertFreeCacheToChunkFreeCache();
-    /* Now we have all chunks in this pool cleared up, all free items returned to their home */
-    /* We start now checking all chunks to see if we can release any */
-    /* We start from Chunks->next, so first chunk is not released */
-    /* Recreate nextFreeChunk list from scratch */
-
-    chunk = Chunks;
-    while ((freechunk = chunk->next) != NULL) {
-        age = squid_curtime - freechunk->lastref;
-        freechunk->nextFreeChunk = NULL;
-        if (freechunk->inuse_count == 0)
-            if (age >= maxage) {
-                chunk->next = freechunk->next;
-                delete freechunk;
-                freechunk = NULL;
-            }
-        if (chunk->next == NULL)
-            break;
-        chunk = chunk->next;
-    }
-
-    /* Recreate nextFreeChunk list from scratch */
-    /* Populate nextFreeChunk list in order of "most filled chunk first" */
-    /* in case of equal fill, put chunk in lower ram first */
-    /* First (create time) chunk is always on top, no matter how full */
-
-    chunk = Chunks;
-    nextFreeChunk = chunk;
-    chunk->nextFreeChunk = NULL;
-
-    while (chunk->next) {
-        chunk->next->nextFreeChunk = NULL;
-        if (chunk->next->inuse_count < chunk_capacity) {
-            listTail = nextFreeChunk;
-            while (listTail->nextFreeChunk) {
-                if (chunk->next->inuse_count > listTail->nextFreeChunk->inuse_count)
-                    break;
-                if ((chunk->next->inuse_count == listTail->nextFreeChunk->inuse_count) &&
-                        (chunk->next->objCache < listTail->nextFreeChunk->objCache))
-                    break;
-                listTail = listTail->nextFreeChunk;
-            }
-            chunk->next->nextFreeChunk = listTail->nextFreeChunk;
-            listTail->nextFreeChunk = chunk->next;
-        }
-        chunk = chunk->next;
-    }
-    /* We started from 2nd chunk. If first chunk is full, remove it */
-    if (nextFreeChunk->inuse_count == chunk_capacity)
-        nextFreeChunk = nextFreeChunk->nextFreeChunk;
-
-    return;
-}
-
 /*
  * Returns all cached frees to their home chunks
  * If chunks unreferenced age is over, destroys Idle chunk
@@ -707,96 +278,10 @@
     memPoolIterateDone(&iter);
 }
 
-bool
-MemPool::idleTrigger(int shift) const
-{
-    return getMeter().idle.level > (chunk_capacity << shift);
-}
-
 /* Persistent Pool stats. for GlobalStats accumulation */
 static MemPoolStats pp_stats;
 
 /*
- * Update MemPoolStats struct for single pool
- */
-int
-MemPool::getStats(MemPoolStats * stats)
-{
-    MemChunk *chunk;
-    int chunks_free = 0;
-    int chunks_partial = 0;
-
-    if (stats != &pp_stats)	/* need skip memset for GlobalStats accumulation */
-        /* XXX Fixme */
-        memset(stats, 0, sizeof(MemPoolStats));
-
-    clean((time_t) 555555);	/* don't want to get chunks released before reporting */
-
-    stats->pool = this;
-    stats->label = objectType();
-    stats->meter = &getMeter();
-    stats->obj_size = obj_size;
-    stats->chunk_capacity = chunk_capacity;
-
-    /* gather stats for each Chunk */
-    chunk = Chunks;
-    while (chunk) {
-        if (chunk->inuse_count == 0)
-            chunks_free++;
-        else if (chunk->inuse_count < chunk_capacity)
-            chunks_partial++;
-        chunk = chunk->next;
-    }
-
-    stats->chunks_alloc += chunkCount;
-    stats->chunks_inuse += chunkCount - chunks_free;
-    stats->chunks_partial += chunks_partial;
-    stats->chunks_free += chunks_free;
-
-    stats->items_alloc += getMeter().alloc.level;
-    stats->items_inuse += getMeter().inuse.level;
-    stats->items_idle += getMeter().idle.level;
-
-    stats->overhead += sizeof(MemPool) + chunkCount * sizeof(MemChunk) + strlen(objectType()) + 1;
-
-    return getMeter().inuse.level;
-}
-
-/* TODO extract common logic to MemAllocate */
-int
-MemMalloc::getStats(MemPoolStats * stats)
-{
-    if (stats != &pp_stats)	/* need skip memset for GlobalStats accumulation */
-        /* XXX Fixme */
-        memset(stats, 0, sizeof(MemPoolStats));
-
-    stats->pool = this;
-    stats->label = objectType();
-    stats->meter = &getMeter();
-    stats->obj_size = obj_size;
-    stats->chunk_capacity = 0;
-
-    stats->chunks_alloc += 0;
-    stats->chunks_inuse += 0;
-    stats->chunks_partial += 0;
-    stats->chunks_free += 0;
-
-    stats->items_alloc += getMeter().alloc.level;
-    stats->items_inuse += getMeter().inuse.level;
-    stats->items_idle += getMeter().idle.level;
-
-    stats->overhead += sizeof(MemMalloc) + strlen(objectType()) + 1;
-
-    return getMeter().inuse.level;
-}
-
-int
-MemMalloc::getInUseCount()
-{
-    return inuse;
-}
-
-/*
  * Totals statistics is returned
  */
 int
@@ -814,7 +299,7 @@
     /* gather all stats for Totals */
     iter = memPoolIterate();
     while ((pool = memPoolIterateNext(iter))) {
-        if (pool->getStats(&pp_stats) > 0)
+        if (pool->getStats(&pp_stats, 1) > 0)
             pools_inuse++;
     }
     memPoolIterateDone(&iter);
@@ -833,7 +318,7 @@
     stats->tot_items_inuse = pp_stats.items_inuse;
     stats->tot_items_idle = pp_stats.items_idle;
 
-    stats->tot_overhead += pp_stats.overhead + MemPools::GetInstance().poolCount * sizeof(MemPool *);
+    stats->tot_overhead += pp_stats.overhead + MemPools::GetInstance().poolCount * sizeof(MemAllocator *);
     stats->mem_idle_limit = MemPools::GetInstance().mem_idle_limit;
 
     return pools_inuse;
@@ -848,19 +333,6 @@
     return ((s + sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*);
 }
 
-MemMalloc::MemMalloc(char const *aLabel, size_t aSize) : MemImplementingAllocator(aLabel, aSize) { inuse = 0; }
-
-bool
-MemMalloc::idleTrigger(int shift) const
-{
-    return false;
-}
-
-void
-MemMalloc::clean(time_t maxage)
-{
-}
-
 int
 memPoolInUseCount(MemAllocator * pool)
 {
@@ -935,8 +407,39 @@
         next(NULL),
         alloc_calls(0),
         free_calls(0),
+        saved_calls(0),
         obj_size(RoundedSize(aSize))
 {
+    memPID = ++Pool_id_counter;
+
+    MemImplementingAllocator *last_pool;
+
+    assert(aLabel != NULL && aSize);
+    /* Append as Last */
+    for (last_pool = MemPools::GetInstance().pools; last_pool && last_pool->next;)
+        last_pool = last_pool->next;
+    if (last_pool)
+        last_pool->next = this;
+    else
+        MemPools::GetInstance().pools = this;
+}
+
+MemImplementingAllocator::~MemImplementingAllocator()
+{
+    MemImplementingAllocator *find_pool, *prev_pool;
+
+    assert(MemPools::GetInstance().pools != NULL && "Called MemImplementingAllocator::~MemImplementingAllocator, but no pool exists!");
+
+    /* Pool clean, remove it from List and free */
+    for (find_pool = MemPools::GetInstance().pools, prev_pool = NULL; (find_pool && this != find_pool); find_pool = find_pool->next)
+        prev_pool = find_pool;
+    assert(find_pool != NULL && "pool to destroy not found");
+
+    if (prev_pool)
+        prev_pool->next = next;
+    else
+        MemPools::GetInstance().pools = next;
+    --MemPools::GetInstance().poolCount;
 }
 
 void

=== added file 'lib/MemPoolChunked.cc'
--- lib/MemPoolChunked.cc	1970-01-01 00:00:00 +0000
+++ lib/MemPoolChunked.cc	2010-05-29 00:59:35 +0000
@@ -0,0 +1,501 @@
+
+/*
+ * $Id$
+ *
+ * DEBUG: section 63    Low Level Memory Pool Management
+ * AUTHOR: Alex Rousskov, Andres Kroonmaa, Robert Collins
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Old way:
+ *   xmalloc each item separately, upon free stack into idle pool array.
+ *   each item is individually malloc()ed from system, imposing libmalloc
+ *   overhead, and additionally we add our overhead of pointer size per item
+ *   as we keep a list of pointer to free items.
+ *
+ * Chunking:
+ *   xmalloc Chunk that fits at least MEM_MIN_FREE (32) items in an array, but
+ *   limit Chunk size to MEM_CHUNK_MAX_SIZE (256K). Chunk size is rounded up to
+ *   MEM_PAGE_SIZE (4K), trying to have chunks in multiples of VM_PAGE size.
+ *   Minimum Chunk size is MEM_CHUNK_SIZE (16K).
+ *   A number of items fits into a single chunk, depending on item size.
+ *   Maximum number of items per chunk is limited to MEM_MAX_FREE (65535).
+ *
+ *   We populate Chunk with a linkedlist, each node at first word of item,
+ *   and pointing at next free item. Chunk->FreeList is pointing at first
+ *   free node. Thus we stuff free housekeeping into the Chunk itself, and
+ *   omit pointer overhead per item.
+ *
+ *   Chunks are created on demand, and new chunks are inserted into linklist
+ *   of chunks so that Chunks with smaller pointer value are placed closer
+ *   to the linklist head. Head is a hotspot, servicing most of requests, so
+ *   slow sorting occurs and Chunks in highest memory tend to become idle
+ *   and freeable.
+ *
+ *   event is registered that runs every 15 secs and checks reference time
+ *   of each idle chunk. If a chunk is not referenced for 15 secs, it is
+ *   released.
+ *
+ *   [If mem_idle_limit is exceeded with pools, every chunk that becomes
+ *   idle is immediately considered for release, unless this is the only
+ *   chunk with free items in it.] (not implemented)
+ *
+ *   In cachemgr output, there are new columns for chunking. Special item,
+ *   Frag, is shown to estimate approximately fragmentation of chunked
+ *   pools. Fragmentation is calculated by taking amount of items in use,
+ *   calculating needed amount of chunks to fit all, and then comparing to
+ *   actual amount of chunks in use. Frag number, in percent, is showing
+ *   how many percent of chunks are in use excessively. 100% meaning that
+ *   twice the needed amount of chunks are in use.
+ *   "part" item shows number of chunks partially filled. This shows how
+ *   badly fragmentation is spread across all chunks.
+ *
+ *   Andres Kroonmaa.
+ *   Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ */
+
+#include "config.h"
+#if HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#include "MemPoolChunked.h"
+
+#define MEM_MAX_MMAP_CHUNKS 2048
+
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+
+/*
+ * XXX This is a boundary violation between lib and src.. would be good
+ * if it could be solved otherwise, but left for now.
+ */
+extern time_t squid_curtime;
+
+/* local prototypes */
+static int memCompChunks(MemChunk * const &, MemChunk * const &);
+static int memCompObjChunks(void * const &, MemChunk * const &);
+
+/* Compare chunks */
+static int
+memCompChunks(MemChunk * const &chunkA, MemChunk * const &chunkB)
+{
+    if (chunkA->objCache > chunkB->objCache)
+        return 1;
+    else if (chunkA->objCache < chunkB->objCache)
+        return -1;
+    else
+        return 0;
+}
+
+/* Compare object to chunk */
+static int
+memCompObjChunks(void *const &obj, MemChunk * const &chunk)
+{
+    /* object is lower in memory than the chunks arena */
+    if (obj < chunk->objCache)
+        return -1;
+    /* object is within the pool */
+    if (obj < (void *) ((char *) chunk->objCache + chunk->pool->chunk_size))
+        return 0;
+    /* object is above the pool */
+    return 1;
+}
+
+MemChunk::MemChunk(MemPoolChunked *aPool)
+{
+    /* should have a pool for this too -
+     * note that this requres:
+     * allocate one chunk for the pool of chunks's first chunk
+     * allocate a chunk from that pool
+     * move the contents of one chunk into the other
+     * free the first chunk.
+     */
+    inuse_count = 0;
+    next = NULL;
+    pool = aPool;
+
+    objCache = xcalloc(1, pool->chunk_size);
+    freeList = objCache;
+    void **Free = (void **)freeList;
+
+    for (int i = 1; i < pool->chunk_capacity; i++) {
+        *Free = (void *) ((char *) Free + pool->obj_size);
+        void **nextFree = (void **)*Free;
+        (void) VALGRIND_MAKE_MEM_NOACCESS(Free, pool->obj_size);
+        Free = nextFree;
+    }
+    nextFreeChunk = pool->nextFreeChunk;
+    pool->nextFreeChunk = this;
+
+    memMeterAdd(pool->getMeter().alloc, pool->chunk_capacity);
+    memMeterAdd(pool->getMeter().idle, pool->chunk_capacity);
+    pool->chunkCount++;
+    lastref = squid_curtime;
+    pool->allChunks.insert(this, memCompChunks);
+}
+
+MemPoolChunked::MemPoolChunked(const char *aLabel, size_t aSize) : MemImplementingAllocator(aLabel, aSize)
+{
+    chunk_size = 0;
+    chunk_capacity = 0;
+    chunkCount = 0;
+    freeCache = 0;
+    nextFreeChunk = 0;
+    Chunks = 0;
+    next = 0;
+
+    setChunkSize(MEM_CHUNK_SIZE);
+
+#if HAVE_MALLOPT && M_MMAP_MAX
+    mallopt(M_MMAP_MAX, MEM_MAX_MMAP_CHUNKS);
+#endif
+}
+
+MemChunk::~MemChunk()
+{
+    memMeterDel(pool->getMeter().alloc, pool->chunk_capacity);
+    memMeterDel(pool->getMeter().idle, pool->chunk_capacity);
+    pool->chunkCount--;
+    pool->allChunks.remove(this, memCompChunks);
+    xfree(objCache);
+}
+
+void
+MemPoolChunked::push(void *obj)
+{
+    void **Free;
+    /* XXX We should figure out a sane way of avoiding having to clear
+     * all buffers. For example data buffers such as used by MemBuf do
+     * not really need to be cleared.. There was a condition based on
+     * the object size here, but such condition is not safe.
+     */
+    if (doZeroOnPush)
+        memset(obj, 0, obj_size);
+    Free = (void **)obj;
+    *Free = freeCache;
+    freeCache = obj;
+    (void) VALGRIND_MAKE_MEM_NOACCESS(obj, obj_size);
+}
+
+/*
+ * Find a chunk with a free item.
+ * Create new chunk on demand if no chunk with frees found.
+ * Insert new chunk in front of lowest ram chunk, making it preferred in future,
+ * and resulting slow compaction towards lowest ram area.
+ */
+void *
+MemPoolChunked::get()
+{
+    void **Free;
+
+    saved_calls++;
+
+    /* first, try cache */
+    if (freeCache) {
+        Free = (void **)freeCache;
+        (void) VALGRIND_MAKE_MEM_DEFINED(Free, obj_size);
+        freeCache = *Free;
+        *Free = NULL;
+        return Free;
+    }
+    /* then try perchunk freelist chain */
+    if (nextFreeChunk == NULL) {
+        /* no chunk with frees, so create new one */
+	saved_calls--; // compensate for the ++ above
+        createChunk();
+    }
+    /* now we have some in perchunk freelist chain */
+    MemChunk *chunk = nextFreeChunk;
+
+    Free = (void **)chunk->freeList;
+    chunk->freeList = *Free;
+    *Free = NULL;
+    chunk->inuse_count++;
+    chunk->lastref = squid_curtime;
+
+    if (chunk->freeList == NULL) {
+        /* last free in this chunk, so remove us from perchunk freelist chain */
+        nextFreeChunk = chunk->nextFreeChunk;
+    }
+    (void) VALGRIND_MAKE_MEM_DEFINED(Free, obj_size);
+    return Free;
+}
+
+/* just create a new chunk and place it into a good spot in the chunk chain */
+void
+MemPoolChunked::createChunk()
+{
+    MemChunk *chunk, *newChunk;
+
+    newChunk = new MemChunk(this);
+
+    chunk = Chunks;
+    if (chunk == NULL) {	/* first chunk in pool */
+        Chunks = newChunk;
+        return;
+    }
+    if (newChunk->objCache < chunk->objCache) {
+        /* we are lowest ram chunk, insert as first chunk */
+        newChunk->next = chunk;
+        Chunks = newChunk;
+        return;
+    }
+    while (chunk->next) {
+        if (newChunk->objCache < chunk->next->objCache) {
+            /* new chunk is in lower ram, insert here */
+            newChunk->next = chunk->next;
+            chunk->next = newChunk;
+            return;
+        }
+        chunk = chunk->next;
+    }
+    /* we are the worst chunk in chain, add as last */
+    chunk->next = newChunk;
+}
+
+void
+MemPoolChunked::setChunkSize(size_t chunksize)
+{
+    int cap;
+    size_t csize = chunksize;
+
+    if (Chunks)		/* unsafe to tamper */
+        return;
+
+    csize = ((csize + MEM_PAGE_SIZE - 1) / MEM_PAGE_SIZE) * MEM_PAGE_SIZE;	/* round up to page size */
+    cap = csize / obj_size;
+
+    if (cap < MEM_MIN_FREE)
+        cap = MEM_MIN_FREE;
+    if (cap * obj_size > MEM_CHUNK_MAX_SIZE)
+        cap = MEM_CHUNK_MAX_SIZE / obj_size;
+    if (cap > MEM_MAX_FREE)
+        cap = MEM_MAX_FREE;
+    if (cap < 1)
+        cap = 1;
+
+    csize = cap * obj_size;
+    csize = ((csize + MEM_PAGE_SIZE - 1) / MEM_PAGE_SIZE) * MEM_PAGE_SIZE;	/* round up to page size */
+    cap = csize / obj_size;
+
+    chunk_capacity = cap;
+    chunk_size = csize;
+}
+
+/*
+ * warning: we do not clean this entry from Pools assuming destruction
+ * is used at the end of the program only
+ */
+MemPoolChunked::~MemPoolChunked()
+{
+    MemChunk *chunk, *fchunk;
+
+    flushMetersFull();
+    clean(0);
+    assert(meter.inuse.level == 0 && "While trying to destroy pool");
+
+    chunk = Chunks;
+    while ( (fchunk = chunk) != NULL) {
+        chunk = chunk->next;
+        delete fchunk;
+    }
+    /* TODO we should be doing something about the original Chunks pointer here. */
+
+}
+
+int
+MemPoolChunked::getInUseCount()
+{
+    return meter.inuse.level;
+}
+
+void *
+MemPoolChunked::allocate()
+{
+    void *p = get();
+    assert(meter.idle.level > 0);
+    memMeterDec(meter.idle);
+    memMeterInc(meter.inuse);
+    return p;
+}
+
+void
+MemPoolChunked::deallocate(void *obj, bool aggressive)
+{
+    push(obj);
+    assert(meter.inuse.level > 0);
+    memMeterDec(meter.inuse);
+    memMeterInc(meter.idle);
+}
+
+void
+MemPoolChunked::convertFreeCacheToChunkFreeCache()
+{
+    void *Free;
+    /*
+     * OK, so we have to go through all the global freeCache and find the Chunk
+     * any given Free belongs to, and stuff it into that Chunk's freelist
+     */
+
+    while ((Free = freeCache) != NULL) {
+        MemChunk *chunk = NULL;
+        chunk = const_cast<MemChunk *>(*allChunks.find(Free, memCompObjChunks));
+        assert(splayLastResult == 0);
+        assert(chunk->inuse_count > 0);
+        chunk->inuse_count--;
+        (void) VALGRIND_MAKE_MEM_DEFINED(Free, sizeof(void *));
+        freeCache = *(void **)Free;	/* remove from global cache */
+        *(void **)Free = chunk->freeList;	/* stuff into chunks freelist */
+        (void) VALGRIND_MAKE_MEM_NOACCESS(Free, sizeof(void *));
+        chunk->freeList = Free;
+        chunk->lastref = squid_curtime;
+    }
+
+}
+
+/* removes empty Chunks from pool */
+void
+MemPoolChunked::clean(time_t maxage)
+{
+    MemChunk *chunk, *freechunk, *listTail;
+    time_t age;
+
+    if (!this)
+        return;
+    if (!Chunks)
+        return;
+
+    flushMetersFull();
+    convertFreeCacheToChunkFreeCache();
+    /* Now we have all chunks in this pool cleared up, all free items returned to their home */
+    /* We start now checking all chunks to see if we can release any */
+    /* We start from Chunks->next, so first chunk is not released */
+    /* Recreate nextFreeChunk list from scratch */
+
+    chunk = Chunks;
+    while ((freechunk = chunk->next) != NULL) {
+        age = squid_curtime - freechunk->lastref;
+        freechunk->nextFreeChunk = NULL;
+        if (freechunk->inuse_count == 0)
+            if (age >= maxage) {
+                chunk->next = freechunk->next;
+                delete freechunk;
+                freechunk = NULL;
+            }
+        if (chunk->next == NULL)
+            break;
+        chunk = chunk->next;
+    }
+
+    /* Recreate nextFreeChunk list from scratch */
+    /* Populate nextFreeChunk list in order of "most filled chunk first" */
+    /* in case of equal fill, put chunk in lower ram first */
+    /* First (create time) chunk is always on top, no matter how full */
+
+    chunk = Chunks;
+    nextFreeChunk = chunk;
+    chunk->nextFreeChunk = NULL;
+
+    while (chunk->next) {
+        chunk->next->nextFreeChunk = NULL;
+        if (chunk->next->inuse_count < chunk_capacity) {
+            listTail = nextFreeChunk;
+            while (listTail->nextFreeChunk) {
+                if (chunk->next->inuse_count > listTail->nextFreeChunk->inuse_count)
+                    break;
+                if ((chunk->next->inuse_count == listTail->nextFreeChunk->inuse_count) &&
+                        (chunk->next->objCache < listTail->nextFreeChunk->objCache))
+                    break;
+                listTail = listTail->nextFreeChunk;
+            }
+            chunk->next->nextFreeChunk = listTail->nextFreeChunk;
+            listTail->nextFreeChunk = chunk->next;
+        }
+        chunk = chunk->next;
+    }
+    /* We started from 2nd chunk. If first chunk is full, remove it */
+    if (nextFreeChunk->inuse_count == chunk_capacity)
+        nextFreeChunk = nextFreeChunk->nextFreeChunk;
+
+    return;
+}
+
+bool
+MemPoolChunked::idleTrigger(int shift) const
+{
+    return meter.idle.level > (chunk_capacity << shift);
+}
+
+/*
+ * Update MemPoolStats struct for single pool
+ */
+int
+MemPoolChunked::getStats(MemPoolStats * stats, int accumulate)
+{
+    MemChunk *chunk;
+    int chunks_free = 0;
+    int chunks_partial = 0;
+
+    if (!accumulate)	/* need skip memset for GlobalStats accumulation */
+        memset(stats, 0, sizeof(MemPoolStats));
+
+    clean((time_t) 555555);	/* don't want to get chunks released before reporting */
+
+    stats->pool = this;
+    stats->label = objectType();
+    stats->meter = &meter;
+    stats->obj_size = obj_size;
+    stats->chunk_capacity = chunk_capacity;
+
+    /* gather stats for each Chunk */
+    chunk = Chunks;
+    while (chunk) {
+        if (chunk->inuse_count == 0)
+            chunks_free++;
+        else if (chunk->inuse_count < chunk_capacity)
+            chunks_partial++;
+        chunk = chunk->next;
+    }
+
+    stats->chunks_alloc += chunkCount;
+    stats->chunks_inuse += chunkCount - chunks_free;
+    stats->chunks_partial += chunks_partial;
+    stats->chunks_free += chunks_free;
+
+    stats->items_alloc += meter.alloc.level;
+    stats->items_inuse += meter.inuse.level;
+    stats->items_idle += meter.idle.level;
+
+    stats->overhead += sizeof(MemPoolChunked) + chunkCount * sizeof(MemChunk) + strlen(objectType()) + 1;
+
+    return meter.inuse.level;
+}

=== added file 'lib/MemPoolMalloc.cc'
--- lib/MemPoolMalloc.cc	1970-01-01 00:00:00 +0000
+++ lib/MemPoolMalloc.cc	2010-05-29 01:06:38 +0000
@@ -0,0 +1,142 @@
+
+/*
+ * $Id$
+ *
+ * DEBUG: section 63    Low Level Memory Pool Management
+ * AUTHOR: Alex Rousskov, Andres Kroonmaa, Robert Collins, Henrik Nordstrom
+ *
+ * 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.
+ *
+ */
+
+
+#include "config.h"
+#if HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#include "MemPoolMalloc.h"
+
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+
+/*
+ * XXX This is a boundary violation between lib and src.. would be good
+ * if it could be solved otherwise, but left for now.
+ */
+extern time_t squid_curtime;
+
+void *
+MemPoolMalloc::allocate()
+{
+    void *obj = freelist.pop();
+    if (obj) {
+	memMeterDec(meter.idle);
+	saved_calls++;
+    } else {
+	obj = xcalloc(1, obj_size);
+	memMeterInc(meter.alloc);
+    }
+    memMeterInc(meter.inuse);
+    return obj;
+}
+
+void
+MemPoolMalloc::deallocate(void *obj, bool aggressive)
+{
+    memMeterDec(meter.inuse);
+    if (aggressive) {
+	xfree(obj);
+	memMeterDec(meter.alloc);
+    } else {
+	if (doZeroOnPush)
+	    memset(obj, 0, obj_size);
+	memMeterInc(meter.idle);
+	freelist.push_back(obj);
+    }
+}
+
+/* TODO extract common logic to MemAllocate */
+int
+MemPoolMalloc::getStats(MemPoolStats * stats, int accumulate)
+{
+    if (!accumulate)	/* need skip memset for GlobalStats accumulation */
+        memset(stats, 0, sizeof(MemPoolStats));
+
+    stats->pool = this;
+    stats->label = objectType();
+    stats->meter = &meter;
+    stats->obj_size = obj_size;
+    stats->chunk_capacity = 0;
+
+    stats->chunks_alloc += 0;
+    stats->chunks_inuse += 0;
+    stats->chunks_partial += 0;
+    stats->chunks_free += 0;
+
+    stats->items_alloc += meter.alloc.level;
+    stats->items_inuse += meter.inuse.level;
+    stats->items_idle += meter.idle.level;
+
+    stats->overhead += sizeof(MemPoolMalloc) + strlen(objectType()) + 1;
+
+    return meter.inuse.level;
+}
+
+int
+MemPoolMalloc::getInUseCount()
+{
+    return meter.inuse.level;
+}
+
+MemPoolMalloc::MemPoolMalloc(char const *aLabel, size_t aSize) : MemImplementingAllocator(aLabel, aSize)
+{
+}
+
+MemPoolMalloc::~MemPoolMalloc()
+{
+    assert(meter.inuse.level == 0 && "While trying to destroy pool");
+    clean(0);
+}
+
+bool
+MemPoolMalloc::idleTrigger(int shift) const
+{
+    return freelist.count >> (shift ? 8 : 0);
+}
+
+void
+MemPoolMalloc::clean(time_t maxage)
+{
+    while (void *obj = freelist.pop()) {
+	memMeterDec(meter.idle);
+	memMeterDec(meter.alloc);
+	xfree(obj);
+    }
+}
+

=== modified file 'src/mem.cc'
--- src/mem.cc	2010-03-21 03:08:26 +0000
+++ src/mem.cc	2010-05-29 01:19:53 +0000
@@ -580,27 +580,38 @@
     MemPoolMeter *pm = mp_st->meter;
     const char *delim = "\t ";
 
+#if HAVE_IOMANIP
+    stream.setf(std::ios_base::fixed);
+#endif
     stream << std::setw(20) << std::left << mp_st->label << delim;
     stream << std::setw(4) << std::right << mp_st->obj_size << delim;
 
     /* Chunks */
-    stream << std::setw(4) << toKB(mp_st->obj_size * mp_st->chunk_capacity) << delim;
-    stream << std::setw(4) << mp_st->chunk_capacity << delim;
-
     if (mp_st->chunk_capacity) {
+	stream << std::setw(4) << toKB(mp_st->obj_size * mp_st->chunk_capacity) << delim;
+	stream << std::setw(4) << mp_st->chunk_capacity << delim;
+
         needed = mp_st->items_inuse / mp_st->chunk_capacity;
 
         if (mp_st->items_inuse % mp_st->chunk_capacity)
             needed++;
 
         excess = mp_st->chunks_inuse - needed;
+
+	stream << std::setw(4) << mp_st->chunks_alloc << delim;
+	stream << std::setw(4) << mp_st->chunks_inuse << delim;
+	stream << std::setw(4) << mp_st->chunks_free << delim;
+	stream << std::setw(4) << mp_st->chunks_partial << delim;
+	stream << std::setprecision(3) << xpercent(excess, needed) << delim;
+    } else {
+	stream << delim;
+	stream << delim;
+	stream << delim;
+	stream << delim;
+	stream << delim;
+	stream << delim;
+	stream << delim;
     }
-
-    stream << std::setw(4) << mp_st->chunks_alloc << delim;
-    stream << std::setw(4) << mp_st->chunks_inuse << delim;
-    stream << std::setw(4) << mp_st->chunks_free << delim;
-    stream << std::setw(4) << mp_st->chunks_partial << delim;
-    stream << std::setprecision(3) << xpercent(excess, needed) << delim;
     /*
      *  Fragmentation calculation:
      *    needed = inuse.level / chunk_capacity
@@ -627,10 +638,10 @@
     stream << toKB(mp_st->obj_size * pm->idle.hwater_level) << delim;
     /* saved */
     stream << (int)pm->gb_saved.count << delim;
-    stream << std::setprecision(3) << xpercent(pm->gb_saved.count, AllMeter->gb_saved.count) << delim;
-    stream << std::setprecision(3) << xpercent(pm->gb_saved.bytes, AllMeter->gb_saved.bytes) << delim;
-    stream << std::setprecision(3) << xdiv(pm->gb_saved.count - pm->gb_osaved.count, xm_deltat) << "\n";
-    pm->gb_osaved.count = pm->gb_saved.count;
+    stream << std::setprecision(3) << xpercent(pm->gb_saved.count, AllMeter->gb_allocated.count) << delim;
+    stream << std::setprecision(3) << xpercent(pm->gb_saved.bytes, AllMeter->gb_allocated.bytes) << delim;
+    stream << std::setprecision(3) << xdiv(pm->gb_allocated.count - pm->gb_oallocated.count, xm_deltat) << "\n";
+    pm->gb_oallocated.count = pm->gb_allocated.count;
 }
 
 static int
@@ -683,7 +694,7 @@
     "In Use\t\t\t\t\t"
     "Idle\t\t\t"
     "Allocations Saved\t\t\t"
-    "Hit Rate\t"
+    "Rate\t"
     "\n"
     " \t (bytes)\t"
     "KB/ch\t obj/ch\t"
@@ -692,7 +703,7 @@
     "(#)\t (KB)\t high (KB)\t high (hrs)\t %alloc\t"
     "(#)\t (KB)\t high (KB)\t"
     "(#)\t %cnt\t %vol\t"
-    "(#) / sec\t"
+    "(#)/sec\t"
     "\n";
     xm_deltat = current_dtime - xm_time;
     xm_time = current_dtime;
@@ -712,7 +723,7 @@
         if (!mp_stats.pool)	/* pool destroyed */
             continue;
 
-        if (mp_stats.pool->getMeter().gb_saved.count > 0)	/* this pool has been used */
+        if (mp_stats.pool->getMeter().gb_allocated.count > 0)	/* this pool has been used */
             sortme[npools++] = mp_stats;
         else
             not_used++;
@@ -746,7 +757,7 @@
     PoolReport(&mp_stats, mp_total.TheMeter, stream);
 
     /* Cumulative */
-    stream << "Cumulative allocated volume: "<< double_to_str(buf, 64, mp_total.TheMeter->gb_saved.bytes) << "\n";
+    stream << "Cumulative allocated volume: "<< double_to_str(buf, 64, mp_total.TheMeter->gb_allocated.bytes) << "\n";
     /* overhead */
     stream << "Current overhead: " << mp_total.tot_overhead << " bytes (" <<
     std::setprecision(3) << xpercent(mp_total.tot_overhead, mp_total.TheMeter->inuse.level) << "%)\n";

# Begin bundle
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

