1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

add a tree insert function that takes a callback fucntion to populate

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)
This commit is contained in:
Ronnie Sahlberg 2007-08-08 11:21:18 +10:00
parent 26d3cd38a9
commit c1bfda5772
4 changed files with 202 additions and 11 deletions

View 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)

View 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)

View 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);

108
ctdb/tests/rb_test.c Normal file
View File

@ -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;
}