=== modified file 'src/MemBlob.cc'
--- src/MemBlob.cc	2010-12-03 01:56:04 +0000
+++ src/MemBlob.cc	2011-03-31 05:31:23 +0000
@@ -15,153 +15,137 @@
  *
  *  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"
 #include "base/TextException.h"
 #include "Debug.h"
+#include "Mem.h"
 #include "MemBlob.h"
+#include "protos.h"
 #if HAVE_IOSTREAM
 #include <iostream>
 #endif
 
-#define MEMBLOB_USES_MEM_POOLS 0
-
-#if MEMBLOB_USES_MEM_POOLS
-#include "protos.h"
-#endif
 
 MemBlobStats MemBlob::Stats;
 InstanceIdDefinitions(MemBlob, "blob");
 
 
 /* MemBlobStats */
 
 MemBlobStats::MemBlobStats(): alloc(0), live(0), append(0)
 {}
 
+MemBlobStats&
+MemBlobStats::operator += (const MemBlobStats& s)
+{
+	alloc+=s.alloc;
+	live+=s.live;
+	append+=s.append;
+	liveBytes+=s.liveBytes;
+
+	return *this;
+}
+
 std::ostream&
 MemBlobStats::dump(std::ostream &os) const
 {
     os <<
     "MemBlob created: " << alloc <<
     "\nMemBlob alive: " << live <<
     "\nMemBlob append calls: " << append <<
     "\nMemBlob currently allocated size: " << liveBytes <<
     "\nlive MemBlob mean current allocation size: " <<
     (static_cast<double>(liveBytes)/(live?live:1)) << std::endl;
     return os;
 }
 
 
 /* MemBlob */
 
 MemBlob::MemBlob(const MemBlob::size_type reserveSize) :
         mem(NULL), capacity(0), size(0) // will be set by memAlloc
 {
     debugs(MEMBLOB_DEBUGSECTION,9, HERE << "constructed, this="
            << static_cast<void*>(this) << " id=" << id
            << " reserveSize=" << reserveSize);
     memAlloc(reserveSize);
 }
 
 MemBlob::MemBlob(const char *buffer, const MemBlob::size_type bufSize) :
         mem(NULL), capacity(0), size(0) // will be set by memAlloc
 {
     debugs(MEMBLOB_DEBUGSECTION,9, HERE << "constructed, this="
            << static_cast<void*>(this) << " id=" << id
            << " buffer=" << static_cast<const void*>(buffer)
            << " bufSize=" << bufSize);
     memAlloc(bufSize);
     append(buffer, bufSize);
 }
 
 MemBlob::~MemBlob()
 {
-#if MEMBLOB_USES_MEM_POOLS
-    //no mempools for now
-    // \todo reinstate mempools use
     memFreeString(capacity,mem);
-#else
-    xfree(mem);
-#endif
     Stats.liveBytes -= capacity;
     --Stats.live;
 
     debugs(MEMBLOB_DEBUGSECTION,9, HERE << "destructed, this="
            << static_cast<void*>(this) << " id=" << id
            << " capacity=" << capacity
            << " size=" << size);
 }
 
-/**
- * Given the requested minimum size, return a rounded allocation size
+/** Given the requested minimum size, return a rounded allocation size
  * for the backing store.
- * This is a stopgap call, this job is eventually expected to be handled
- * by MemPools via memAllocString.
  */
