]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
add a tree insert function that takes a callback fucntion to populate
authorRonnie Sahlberg <sahlberg@ronnie>
Wed, 8 Aug 2007 01:21:18 +0000 (11:21 +1000)
committerRonnie Sahlberg <sahlberg@ronnie>
Wed, 8 Aug 2007 01:21:18 +0000 (11:21 +1000)
the data of the tree.
this callback makes it more convenient to manage cases where one might
want to insert multiple entries into the tree with the same key

rename the tree->tree pointer to tree->root  since this is supposed to
point to the root of the tree

add a small test utility

(This used to be ctdb commit f6313bed9c53e0d1c36c9e08ac707e88e2a4fcd5)

ctdb/Makefile.in
ctdb/common/rb_tree.c
ctdb/common/rb_tree.h
ctdb/tests/rb_test.c [new file with mode: 0644]

index bc717dda6fb5ce89b51583e645fdcafe1f8627f2..e1ddcd527a0eb6ee260c2ceef506800d98451a32 100644 (file)
@@ -50,7 +50,9 @@ CTDB_SERVER_OBJ = server/ctdbd.o server/ctdb_daemon.o server/ctdb_lockwait.o \
        server/ctdb_traverse.o server/eventscript.o server/ctdb_takeover.o \
        $(CTDB_CLIENT_OBJ) $(CTDB_TCP_OBJ) @INFINIBAND_WRAPPER_OBJ@
 
-TEST_BINS=bin/ctdb_bench bin/ctdb_fetch bin/ctdb_store @INFINIBAND_BINS@
+TEST_BINS=bin/ctdb_bench bin/ctdb_fetch bin/ctdb_store bin/rb_test \
+       @INFINIBAND_BINS@
+
 BINS = bin/ctdb @CTDB_SCSI_IO@ bin/smnotify
 SBINS = bin/ctdbd
 
@@ -101,6 +103,10 @@ utils/smnotify/gen_smnotify.c: utils/smnotify/smnotify.x utils/smnotify/smnotify
        @echo Generating $@
        rpcgen -C -l utils/smnotify/smnotify.x > utils/smnotify/gen_smnotify.c 
 
+bin/rb_test: $(CTDB_CLIENT_OBJ) tests/rb_test.o 
+       @echo Linking $@
+       @$(CC) $(CFLAGS) -o $@ tests/rb_test.o $(CTDB_CLIENT_OBJ) $(LIB_FLAGS)
+
 bin/ctdb_bench: $(CTDB_CLIENT_OBJ) tests/ctdb_bench.o 
        @echo Linking $@
        @$(CC) $(CFLAGS) -o $@ tests/ctdb_bench.o $(CTDB_CLIENT_OBJ) $(LIB_FLAGS)
index 57b0a86ab09d824a2e87b05dc94e311eb17cd47d..5139560ae29a5d1fbda3e34e8567d194b22aa3e3 100644 (file)
@@ -90,7 +90,7 @@ trbt_rotate_left(trbt_node_t *node)
                        node->parent->right=node->right;
                }
        } else {
-               tree->tree=node->right;
+               tree->root=node->right;
        }
        node->right->parent=node->parent;
        node->parent=node->right;
@@ -113,7 +113,7 @@ trbt_rotate_right(trbt_node_t *node)
                        node->parent->right=node->left;
                }
        } else {
-               tree->tree=node->left;
+               tree->root=node->left;
        }
        node->left->parent=node->parent;
        node->parent=node->left;
@@ -470,7 +470,7 @@ delete_node(trbt_node_t *node)
                        parent->right = child;
                }
        } else {
-               node->tree->tree = child;
+               node->tree->root = child;
        }
        child->parent = node->parent;
 
