=== modified file 'src/mem.cc'
--- src/mem.cc	2010-10-28 18:52:59 +0000
+++ src/mem.cc	2011-03-31 20:11:46 +0000
@@ -44,85 +44,99 @@
 #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;
 
+/* all pools are ready to be used */
+static bool MemIsInitialized=false;
+
 /* string pools */
-#define mem_str_pool_count 3
+#define mem_str_pool_count 6
 
 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 */
+    },
+    {
+        "1KB Strings", MemAllocator::RoundedSize(1024)
+    },
+    {
+        "4KB Strings", MemAllocator::RoundedSize(4096)
+    },
+    {
+        "16KB Strings", MemAllocator::RoundedSize(1024*16)
+    }
 };
 
+// must be at least one byte bigger than the biggest string size
+static const size_t SizeOfStringBeforePoolsAreInitialized = 1024*16+4;
+
 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++) {
+    for (i = 0; i < mem_str_pool_count; ++i) {
         const MemAllocator *pool = StrPools[i].pool;
         const int plevel = pool->getMeter().inuse.level;
         stream << std::setw(20) << std::left << pool->objectType();
         stream << std::right << "\t " << xpercentInt(plevel, StrCountMeter.level);
         stream << "\t " << xpercentInt(plevel * pool->objectSize(), StrVolumeMeter.level) << "\n";
         pooled_count += plevel;
         pooled_volume += plevel * pool->objectSize();
     }
 
     /* malloc strings */
     stream << std::setw(20) << std::left << "Other Strings";
 
     stream << std::right << "\t ";
 
     stream << xpercentInt(StrCountMeter.level - pooled_count, StrCountMeter.level) << "\t ";
 
     stream << xpercentInt(StrVolumeMeter.level - pooled_volume, StrVolumeMeter.level) << "\n\n";
 }
 
 static void
@@ -173,90 +187,96 @@
     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);
 
-    for (i = 0; i < mem_str_pool_count; i++) {
+    // if pools are not yet ready, make sure that
+    // the requested size is not poolable
+    if (!MemIsInitialized && net_size < SizeOfStringBeforePoolsAreInitialized)
+    	net_size=SizeOfStringBeforePoolsAreInitialized;
+
+    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);
+    // may forget [de]allocations until MemIsInitialized
     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;
+            }
         }
     }
 
+    // may forget [de]allocations until MemIsInitialized
     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;
         size = 4 * 1024;
     } else if (net_size <= 8 * 1024) {
         type = MEM_8K_BUF;
@@ -413,48 +433,49 @@
     memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0);
 #if USE_CACHE_DIGESTS
 
     memDataInit(MEM_CACHE_DIGEST, "CacheDigest", sizeof(CacheDigest), 0);
 #endif
 
     memDataInit(MEM_LINK_LIST, "link_list", sizeof(link_list), 10);
     memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10);
     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++) {
+    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);
 }
 
@@ -586,41 +607,41 @@
 {
     int excess = 0;
     int needed = 0;
     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 */
     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++;
+            ++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;
     }
     /*
      *  Fragmentation calculation:
      *    needed = inuse.level / chunk_capacity
@@ -715,51 +736,51 @@
     "(#)/sec\t"
     "\n";
     xm_deltat = current_dtime - xm_time;
     xm_time = current_dtime;
 
     /* Get stats for Totals report line */
     memPoolGetGlobalStats(&mp_total);
 
     MemPoolStats *sortme = (MemPoolStats *) xcalloc(mp_total.tot_pools_alloc ,sizeof(*sortme));
     int npools = 0;
 
     /* main table */
     iter = memPoolIterate();
 
     while ((pool = memPoolIterateNext(iter))) {
         pool->getStats(&mp_stats);
 
         if (!mp_stats.pool)	/* pool destroyed */
             continue;
 
-        if (mp_stats.pool->getMeter().gb_allocated.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++;
+            ++not_used;
     }
 
     memPoolIterateDone(&iter);
 
     qsort(sortme, npools, sizeof(*sortme), MemPoolReportSorter);
 
-    for (int i = 0; i< npools; i++) {
+    for (int i = 0; i< npools; ++i) {
         PoolReport(&sortme[i], mp_total.TheMeter, stream);
     }
 
     xfree(sortme);
 
     mp_stats.pool = NULL;
     mp_stats.label = "Total";
     mp_stats.meter = mp_total.TheMeter;
     mp_stats.obj_size = 1;
     mp_stats.chunk_capacity = 0;
     mp_stats.chunk_size = 0;
     mp_stats.chunks_alloc = mp_total.tot_chunks_alloc;
     mp_stats.chunks_inuse = mp_total.tot_chunks_inuse;
     mp_stats.chunks_partial = mp_total.tot_chunks_partial;
     mp_stats.chunks_free = mp_total.tot_chunks_free;
     mp_stats.items_alloc = mp_total.tot_items_alloc;
     mp_stats.items_inuse = mp_total.tot_items_inuse;
     mp_stats.items_idle = mp_total.tot_items_idle;
     mp_stats.overhead = mp_total.tot_overhead;
 