-MemBlob::size_type
+// TODO: exploit better integration with MemPools, moving much of this there.
+// TODO: have MemPools do system page size magic. They don't really belong here
+inline MemBlob::size_type
 MemBlob::calcAllocSize(const size_type sz) const
 {
-    if (sz <= 36) return 36;
-    if (sz <= 128) return 128;
-    if (sz <= 512) return 512;
-    if (sz <= 4096) return RoundTo(sz, 512);
-    // XXX: recover squidSystemPageSize functionality. It's easy for
-    //      the main squid, harder for tests
-#if 0
-    return RoundTo(sz, squidSystemPageSize);
-#else
-    return RoundTo(sz, 4096);
-#endif
+    return sz;
 }
 
 /** Allocate an available space area of at least minSize bytes in size.
  *  Must be called by constructors and only by constructors.
  */
 void
 MemBlob::memAlloc(const size_type minSize)
 {
     size_t actualAlloc = calcAllocSize(minSize);
 
     Must(!mem);
-#if MEMBLOB_USES_MEM_POOLS
-    // XXX: for now, do without mempools. In order to do it, MemPools
-    //  need to be singletons so that initialization order can be enforced
-    mem = static_cast<char*>(memAllocString(minSize, &actualAlloc));
-#else
-    // \todo reinstate mempools use
-    mem = static_cast<char*>(xmalloc(actualAlloc));
-#endif
+    mem = static_cast<char*>(memAllocString(actualAlloc, &actualAlloc));
     Must(mem);
 
     capacity = actualAlloc;
     size = 0;
     debugs(MEMBLOB_DEBUGSECTION, 8,
            id << " memAlloc: requested=" << minSize <<
            ", received=" << capacity);
     ++Stats.live;
     ++Stats.alloc;
     Stats.liveBytes += capacity;
 }
 
 void
 MemBlob::append(const char *source, const size_type n)
 {
     if (n > 0) { // appending zero bytes is allowed but only affects the stats
         Must(willFit(n));
         Must(source);
         /// \note memcpy() is safe because we copy to an unused area
         memcpy(mem + size, source, n);

=== modified file 'src/MemBlob.h'
--- src/MemBlob.h	2010-10-28 15:50:51 +0000
+++ src/MemBlob.h	2011-03-31 05:28:45 +0000
@@ -29,40 +29,42 @@
  */
 
 #ifndef SQUID_MEMBLOB_H_
 #define SQUID_MEMBLOB_H_
 
 #define MEMBLOB_DEBUGSECTION 24
 
 #include "base/InstanceId.h"
 #include "MemPool.h"
 #include "RefCount.h"
 
 /// Various MemBlob class-wide statistics.
 class MemBlobStats
 {
 public:
     MemBlobStats();
 
     /// dumps class-wide statistics
     std::ostream& dump(std::ostream& os) const;
 
+    MemBlobStats& operator += (const MemBlobStats&);
+
 public:
     uint64_t alloc;     ///< number of MemBlob instances created so far
     uint64_t live;      ///< number of MemBlob instances currently alive
     uint64_t append;    ///< number of MemBlob::append() calls
     uint64_t liveBytes; ///< the total size of currently allocated storage
 };
 
 
 /** Refcountable, fixed-size, content-agnostic memory buffer.
  *
  * Allocated memory block is divided into two sequential areas:
  * "used memory" and "available space". The used area can be filled during
  * construction, grows via the append() call, and can be clear()ed.
  *
  * MemBlob users can cooperate to safely share the used area. However, MemBlob
  * provides weak use accounting and no sharing protections besides refcounting.
  */
 class MemBlob: public RefCountable
 {
 public:

=== modified file 'src/mem.cc'
--- src/mem.cc	2011-03-30 16:50:18 +0000
+++ src/mem.cc	2011-03-31 05:30:38 +0000
@@ -44,66 +44,74 @@
 #include "SquidTime.h"
 
 #if HAVE_IOMANIP
 #include <iomanip>
 #endif
 #if HAVE_OSTREAM
 #include <ostream>
 #endif
 
 /* module globals */
 const size_t squidSystemPageSize=getpagesize();
 
 /* local prototypes */
 static void memStringStats(std::ostream &);
 
 /* module locals */
 static MemAllocator *MemPools[MEM_MAX];
 static double xm_time = 0;
 static double xm_deltat = 0;
 
+/* explicit initialization state */
+static bool MemIsInitialized=false;
+
 /* string pools */
-#define mem_str_pool_count 3
+#define mem_str_pool_count 5
 
 static const struct {
     const char *name;
     size_t obj_size;
 }
-
+/* note: string pools must be sorted in ascending order by size */
 StrPoolsAttrs[mem_str_pool_count] = {
-
     {
         "Short Strings", MemAllocator::RoundedSize(36),
-    },				/* to fit rfc1123 and similar */
+    },  /* to fit rfc1123 and similar */
     {
         "Medium Strings", MemAllocator::RoundedSize(128),
-    },				/* to fit most urls */
+    },  /* to fit most urls */
     {
         "Long Strings", MemAllocator::RoundedSize(512)
-    }				/* other */
+    },
+    {
+        "Big Strings", MemAllocator::RoundedSize(1024)
+    },
+    {
+        "Huge Strings", MemAllocator::RoundedSize(4096)
+    }  /* other */
 };
 
 static struct {
     MemAllocator *pool;
 }
-
 StrPools[mem_str_pool_count];
