From: Ronnie Sahlberg Date: Wed, 8 Aug 2007 02:30:12 +0000 (+1000) Subject: add helpers to add/lookup/delete nodes in a tree where the key is an X-Git-Tag: tevent-0.9.20~348^2~2442^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9525b010aa9fa2aa35ebf75ba483c1bde7fd74ea;p=thirdparty%2Fsamba.git add helpers to add/lookup/delete nodes in a tree where the key is an array of uint32 (This used to be ctdb commit b7e0996e7735c8629d07453b9d335990c2dbc3db) --- diff --git a/ctdb/common/rb_tree.c b/ctdb/common/rb_tree.c index 5139560ae29..17388f9562a 100644 --- a/ctdb/common/rb_tree.c +++ b/ctdb/common/rb_tree.c @@ -713,6 +713,125 @@ trbt_insert32_callback(trbt_tree_t *tree, uint32_t key, void *(*callback)(void * +struct trbt_array_param { + void *(*callback)(void *param, void *data); + void *param; + uint32_t keylen; + uint32_t *key; + trbt_tree_t *tree; +}; +static void *array_insert_callback(void *p, void *data) +{ + struct trbt_array_param *param = (struct trbt_array_param *)p; + trbt_tree_t *tree = NULL; + + + /* if keylen has reached 0 we are done and can call the users + callback function with the users parameters + */ + if (param->keylen == 0) { + return param->callback(param->param, data); + } + + + /* keylen is not zero yes so we must create/process more subtrees */ + /* if data is NULL this means we did not yet have a subtree here + and we must create one. + */ + if (data == NULL) { + /* create a new subtree and hang it off our current tree */ + tree = trbt_create(param->tree); + } else { + /* we already have a subtree for this path */ + tree = (trbt_tree_t *)data; + } + + trbt_insertarray32_callback(tree, param->keylen, param->key, param->callback, param->param); + + /* now return either the old tree we got in *data or the new tree + we created to our caller so he can update his pointer in his + tree to point to our subtree + */ + return tree; +} + + + +/* insert into the tree using an array of uint32 as a key */ +void +trbt_insertarray32_callback(trbt_tree_t *tree, uint32_t keylen, uint32_t *key, void *(*cb)(void *param, void *data), void *pm) +{ + struct trbt_array_param tap; + + /* keylen-1 and key[1] since the call to insert32 will consume the + first part of the key. + */ + tap.callback= cb; + tap.param = pm; + tap.keylen = keylen-1; + tap.key = &key[1]; + tap.tree = tree; + + trbt_insert32_callback(tree, key[0], array_insert_callback, &tap); +} + + +/* lookup the tree using an array of uint32 as a key */ +void * +trbt_lookuparray32(trbt_tree_t *tree, uint32_t keylen, uint32_t *key) +{ + /* if keylen is 1 we can do a regular lookup and return this to the + user + */ + if (keylen == 1) { + return trbt_lookup32(tree, key[0]); + } + + /* we need to lookup the next subtree */ + tree = trbt_lookup32(tree, key[0]); + if (tree == NULL) { + /* the key does not exist, return NULL */ + return NULL; + } + + /* now lookup the next part of the key in our new tree */ + return trbt_lookuparray32(tree, keylen-1, &key[1]); +} + + +/* delete a node from the tree using an array of uint32 as a key */ +void +trbt_deletearray32(trbt_tree_t *tree, uint32_t keylen, uint32_t *key) +{ + trbt_tree_t *next_tree; + + /* if we have reached the leaftree we can just delete the node + if it exists + */ + if (keylen == 1) { + trbt_delete32(tree, key[0]); + return; + } + + + /* find the next subtree and recurse into it if it exists */ + next_tree = trbt_lookup32(tree, key[0]); + if (next_tree == NULL) { + return; + } + + trbt_deletearray32(next_tree, keylen-1, &key[1]); + + + /* when we returned from recursing into the the subtree, + that subtree might have become empty in which case we can delete it + as well + */ + if (next_tree->root == NULL) { + trbt_delete32(tree, key[0]); + } +} + # if 0 static void printtree(trbt_node_t *node, int levels) { diff --git a/ctdb/common/rb_tree.h b/ctdb/common/rb_tree.h index ad095dd50ff..f94a4b6a270 100644 --- a/ctdb/common/rb_tree.h +++ b/ctdb/common/rb_tree.h @@ -63,3 +63,14 @@ void trbt_insert32_callback(trbt_tree_t *tree, uint32_t key, void *(*callback)(v /* Delete a node from the tree and free all data associated with it */ void trbt_delete32(trbt_tree_t *tree, uint32_t key); + +/* insert into the tree with a key based on an array of uint32 */ +void trbt_insertarray32_callback(trbt_tree_t *tree, uint32_t keylen, uint32_t *key, void *(*callback)(void *param, void *data), void *param); + +/* Lookup a node in the tree with a key based on an array of uint32 + and return a pointer to data or NULL */ +void *trbt_lookuparray32(trbt_tree_t *tree, uint32_t keylen, uint32_t *key); + +/* Delete a node in the tree with a key based on an array of uint32 + and return a pointer to data or NULL */ +void trbt_deletearray32(trbt_tree_t *tree, uint32_t keylen, uint32_t *key); diff --git a/ctdb/tests/rb_test.c b/ctdb/tests/rb_test.c index b1c62a3447e..04ae7d2cf15 100644 --- a/ctdb/tests/rb_test.c +++ b/ctdb/tests/rb_test.c @@ -62,6 +62,11 @@ int main(int argc, const char *argv[]) struct event_context *ev; int i; trbt_tree_t *tree; + uint32_t *data; + uint32_t key1[3] = {0,0,0}; + uint32_t key2[3] = {0,0,1}; + uint32_t key3[3] = {0,1,0}; + uint32_t key4[3] = {2,0,0}; pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST); @@ -96,13 +101,72 @@ int main(int argc, const char *argv[]) printf("first 3 keys should have data==1\n"); printf("the rest of the keys should have data==2\n"); for (i=0; i