]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Summary: Merge delay class 4 performance enhancements.
authorrobertc <>
Sat, 8 Feb 2003 08:45:46 +0000 (08:45 +0000)
committerrobertc <>
Sat, 8 Feb 2003 08:45:46 +0000 (08:45 +0000)
Keywords:

Patches applied:

  * robertc@squid-cache.org--squid/squid--delay-class-4--3.0--patch-31
     Convert ACL.h listed types to SplayNode.

  * robertc@squid-cache.org--squid/squid--delay-class-4--3.0--patch-30
     Make splay trees typesafe, and use in DelayUser class.

  * robertc@squid-cache.org--squid/squid--delay-class-4--3.0--patch-29
     Separate splay usage from global includes.

13 files changed:
include/MemPool.h
include/splay.h
lib/MemPool.c
lib/Splay.cc
src/ACL.h
src/DelayUser.cc
src/DelayUser.h
src/acl.cc
src/enums.h
src/mem.cc
src/structs.h
src/typedefs.h
test-suite/splay.cc

index 75f347fbc047b8490565134d6ad3846843a1ea44..0198db30cdd2e96a4daea73efd0e31e1c215383b 100644 (file)
@@ -5,7 +5,13 @@
 #include "config.h"
 #include "Array.h"
 #include "util.h"
+#ifdef __cplusplus
+template <class V>
+class SplayNode;
+typedef SplayNode<void *> splayNode;
+#else
 #include "splay.h"
+#endif
 #include "memMeter.h"
 
 #if HAVE_GNUMALLOC_H
index ea131fcdcadb06e37d9340a5087e4d77449f7ab4..c4da3c886c379f8f0c2a5ff0b7c11ba7480cb46a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: splay.h,v 1.14 2003/02/05 10:36:31 robertc Exp $
+ * $Id: splay.h,v 1.15 2003/02/08 01:45:46 robertc Exp $
  */
 
 #ifndef SQUID_SPLAY_H
@@ -13,42 +13,202 @@ typedef struct _splay_node {
     struct _splay_node *right;
 } splayNode;
 
-typedef int SPLAYCMP(const void *a, const void *b);
-typedef void SPLAYWALKEE(void *nodedata, void *state);
-typedef void SPLAYFREE(void *);
+typedef int SPLAYCMP(const void **a, const void **b);
+typedef void SPLAYWALKEE(void **nodedata, void *state);
 
 SQUIDCEXTERN int splayLastResult;
 
+/* MUST match C++ prototypes */
 SQUIDCEXTERN splayNode *splay_insert(void *, splayNode *, SPLAYCMP *);
-SQUIDCEXTERN splayNode *splay_splay(const void *, splayNode *, SPLAYCMP *);
+SQUIDCEXTERN splayNode *splay_splay(const void **, splayNode *, SPLAYCMP *);
 SQUIDCEXTERN splayNode *splay_delete(const void *, splayNode *, SPLAYCMP *);
-SQUIDCEXTERN void splay_destroy(splayNode *, SPLAYFREE *);
 SQUIDCEXTERN void splay_walk(splayNode *, SPLAYWALKEE *, void *);
 #else
 
+
 template <class V>
 class SplayNode {
   public:
     typedef V Value;
-    Value *data;
-    SplayNode<V> *left;
-    SplayNode<V> *right;
+    typedef int SPLAYCMP(Value const &a, Value const &b);
+    typedef void SPLAYFREE(Value &);
+    typedef void SPLAYWALKEE(Value const & nodedata, void *state);
+    Value data;
+    mutable SplayNode<V> *left;
+    mutable SplayNode<V> *right;
+    void destroy(SPLAYFREE *);
+    void walk(SPLAYWALKEE *, void *callerState);
+    SplayNode<V> * remove(const Value data, SPLAYCMP * compare);
+    SplayNode<V> * insert(Value data, SPLAYCMP * compare);
+    SplayNode<V> * splay(const Value &data, SPLAYCMP * compare) const;
 };
 
-typedef SplayNode<void> splayNode;
+typedef SplayNode<void *> splayNode;
+
+template <class V>
+class Splay {
+  public:
+    typedef V Value;
+    typedef int SPLAYCMP(Value const &a, Value const &b);
+    Splay():head(NULL){}
+    mutable SplayNode<V> * head;
+    Value const *find (Value const &, SPLAYCMP *compare) const;
+};
 
-typedef int SPLAYCMP(const void *a, const void *b);
-typedef void SPLAYWALKEE(void *nodedata, void *state);
-typedef void SPLAYFREE(void *);
 
 SQUIDCEXTERN int splayLastResult;
 
-SQUIDCEXTERN splayNode *splay_insert(void *, splayNode *, SPLAYCMP *);
-SQUIDCEXTERN splayNode *splay_splay(const void *, splayNode *, SPLAYCMP *);
-SQUIDCEXTERN splayNode *splay_delete(const void *, splayNode *, SPLAYCMP *);
-SQUIDCEXTERN void splay_destroy(splayNode *, SPLAYFREE *);
-SQUIDCEXTERN void splay_walk(splayNode *, SPLAYWALKEE *, void *);
+SQUIDCEXTERN splayNode *splay_insert(void *, splayNode *, splayNode::SPLAYCMP *);
+SQUIDCEXTERN splayNode *splay_delete(const void *, splayNode *, splayNode::SPLAYCMP *);
+SQUIDCEXTERN splayNode *splay_splay(const void **, splayNode *, splayNode::SPLAYCMP *);
+SQUIDCEXTERN void splay_destroy(splayNode *, splayNode::SPLAYFREE *);
+SQUIDCEXTERN void splay_walk(splayNode *, splayNode::SPLAYWALKEE *, void *callerState);
+
+/* inline methods */
+template<class V>
+void
+SplayNode<V>::walk(SPLAYWALKEE * walkee, void *state)
+{
+    if (this == NULL)
+       return;
+    if (left)
+       left->walk(walkee, state);
+    walkee(data, state);
+    if (right)
+       right->walk(walkee, state);
+}
+
+template<class V>
+void
+SplayNode<V>::destroy(SPLAYFREE * free_func)
+{
+    if (!this)
+       return;
+    if (left)
+       left->destroy(free_func);
+    if (right)
+       right->destroy(free_func);
+    free_func(data);
+    delete this;
+}
+
+template<class V>
+SplayNode<V> *
+SplayNode<V>::remove(Value const data, SPLAYCMP * compare)
+{
+    if (this == NULL)
+       return NULL;
+    SplayNode<V> *result = splay(data, compare);
+    if (splayLastResult == 0) {        /* found it */
+       SplayNode<V> *newTop;
+       if (result->left == NULL) {
+           newTop = result->right;
+       } else {
+           newTop = result->left->splay(data, compare);
+           /* temporary */
+           newTop->right = result->right;
+           result->right = NULL;
+       }
+       delete result;
+       return newTop;
+    }
+    return result;                     /* It wasn't there */
+}
 
