map: free unused leaf nodes

So if a node has no children and no value or notifier
then it is freed.

Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
This commit is contained in:
Angus Salkeld 2012-01-05 13:37:24 +11:00
parent 5d8c96314e
commit 7ff28b99bc
2 changed files with 28 additions and 3 deletions

View File

@ -332,6 +332,26 @@ trie_lookup(struct trie *t, const char *key, int exact_match)
return cur_node;
}
static void
trie_node_release(struct trie *t, struct trie_node *node)
{
if (node->num_children == 0 &&
node->refcount == 0 &&
node->parent != NULL &&
qb_list_empty(&node->notifier_head)) {
struct trie_node *p = node->parent;
/*
* unlink the node from the parent
*/
p->children[node->idx] = NULL;
free(node);
t->num_nodes--;
t->mem_used -= sizeof(struct trie_node);
trie_node_release(t, p);
}
}
static void
trie_node_destroy(struct trie *t, struct trie_node *n)
{
@ -342,6 +362,8 @@ trie_node_destroy(struct trie *t, struct trie_node *n)
n->key = NULL;
n->value = NULL;
trie_node_release(t, n);
}
static void
@ -367,7 +389,6 @@ trie_print_node(struct trie_node *n, struct trie_node *r, const char *suffix)
}
}
static void
trie_node_ref(struct trie *t, struct trie_node *node)
{
@ -628,6 +649,7 @@ trie_notify_del(qb_map_t * m, const char *key,
}
}
if (found) {
trie_node_release(t, n);
return 0;
} else {
return -ENOENT;

View File

@ -97,15 +97,18 @@ static int32_t
check_order(const char *key, void *value, void *data)
{
int *o = (int*)data;
ck_assert(chars[*o][0] == key[0]);
ck_assert_str_eq(chars[*o], key);
ck_assert_str_eq(chars[*o], value);
(*o)++;
return QB_FALSE;
}
static int32_t
check_order2(const char *key, void *value, void *data)
{
int *o = (int*)data;
ck_assert(chars2[*o][0] == key[0]);
ck_assert_str_eq(chars2[*o], key);
ck_assert_str_eq(chars2[*o], value);
(*o)++;
return QB_FALSE;
}