+
 static MemMeter StrCountMeter;
 static MemMeter StrVolumeMeter;
 
 static MemMeter HugeBufCountMeter;
 static MemMeter HugeBufVolumeMeter;
 
 /* local routines */
 
 static void
 memStringStats(std::ostream &stream)
 {
     int i;
     int pooled_count = 0;
     size_t pooled_volume = 0;
     /* heading */
     stream << "String Pool\t Impact\t\t\n \t (%strings)\t (%volume)\n";
     /* table body */
 
     for (i = 0; i < mem_str_pool_count; ++i) {
         const MemAllocator *pool = StrPools[i].pool;
@@ -173,87 +181,93 @@
     assert(MemPools[type] == NULL);
     MemPools[type] = memPoolCreate(name, size);
     MemPools[type]->zeroOnPush(zeroOnPush);
 }
 
 
 /* find appropriate pool and use it (pools always init buffer with 0s) */
 void *
 memAllocate(mem_type type)
 {
     return MemPools[type]->alloc();
 }
 
 /* give memory back to the pool */
 void
 memFree(void *p, int type)
 {
     MemPools[type]->freeOne(p);
 }
 
-/* allocate a variable size buffer using best-fit pool */
 void *
 memAllocString(size_t net_size, size_t * gross_size)
 {
-    int i;
     MemAllocator *pool = NULL;
     assert(gross_size);
 
+    // if pools are not yet ready, make sure that
+    // the requested size is not poolable
+    if (!MemIsInitialized &&
+    		net_size <= StrPoolsAttrs[mem_str_pool_count-1].obj_size)
+        net_size=1+StrPoolsAttrs[mem_str_pool_count-1].obj_size;
+
+    unsigned int i=0;
     for (i = 0; i < mem_str_pool_count; ++i) {
         if (net_size <= StrPoolsAttrs[i].obj_size) {
             pool = StrPools[i].pool;
             break;
         }
     }
 
     *gross_size = pool ? StrPoolsAttrs[i].obj_size : net_size;
     assert(*gross_size >= net_size);
     memMeterInc(StrCountMeter);
     memMeterAdd(StrVolumeMeter, *gross_size);
     return pool ? pool->alloc() : xcalloc(1, net_size);
 }
 
 extern size_t memStringCount();
 size_t
 memStringCount()
 {
     size_t result = 0;
 
     for (int counter = 0; counter < mem_str_pool_count; ++counter)
         result += memPoolInUseCount(StrPools[counter].pool);
 
     return result;
 }
 
 /* free buffer allocated with memAllocString() */
 void
 memFreeString(size_t size, void *buf)
 {
-    int i;
     MemAllocator *pool = NULL;
-    assert(size && buf);
+    assert(buf);
 
-    for (i = 0; i < mem_str_pool_count; ++i) {
-        if (size <= StrPoolsAttrs[i].obj_size) {
-            assert(size == StrPoolsAttrs[i].obj_size);
-            pool = StrPools[i].pool;
-            break;
+    if (MemIsInitialized) {
+        for (unsigned int i = 0; i < mem_str_pool_count; ++i) {
+            if (size <= StrPoolsAttrs[i].obj_size) {
+                assert(size == StrPoolsAttrs[i].obj_size);
+                pool = StrPools[i].pool;
+                break;
+            }
         }
     }
 
     memMeterDec(StrCountMeter);
     memMeterDel(StrVolumeMeter, size);
     pool ? pool->freeOne(buf) : xfree(buf);
 }
 
 /* Find the best fit MEM_X_BUF type */
 static mem_type
 memFindBufSizeType(size_t net_size, size_t * gross_size)
 {
     mem_type type;
     size_t size;
 
     if (net_size <= 2 * 1024) {
         type = MEM_2K_BUF;
         size = 2 * 1024;
     } else if (net_size <= 4 * 1024) {
         type = MEM_4K_BUF;
@@ -421,40 +435,41 @@
     memDataInit(MEM_DREAD_CTRL, "dread_ctrl", sizeof(dread_ctrl), 0);
     memDataInit(MEM_DWRITE_Q, "dwrite_q", sizeof(dwrite_q), 0);
     memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0);
     memDataInit(MEM_HTTP_HDR_CONTENT_RANGE, "HttpHdrContRange", sizeof(HttpHdrContRange), 0);
     memDataInit(MEM_NETDBENTRY, "netdbEntry", sizeof(netdbEntry), 0);
     memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0);
     memDataInit(MEM_RELIST, "relist", sizeof(relist), 0);
     memDataInit(MEM_CLIENT_INFO, "ClientInfo", sizeof(ClientInfo), 0);
     memDataInit(MEM_MD5_DIGEST, "MD5 digest", SQUID_MD5_DIGEST_LENGTH, 0);
     MemPools[MEM_MD5_DIGEST]->setChunkSize(512 * 1024);
 
     /** Lastly init the string pools. */
     for (i = 0; i < mem_str_pool_count; ++i) {
         StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size);
         StrPools[i].pool->zeroOnPush(false);
 
         if (StrPools[i].pool->objectSize() != StrPoolsAttrs[i].obj_size)
             debugs(13, 1, "Notice: " << StrPoolsAttrs[i].name << " is " << StrPools[i].pool->objectSize() << " bytes instead of requested " << StrPoolsAttrs[i].obj_size << " bytes");
     }
 
+    MemIsInitialized=true;
     /** \par
      * finally register with the cache manager */
     RegisterWithCacheManager();
 }
 
 void
 Mem::Report()
 {
     debugs(13, 3, "Memory pools are '" <<
            (Config.onoff.mem_pools ? "on" : "off")  << "'; limit: " <<
            std::setprecision(3) << toMB(MemPools::GetInstance().idleLimit()) <<
            " MB");
 }
 
 void
 Mem::RegisterWithCacheManager(void)
 {
     Mgr::RegisterAction("mem", "Memory Utilization", Mem::Stats, 0, 1);
 }
 

