From: Yuri Schaeffer Date: Tue, 8 Oct 2013 12:42:49 +0000 (+0000) Subject: Counting and testing number of elements in the addrtree X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9970319a6f8be57881c9a6ddfe92663986caacf2;p=thirdparty%2Funbound.git Counting and testing number of elements in the addrtree git-svn-id: file:///svn/unbound/branches/edns-subnet@2974 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/edns-subnet/addrtree.c b/edns-subnet/addrtree.c index ee3e80ccb..69b662874 100644 --- a/edns-subnet/addrtree.c +++ b/edns-subnet/addrtree.c @@ -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; diff --git a/edns-subnet/addrtree.h b/edns-subnet/addrtree.h index 9d65ac3cc..94db90388 100644 --- a/edns-subnet/addrtree.h +++ b/edns-subnet/addrtree.h @@ -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 { diff --git a/testcode/unitvandergaast.c b/testcode/unitvandergaast.c index 3db06e88b..32df27c4e 100644 --- a/testcode/unitvandergaast.c +++ b/testcode/unitvandergaast.c @@ -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));