]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Counting and testing number of elements in the addrtree
authorYuri Schaeffer <yuri@nlnetlabs.nl>
Tue, 8 Oct 2013 12:42:49 +0000 (12:42 +0000)
committerYuri Schaeffer <yuri@nlnetlabs.nl>
Tue, 8 Oct 2013 12:42:49 +0000 (12:42 +0000)
git-svn-id: file:///svn/unbound/branches/edns-subnet@2974 be551aaa-1e26-0410-a405-d3ace91eadb9

edns-subnet/addrtree.c
edns-subnet/addrtree.h
testcode/unitvandergaast.c

index ee3e80ccb7570ca3602b3431114fb042b3fb53c0..69b66287451b2ef195fb8121edd844e3eb6a6a2d 100644 (file)
@@ -46,13 +46,15 @@ edge_create(struct addrnode* node, const addrkey_t* addr, addrlen_t addrlen)
  * @param ttl: Element is valid up to this time. Absolute, seconds
  * @return new addrnode or NULL on failure
  */
-static struct addrnode* 
-node_create(void* elem, addrlen_t scope, time_t ttl)
+static struct addrnode * 
+node_create(struct addrtree *tree, void* elem, addrlen_t scope, 
+       time_t ttl)
 {
        struct addrnode* node = (struct addrnode*)malloc( sizeof (*node) );
        if (!node)
                return NULL;
        node->elem = elem;
+       if (elem) tree->elem_count++;
        node->scope = scope;
        node->ttl = ttl;
        node->edge[0] = NULL;
@@ -69,7 +71,7 @@ struct addrtree* addrtree_create(addrlen_t max_depth,
        tree = (struct addrtree*)malloc( sizeof (*tree) );
        if(!tree)
                return NULL;
-       tree->root = node_create(NULL, 0, 0);
+       tree->root = node_create(tree, NULL, 0, 0);
        if (!tree->root) {
                free(tree);
                return NULL;
@@ -78,6 +80,7 @@ struct addrtree* addrtree_create(addrlen_t max_depth,
        tree->delfunc = delfunc;
        tree->sizefunc = sizefunc;
        tree->env = env;
+       tree->elem_count = 0;
        return tree;
 }
 
@@ -115,11 +118,12 @@ size_t addrtree_size(const struct addrtree* tree)
  * @param node: Node to be cleaned
  */
 static void
-clean_node(const struct addrtree* tree, struct addrnode* node)
+clean_node(struct addrtree* tree, struct addrnode* node)
 {
        if (!node->elem) return;
        tree->delfunc(tree->env, node->elem);
        node->elem = NULL;
+       tree->elem_count--;
 }
 
 /** 
@@ -132,7 +136,7 @@ clean_node(const struct addrtree* tree, struct addrnode* node)
  *        parentnode is NULL
  */
 static void
-purge_node(const struct addrtree* tree, struct addrnode* node, 
+purge_node(struct addrtree* tree, struct addrnode* node, 
        struct addrnode* parentnode, struct addredge* parentedge)
 {
        struct addredge *child_edge = NULL;
@@ -272,6 +276,7 @@ addrtree_insert(struct addrtree* tree, const addrkey_t* addr,
                if (depth == sourcemask) {
                        /* update this node's scope and data */
                        clean_node(tree, node);
+                       tree->elem_count++;
                        node->elem = elem;
                        node->scope = scope;
                        return;
@@ -288,7 +293,7 @@ addrtree_insert(struct addrtree* tree, const addrkey_t* addr,
                }
                /* Case 2: New leafnode */
                if (!edge) {
-                       newnode = node_create(elem, scope, ttl);
+                       newnode = node_create(tree, elem, scope, ttl);
                        node->edge[index] = edge_create(newnode, addr, sourcemask);
                        if (!node->edge[index])
                                free(newnode);
@@ -306,9 +311,10 @@ addrtree_insert(struct addrtree* tree, const addrkey_t* addr,
                        continue;
                }
                /* Case 4: split. */
-               if (!(newnode = node_create(NULL, 0, 0)))
+               if (!(newnode = node_create(tree, NULL, 0, 0)))
                        return;
                if (!(newedge = edge_create(newnode, addr, common))) {
+                       clean_node(tree, newnode);
                        free(newnode);
                        return;
                }               
@@ -324,7 +330,7 @@ addrtree_insert(struct addrtree* tree, const addrkey_t* addr,
                } else {
                        /* Data is stored in other leafnode */
                        node = newnode;
-                       newnode = node_create(elem, scope, ttl);
+                       newnode = node_create(tree, elem, scope, ttl);
                        node->edge[index^1] = edge_create(newnode, addr, sourcemask);
                }
                return;
index 9d65ac3cc3b989597988256b1c99e8aae79b7782..94db90388c4c651b924a08de0af4e7c88787e58c 100644 (file)
@@ -38,12 +38,14 @@ typedef uint8_t addrkey_t;
 
 struct addrtree {
        struct addrnode* root;
+       /** Number of elements in the tree (not always equal to number of 
+        * nodes) */
+       unsigned int elem_count;
        /** Maximum prefix length we are willing to cache. */
        addrlen_t max_depth;
        void (*delfunc)(void *, void *);
        size_t (*sizefunc)(void *);
        void *env;
-       
 };
 
 struct addrnode {
index 3db06e88bef8940184b8b463b6ff10bb55d5cc29..32df27c4e8a53ea648ea3b425f9f73b8f20067f0 100644 (file)
@@ -156,6 +156,7 @@ static void elemfree(void *envptr, void *elemptr)
 static void consistency_test(void)
 {
        int i, l, r;
+       unsigned int count;
        addrkey_t *k;
        struct addrtree* t;
        struct module_env env;
@@ -165,16 +166,23 @@ static void consistency_test(void)
        srand(9195); /* just some value for reproducibility */
 
        t = addrtree_create(100, &elemfree, NULL, &env);
+       count = t->elem_count;
+       unit_assert(count == 0);
        for (i = 0; i < 1000; i++) {
                l = randomkey(&k, 128);
                elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
                addrtree_insert(t, k, l, 64, elem, timenow + 10, timenow);
+               /* This should always hold because no items ever expire. They
+                * could be overwritten, though. */
+               unit_assert( count <= t->elem_count );
+               count = t->elem_count;
                free(k);
                unit_assert( !addrtree_inconsistent(t) );
        }
        addrtree_delete(t);
        unit_show_func("edns-subnet/addrtree.h", "Tree consistency with purge");
        t = addrtree_create(8, &elemfree, NULL, &env);
+       unit_assert(t->elem_count == 0);
        for (i = 0; i < 1000; i++) {
                l = randomkey(&k, 128);
                elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));