+template<class V>
+SplayNode<V> *
+SplayNode<V>::insert(Value data, SPLAYCMP * compare)
+{
+    /* create node to insert */
+    SplayNode<V> *newNode = new SplayNode<V>;
+    newNode->data = data;
+    if (this == NULL) {
+       newNode->left = newNode->right = NULL;
+       return newNode;
+    }
+    
+    SplayNode<V> *newTop = splay(data, compare);
+    if (splayLastResult < 0) {
+       newNode->left = newTop->left;
+       newNode->right = newTop;
+       newTop->left = NULL;
+       return newNode;
+    } else if (splayLastResult > 0) {
+       newNode->right = newTop->right;
+       newNode->left = newTop;
+       newTop->right = NULL;
+       return newNode;
+    } else {
+       /* duplicate entry */
+       delete newNode;
+       return newTop;
+    }
+}
+
+template<class V>
+SplayNode<V> *
+SplayNode<V>::splay(Value const &data, SPLAYCMP * compare) const
+{
+    if (this == NULL)
+       return NULL;
+    SplayNode<V> N;
+    SplayNode<V> *l;
+    SplayNode<V> *r;
+    SplayNode<V> *y;
+    N.left = N.right = NULL;
+    l = r = &N;
+
+    SplayNode<V> *top = const_cast<SplayNode<V> *>(this);
+    for (;;) {
+       splayLastResult = compare(data, top->data);
+       if (splayLastResult < 0) {
+           if (top->left == NULL)
+               break;
+           if ((splayLastResult = compare(data, top->left->data)) < 0) {
+               y = top->left;  /* rotate right */
+               top->left = y->right;
+               y->right = top;
+               top = y;
+               if (top->left == NULL)
+                   break;
+           }
+           r->left = top;      /* link right */
+           r = top;
+           top = top->left;
+       } else if (splayLastResult > 0) {
+           if (top->right == NULL)
+               break;
+           if ((splayLastResult = compare(data, top->right->data)) > 0) {
+               y = top->right; /* rotate left */
+               top->right = y->left;
+               y->left = top;
+               top = y;
+               if (top->right == NULL)
+                   break;
+           }
+           l->right = top;     /* link left */
+           l = top;
+           top = top->right;
+       } else {
+           break;
+       }
+    }
+    l->right = top->left;      /* assemble */
+    r->left = top->right;
+    top->left = N.right;
+    top->right = N.left;
+    return top;
+}
+
+template <class V>
+typename Splay<V>::Value const *
+Splay<V>::find (Value const &value, SPLAYCMP *compare) const
+{
+    head = head->splay(value, compare);
+    if (splayLastResult != 0)
+       return NULL;
+    return &head->data;
+}
 
 #endif
 
index 63478c3073327509380fd1f14ade20fe7d12c7c9..628cce286f6ab891509c0c0a77b48ccffe3600ec 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: MemPool.c,v 1.15 2003/01/23 00:37:01 robertc Exp $
+ * $Id: MemPool.c,v 1.16 2003/02/08 01:45:47 robertc Exp $
  *
  * DEBUG: section 63    Low Level Memory Pool Management
  * AUTHOR: Alex Rousskov, Andres Kroonmaa
@@ -132,8 +132,8 @@ static int Pool_id_counter = 0;
 static MemPool *lastPool;
 
 /* local prototypes */
-static int memCompChunks(MemChunk * chunkA, MemChunk * chunkB);
-static int memCompObjChunks(void *obj, MemChunk * chunk);
+static SPLAYCMP memCompChunks;
+static SPLAYCMP memCompObjChunks;
 #if !DISABLE_POOLS
 static MemChunk *memPoolChunkNew(MemPool * pool);
 #endif
@@ -187,7 +187,15 @@ memPoolSetIdleLimit(size_t new_idle_limit)
 
 /* Compare chunks */
 static int
-memCompChunks(MemChunk * chunkA, MemChunk * chunkB)
+memCompChunksSafe(MemChunk * chunkA, MemChunk * chunkB);
+static int
+memCompChunks(const void **chunkA, const void **chunkB)
+{
+    return memCompChunksSafe((MemChunk *)*chunkA, (MemChunk *)*chunkB);
+}
+
+static int
+memCompChunksSafe(MemChunk * chunkA, MemChunk * chunkB)
 {
     if (chunkA->objCache > chunkB->objCache)
        return 1;
@@ -199,8 +207,14 @@ memCompChunks(MemChunk * chunkA, MemChunk * chunkB)
 
 /* Compare object to chunk */
 /* XXX Note: this depends on lastPool */
+static int memCompObjChunksSafe(void *obj, MemChunk * chunk);
 static int
-memCompObjChunks(void *obj, MemChunk * chunk)
+memCompObjChunks(const void **obj, const void **chunk)
+{
+    return memCompObjChunksSafe((void *)*obj, (MemChunk *)*chunk);
+}
+
+static int memCompObjChunksSafe(void *obj, MemChunk * chunk)
 {
     if (obj < chunk->objCache)
        return -1;
@@ -234,7 +248,7 @@ memPoolChunkNew(MemPool * pool)
     pool->chunkCount++;
     chunk->lastref = squid_curtime;
     lastPool = pool;
-    pool->allChunks = splay_insert(chunk, pool->allChunks, (SPLAYCMP *) memCompChunks);
+    pool->allChunks = splay_insert(chunk, pool->allChunks, memCompChunks);
     return chunk;
 }
 #endif
@@ -247,7 +261,7 @@ memPoolChunkDestroy(MemPool * pool, MemChunk * chunk)
     pool->idle -= pool->chunk_capacity;
     pool->chunkCount--;
     lastPool = pool;
-    pool->allChunks = splay_delete(chunk, pool->allChunks, (SPLAYCMP *) memCompChunks);
+    pool->allChunks = splay_delete(chunk, pool->allChunks, memCompChunks);
     xfree(chunk->objCache);
     xfree(chunk);
 }
