]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/cbdata.cc
Cleanup: zap CVS Id tags
[thirdparty/squid.git] / src / cbdata.cc
index 91b7cc6a596d9e2d5852d41679e09af318a31f42..5675a787f94065f6120acf9824d2a097dc3be1bc 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: cbdata.cc,v 1.71 2006/05/29 00:15:01 robertc Exp $
+ * $Id$
  *
  * DEBUG: section 45    Callback Data Registry
  * ORIGINAL AUTHOR: Duane Wessels
  *  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.
  *
  */
 
-/*
+/**
+ \defgroup CBDATAInternal Callback Data Allocator Internals
+ \ingroup CBDATAAPI
+ *
  * These routines manage a set of registered callback data pointers.
- * One of the easiest ways to make Squid coredump is to issue a 
+ * One of the easiest ways to make Squid coredump is to issue a
  * callback to for some data structure which has previously been
  * freed.  With these routines, we register (add) callback data
  * pointers, lock them just before registering the callback function,
@@ -45,7 +48,7 @@
  * when finished.
  */
 
-#include "squid.h"
+#include "cbdata.h"
 #include "CacheManager.h"
 #include "Store.h"
 #if CBDATA_DEBUG
@@ -53,8 +56,9 @@
 #endif
 #include "Generic.h"
 
-/* XXX Remove me */
-#include "PeerSelectState.h"
+#if WITH_VALGRIND
+#define HASHED_CBDATA 1
+#endif
 
 static int cbdataCount = 0;
 #if CBDATA_DEBUG