@@ -497,7 +497,7 @@ delete_node(trbt_node_t *node)
         */
        if (child == &dc) {
                if (child->parent == NULL) {
-                       node->tree->tree = NULL;
+                       node->tree->root = NULL;
                } else if (child == child->parent->left) {
                        child->parent->left = NULL;
                } else {
@@ -538,13 +538,13 @@ trbt_insert32(trbt_tree_t *tree, uint32_t key, void *data)
 {
        trbt_node_t *node;
 
-       node=tree->tree;
+       node=tree->root;
 
        /* is this the first node ?*/
        if(!node){
                node = trbt_create_node(tree, NULL, key, data);
 
-               tree->tree=node;
+               tree->root=node;
                return NULL;
        }
 
@@ -603,7 +603,7 @@ trbt_lookup32(trbt_tree_t *tree, uint32_t key)
 {
        trbt_node_t *node;
 
-       node=tree->tree;
+       node=tree->root;
 
        while(node){
                if(key==node->key32){
@@ -626,7 +626,7 @@ trbt_delete32(trbt_tree_t *tree, uint32_t key)
 {
        trbt_node_t *node;
 
-       node=tree->tree;
+       node=tree->root;
 
        while(node){
                if(key==node->key32){
@@ -645,6 +645,73 @@ trbt_delete32(trbt_tree_t *tree, uint32_t key)
 }
 
 
+void 
+trbt_insert32_callback(trbt_tree_t *tree, uint32_t key, void *(*callback)(void *param, void *data), void *param)
+{
+       trbt_node_t *node;
+
+       node=tree->root;
+
+       /* is this the first node ?*/
+       if(!node){
+               node = trbt_create_node(tree, NULL, key, 
+                               callback(param, NULL));
+
+               tree->root=node;
+               return;
+       }
+
+       /* it was not the new root so walk the tree until we find where to
+        * insert this new leaf.
+        */
+       while(1){
+               /* this node already exists, replace data and return the 
+                  old data
+                */
+               if(key==node->key32){
+                       node->data  = talloc_steal(node, 
+                                       callback(param, node->data));
+
+                       return;
+               }
+               if(key<node->key32) {
+                       if(!node->left){
+                               /* new node to the left */
+                               trbt_node_t *new_node;
+
+                               new_node = trbt_create_node(tree, node, key,
+                                               callback(param, NULL));
+                               node->left=new_node;
+                               node=new_node;
+
+                               break;
+                       }
+                       node=node->left;
+                       continue;
+               }
+               if(key>node->key32) {
+                       if(!node->right){
+                               /* new node to the right */
+                               trbt_node_t *new_node;
+
+                               new_node = trbt_create_node(tree, node, key,
+                                               callback(param, NULL));
+                               node->right=new_node;
+                               node=new_node;
+                               break;
+                       }
+                       node=node->right;
+                       continue;
+               }
+       }
+
+       /* node will now point to the newly created node */
+       node->rb_color=TRBT_RED;
+       trbt_insert_case1(tree, node);
+       return;
+}
+
+
 
 # if 0
 static void printtree(trbt_node_t *node, int levels)
index 603ebfad34bea54603c82adaeb2379e6aa99ee42..ad095dd50ff0ee22e80786afcc44015376a17bdd 100644 (file)
@@ -32,7 +32,7 @@ typedef struct _trbt_node_t {
 } trbt_node_t;
 
 typedef struct _trbt_tree_t {
-       trbt_node_t *tree;
+       trbt_node_t *root;
 } trbt_tree_t;
 
 
@@ -49,7 +49,17 @@ void *trbt_lookup32(trbt_tree_t *tree, uint32_t key);
 */
 void *trbt_insert32(trbt_tree_t *tree, uint32_t key, void *data);
 
+/* Insert a new node into the tree.
+   If this is a new node:
+     callback is called with data==NULL and param=param
+     the returned value from the callback is talloc_stolen and inserted in the
+     tree.
+   If a node already exists for this key then:
+     callback is called with data==existing data and param=param
+     the returned calue is talloc_stolen and inserted in the tree
+*/
+void trbt_insert32_callback(trbt_tree_t *tree, uint32_t key, void *(*callback)(void *param, void *data), void *param);
+
 /* Delete a node from the tree and free all data associated with it */
 void trbt_delete32(trbt_tree_t *tree, uint32_t key);
 
-
diff --git a/ctdb/tests/rb_test.c b/ctdb/tests/rb_test.c
new file mode 100644 (file)
index 0000000..b1c62a3
--- /dev/null
@@ -0,0 +1,108 @@
+/* 
+   simple rb test tool
+
+   Copyright (C) Ronnie Sahlberg 2007
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/events/events.h"
+#include "lib/util/dlinklist.h"
+#include "system/filesys.h"
+#include "popt.h"
+#include "cmdline.h"
+
+#include <sys/time.h>
+#include <time.h>
+#include "common/rb_tree.h"
+
+int num_records;
+
+void *callback(void *param, void *d)
+{
+       uint32_t *data = (uint32_t *)d;
+
+       if(!data){
+               data = talloc(NULL, uint32_t);
+               *data = 0;
+       }
+       (*data)++;
+
+       return data;
+}
+       
+                               
+/*
+  main program
+*/
+int main(int argc, const char *argv[])
+{
+       struct poptOption popt_options[] = {
+               POPT_AUTOHELP
+               POPT_CTDB_CMDLINE
+               { "num-records", 'r', POPT_ARG_INT, &num_records, 0, "num_records", "integer" },
+               POPT_TABLEEND
+       };
+       int opt;
+       const char **extra_argv;
+       int extra_argc = 0;
+       poptContext pc;
+       struct event_context *ev;
+       int i;
+       trbt_tree_t *tree;
+
+       pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
+
+       while ((opt = poptGetNextOpt(pc)) != -1) {
+               switch (opt) {
+               default:
+                       fprintf(stderr, "Invalid option %s: %s\n", 
+                               poptBadOption(pc, 0), poptStrerror(opt));
+                       exit(1);
+               }
+       }
+
+       /* setup the remaining options for the main program to use */
+       extra_argv = poptGetArgs(pc);
+       if (extra_argv) {
+               extra_argv++;
+               while (extra_argv[extra_argc]) extra_argc++;
+       }
+
+       ev = event_context_init(NULL);
+
+
+       printf("testing trbt_insert32_callback for %d records\n", num_records);
+       tree = trbt_create(NULL);
+       for (i=0; i<num_records; i++) {
+               trbt_insert32_callback(tree, i, callback, NULL);
+       }
+       for (i=3; i<num_records; i++) {
+               trbt_insert32_callback(tree, i, callback, NULL);
+       }
+
+       printf("first 3 keys should have data==1\n");
+       printf("the rest of the keys should have data==2\n");
+       for (i=0; i<num_records; i++) {
+               uint32_t *data;
+
+               data = trbt_lookup32(tree, i);
+               printf("key:%d data:%d\n", i, *data);
+       }
+
+
+
+       return 0;
+}