@@ -574,7 +588,7 @@ memPoolCleanOne(MemPool * pool, time_t maxage)
 
     while ((Free = pool->freeCache) != NULL) {
        lastPool = pool;
-       pool->allChunks = splay_splay(Free, pool->allChunks, (SPLAYCMP *) memCompObjChunks);
+       pool->allChunks = splay_splay((const void **)&Free, pool->allChunks, memCompObjChunks);
        assert(splayLastResult == 0);
        chunk = pool->allChunks->data;
        assert(chunk->inuse_count > 0);
index a0863affd998b0e1b498f77d10f45f721cdeadce..c53f49968d8a2963611abc2de79f814dab0c8d71 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: Splay.cc,v 1.1 2003/02/05 10:36:40 robertc Exp $
+ * $Id: Splay.cc,v 1.2 2003/02/08 01:45:47 robertc Exp $
  *
  * based on ftp://ftp.cs.cmu.edu/user/sleator/splaying/top-down-splay.c
  * http://bobo.link.cs.cmu.edu/cgi-bin/splay/splay-cgi.pl
 int splayLastResult = 0;
 
 splayNode *
-splay_insert(void *data, splayNode * top, SPLAYCMP * compare)
+splay_insert(void *data, splayNode * top, splayNode::SPLAYCMP * compare)
 {
-    splayNode *newNode = new splayNode;
-    newNode->data = data;
-    if (top == NULL) {
-       newNode->left = newNode->right = NULL;
-       return newNode;
-    }
-    top = splay_splay(data, top, compare);
-    if (splayLastResult < 0) {
-       newNode->left = top->left;
-       newNode->right = top;
-       top->left = NULL;
-       return newNode;
-    } else if (splayLastResult > 0) {
-       newNode->right = top->right;
-       newNode->left = top;
-       top->right = NULL;
-       return newNode;
-    } else {
-       /* duplicate entry */
-       xfree(newNode);
-       return top;
-    }
+    return top->insert (data, compare);
 }
 
 splayNode *
-splay_splay(const void *data, splayNode * top, SPLAYCMP * compare)
+splay_splay(const void **data, splayNode * top, splayNode::SPLAYCMP * compare)
 {
-    splayNode N;
-    splayNode *l;
-    splayNode *r;
-    splayNode *y;
-    if (top == NULL)
-       return top;
-    N.left = N.right = NULL;
-    l = r = &N;
-
-    for (;;) {
-       splayLastResult = compare(data, top->data);
-       if (splayLastResult < 0) {
-           if (top->left == NULL)
-               break;
-           if ((splayLastResult = compare(data, top->left->data)) < 0) {
-               y = top->left;  /* rotate right */
-               top->left = y->right;
-               y->right = top;
-               top = y;
-               if (top->left == NULL)
-                   break;
-           }
-           r->left = top;      /* link right */
-           r = top;
-           top = top->left;
-       } else if (splayLastResult > 0) {
-           if (top->right == NULL)
-               break;
-           if ((splayLastResult = compare(data, top->right->data)) > 0) {
-               y = top->right; /* rotate left */
-               top->right = y->left;
-               y->left = top;
-               top = y;
-               if (top->right == NULL)
-                   break;
-           }
-           l->right = top;     /* link left */
-           l = top;
-           top = top->right;
-       } else {
-           break;
-       }
-    }
-    l->right = top->left;      /* assemble */
-    r->left = top->right;
-    top->left = N.right;
-    top->right = N.left;
-    return top;
+    return top->splay((void * const)*data, compare);
 }
 
 splayNode *
-splay_delete(const void *data, splayNode * top, SPLAYCMP * compare)
+splay_delete(const void *data, splayNode * top, splayNode::SPLAYCMP * compare)
 {
-    splayNode *x;
-    if (top == NULL)
-       return NULL;
-    top = splay_splay(data, top, compare);
-    if (splayLastResult == 0) {        /* found it */
-       if (top->left == NULL) {
-           x = top->right;
-       } else {
-           x = splay_splay(data, top->left, compare);
-           x->right = top->right;
-       }
-       xfree(top);
-       return x;
-    }
-    return top;                        /* It wasn't there */
+    return top->remove ((void * const)data, compare);
 }
 
 void
-splay_destroy(splayNode * top, SPLAYFREE * free_func)
+splay_destroy(splayNode * top, splayNode::SPLAYFREE * free_func)
 {
-    if (top->left)
-       splay_destroy(top->left, free_func);
-    if (top->right)
-       splay_destroy(top->right, free_func);
-    free_func(top->data);
-    xfree(top);
+    top->destroy(free_func);
 }
 
 void
-splay_walk(splayNode * top, SPLAYWALKEE * walkee, void *state)
+splay_walk(splayNode * top, splayNode::SPLAYWALKEE * walkee, void *state)
 {
-    if (top->left)
-       splay_walk(top->left, walkee, state);
-    walkee(top->data, state);
-    if (top->right)
-       splay_walk(top->right, walkee, state);
+    top->walk(walkee,state);
 }
 
 #ifdef DEBUG
index ca7c0d65dae039f3b16eca680367c6839b346dc7..c691899822edbffc9164aeb89a40452e0e6ca035 100644 (file)
--- a/src/ACL.h
+++ b/src/ACL.h
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ACL.h,v 1.1 2003/02/05 10:36:48 robertc Exp $
+ * $Id: ACL.h,v 1.2 2003/02/08 01:45:47 robertc Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
 
 #ifndef SQUID_ACL_H
 #define SQUID_ACL_H
-  
+#include "splay.h"
+
+/* As ACL's get refactored, these probably need better homes */
+
+#if USE_SSL
+class acl_cert_data {
+  public:
+    void *operator new(size_t);
+    void operator delete(void *);
+    virtual void deleteSelf() const;
+    SplayNode<char*> *values;
+    char *attribute;
+  private:
+    static MemPool *Pool;
+};
+#endif
+
+class acl_user_data {
+  public:
+    void *operator new(size_t);
+    void operator delete(void *);
+    virtual void deleteSelf() const;
+    SplayNode<char *> *names;
+    struct {
+       unsigned int case_insensitive:1;
+       unsigned int required:1;
+    } flags;
+  private:
+    static MemPool *Pool;
+};
+
 void dump_acl_access(StoreEntry * entry, const char *name, acl_access * head);
 
 #endif /* SQUID_ACL_H */
index b94a82b1784c549c69a06a5a96f374ee38b4a105..5c8de374e93c31612de7be6e1b2882832f28b3bb 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: DelayUser.cc,v 1.2 2003/02/06 09:57:36 robertc Exp $
+ * $Id: DelayUser.cc,v 1.3 2003/02/08 01:45:47 robertc Exp $
  *
  * DEBUG: section 77    Delay Pools
  * AUTHOR: Robert Collins <robertc@squid-cache.org>
@@ -69,9 +69,32 @@ DelayUser::DelayUser()
     DelayPools::registerForUpdates (this);
 }
 