@@ -67,7 +71,7 @@ class CBDataCall
 {
 
 public:
-    CBDataCall (char const *callLabel, char const *aFile, int aLine) : label(callLabel), file(aFile), line(aLine){}
+    CBDataCall (char const *callLabel, char const *aFile, int aLine) : label(callLabel), file(aFile), line(aLine) {}
 
     char const *label;
     char const *file;
@@ -76,19 +80,30 @@ public:
 
 #endif
 
+/// \ingroup CBDATAInternal
 #define OFFSET_OF(TYPE, MEMBER) ((size_t) &(((TYPE) *)0)->(MEMBER))
 
+/// \ingroup CBDATAInternal
 class cbdata
 {
-
+    /** \todo examine making cbdata templated on this - so we get type
+     * safe access to data - RBC 20030902 */
 public:
+#if HASHED_CBDATA
+    hash_link hash;    // Must be first
+#endif
+
 #if CBDATA_DEBUG
 
     void dump(StoreEntry *)const;
 #endif
 
+#if !HASHED_CBDATA
     void *operator new(size_t size, void *where);
     void operator delete(void *where, void *where2);
+#else
+    MEMPROXY_CLASS(cndata);
+#endif
 
     ~cbdata();
     int valid;
@@ -96,8 +111,7 @@ public:
     cbdata_type type;
 #if CBDATA_DEBUG
 
-    void addHistory(char const *label, char const *file, int line)
-    {
+    void addHistory(char const *label, char const *file, int line) {
         if (calls.size() > 1000)
             return;
 
@@ -112,20 +126,21 @@ public:
 
     /* cookie used while debugging */
     long cookie;
-    /* MUST be the last per-instance member */
-    /* TODO: examine making cbdata templated on this - so we get type
-     * safe access to data - RBC 20030902 */
-    void *data;
-void check(int line) const {assert(cookie == ((long)this ^ Cookie));}
+    void check(int line) const {assert(cookie == ((long)this ^ Cookie));}
+    static const long Cookie;
 
+#if !HASHED_CBDATA
     size_t dataSize() const { return sizeof(data);}
-
-    static const long Cookie;
     static long MakeOffset();
     static const long Offset;
+    /* MUST be the last per-instance member */
+    void *data;
+#endif
+
 };
 
 const long cbdata::Cookie((long)0xDEADBEEF);
+#if !HASHED_CBDATA
 const long cbdata::Offset(MakeOffset());
 
 void *
@@ -135,13 +150,15 @@ cbdata::operator new(size_t size, void *where)
     return where;
 }
 
+/**
+ * Only ever invoked when placement new throws
+ * an exception. Used to prevent an incorrect
+ * free.
+ */
 void
 cbdata::operator delete(void *where, void *where2)
 {
-    /* Only ever invoked when placement new throws
-     * an exception. Used to prevent an incorrect
-     * free.
-     */
+    ; // empty.
 }
 
 long
@@ -151,21 +168,42 @@ cbdata::MakeOffset()
     void **dataOffset = &zero->data;
     return (long)dataOffset;
 }
+#else
+MEMPROXY_CLASS_INLINE(cbdata);
+#endif
 
 static OBJH cbdataDump;
 #ifdef CBDATA_DEBUG
 static OBJH cbdataDumpHistory;
 #endif
 
-struct CBDataIndex
-{
-    MemAllocatorProxy *pool;
+/// \ingroup CBDATAInternal
+struct CBDataIndex {
+    MemAllocator *pool;
     FREE *free_func;
 }
-
 *cbdata_index = NULL;
+
+/// \ingroup CBDATAInternal
 int cbdata_types = 0;
 
+#if HASHED_CBDATA
+static hash_table *cbdata_htable = NULL;
+
+static int
+cbdata_cmp(const void *p1, const void *p2)
+{
+    return (char *) p1 - (char *) p2;
+}
+
+static unsigned int
+cbdata_hash(const void *p, unsigned int mod)
+{
+    return ((unsigned long) p >> 8) % mod;
+}
+#endif
+
+
 cbdata::~cbdata()
 {
 #if CBDATA_DEBUG
@@ -178,34 +216,43 @@ cbdata::~cbdata()
 
     FREE *free_func = cbdata_index[type].free_func;
 
+#if HASHED_CBDATA
+    void *p = hash.key;
+#else
+    void *p = &data;
+#endif
+
     if (free_func)
-        free_func(&data);
+        free_func(p);
 }
 
 static void
 cbdataInternalInitType(cbdata_type type, const char *name, int size, FREE * free_func)
 {
     char *label;
+    assert (type == cbdata_types + 1);
 
-    if (type >= cbdata_types) {
-        cbdata_index = (CBDataIndex *)xrealloc(cbdata_index, (type + 1) * sizeof(*cbdata_index));
-        memset(&cbdata_index[cbdata_types], 0,
-               (type + 1 - cbdata_types) * sizeof(*cbdata_index));
-        cbdata_types = type + 1;
-    }
-
-    if (cbdata_index[type].pool)
-        return;
+    cbdata_index = (CBDataIndex *)xrealloc(cbdata_index, (type + 1) * sizeof(*cbdata_index));
+    memset(&cbdata_index[type], 0, sizeof(*cbdata_index));
+    cbdata_types = type;
 
     label = (char *)xmalloc(strlen(name) + 20);
 
     snprintf(label, strlen(name) + 20, "cbdata %s (%d)", name, (int) type);
 
+#if !HASHED_CBDATA
     assert((size_t)cbdata::Offset == (sizeof(cbdata) - ((cbdata *)NULL)->dataSize()));
+    size += cbdata::Offset;
+#endif
 
-    cbdata_index[type].pool = new MemAllocatorProxy(label, size + cbdata::Offset);
+    cbdata_index[type].pool = memPoolCreate(label, size);
 
     cbdata_index[type].free_func = free_func;
+
+#if HASHED_CBDATA
+    if (!cbdata_htable)
+        cbdata_htable = hash_create(cbdata_cmp, 1 << 12, cbdata_hash);
+#endif
 }
 
 cbdata_type
@@ -214,7 +261,7 @@ cbdataInternalAddType(cbdata_type type, const char *name, int size, FREE * free_
     if (type)
         return type;
 
-    type = (cbdata_type)cbdata_types;
+    type = (cbdata_type)(cbdata_types + 1);
 
     cbdataInternalInitType(type, name, size, free_func);
 
@@ -222,37 +269,17 @@ cbdataInternalAddType(cbdata_type type, const char *name, int size, FREE * free_
 }
 
 void
-cbdataInit(void)
+cbdataRegisterWithCacheManager(void)
 {
-    debug(45, 3) ("cbdataInit\n");
-#define CREATE_CBDATA(type) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), NULL)
-#define CREATE_CBDATA_FREE(type, free_func) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), free_func)
-    /* XXX
-     * most of these should be moved out to their respective module.
-     */
-    CREATE_CBDATA(ErrorState);
-    CREATE_CBDATA(generic_cbdata);
-    CREATE_CBDATA(helper);
-    CREATE_CBDATA(helper_server);
-    CREATE_CBDATA(statefulhelper);
-    CREATE_CBDATA(helper_stateful_server);
-    CREATE_CBDATA(ps_state);
-    CREATE_CBDATA(RemovalPolicy);
-    CREATE_CBDATA(RemovalPolicyWalker);
-    CREATE_CBDATA(RemovalPurgeWalker);
-}
-
-void
-cbdataRegisterWithCacheManager(CacheManager & manager)
-{
-    manager.registerAction("cbdata",
-                           "Callback Data Registry Contents",
-                           cbdataDump, 0, 1);
+    CacheManager *manager=CacheManager::GetInstance();
+    manager->registerAction("cbdata",
+                            "Callback Data Registry Contents",
+                            cbdataDump, 0, 1);
 #if CBDATA_DEBUG
 
-    manager.registerAction("cbdatahistory",
-                           "Detailed call history for all current cbdata contents",
-                           cbdataDumpHistory, 0, 1);
+    manager->registerAction("cbdatahistory",
+                            "Detailed call history for all current cbdata contents",
+                            cbdataDumpHistory, 0, 1);
 #endif
 }
 
@@ -263,27 +290,38 @@ cbdataInternalAllocDbg(cbdata_type type, const char *file, int line)
 cbdataInternalAlloc(cbdata_type type)
 #endif
 {
-    cbdata *p;
-    assert(type > 0 && type < cbdata_types);
-    p = new (cbdata_index[type].pool->alloc()) cbdata;
-    //    p = (cbdata *)cbdata_index[type].pool->alloc();
-
-    p->type = type;
-    p->valid = 1;
-    p->locks = 0;
-    p->cookie = (long) p ^ cbdata::Cookie;
+    cbdata *c;
+    void *p;
+    assert(type > 0 && type <= cbdata_types);
+    /* placement new: the pool alloc gives us cbdata + user type memory space
+     * and we init it with cbdata at the start of it
+     */
+#if HASHED_CBDATA
+    c = new cbdata;
+    p = cbdata_index[type].pool->alloc();
+    c->hash.key = p;
+    hash_join(cbdata_htable, &c->hash);
+#else
+    c = new (cbdata_index[type].pool->alloc()) cbdata;
+    p = (void *)&c->data;
+#endif
+
+    c->type = type;
+    c->valid = 1;
+    c->locks = 0;
+    c->cookie = (long) c ^ cbdata::Cookie;
     cbdataCount++;
 #if CBDATA_DEBUG
 
-    p->file = file;
-    p->line = line;
-    p->calls = Stack<CBDataCall *> ();
-    p->addHistory("Alloc", file, line);
-    dlinkAdd(p, &p->link, &cbdataEntries);
-    debug(45, 3) ("cbdataAlloc: %p %s:%d\n", &p->data, file, line);
+    c->file = file;
+    c->line = line;
+    c->calls = Stack<CBDataCall *> ();
+    c->addHistory("Alloc", file, line);
+    dlinkAdd(c, &c->link, &cbdataEntries);
+    debugs(45, 3, "cbdataAlloc: " << p << " " << file << ":" << line);
 #endif
 
-    return (void *) &p->data;
+    return p;
 }
 
 void *
@@ -294,13 +332,17 @@ cbdataInternalFree(void *p)
 #endif
 {
     cbdata *c;
+#if HASHED_CBDATA
+    c = (cbdata *) hash_lookup(cbdata_htable, p);
+#else
     c = (cbdata *) (((char *) p) - cbdata::Offset);
+#endif
 #if CBDATA_DEBUG
 
-    debug(45, 3) ("cbdataFree: %p %s:%d\n", p, file, line);
+    debugs(45, 3, "cbdataFree: " << p << " " << file << ":" << line);
 #else
 
-    debug(45, 9) ("cbdataFree: %p\n", p);
+    debugs(45, 9, "cbdataFree: " << p);
 #endif
 
     c->check(__LINE__);
@@ -312,32 +354,36 @@ cbdataInternalFree(void *p)
 #endif
 
     if (c->locks) {
-        debug(45, 9) ("cbdataFree: %p has %d locks, not freeing\n",
-                      p, c->locks);
+        debugs(45, 9, "cbdataFree: " << p << " has " << c->locks << " locks, not freeing");
         return NULL;
     }
 
     cbdataCount--;
-    debug(45, 9) ("cbdataFree: Freeing %p\n", p);
+    debugs(45, 9, "cbdataFree: Freeing " << p);
 #if CBDATA_DEBUG
 
     dlinkDelete(&c->link, &cbdataEntries);
 #endif
 
-    cbdata_type theType = c->type;
-    c->cbdata::~cbdata();
-
     /* This is ugly. But: operator delete doesn't get
-     * the type parameter, so we can't use that 
+     * the type parameter, so we can't use that
      * to free the memory.
      * So, we free it ourselves.
-     * Note that this means a non-placement 
+     * Note that this means a non-placement
      * new would be a seriously bad idea.
      * Lastly, if we where a templated class,
      * we could use the normal delete operator
      * and it would Just Work. RBC 20030902
      */
+    cbdata_type theType = c->type;
+#if HASHED_CBDATA
+    hash_remove_link(cbdata_htable, &c->hash);
+    delete c;
+    cbdata_index[theType].pool->free((void *)p);
+#else
+    c->cbdata::~cbdata();
     cbdata_index[theType].pool->free(c);
+#endif
     return NULL;
 }
 
@@ -353,17 +399,21 @@ cbdataInternalLock(const void *p)
     if (p == NULL)
         return;
 
+#if HASHED_CBDATA
+    c = (cbdata *) hash_lookup(cbdata_htable, p);
+#else
     c = (cbdata *) (((char *) p) - cbdata::Offset);
+#endif
 
 #if CBDATA_DEBUG
 
-    debug(45, 3) ("cbdataLock: %p=%d %s:%d\n", p, c ? c->locks + 1 : -1, file, line);
+    debugs(45, 3, "cbdataLock: " << p << "=" << (c ? c->locks + 1 : -1) << " " << file << ":" << line);
 
     c->addHistory("Reference", file, line);
 
 #else
 
-    debug(45, 9) ("cbdataLock: %p=%d\n", p, c ? c->locks + 1 : -1);
+    debugs(45, 9, "cbdataLock: " << p << "=" << (c ? c->locks + 1 : -1));
 
 #endif
 
@@ -386,17 +436,21 @@ cbdataInternalUnlock(const void *p)
     if (p == NULL)
         return;
 
+#if HASHED_CBDATA
+    c = (cbdata *) hash_lookup(cbdata_htable, p);
+#else
     c = (cbdata *) (((char *) p) - cbdata::Offset);
+#endif
 
 #if CBDATA_DEBUG
 
-    debug(45, 3) ("cbdataUnlock: %p=%d %s:%d\n", p, c ? c->locks - 1 : -1, file, line);
+    debugs(45, 3, "cbdataUnlock: " << p << "=" << (c ? c->locks - 1 : -1) << " " << file << ":" << line);
 
     c->addHistory("Dereference", file, line);
 
 #else
 
-    debug(45, 9) ("cbdataUnlock: %p=%d\n", p, c ? c->locks - 1 : -1);
+    debugs(45, 9, "cbdataUnlock: " << p << "=" << (c ? c->locks - 1 : -1));
 
 #endif
 
@@ -413,7 +467,7 @@ cbdataInternalUnlock(const void *p)
 
     cbdataCount--;
 
-    debug(45, 9) ("cbdataUnlock: Freeing %p\n", p);
+    debugs(45, 9, "cbdataUnlock: Freeing " << p);
 
 #if CBDATA_DEBUG
 
@@ -421,21 +475,25 @@ cbdataInternalUnlock(const void *p)
 
 #endif
 
-    cbdata_type theType = c->type;
-
-    c->cbdata::~cbdata();
-
     /* This is ugly. But: operator delete doesn't get
-     * the type parameter, so we can't use that 
+     * the type parameter, so we can't use that
      * to free the memory.
      * So, we free it ourselves.
-     * Note that this means a non-placement 
+     * Note that this means a non-placement
      * new would be a seriously bad idea.
      * Lastly, if we where a templated class,
      * we could use the normal delete operator
      * and it would Just Work. RBC 20030902
      */
+    cbdata_type theType = c->type;
+#if HASHED_CBDATA
+    hash_remove_link(cbdata_htable, &c->hash);
+    delete c;
+    cbdata_index[theType].pool->free((void *)p);
+#else
+    c->cbdata::~cbdata();
     cbdata_index[theType].pool->free(c);
+#endif
 }
 
 int
@@ -446,9 +504,13 @@ cbdataReferenceValid(const void *p)
     if (p == NULL)
         return 1;              /* A NULL pointer cannot become invalid */
 
-    debug(45, 9) ("cbdataReferenceValid: %p\n", p);
+    debugs(45, 9, "cbdataReferenceValid: " << p);
 
+#if HASHED_CBDATA
+    c = (cbdata *) hash_lookup(cbdata_htable, p);
+#else
     c = (cbdata *) (((char *) p) - cbdata::Offset);
+#endif
 
     c->check(__LINE__);
 
@@ -488,16 +550,19 @@ cbdataInternalReferenceDoneValid(void **pp, void **tp)
 void
 cbdata::dump(StoreEntry *sentry) const
 {
+#if HASHED_CBDATA
+    void *p = (void *)hash.key;
+#else
+    void *p = (void *)&data;
+#endif
     storeAppendPrintf(sentry, "%c%p\t%d\t%d\t%20s:%-5d\n", valid ? ' ' :
-                      '!', &data, type, locks, file, line);
+                      '!', p, type, locks, file, line);
 }
 
-struct CBDataDumper : public unary_function<cbdata, void>
-{
-    CBDataDumper(StoreEntry *anEntry):where(anEntry){}
+struct CBDataDumper : public unary_function<cbdata, void> {
+    CBDataDumper(StoreEntry *anEntry):where(anEntry) {}
 
-    void operator()(cbdata const &x)
-    {
+    void operator()(cbdata const &x) {
         x.dump(where);
     }
 
@@ -519,10 +584,14 @@ cbdataDump(StoreEntry * sentry)
     storeAppendPrintf(sentry, "types\tsize\tallocated\ttotal\n");
 
     for (int i = 1; i < cbdata_types; i++) {
-        MemAllocatorProxy *pool = cbdata_index[i].pool;
+        MemAllocator *pool = cbdata_index[i].pool;
 
         if (pool) {
+#if HASHED_CBDATA
+            int obj_size = pool->objectSize();
+#else
             int obj_size = pool->objectSize() - cbdata::Offset;
+#endif
             storeAppendPrintf(sentry, "%s\t%d\t%ld\t%ld\n", pool->objectType() + 7, obj_size, (long int)pool->getMeter().inuse.level, (long int)obj_size * pool->getMeter().inuse.level);
         }
     }
@@ -535,26 +604,24 @@ cbdataDump(StoreEntry * sentry)
     storeAppendPrintf(sentry, "\nsee also \"Memory utilization\" for detailed per type statistics\n");
 }
 
+CBDATA_CLASS_INIT(generic_cbdata);
+
 #if CBDATA_DEBUG
 
-struct CBDataCallDumper : public unary_function<CBDataCall, void>
-{
-    CBDataCallDumper (StoreEntry *anEntry):where(anEntry){}
+struct CBDataCallDumper : public unary_function<CBDataCall, void> {
+    CBDataCallDumper (StoreEntry *anEntry):where(anEntry) {}
 
-    void operator()(CBDataCall const &x)
-    {
+    void operator()(CBDataCall const &x) {
         storeAppendPrintf(where, "%s\t%s\t%d\n", x.label, x.file, x.line);
     }
 
     StoreEntry *where;
 };
 
-struct CBDataHistoryDumper : public CBDataDumper
-{
-    CBDataHistoryDumper(StoreEntry *anEntry):CBDataDumper(anEntry),where(anEntry), callDumper(anEntry){}
+struct CBDataHistoryDumper : public CBDataDumper {
+    CBDataHistoryDumper(StoreEntry *anEntry):CBDataDumper(anEntry),where(anEntry), callDumper(anEntry) {}
 
-    void operator()(cbdata const &x)
-    {
+    void operator()(cbdata const &x) {
         CBDataDumper::operator()(x);
         storeAppendPrintf(where, "\n");
         storeAppendPrintf(where, "Action\tFile\tLine\n");