diff options
Diffstat (limited to 'mysys/tree.c')
-rw-r--r-- | mysys/tree.c | 68 |
1 files changed, 53 insertions, 15 deletions
diff --git a/mysys/tree.c b/mysys/tree.c index ccf0aa05509..8cae30e2d3e 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -66,7 +66,7 @@ #define DEFAULT_ALLOC_SIZE 8192 #define DEFAULT_ALIGN_SIZE 8192 -static void delete_tree_element(TREE *,TREE_ELEMENT *); +static int delete_tree_element(TREE *,TREE_ELEMENT *, my_bool abort); static int tree_walk_left_root_right(TREE *,TREE_ELEMENT *, tree_walk_action,void *); static int tree_walk_right_root_left(TREE *,TREE_ELEMENT *, @@ -128,28 +128,37 @@ void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit, } if (!(tree->with_delete= MY_TEST(my_flags & MY_TREE_WITH_DELETE))) { - init_alloc_root(&tree->mem_root, default_alloc_size, 0, MYF(my_flags)); + init_alloc_root(&tree->mem_root, "tree", default_alloc_size, 0, + MYF(my_flags)); tree->mem_root.min_malloc= sizeof(TREE_ELEMENT)+tree->size_of_element; } DBUG_VOID_RETURN; } -static void free_tree(TREE *tree, myf free_flags) +static int free_tree(TREE *tree, my_bool abort, myf free_flags) { + int error, first_error= 0; DBUG_ENTER("free_tree"); DBUG_PRINT("enter",("tree: %p", tree)); if (tree->root) /* If initialized */ { if (tree->with_delete) - delete_tree_element(tree,tree->root); + { + if ((error= delete_tree_element(tree, tree->root, abort))) + { + first_error= first_error ? first_error : error; + abort= 1; + } + } else { if (tree->free) { if (tree->memory_limit) (*tree->free)(NULL, free_init, tree->custom_arg); - delete_tree_element(tree,tree->root); + if ((error= delete_tree_element(tree, tree->root, abort))) + first_error= first_error ? first_error : error; if (tree->memory_limit) (*tree->free)(NULL, free_end, tree->custom_arg); } @@ -160,32 +169,61 @@ static void free_tree(TREE *tree, myf free_flags) tree->elements_in_tree=0; tree->allocated=0; - DBUG_VOID_RETURN; + DBUG_RETURN(first_error); } -void delete_tree(TREE* tree) + +/** + Delete tree. + + @param tree Tree + @param abort 0 if normal, 1 if tree->free should not be called. + + @return 0 ok + <> 0 Returns first <> 0 from (tree->free)(*,free_free,*) + + @Notes + If one (tree->free)(,free_free,) returns <> 0, no future + tree->free(*,free_free,*) will be called. + Other tree->free operations (free_init, free_end) will be called +*/ + + +int delete_tree(TREE* tree, my_bool abort) { - free_tree(tree, MYF(0)); /* my_free() mem_root if applicable */ + return free_tree(tree, abort, MYF(0)); /* my_free() mem_root if applicable */ } -void reset_tree(TREE* tree) +int reset_tree(TREE* tree) { /* do not free mem_root, just mark blocks as free */ - free_tree(tree, MYF(MY_MARK_BLOCKS_FREE)); + return free_tree(tree, 0, MYF(MY_MARK_BLOCKS_FREE)); } -static void delete_tree_element(TREE *tree, TREE_ELEMENT *element) +static int delete_tree_element(TREE *tree, TREE_ELEMENT *element, + my_bool abort) { + int error, first_error= 0; if (element != &null_element) { - delete_tree_element(tree,element->left); - if (tree->free) - (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); - delete_tree_element(tree,element->right); + if ((first_error= delete_tree_element(tree, element->left, abort))) + abort= 1; + if (!abort && tree->free) + { + if ((error= (*tree->free)(ELEMENT_KEY(tree,element), free_free, + tree->custom_arg))) + { + first_error= first_error ? first_error : error; + abort= 1; + } + } + if ((error= delete_tree_element(tree, element->right, abort))) + first_error= first_error ? first_error : error; if (tree->with_delete) my_free(element); } + return first_error; } |