+static SplayNode<DelayUserBucket::Pointer>::SPLAYFREE DelayUserFree;
+
 DelayUser::~DelayUser()
 {
     DelayPools::deregisterForUpdates (this);
+    buckets.head->destroy (DelayUserFree);
+}
+
+static SplayNode<DelayUserBucket::Pointer>::SPLAYCMP DelayUserCmp;
+
+int
+DelayUserCmp(DelayUserBucket::Pointer const &left, DelayUserBucket::Pointer const &right)
+{
+    /* for rate limiting, case insensitive */
+    return strcasecmp(left->authUser->username(), right->authUser->username());
+}
+
+void
+DelayUserFree(DelayUserBucket::Pointer &)
+{
+}
+
+void
+DelayUserStatsWalkee(DelayUserBucket::Pointer const &current, void *state)
+{
+    current->stats ((StoreEntry *)state);
 }
 
 void
@@ -81,15 +104,11 @@ DelayUser::stats(StoreEntry * sentry)
     if (spec.restore_bps == -1)
        return;
     storeAppendPrintf(sentry, "\t\tCurrent: ");
-    if (!buckets.size()) {
+    if (!buckets.head) {
        storeAppendPrintf (sentry, "Not used yet.\n\n");
        return;
     }
-    iterator pos = buckets.begin();
-    while (pos != buckets.end()) {
-       (*pos)->stats(sentry);
-       ++pos;
-    }
+    buckets.head->walk(DelayUserStatsWalkee, sentry);
     storeAppendPrintf(sentry, "\n\n");
 }
 
@@ -99,14 +118,24 @@ DelayUser::dump(StoreEntry *entry) const
     spec.dump(entry);
 }
 
+struct DelayUserUpdater 
+{
+    DelayUserUpdater (DelaySpec &_spec, int _incr):spec(_spec),incr(_incr){};
+    DelaySpec spec;
+    int incr;
+};
+void
+DelayUserUpdateWalkee(DelayUserBucket::Pointer const &current, void *state)
+{
+    DelayUserUpdater *t = (DelayUserUpdater *)state;
+    /* This doesn't change the value of the DelayUserBucket, so is safe */
+    const_cast<DelayUserBucket *>(current.getRaw())->theBucket.update(t->spec, t->incr);
+}
 void
 DelayUser::update(int incr)
 {
-    iterator pos = buckets.begin();
-    while (pos != buckets.end()) {
-       (*pos)->theBucket.update(spec, incr);
-       ++pos;
-    }
+    DelayUserUpdater updater(spec, incr);
+    buckets.head->walk (DelayUserUpdateWalkee, &updater);
 }
 
 void
@@ -178,18 +207,14 @@ DelayUserBucket::stats (StoreEntry *entry) const
 
 DelayUser::Id::Id(DelayUser::Pointer aDelayUser,AuthUser *aUser) : theUser(aDelayUser)
 {
-    DelayUser::iterator pos = theUser->buckets.begin();
-    while (pos != theUser->buckets.end()) {
-       if ((*pos)->authUser == aUser) {
-           theBucket = (*pos);
-           return;
-       }
-       ++pos;
-    }
-    
     theBucket = new DelayUserBucket(aUser);
+    DelayUserBucket::Pointer const *existing = theUser->buckets.find(theBucket, DelayUserCmp);
+    if (existing) {
+       theBucket = *existing;
+       return;
+    }
     theBucket->theBucket.init(theUser->spec);
-    theUser->buckets.push_back (theBucket);
+    theUser->buckets.head = theUser->buckets.head->insert (theBucket, DelayUserCmp);
 }
 
 DelayUser::Id::~Id()
index c9a079049b93b1002035831e39f02b25856be469..f539e43db95c676ec3d3a5263445c47c54d278d8 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: DelayUser.h,v 1.1 2003/02/05 21:06:30 robertc Exp $
+ * $Id: DelayUser.h,v 1.2 2003/02/08 01:45:47 robertc Exp $
  *
  * DEBUG: section 77    Delay Pools
  * AUTHOR: Robert Collins <robertc@squid-cache.org>
@@ -47,6 +47,7 @@
 #include "DelayBucket.h"
 #include "DelaySpec.h"
 #include "Array.h"
+#include "splay.h"
 
 class DelayUserBucket : public RefCountable {
   public:
@@ -90,7 +91,6 @@ private:
        DelayUserBucket::Pointer theBucket;
     };
     DelaySpec spec;
-    Vector<DelayUserBucket::Pointer> buckets;
-    typedef Vector<DelayUserBucket::Pointer>::iterator iterator;
+    Splay<DelayUserBucket::Pointer> buckets;
 };
 #endif /* DELAYUSER_H */
index a599c013a850ae1bc052fbc46f1aded47e0331de..ef840c18fcf5cee3787b8bc8735621bff18c4d81 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: acl.cc,v 1.297 2003/01/28 01:29:33 robertc Exp $
+ * $Id: acl.cc,v 1.298 2003/02/08 01:45:47 robertc Exp $
  *
  * DEBUG: section 28    Access Control
  * AUTHOR: Duane Wessels
@@ -33,6 +33,7 @@
  */
 
 #include "squid.h"
+#include "ACL.h"
 #include "ACLChecklist.h"
 #include "splay.h"
 #include "HttpRequest.h"
@@ -87,21 +88,21 @@ static wordlist *aclDumpIntlistList(intlist * data);
 static wordlist *aclDumpIntRangeList(intrange * data);
 static wordlist *aclDumpProtoList(intlist * data);
 static wordlist *aclDumpMethodList(intlist * data);
