diff options
author | Monty <monty@mariadb.org> | 2017-05-17 00:34:48 +0300 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2017-05-17 00:34:48 +0300 |
commit | 6378c95ee07cccc2f2187b2caddc4496e14827d9 (patch) | |
tree | 1e7b9066e15288e3471f0c800e5dda820d3d0daf /mysys/tree.c | |
parent | 314350a722e65081472113c53657ad239f3bef72 (diff) | |
download | mariadb-git-6378c95ee07cccc2f2187b2caddc4496e14827d9.tar.gz |
Fix that end_bulk_insert() doesn't write to to-be-deleted files
This affected mainly MyISAM and Aria engines.
Also fixed that end_bulk_insert() detects errors from
internal mi_end_bulk_insert() and ma_end_bulk_insert()
- delete_tree() and delete_tree_element() now has an
extra argument that marks if future calls to
tree->free should be ignored.
- tree->free changed to function returning int, to be
able to signal errors.
- Restored deleting flag in MyISAM that was accidently
disabled in mi_extra(PREPARE_FOR_DROP)
Diffstat (limited to 'mysys/tree.c')
-rw-r--r-- | mysys/tree.c | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/mysys/tree.c b/mysys/tree.c index 5eaeb30037d..e106dd43c00 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 *, @@ -136,22 +136,30 @@ void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit, 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: 0x%lx", (long) 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); } @@ -162,32 +170,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 != &tree->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; } |