summaryrefslogtreecommitdiff
path: root/mysys/tree.c
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2017-05-17 00:34:48 +0300
committerMonty <monty@mariadb.org>2017-05-17 00:34:48 +0300
commit6378c95ee07cccc2f2187b2caddc4496e14827d9 (patch)
tree1e7b9066e15288e3471f0c800e5dda820d3d0daf /mysys/tree.c
parent314350a722e65081472113c53657ad239f3bef72 (diff)
downloadmariadb-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.c65
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;
}