-static SPLAYCMP aclIpAddrNetworkCompare;
-static SPLAYCMP aclIpNetworkCompare;
-static SPLAYCMP aclHostDomainCompare;
-static SPLAYCMP aclDomainCompare;
-static SPLAYWALKEE aclDumpIpListWalkee;
-static SPLAYWALKEE aclDumpDomainListWalkee;
-static SPLAYFREE aclFreeIpData;
+static splayNode::SPLAYCMP aclIpAddrNetworkCompare;
+static splayNode::SPLAYCMP aclIpNetworkCompare;
+static splayNode::SPLAYCMP aclHostDomainCompare;
+template<class T> int aclDomainCompare(T const &a, T const &b);
+static splayNode::SPLAYWALKEE aclDumpIpListWalkee;
+static splayNode::SPLAYWALKEE aclDumpDomainListWalkee;
+static splayNode::SPLAYFREE aclFreeIpData;
 
 #if USE_ARP_ACL
 static void aclParseArpList(void *curlist);
 static int decode_eth(const char *asc, char *eth);
 static int aclMatchArp(void *dataptr, struct in_addr c);
 static wordlist *aclDumpArpList(void *);
-static SPLAYCMP aclArpCompare;
-static SPLAYWALKEE aclDumpArpListWalkee;
+static splayNode::SPLAYCMP aclArpCompare;
+static splayNode::SPLAYWALKEE aclDumpArpListWalkee;
 #endif
 static int aclCacheMatchAcl(dlink_list * cache, squid_acl acltype, void *data, char const *MatchParam);
 #if USE_SSL
@@ -112,6 +113,27 @@ static wordlist *aclDumpCertList(void *data);
 static void aclDestroyCertList(void *data);
 #endif
 
+template<class T>
+inline void
+xRefFree(T &thing)
+{
+    xfree (thing);
+}
+
+template<class T>
+inline int
+splaystrcmp (T&l, T&r)
+{
+    return strcmp ((char *)l,(char *)r);
+}
+
+template<class T>
+inline int
+splaystrcasecmp (T&l, T&r)
+{
+    return strcasecmp ((char *)l,(char *)r);
+}
+
 static squid_acl
 aclStrToType(const char *s)
 {
@@ -640,12 +662,12 @@ aclParseUserList(void **current)
 {
     char *t = NULL;
     acl_user_data *data;
-    splayNode *Top = NULL;
+    SplayNode<char *> *Top = NULL;
 
     debug(28, 2) ("aclParseUserList: parsing user list\n");
     if (*current == NULL) {
        debug(28, 3) ("aclParseUserList: current is null. Creating\n");
-       *current = memAllocate(MEM_ACL_USER_DATA);
+       *current = new acl_user_data;
     }
     data = (acl_user_data*)*current;
     Top = data->names;
@@ -660,7 +682,7 @@ aclParseUserList(void **current)
        } else {
            if (data->flags.case_insensitive)
                Tolower(t);
-           Top = splay_insert(xstrdup(t), Top, (SPLAYCMP *) strcmp);
+           Top = Top->insert(xstrdup(t), splaystrcmp);
        }
     }
     debug(28, 3) ("aclParseUserList: Case-insensitive-switch is %d\n",
@@ -672,7 +694,7 @@ aclParseUserList(void **current)
        debug(28, 6) ("aclParseUserList: Got token: %s\n", t);
        if (data->flags.case_insensitive)
            Tolower(t);
-       Top = splay_insert(xstrdup(t), Top, (SPLAYCMP *) strcmp);
+       Top = Top->insert(xstrdup(t), splaystrcmp);
     }
     data->names = Top;
 }
@@ -698,7 +720,7 @@ static void
 aclParseCertList(void *curlist)
 {
     acl_cert_data **datap = (acl_cert_data **)curlist;
-    splayNode **Top;
+    SplayNode<char *> **Top;
     char *t;
     char *attribute = strtokFile();
     if (!attribute)
@@ -707,12 +729,12 @@ aclParseCertList(void *curlist)
        if (strcasecmp((*datap)->attribute, attribute) != 0)
            self_destruct();
     } else {
-       *datap = (acl_cert_data *)memAllocate(MEM_ACL_CERT_DATA);
+       *datap = new acl_cert_data;
        (*datap)->attribute = xstrdup(attribute);
     }
     Top = &(*datap)->values;
     while ((t = strtokFile())) {
-       *Top = splay_insert(xstrdup(t), *Top, aclDomainCompare);
+       *Top = (*Top)->insert(xstrdup(t), aclDomainCompare);
     }
 }
 
@@ -728,7 +750,7 @@ aclMatchUserCert(void *data, ACLChecklist * checklist)
     value = sslGetUserAttribute(ssl, cert_data->attribute);
     if (!value)
        return 0;
-    cert_data->values = splay_splay(value, cert_data->values, (SPLAYCMP *) strcmp);
+    cert_data->values = cert_data->values->splay(const_cast<char *>(value), splaystrcmp);
     return !splayLastResult;
 }
 
@@ -744,7 +766,7 @@ aclMatchCACert(void *data, ACLChecklist * checklist)
     value = sslGetCAAttribute(ssl, cert_data->attribute);
     if (!value)
        return 0;
-    cert_data->values = splay_splay(value, cert_data->values, (SPLAYCMP *) strcmp);
+    cert_data->values = cert_data->values->splay(const_cast<char *>(value), splaystrcmp);
     return !splayLastResult;
 }
 
@@ -754,16 +776,16 @@ aclDestroyCertList(void *curlist)
     acl_cert_data **datap = (acl_cert_data **)curlist;
     if (!*datap)
        return;
-    splay_destroy((*datap)->values, xfree);
-    memFree(*datap, MEM_ACL_CERT_DATA);
+    (*datap)->values->destroy(xRefFree);
+    delete *datap;
     *datap = NULL;
 }
 
 static void
-aclDumpCertListWalkee(void *node_data, void *outlist)
+aclDumpCertListWalkee(char *const&node_data, void *outlist)
 {
     wordlist **wl = (wordlist **)outlist;
-    wordlistAdd(wl, (const char *)node_data);
+    wordlistAdd(wl, node_data);
 }
 
 static wordlist *
@@ -772,8 +794,7 @@ aclDumpCertList(void *curlist)
     acl_cert_data *data = (acl_cert_data *)curlist;
     wordlist *wl = NULL;
     wordlistAdd(&wl, data->attribute);
