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:
parent
26d3cd38a9
commit
c1bfda5772
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
108
ctdb/tests/rb_test.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user