/* traverse a tree starting at node */
-static void
+static int
trbt_traversearray32_node(trbt_node_t *node, uint32_t keylen,
- void (*callback)(void *param, void *data),
+ int (*callback)(void *param, void *data),
void *param)
{
if (node->left) {
- trbt_traversearray32_node(node->left, keylen, callback, param);
+ int ret;
+ ret = trbt_traversearray32_node(node->left, keylen, callback, param);
+ if (ret != 0) {
+ return ret;
+ }
}
/* this is the smallest node in this subtree
otherwise we must pull the next subtree and traverse that one as well
*/
if (keylen == 0) {
- callback(param, node->data);
+ int ret;
+
+ ret = callback(param, node->data);
+ if (ret != 0) {
+ return ret;
+ }
} else {
- trbt_traversearray32(node->data, keylen, callback, param);
+ int ret;
+
+ ret = trbt_traversearray32(node->data, keylen, callback, param);
+ if (ret != 0) {
+ return ret;
+ }
}
if (node->right) {
- trbt_traversearray32_node(node->right, keylen, callback, param);
+ int ret;
+
+ ret = trbt_traversearray32_node(node->right, keylen, callback, param);
+ if (ret != 0) {
+ return ret;
+ }
}
+
+ return 0;
}
/* traverse the tree using an array of uint32 as a key */
-void
+int
trbt_traversearray32(trbt_tree_t *tree, uint32_t keylen,
- void (*callback)(void *param, void *data),
+ int (*callback)(void *param, void *data),
void *param)
{
trbt_node_t *node;
if (tree == NULL) {
- return;
+ return 0;
}
node=tree->root;
if (node == NULL) {
- return;
+ return 0;
}
- trbt_traversearray32_node(node, keylen-1, callback, param);
+ return trbt_traversearray32_node(node, keylen-1, callback, param);
}
}
-#if 0
+#if TEST_RB_TREE
static void printtree(trbt_node_t *node, int levels)
{
int i;
printtree(node->left, levels+1);
for(i=0;i<levels;i++)printf(" ");
- printf("key:%d COLOR:%s (node:0x%08x parent:0x%08x left:0x%08x right:0x%08x)\n",node->key32,node->rb_color==TRBT_BLACK?"BLACK":"RED",(int)node,(int)node->parent, (int)node->left,(int)node->right);
+ printf("key:%d COLOR:%s (node:%p parent:%p left:%p right:%p)\n",node->key32,node->rb_color==TRBT_BLACK?"BLACK":"RED", node, node->parent, node->left, node->right);
printtree(node->right, levels+1);
printf("\n");
}
printf("---\n");
printtree(tree->root->left, 1);
- printf("root node key:%d COLOR:%s (node:0x%08x left:0x%08x right:0x%08x)\n",tree->root->key32,tree->root->rb_color==TRBT_BLACK?"BLACK":"RED",(int)tree->root,(int)tree->root->left,(int)tree->root->right);
+ printf("root node key:%d COLOR:%s (node:%p left:%p right:%p)\n",tree->root->key32,tree->root->rb_color==TRBT_BLACK?"BLACK":"RED", tree->root, tree->root->left, tree->root->right);
printtree(tree->root->right, 1);
printf("===\n");
}
-#endif
-# if 0
void
test_tree(void)
{
int NUM=15;
int cnt=0;
- tree=trbt_create(talloc_new(NULL));
+ tree=trbt_create(talloc_new(NULL), 0);
#if 0
for(i=0;i<10;i++){
printf("adding node %i\n",i);
and return a pointer to data or NULL */
void *trbt_lookuparray32(trbt_tree_t *tree, uint32_t keylen, uint32_t *key);
-/* Traverse a tree with a key based on an array of uint32 */
-void trbt_traversearray32(trbt_tree_t *tree, uint32_t keylen, void (*callback)(void *param, void *data), void *param);
+/* Traverse a tree with a key based on an array of uint32
+ returns 0 if traverse completed
+ !0 if the traverse was aborted
+
+ If the callback returns !0 the traverse will be aborted
+*/
+int trbt_traversearray32(trbt_tree_t *tree, uint32_t keylen, int (*callback)(void *param, void *data), void *param);
/* Lookup the first node in the tree with a key based on an array of uint32
and return a pointer to data or NULL */
struct ctdb_server_id_list *list;
};
-static void server_id_count(void *param, void *data)
+static int server_id_count(void *param, void *data)
{
struct count_server_ids *svid = talloc_get_type(param,
struct count_server_ids);
if (svid == NULL) {
DEBUG(DEBUG_ERR, (__location__ " Got null pointer for svid\n"));
- return;
+ return -1;
}
svid->count++;
+ return 0;
}
-static void server_id_store(void *param, void *data)
+static int server_id_store(void *param, void *data)
{
struct count_server_ids *svid = talloc_get_type(param,
struct count_server_ids);
if (svid == NULL) {
DEBUG(DEBUG_ERR, (__location__ " Got null pointer for svid\n"));
- return;
+ return -1;
}
if (svid->count >= svid->list->num) {
DEBUG(DEBUG_ERR, (__location__ " size of server id tree changed during traverse\n"));
- return;
+ return -1;
}
memcpy(&svid->list->server_ids[svid->count], server_id, sizeof(struct ctdb_server_id));
svid->count++;
+ return 0;
}
/*
return parm;
}
-void getips_count_callback(void *param, void *data)
+static int getips_count_callback(void *param, void *data)
{
struct ctdb_public_ip_list **ip_list = (struct ctdb_public_ip_list **)param;
struct ctdb_public_ip_list *new_ip = (struct ctdb_public_ip_list *)data;
new_ip->next = *ip_list;
*ip_list = new_ip;
+ return 0;
}
static struct ctdb_public_ip_list *
by a RST)
this callback is called for each connection we are currently trying to kill
*/
-static void tickle_connection_traverse(void *param, void *data)
+static int tickle_connection_traverse(void *param, void *data)
{
struct ctdb_killtcp_con *con = talloc_get_type(data, struct ctdb_killtcp_con);
if (con->count >= 5) {
/* can't delete in traverse: reparent to delete_cons */
talloc_steal(param, con);
- return;
+ return 0;
}
/* othervise, try tickling it again */
(ctdb_sock_addr *)&con->dst_addr,
(ctdb_sock_addr *)&con->src_addr,
0, 0, 0);
+ return 0;
}
* traverse the tree of records to delete and marshall them into
* a blob
*/
-static void delete_traverse(void *param, void *data)
+static int delete_traverse(void *param, void *data)
{
struct delete_record_data *dd = talloc_get_type(data, struct delete_record_data);
struct delete_records_list *recs = talloc_get_type(param, struct delete_records_list);
rec = ctdb_marshall_record(dd, recs->records->db_id, dd->key, &dd->hdr, tdb_null);
if (rec == NULL) {
DEBUG(DEBUG_ERR, (__location__ " failed to marshall record\n"));
- return;
+ return 0;
}
old_size = talloc_get_size(recs->records);
recs->records = talloc_realloc_size(NULL, recs->records, old_size + rec->length);
if (recs->records == NULL) {
DEBUG(DEBUG_ERR,(__location__ " Failed to expand\n"));
- return;
+ return 0;
}
recs->records->count++;
memcpy(old_size+(uint8_t *)(recs->records), rec, rec->length);
+ return 0;
}
/**
* add it to the list of records that are to be sent to
* the lmaster with the VACUUM_FETCH message.
*/
-static void delete_queue_traverse(void *param, void *data)
+static int delete_queue_traverse(void *param, void *data)
{
struct delete_record_data *dd =
talloc_get_type(data, struct delete_record_data);
if (res != 0) {
DEBUG(DEBUG_ERR, (__location__ " Error getting chainlock.\n"));
vdata->fast_error++;
- return;
+ return 0;
}
tdb_data = tdb_fetch(ctdb_db->ltdb->tdb, dd->key);
}
tdb_chainunlock(ctdb_db->ltdb->tdb, dd->key);
- return;
+ return 0;
}
/*
return p;
}
-void traverse(void *p, void *d)
+int traverse(void *p, void *d)
{
uint32_t *data = (uint32_t *)d;
printf("traverse data:%d\n",*data);
+ return 0;
}
-void random_traverse(void *p, void *d)
+int random_traverse(void *p, void *d)
{
printf("%s ",(char *)d);
+ return 0;
}
static uint32_t calc_checksum = 0;
-void traverse_checksum(void *p, void *d)
+int traverse_checksum(void *p, void *d)
{
int i,j,k;
sscanf(d, "%d.%d.%d", &i, &j, &k);
calc_checksum += i*100+j*10+k;
+ return 0;
+}
+
+int count_traverse(void *p, void *d)
+{
+ int *count = p;
+ (*count)++;
+ return 0;
}
-
+
+int count_traverse_abort(void *p, void *d)
+{
+ int *count = p;
+ (*count)++;
+ return -1;
+}
+
/*
main program
*/
{ "num-records", 'r', POPT_ARG_INT, &num_records, 0, "num_records", "integer" },
POPT_TABLEEND
};
- int opt;
+ int opt, traverse_count;
const char **extra_argv;
int extra_argc = 0;
poptContext pc;
printf("\n");
printf("first node: %s\n", (char *)trbt_findfirstarray32(tree, 3));
+ traverse_count = 0;
+ trbt_traversearray32(tree, 3, count_traverse, &traverse_count);
+ printf("\n");
+ printf("number of entries in traverse %d\n", traverse_count);
+ traverse_count = 0;
+ trbt_traversearray32(tree, 3, count_traverse_abort, &traverse_count);
+ printf("\n");
+ printf("number of entries in aborted traverse %d\n", traverse_count);
+ if (traverse_count != 1) {
+ printf("Failed to abort the traverse. Should have been aborted after 1 element but did iterate over %d elements\n", traverse_count);
+ exit(10);
+ }
printf("\ndeleting all entries\n");
for(i=0;i<10;i++){
for(j=0;j<10;j++){
return 0;
}
-void getips_store_callback(void *param, void *data)
+static int getips_store_callback(void *param, void *data)
{
struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
struct ctdb_all_public_ips *ips = param;
i = ips->num++;
ips->ips[i].pnn = node_ip->pnn;
ips->ips[i].addr = node_ip->addr;
+ return 0;
}
-void getips_count_callback(void *param, void *data)
+static int getips_count_callback(void *param, void *data)
{
uint32_t *count = param;
(*count)++;
+ return 0;
}
#define IP_KEYLEN 4
traverse the tree of records to delete and marshall them into
a blob
*/
-static void
+static int
delete_traverse(void *param, void *data)
{
struct delete_record_data *dd = talloc_get_type(data, struct delete_record_data);
rec = ctdb_marshall_record(dd, recs->records->db_id, dd->key, &dd->hdr, tdb_null);
if (rec == NULL) {
DEBUG(DEBUG_ERR, (__location__ " failed to marshall record\n"));
- return;
+ return 0;
}
old_size = talloc_get_size(recs->records);
recs->records = talloc_realloc_size(NULL, recs->records, old_size + rec->length);
if (recs->records == NULL) {
DEBUG(DEBUG_ERR,(__location__ " Failed to expand\n"));
- return;
+ return 0;
}
recs->records->count++;
memcpy(old_size+(uint8_t *)(recs->records), rec, rec->length);
+ return 0;
}
-static void delete_record(void *param, void *d)
+static int delete_record(void *param, void *d)
{
struct delete_record_data *dd = talloc_get_type(d, struct delete_record_data);
struct ctdb_context *ctdb = dd->ctdb;
/* its deleted on all other nodes - refetch, check and delete */
if (tdb_chainlock_nonblock(ctdb_db->ltdb->tdb, dd->key) != 0) {
/* the chain is busy - come back later */
- return;
+ return 0;
}
data = tdb_fetch(ctdb_db->ltdb->tdb, dd->key);
if (data.dptr == NULL) {
tdb_chainunlock(ctdb_db->ltdb->tdb, dd->key);
- return;
+ return 0;
}
if (data.dsize != sizeof(struct ctdb_ltdb_header)) {
free(data.dptr);
tdb_chainunlock(ctdb_db->ltdb->tdb, dd->key);
- return;
+ return 0;
}
hdr = (struct ctdb_ltdb_header *)data.dptr;
dd->hdr.rsn != hdr->rsn) {
tdb_chainunlock(ctdb_db->ltdb->tdb, dd->key);
free(data.dptr);
- return;
+ return 0;
}
ctdb_block_signal(SIGALRM);
free(data.dptr);
(*count)++;
+ return 0;
}
/* vacuum one database */