-    if (data->values)
-       splay_walk(data->values, aclDumpCertListWalkee, &wl);
+    data->values->walk(aclDumpCertListWalkee, &wl);
     return wl;
 }
 #endif
@@ -1131,7 +1152,8 @@ aclMatchIp(void *dataptr, struct in_addr c)
     x.addr2 = any_addr;
     x.mask = no_addr;
     x.next = NULL;
-    *Top = splay_splay(&x, *Top, aclIpAddrNetworkCompare);
+    const void *X = &x;
+    *Top = splay_splay(&X, *Top, aclIpAddrNetworkCompare);
     debug(28, 3) ("aclMatchIp: '%s' %s\n",
        inet_ntoa(c), splayLastResult ? "NOT found" : "found");
     return !splayLastResult;
@@ -1148,7 +1170,8 @@ aclMatchDomainList(void *dataptr, const char *host)
     if (host == NULL)
        return 0;
     debug(28, 3) ("aclMatchDomainList: checking '%s'\n", host);
-    *Top = splay_splay(host, *Top, aclHostDomainCompare);
+    const void * __host = host;
+    *Top = splay_splay(&__host, *Top, aclHostDomainCompare);
     debug(28, 3) ("aclMatchDomainList: '%s' %s\n",
        host, splayLastResult ? "NOT found" : "found");
     return !splayLastResult;
@@ -1185,7 +1208,7 @@ static int
 aclMatchUser(void *proxyauth_acl, char const *user)
 {
     acl_user_data *data = (acl_user_data *) proxyauth_acl;
-    splayNode *Top = data->names;
+    SplayNode<char *> *Top = data->names;
 
     debug(28, 7) ("aclMatchUser: user is %s, case_insensitive is %d\n",
        user, data->flags.case_insensitive);
@@ -1200,10 +1223,10 @@ aclMatchUser(void *proxyauth_acl, char const *user)
        return 1;
     }
     if (data->flags.case_insensitive)
-       Top = splay_splay(user, Top, (SPLAYCMP *) strcasecmp);
+       Top = Top->splay((char *)user, splaystrcasecmp);
     else
-       Top = splay_splay(user, Top, (SPLAYCMP *) strcmp);
-    /* Top=splay_splay(user,Top,(SPLAYCMP *)dumping_strcmp); */
+       Top = Top->splay((char *)user, splaystrcmp);
+    /* Top=splay_splay(user,Top,(splayNode::SPLAYCMP *)dumping_strcmp); */
     debug(28, 7) ("aclMatchUser: returning %d,Top is %p, Top->data is %s\n",
        !splayLastResult, Top, (char *) (Top ? Top->data : "Unavailable"));
     data->names = Top;
@@ -2212,7 +2235,7 @@ aclDestroyRegexList(relist * data)
 }
 
 static void
-aclFreeIpData(void *p)
+aclFreeIpData(void * &p)
 {
     memFree(p, MEM_ACL_IP_DATA);
 }
@@ -2222,8 +2245,8 @@ aclFreeUserData(void *data)
 {
     acl_user_data *d = (acl_user_data *)data;
     if (d->names)
-       splay_destroy(d->names, xfree);
-    memFree(d, MEM_ACL_USER_DATA);
+       d->names->destroy(xRefFree);
+    delete d;
 }
 
 
@@ -2246,7 +2269,7 @@ aclDestroyAcls(acl ** head)
 #endif
        case ACL_DST_DOMAIN:
        case ACL_SRC_DOMAIN:
-           splay_destroy((splayNode *)a->data, xfree);
+           splay_destroy((splayNode *)a->data, xRefFree);
            break;
 #if SQUID_SNMP
        case ACL_SNMP_COMMUNITY:
@@ -2379,20 +2402,20 @@ aclDestroyIntRange(intrange * list)
 
 /* compare two domains */
 
