From c9dce03295b66b081f60e4f076be3cd1c0a45fd6 Mon Sep 17 00:00:00 2001 From: Celine Mercier Date: Mon, 5 Sep 2016 12:29:52 +0200 Subject: [PATCH] Fixed major bug when cloning an AVL group (last AVL of new group was not correctly enlarged before copying the data) + minor improvements --- src/obiavl.c | 52 +++++++++++++++++++++++++++++++++++++++++----------- src/obiavl.h | 5 ++++- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/obiavl.c b/src/obiavl.c index 8c68ae3..8874687 100644 --- a/src/obiavl.c +++ b/src/obiavl.c @@ -790,7 +790,7 @@ int truncate_avl_to_size_used(OBIDMS_avl_p avl) // TODO is it necessary to unmap // Set new data size and new max node count (avl->header)->avl_size = new_data_size; - (avl->header)->nb_items_max = floor(new_data_size / sizeof(AVL_node_t)); + (avl->header)->nb_items_max = (index_t) floor(((double) (avl->header)->avl_size) / ((double) sizeof(AVL_node_t))); return 0; } @@ -905,12 +905,12 @@ int grow_avl(OBIDMS_avl_p avl) // TODO Lock when needed return -1; } - // Set new maximum number of items - (avl->header)->nb_items_max = floor(((double) new_data_size) / ((double) sizeof(AVL_node_t))); - // Set the new avl size (avl->header)->avl_size = new_data_size; + // Set new maximum number of items + (avl->header)->nb_items_max = (index_t) floor(((double) (avl->header)->avl_size) / ((double) sizeof(AVL_node_t))); + return 0; } @@ -1012,7 +1012,7 @@ int unmap_an_avl(OBIDMS_avl_p avl) obidebug(1, "\nError unmapping the data of an AVL tree"); return -1; } - if (munmap(avl->tree, (((avl->header)->nb_items_max) * sizeof(AVL_node_t))) < 0) + if (munmap(avl->tree, (avl->header)->avl_size) < 0) { obi_set_errno(OBI_AVL_ERROR); obidebug(1, "\nError unmapping the tree of an AVL tree"); @@ -1038,7 +1038,7 @@ int remap_an_avl(OBIDMS_avl_p avl) } avl->tree = mmap(NULL, - ((avl->header)->nb_items_max) * sizeof(AVL_node_t), + (avl->header)->avl_size, PROT_READ, MAP_SHARED, avl->avl_fd, @@ -1686,7 +1686,7 @@ OBIDMS_avl_p obi_create_avl(OBIDMS_p dms, const char* avl_name, int avl_idx) (avl->header)->header_size = header_size; (avl->header)->avl_size = data_size; (avl->header)->nb_items = 0; - (avl->header)->nb_items_max = (index_t) floor(((double) get_initial_avl_size()) / ((double) sizeof(AVL_node_t))); + (avl->header)->nb_items_max = (index_t) floor(((double) (avl->header)->avl_size) / ((double) sizeof(AVL_node_t))); (avl->header)->root_idx = -1; (avl->header)->creation_date = time(NULL); strcpy((avl->header)->avl_name, complete_avl_name); @@ -1916,7 +1916,7 @@ OBIDMS_avl_p obi_open_avl(OBIDMS_p dms, const char* avl_name, int avl_idx) } avl->tree = mmap(NULL, - (((avl->header)->nb_items_max) * sizeof(AVL_node_t)), + (avl->header)->avl_size, PROT_READ, MAP_SHARED, avl_file_descriptor, @@ -2069,8 +2069,20 @@ OBIDMS_avl_group_p obi_open_avl_group(OBIDMS_p dms, const char* avl_name) } -void obi_clone_avl(OBIDMS_avl_p avl, OBIDMS_avl_p new_avl) +int obi_clone_avl(OBIDMS_avl_p avl, OBIDMS_avl_p new_avl) { + // Grow the new AVL as needed before copying + while (((new_avl->header)->nb_items_max) < ((avl->header)->nb_items)) + { + if (grow_avl(new_avl) < 0) + return -1; + } + while ((((new_avl->data)->header)->data_size_max) < (((avl->data)->header)->data_size_used)) + { + if (grow_avl_data(new_avl->data) < 0) + return -1; + } + // Clone AVL tree memcpy(new_avl->tree, avl->tree, (avl->header)->avl_size); (new_avl->header)->avl_size = (avl->header)->avl_size; @@ -2083,6 +2095,9 @@ void obi_clone_avl(OBIDMS_avl_p avl, OBIDMS_avl_p new_avl) ((new_avl->data)->header)->data_size_used = ((avl->data)->header)->data_size_used; ((new_avl->data)->header)->data_size_max = ((avl->data)->header)->data_size_max; ((new_avl->data)->header)->nb_items = ((avl->data)->header)->nb_items; + + //avl_print(new_avl); + return 0; } @@ -2093,27 +2108,42 @@ OBIDMS_avl_group_p obi_clone_avl_group(OBIDMS_avl_group_p avl_group, const char* // Create the new AVL group new_avl_group = obi_create_avl_group(avl_group->dms, new_avl_name); + if (new_avl_group == NULL) + return NULL; // Create hard links to all the full AVLs that won't be modified: all but the last one for (i=0; i<(avl_group->last_avl_idx); i++) { if (add_existing_avl_in_group(new_avl_group, avl_group, i) < 0) + { + obidebug(1, "\nError adding an existing AVL tree in a new group of AVL trees"); return NULL; + } } // Create the last AVL to copy data in it if (add_new_avl_in_group(new_avl_group) < 0) { + obidebug(1, "\nError creating a new AVL tree in a new group of AVL trees"); obi_close_avl_group(new_avl_group); return NULL; } - // Copy the data from the last AVL to a new one that can be modified - obi_clone_avl((avl_group->sub_avls)[avl_group->last_avl_idx], (new_avl_group->sub_avls)[new_avl_group->last_avl_idx]); + // Copy the data from the last AVL to the new one that can be modified + if ((((avl_group->sub_avls)[avl_group->last_avl_idx])->header)->nb_items > 0) + { + if (obi_clone_avl((avl_group->sub_avls)[avl_group->last_avl_idx], (new_avl_group->sub_avls)[new_avl_group->last_avl_idx]) < 0) + { + obidebug(1, "\nError copying an AVL tree in a new group of AVL trees"); + obi_close_avl_group(new_avl_group); + return NULL; + } + } // Close old AVL group if (obi_close_avl_group(avl_group) < 0) { + obidebug(1, "\nError closing a group of AVL trees after cloning it to make a new group"); obi_close_avl_group(new_avl_group); return NULL; } diff --git a/src/obiavl.h b/src/obiavl.h index e3655f1..3fa0f29 100644 --- a/src/obiavl.h +++ b/src/obiavl.h @@ -298,10 +298,13 @@ OBIDMS_avl_group_p obi_open_avl_group(OBIDMS_p dms, const char* avl_name); * @param avl A pointer on the AVL to clone. * @param new_avl A pointer on the new AVL to fill. * + * @retval 0 if the operation was successfully completed. + * @retval -1 if an error occurred. + * * @since May 2016 * @author Celine Mercier (celine.mercier@metabarcoding.org) */ -void obi_clone_avl(OBIDMS_avl_p avl, OBIDMS_avl_p new_avl); +int obi_clone_avl(OBIDMS_avl_p avl, OBIDMS_avl_p new_avl); /**