-static int
-aclDomainCompare(const void *a, const void *b)
+template<class T>
+int
+aclDomainCompare(T const &a, T const &b)
 {
-    const char *d1;
-    const char *d2;
+    char * const d1 = (char *const)b;
+    char * const d2 = (char *const )a;
     int ret;
-    d1 = (const char *)b;
-    d2 = (const char *)a;
     ret = aclHostDomainCompare(d1, d2);
     if (ret != 0) {
-       d1 = (const char *)a;
-       d2 = (const char *)b;
-       ret = aclHostDomainCompare(d1, d2);
+       char *const d3 = d2;
+       char *const d4 = d1;
+       ret = aclHostDomainCompare(d3, d4);
     }
+    /* FIXME this warning may display d1 and d2 when it should display d3 and d4 */
     if (ret == 0) {
        debug(28, 0) ("WARNING: '%s' is a subdomain of '%s'\n", d1, d2);
        debug(28, 0) ("WARNING: because of this '%s' is ignored to keep splay tree searching predictable\n", (char *) a);
@@ -2404,7 +2427,7 @@ aclDomainCompare(const void *a, const void *b)
 /* compare a host and a domain */
 
 static int
-aclHostDomainCompare(const void *a, const void *b)
+aclHostDomainCompare( void *const &a, void * const &b)
 {
     const char *h = (const char *)a;
     const char *d = (const char *)b;
@@ -2441,7 +2464,7 @@ aclIpDataToStr(const acl_ip_data * ip, char *buf, int len)
  * bits with the network subnet mask.
  */
 static int
-aclIpNetworkCompare2(const acl_ip_data * p, const acl_ip_data * q)
+aclIpNetworkCompare2(acl_ip_data * const &p, acl_ip_data * const &q)
 {
     struct in_addr A = p->addr1;
     const struct in_addr B = q->addr1;
@@ -2473,18 +2496,16 @@ aclIpNetworkCompare2(const acl_ip_data * p, const acl_ip_data * q)
  * sorting algorithm.  Much like aclDomainCompare.
  */
 static int
-aclIpNetworkCompare(const void *a, const void *b)
+aclIpNetworkCompare(void * const & a, void * const &b)
 {
-    const acl_ip_data *n1;
-    const acl_ip_data *n2;
+    acl_ip_data * const n1 = (acl_ip_data *const)b;
+    acl_ip_data * const n2 = (acl_ip_data *const)a;
     int ret;
-    n1 = (const acl_ip_data *)b;
-    n2 = (const acl_ip_data *)a;
     ret = aclIpNetworkCompare2(n1, n2);
     if (ret != 0) {
-       n1 = (const acl_ip_data *)a;
-       n2 = (const acl_ip_data *)b;
-       ret = aclIpNetworkCompare2(n1, n2);
+       acl_ip_data * const n3 = n2;
+       acl_ip_data * const n4 = n1;
+       ret = aclIpNetworkCompare2(n3, n4);
     }
     if (ret == 0) {
        char buf_n1[60];
@@ -2493,6 +2514,7 @@ aclIpNetworkCompare(const void *a, const void *b)
        aclIpDataToStr(n1, buf_n1, 60);
        aclIpDataToStr(n2, buf_n2, 60);
        aclIpDataToStr((acl_ip_data *) a, buf_a, 60);
+       /* TODO: this warning may display the wrong way around */
        debug(28, 0) ("WARNING: '%s' is a subnetwork of "
            "'%s'\n", buf_n1, buf_n2);
        debug(28, 0) ("WARNING: because of this '%s' is ignored "
@@ -2511,13 +2533,13 @@ aclIpNetworkCompare(const void *a, const void *b)
  * function is called via aclMatchIp() and the splay library.
  */
 static int
-aclIpAddrNetworkCompare(const void *a, const void *b)
+aclIpAddrNetworkCompare(void *const &a, void * const &b)
 {
-    return aclIpNetworkCompare2((const acl_ip_data *)a, (const acl_ip_data *)b);
+    return aclIpNetworkCompare2((acl_ip_data * const)a, (acl_ip_data * const)b);
 }
 
 static void
-aclDumpUserListWalkee(void *node_data, void *outlist)
+aclDumpUserListWalkee(char * const & node_data, void *outlist)
 {
     /* outlist is really a wordlist ** */
     wordlistAdd((wordlist **)outlist, (char const *)node_data);
@@ -2536,12 +2558,12 @@ aclDumpUserList(acl_user_data * data)
     if (data->flags.required)
        wordlistAdd(&wl, "REQUIRED");
     else if (data->names)
-       splay_walk(data->names, aclDumpUserListWalkee, &wl);
+       data->names->walk(aclDumpUserListWalkee, &wl);
     return wl;
 }
 
 static void
-aclDumpIpListWalkee(void *node, void *state)
+aclDumpIpListWalkee(void * const & node, void *state)
 {
     acl_ip_data *ip = (acl_ip_data *)node;
     MemBuf mb;
@@ -2565,7 +2587,7 @@ aclDumpIpList(void *data)
 }
 
 static void
-aclDumpDomainListWalkee(void *node, void *state)
+aclDumpDomainListWalkee(void * const &node, void *state)
 {
     char *domain = (char *)node;
     wordlistAdd((wordlist **)state, domain);
@@ -3023,7 +3045,7 @@ aclMatchArp(void *dataptr, struct in_addr c)
 }
 
 static int
-aclArpCompare(const void *a, const void *b)
+aclArpCompare(void * const &a, void * const &b)
 {
 #if defined(_SQUID_LINUX_)
     const unsigned short *d1 = (const unsigned short *)a;
@@ -3105,7 +3127,7 @@ checkARP(u_long ip, char *eth)
 #endif
 
 static void
-aclDumpArpListWalkee(void *node, void *state)
+aclDumpArpListWalkee(void * &node, void *state)
 {
     acl_arp_data *arp = (acl_arp_data *)node;
     static char buf[24];
@@ -3125,3 +3147,53 @@ aclDumpArpList(void *data)
 
 /* ==== END ARP ACL SUPPORT =============================================== */
 #endif /* USE_ARP_ACL */
+
+/* to be split into separate files in the future */
+
+MemPool *acl_user_data::Pool(NULL);
+void *
+acl_user_data::operator new (size_t byteCount)
+{
+    /* derived classes with different sizes must implement their own new */
+    assert (byteCount == sizeof (acl_user_data));
+    if (!Pool)
+       Pool = memPoolCreate("acl_user_data", sizeof (acl_user_data));
+    return memPoolAlloc(Pool);
+}
+
+void
+acl_user_data::operator delete (void *address)
+{
+    memPoolFree (Pool, address);
+}
+
+void
+acl_user_data::deleteSelf() const
+{
+    delete this;
+}
+
+#if USE_SSL
+MemPool *acl_cert_data::Pool(NULL);
+void *
+acl_cert_data::operator new (size_t byteCount)
+{
+    /* derived classes with different sizes must implement their own new */
+    assert (byteCount == sizeof (acl_cert_data));
+    if (!Pool)
+       Pool = memPoolCreate("acl_cert_data", sizeof (acl_cert_data));
+    return memPoolAlloc(Pool);
+}
+
+void
+acl_cert_data::operator delete (void *address)
+{
+    memPoolFree (Pool, address);
+}
+
+void
+acl_cert_data::deleteSelf() const
+{
+    delete this;
+}
+#endif /* USE_SSL */
index 5fdeb4f95ab11aa62e9bdd2e2c08aeecd3ee91c3..781bff123da482ece9d80676190aa84fa174517a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: enums.h,v 1.221 2003/01/28 01:29:34 robertc Exp $
+ * $Id: enums.h,v 1.222 2003/02/08 01:45:47 robertc Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -590,7 +590,6 @@ typedef enum {
     MEM_ACL_LIST,
     MEM_ACL_NAME_LIST,
     MEM_ACL_PROXY_AUTH_MATCH,
-    MEM_ACL_USER_DATA,
     MEM_ACL_TIME_DATA,
 #if USE_CACHE_DIGESTS
     MEM_CACHE_DIGEST,
@@ -622,9 +621,6 @@ typedef enum {
 #endif
     MEM_EVENT,
     MEM_SWAP_LOG_DATA,
-#if USE_SSL
-    MEM_ACL_CERT_DATA,
-#endif
     MEM_MAX
 } mem_type;
 
index 8706bc760a4fa07864dc3a3ea8f1591da465d8d3..3dc5e65608dae93d9c8d1ee571ac878b33c822c3 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: mem.cc,v 1.70 2003/01/23 00:37:23 robertc Exp $
+ * $Id: mem.cc,v 1.71 2003/02/08 01:45:47 robertc Exp $
  *
  * DEBUG: section 13    High Level Memory Pool Management
  * AUTHOR: Harvest Derived
@@ -351,14 +351,9 @@ Mem::Init(void)
     memDataInit(MEM_ACL_IP_DATA, "acl_ip_data", sizeof(acl_ip_data), 0);
     memDataInit(MEM_ACL_LIST, "acl_list", sizeof(acl_list), 0);
     memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0);
-#if USE_SSL
-    memDataInit(MEM_ACL_CERT_DATA, "acl_cert_data", sizeof(acl_cert_data), 0);
-#endif
     memDataInit(MEM_ACL_TIME_DATA, "acl_time_data", sizeof(acl_time_data), 0);
     memDataInit(MEM_ACL_PROXY_AUTH_MATCH, "acl_proxy_auth_match_cache",
        sizeof(acl_proxy_auth_match_cache), 0);
-    memDataInit(MEM_ACL_USER_DATA, "acl_user_data",
-       sizeof(acl_user_data), 0);
 #if USE_CACHE_DIGESTS
     memDataInit(MEM_CACHE_DIGEST, "CacheDigest", sizeof(CacheDigest), 0);
 #endif
index 9c18dccdbe2fcdafcf4fa257705e98f87e83cc03..bea093cdb0cc7b49c81edb92747a419a81b0f2f5 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.446 2003/02/05 10:36:55 robertc Exp $
+ * $Id: structs.h,v 1.447 2003/02/08 01:45:50 robertc Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -35,7 +35,6 @@
 #define SQUID_STRUCTS_H
 
 #include "config.h"
-#include "splay.h"
 
 struct _dlink_node {
     void *data;
@@ -48,21 +47,6 @@ struct _dlink_list {
     dlink_node *tail;
 };
 
-#if USE_SSL
-struct _acl_cert_data {
-    splayNode *values;
-    char *attribute;
-};
-#endif
-
-struct _acl_user_data {
-    splayNode *names;
-    struct {
-       unsigned int case_insensitive:1;
-       unsigned int required:1;
-    } flags;
-};
-
 struct _acl_user_ip_data {
     size_t max;
     struct {
index 67fc58564066aef146290b88b0f501929342f670..e34959e0cd22b0d5c9788080dc340366cff62a03 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.148 2003/02/05 10:36:56 robertc Exp $
+ * $Id: typedefs.h,v 1.149 2003/02/08 01:45:51 robertc Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -64,10 +64,6 @@ typedef struct AuthUserIP auth_user_ip_t;
 typedef struct _acl_proxy_auth_match_cache acl_proxy_auth_match_cache;
 typedef struct _authscheme_entry authscheme_entry_t;
 typedef struct _authScheme authScheme;
-#if USE_SSL
-typedef struct _acl_cert_data acl_cert_data;
-#endif
-typedef struct _acl_user_data acl_user_data;
 typedef struct _acl_user_ip_data acl_user_ip_data;
 typedef struct _acl_arp_data acl_arp_data;
 typedef struct _acl_snmp_comm acl_snmp_comm;
index c1db482132b005cad8c7fa2e9530611eeeba411a..324fc80a3bbae565d737d11d8d8089084ac5dc3c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: splay.cc,v 1.1 2003/02/05 10:37:14 robertc Exp $
+ * $Id: splay.cc,v 1.2 2003/02/08 01:45:51 robertc Exp $
  *
  * based on ftp://ftp.cs.cmu.edu/user/sleator/splaying/top-down-splay.c
  * http://bobo.link.cs.cmu.edu/cgi-bin/splay/splay-cgi.pl
@@ -25,33 +25,114 @@ typedef struct {
 } intnode;
 
 int
-compareint(void const *a, void const *n)
+compareintvoid(void * const &a, void * const &n)
 {
     intnode *A = (intnode *)a;
     intnode *B = (intnode *)n;
-    //((splayNode *)n)->data;
     return A->i - B->i;
 }
 
+int
+compareint(intnode * const &a, intnode * const &b)
+{
+    return a->i - b->i;
+}
+
 void
-printint(void *a, void *state)
+printintvoid(void * const &a, void *state)
 {
     intnode *A = (intnode *)a;
     printf("%d\n", A->i);
 }
 
+void
+printint (intnode * const &a, void *state)
+{
+    printf("%d\n",a->i);
+}
+
+void
+destintvoid(void * &data)
+{
+    intnode *i = (intnode *)data;
+    xfree (i);
+}
+
+void
+destint(intnode * &data)
+{
+    delete data;
+}
+
+int
+compareintref(intnode const &a, intnode const &b)
+{
+    return a.i - b.i;
+}
+
+void
+printintref (intnode const &a, void *unused)
+{
+    printf("%d\n",a.i);
+}
+
+void
+destintref (intnode &)
+{
+}
+
 int
 main(int argc, char *argv[])
 {
     int i;
     intnode *I;
+    /* test void * splay containers */
     splayNode *top = NULL;
     srandom(time(NULL));
     for (i = 0; i < 100; i++) {
        I = (intnode *)xcalloc(sizeof(intnode), 1);
        I->i = random();
-       top = splay_insert(I, top, compareint);
+       top = splay_insert(I, top, compareintvoid);
+    }
+    splay_walk(top, printintvoid, NULL);
+    
+    top->walk(printintvoid, NULL);
+    top->destroy(destintvoid);
+    /* check we don't segfault on NULL splay calls */
+    top = NULL;
+    top->splay(NULL, compareintvoid);
+
+    /* test typesafe splay containers */
+      {
+    /* intnode* */
+    SplayNode<intnode *> *safeTop = NULL;
+    for (i = 0; i < 100; i++) {
+       I = new intnode;
+       I->i = random();
+       safeTop = safeTop->insert(I, compareint);
+    }
+    safeTop->walk(printint, NULL);
+    
+    safeTop->destroy(destint);
+    /* check we don't segfault on NULL splay calls */
+    safeTop = NULL;
+    safeTop->splay(NULL, compareint);
+      }
+      {
+    /* intnode */
+    SplayNode<intnode> *safeTop = NULL;
+    for (i = 0; i < 100; i++) {
+       intnode I;
+       I.i = random();
+       safeTop = safeTop->insert(I, compareintref);
     }
-    splay_walk(top, printint, NULL);
+    safeTop->walk(printintref, NULL);
+    
+    safeTop->destroy(destintref);
+    /* check we don't segfault on NULL splay calls */
+    safeTop = NULL;
+    safeTop->splay(intnode(), compareintref);
+    safeTop->walk(printintref, NULL);
+}
     return 0;
 }