diff --git a/src/obiavl.c b/src/obiavl.c index 23c1c7c..5b786d1 100644 --- a/src/obiavl.c +++ b/src/obiavl.c @@ -923,7 +923,7 @@ int remap_an_avl(OBIDMS_avl_p avl) int add_new_avl_in_group(OBIDMS_avl_group_p avl_group) { // Check that maximum number of AVLs in a group was not reached - if (avl_group->current_avl_idx == (MAX_NB_OF_AVLS_IN_GROUP-1)) + if (avl_group->last_avl_idx == (MAX_NB_OF_AVLS_IN_GROUP - 1)) { obi_set_errno(OBI_AVL_ERROR); obidebug(1, "\nError: Trying to add new AVL in AVL group but maximum number of AVLs in a group reached"); @@ -931,15 +931,15 @@ int add_new_avl_in_group(OBIDMS_avl_group_p avl_group) } // Unmap the previous AVL - if (unmap_an_avl((avl_group->sub_avls)[avl_group->current_avl_idx]) < 0) + if (unmap_an_avl((avl_group->sub_avls)[avl_group->last_avl_idx]) < 0) return -1; // Increment current AVL index - (avl_group->current_avl_idx)++; + (avl_group->last_avl_idx)++; // Create the new AVL - (avl_group->sub_avls)[avl_group->current_avl_idx] = obi_create_avl(avl_group->dms, avl_group->name, avl_group->current_avl_idx); - if ((avl_group->sub_avls)[avl_group->current_avl_idx] == NULL) + (avl_group->sub_avls)[avl_group->last_avl_idx] = obi_create_avl(avl_group->dms, avl_group->name, avl_group->last_avl_idx); + if ((avl_group->sub_avls)[avl_group->last_avl_idx] == NULL) { obidebug(1, "\nError creating a new AVL tree in a group"); return -1; @@ -1823,7 +1823,7 @@ OBIDMS_avl_group_p obi_create_avl_group(OBIDMS_p dms, const char* avl_name) return NULL; } - avl_group->current_avl_idx = 0; + avl_group->last_avl_idx = 0; strcpy(avl_group->name, avl_name); avl_group->dms = dms; @@ -1845,7 +1845,7 @@ OBIDMS_avl_group_p obi_open_avl_group(OBIDMS_p dms, const char* avl_name) { OBIDMS_avl_group_p avl_group; char* avl_dir_name; - int avl_count; + int last_avl_idx; int i; // Check if the group isn't already open @@ -1869,21 +1869,21 @@ OBIDMS_avl_group_p obi_open_avl_group(OBIDMS_p dms, const char* avl_name) avl_dir_name = get_full_path_of_avl_dir(dms, avl_name); if (avl_dir_name == NULL) return NULL; - avl_count = count_dir(avl_dir_name) / 2; - if (avl_count < 0) + last_avl_idx = count_dir(avl_dir_name) / 2; + if (last_avl_idx < 0) { obidebug(1, "\nError counting the AVLs in an AVL directory: %s", avl_name); return NULL; } // Open the AVLs - for (i=0; isub_avls)[i] = obi_open_avl(dms, avl_name, i); if ((avl_group->sub_avls)[i] == NULL) return NULL; } - avl_group->current_avl_idx = avl_count-1; // TODO latest. discuss + avl_group->last_avl_idx = last_avl_idx-1; // TODO latest. discuss strcpy(avl_group->name, avl_name); avl_group->dms = dms; @@ -1901,6 +1901,56 @@ 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) +{ + // Clone AVL tree + memcpy(new_avl->tree, avl->tree, (avl->header)->avl_size); + (new_avl->header)->avl_size = (avl->header)->avl_size; + (new_avl->header)->nb_items = (avl->header)->nb_items; + (new_avl->header)->root_idx = (avl->header)->root_idx; + (new_avl->header)->bloom_filter = (avl->header)->bloom_filter; + + // Clone AVL data + memcpy((new_avl->data)->data, (avl->data)->data, ((avl->data)->header)->data_size_used); + ((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; +} + + +OBIDMS_avl_group_p obi_clone_avl_group(OBIDMS_avl_group_p avl_group, const char* new_avl_name) +{ + OBIDMS_avl_group_p new_avl_group; + int i; + + // Create the new AVL group + new_avl_group = obi_create_avl_group(avl_group->dms, new_avl_name); + + // Copy the data from each old AVL to the new ones + for (i=0; i<=(avl_group->last_avl_idx); i++) + { + if (i > 0) // Don't need to create the 1st AVL + { + if (add_new_avl_in_group(new_avl_group) < 0) + { + obi_close_avl_group(new_avl_group); + return NULL; + } + } + obi_clone_avl((avl_group->sub_avls)[i], (new_avl_group->sub_avls)[i]); + } + + // Close old AVL group + if (obi_close_avl_group(avl_group) < 0) + { + obi_close_avl_group(new_avl_group); + return NULL; + } + + return new_avl_group; +} + + int obi_close_avl(OBIDMS_avl_p avl) { int ret_val = 0; @@ -1946,7 +1996,7 @@ int obi_close_avl_group(OBIDMS_avl_group_p avl_group) ret_val = obi_dms_unlist_indexer(avl_group->dms, avl_group); // Close each AVL of the group - for (i=0; i < (avl_group->current_avl_idx); i++) + for (i=0; i < (avl_group->last_avl_idx); i++) if (obi_close_avl((avl_group->sub_avls)[i]) < 0) ret_val = -1; @@ -2157,18 +2207,18 @@ index_t obi_avl_group_add(OBIDMS_avl_group_p avl_group, Obi_blob_p value) index_t index_with_avl; int i; - if (maybe_in_avl((avl_group->sub_avls)[avl_group->current_avl_idx], value)) + if (maybe_in_avl((avl_group->sub_avls)[avl_group->last_avl_idx], value)) { - index_in_avl = (int32_t) obi_avl_find((avl_group->sub_avls)[avl_group->current_avl_idx], value); + index_in_avl = (int32_t) obi_avl_find((avl_group->sub_avls)[avl_group->last_avl_idx], value); if (index_in_avl >= 0) { - index_with_avl = avl_group->current_avl_idx; + index_with_avl = avl_group->last_avl_idx; index_with_avl = index_with_avl << 32; index_with_avl = index_with_avl + index_in_avl; return index_with_avl; } } - for (i=0; i < (avl_group->current_avl_idx); i++) + for (i=0; i < (avl_group->last_avl_idx); i++) { if (maybe_in_avl((avl_group->sub_avls)[i], value)) { @@ -2192,24 +2242,23 @@ index_t obi_avl_group_add(OBIDMS_avl_group_p avl_group, Obi_blob_p value) // Check if the AVL group is writable if (!(avl_group->writable)) { - obi_set_errno(OBI_AVL_ERROR); - obidebug(1, "\nTrying to add a value in an AVL group that is read-only."); + obi_set_errno(OBI_READ_ONLY_INDEXER_ERROR); return -1; } // Check if need to make new AVL - if (((((avl_group->sub_avls)[avl_group->current_avl_idx])->header)->nb_items == MAX_NODE_COUNT_PER_AVL) || (((((avl_group->sub_avls)[avl_group->current_avl_idx])->data)->header)->data_size_used >= MAX_DATA_SIZE_PER_AVL)) + if (((((avl_group->sub_avls)[avl_group->last_avl_idx])->header)->nb_items == MAX_NODE_COUNT_PER_AVL) || (((((avl_group->sub_avls)[avl_group->last_avl_idx])->data)->header)->data_size_used >= MAX_DATA_SIZE_PER_AVL)) { if (add_new_avl_in_group(avl_group) < 0) return -1; } // Add in the current AVL - bloom_add(&((((avl_group->sub_avls)[avl_group->current_avl_idx])->header)->bloom_filter), value, obi_blob_sizeof(value)); - index_in_avl = (int32_t) obi_avl_add((avl_group->sub_avls)[avl_group->current_avl_idx], value); + bloom_add(&((((avl_group->sub_avls)[avl_group->last_avl_idx])->header)->bloom_filter), value, obi_blob_sizeof(value)); + index_in_avl = (int32_t) obi_avl_add((avl_group->sub_avls)[avl_group->last_avl_idx], value); // Build the index containing the AVL index - index_with_avl = avl_group->current_avl_idx; + index_with_avl = avl_group->last_avl_idx; index_with_avl = index_with_avl << 32; index_with_avl = index_with_avl + index_in_avl; diff --git a/src/obiavl.h b/src/obiavl.h index aeb25d3..6b05d4e 100644 --- a/src/obiavl.h +++ b/src/obiavl.h @@ -160,7 +160,7 @@ typedef struct OBIDMS_avl { typedef struct OBIDMS_avl_group { OBIDMS_avl_p sub_avls[MAX_NB_OF_AVLS_IN_GROUP]; /**< Array containing the pointers to the AVL trees of the group. */ - int current_avl_idx; /**< Index in the sub_avls array of the AVL tree currently being filled. + int last_avl_idx; /**< Index in the sub_avls array of the AVL tree currently being filled. */ char name[AVL_MAX_NAME+1]; /**< Base name of the AVL group. The AVL trees in it have names of the form basename_idx. */ @@ -290,6 +290,37 @@ OBIDMS_avl_group_p obi_create_avl_group(OBIDMS_p dms, const char* avl_name); OBIDMS_avl_group_p obi_open_avl_group(OBIDMS_p dms, const char* avl_name); +/** + * @brief Clones an AVL. + * + * The tree and the data are both cloned into the new AVL. + * + * @param avl A pointer on the AVL to clone. + * @param new_avl A pointer on the new AVL to fill. + * + * @since May 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +void obi_clone_avl(OBIDMS_avl_p avl, OBIDMS_avl_p new_avl); + + +/** + * @brief Clones an AVL group. + * + * @warning The AVL group that has be cloned is closed by the function. + * + * @param avl_group A pointer on the AVL group to clone. + * @param new_avl_name The name of the new AVL group. + * + * @returns A pointer on the new AVL group structure. + * @retval NULL if an error occurred. + * + * @since May 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +OBIDMS_avl_group_p obi_clone_avl_group(OBIDMS_avl_group_p avl_group, const char* new_avl_name); + + /** * @brief Closes an AVL tree. * diff --git a/src/obiblob_indexer.c b/src/obiblob_indexer.c index a937ec0..22c44b7 100644 --- a/src/obiblob_indexer.c +++ b/src/obiblob_indexer.c @@ -30,6 +30,8 @@ inline Obi_indexer_p obi_create_indexer(OBIDMS_p dms, const char* name); inline Obi_indexer_p obi_open_indexer(OBIDMS_p dms, const char* name); +inline Obi_indexer_p obi_clone_indexer(Obi_indexer_p indexer, const char* name); + inline int obi_close_indexer(Obi_indexer_p indexer); inline index_t obi_indexer_add(Obi_indexer_p indexer, Obi_blob_p value); diff --git a/src/obiblob_indexer.h b/src/obiblob_indexer.h index 6aa5e9d..1f1d662 100644 --- a/src/obiblob_indexer.h +++ b/src/obiblob_indexer.h @@ -107,6 +107,24 @@ inline Obi_indexer_p obi_open_indexer(OBIDMS_p dms, const char* name) } +/** + * @brief Clones an indexer. + * + * @param indexer The indexer to clone. + * @param name The name of the new indexer. + * + * @returns A pointer on the new indexer structure. + * @retval NULL if an error occurred. + * + * @since May 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +inline Obi_indexer_p obi_clone_indexer(Obi_indexer_p indexer, const char* name) +{ + return obi_clone_avl_group(indexer, name); +} + + /** * @brief Closes an indexer. * diff --git a/src/obidmscolumn_seq.c b/src/obidmscolumn_seq.c index 413ca2f..c7daadf 100644 --- a/src/obidmscolumn_seq.c +++ b/src/obidmscolumn_seq.c @@ -27,15 +27,30 @@ int obi_column_set_obiseq_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, const char* value) { index_t idx; + char* new_indexer_name; if (obi_column_prepare_to_set_value(column, line_nb) < 0) return -1; // Add the value in the indexer idx = obi_index_dna_seq(column->indexer, value); - if (idx == -1) - return -1; - + if (idx == -1) // An error occurred + { + if (obi_errno == OBI_READ_ONLY_INDEXER_ERROR) + { + // If the error is that the indexer is read-only, clone it + new_indexer_name = obi_build_indexer_name((column->header)->name, (column->header)->version); + if (new_indexer_name == NULL) + return -1; + column->indexer = obi_clone_indexer(column->indexer, new_indexer_name); // TODO Need to lock this somehow? + // Add the value in the new indexer + idx = obi_index_dna_seq(column->indexer, value); + if (idx == -1) + return -1; + } + else + return -1; + } // Add the value's index in the column *(((index_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = idx; diff --git a/src/obidmscolumn_str.c b/src/obidmscolumn_str.c index 74d1d8e..1b46c86 100644 --- a/src/obidmscolumn_str.c +++ b/src/obidmscolumn_str.c @@ -27,6 +27,7 @@ int obi_column_set_obistr_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, const char* value) { index_t idx; + char* new_indexer_name; // TODO // size_t i; @@ -44,8 +45,23 @@ int obi_column_set_obistr_with_elt_idx(OBIDMS_column_p column, index_t line_nb, // Add the value in the indexer idx = obi_index_char_str(column->indexer, value); - if (idx == -1) - return -1; + if (idx == -1) // An error occurred + { + if (obi_errno == OBI_READ_ONLY_INDEXER_ERROR) + { + // If the error is that the indexer is read-only, clone it + new_indexer_name = obi_build_indexer_name((column->header)->name, (column->header)->version); + if (new_indexer_name == NULL) + return -1; + column->indexer = obi_clone_indexer(column->indexer, new_indexer_name); // TODO Need to lock this somehow? + // Add the value in the new indexer + idx = obi_index_char_str(column->indexer, value); + if (idx == -1) + return -1; + } + else + return -1; + } // Add the value's index in the column *(((index_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = idx; diff --git a/src/obierrno.h b/src/obierrno.h index dfd921e..fcc4eed 100644 --- a/src/obierrno.h +++ b/src/obierrno.h @@ -114,7 +114,9 @@ extern int obi_errno; */ #define OBI_INDEXER_ERROR (27) /** Error handling a blob indexer */ -#define OBI_ALIGN_ERROR (28) /** Error while aligning sequences +#define OBI_READ_ONLY_INDEXER_ERROR (28) /** Error trying to modify a read-only a blob indexer + */ +#define OBI_ALIGN_ERROR (29) /** Error while aligning sequences */ /**@}*/ diff --git a/src/obiview.c b/src/obiview.c index 333b9ef..e06bf37 100644 --- a/src/obiview.c +++ b/src/obiview.c @@ -603,19 +603,19 @@ Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p v // TODO Add quality column? // Adding sequence column - if (obi_view_add_column(view, NUC_SEQUENCE_COLUMN, -1, OBI_SEQ, 0, 1, NUC_SEQUENCE_COLUMN, NUC_SEQUENCE_INDEXER, "Nucleotide sequences", true) < 0) + if (obi_view_add_column(view, NUC_SEQUENCE_COLUMN, -1, OBI_SEQ, 0, 1, NUC_SEQUENCE_COLUMN, "", "Nucleotide sequences", true) < 0) { obidebug(1, "Error adding an obligatory column in a nucleotide sequences view"); return NULL; } // Adding id column - if (obi_view_add_column(view, ID_COLUMN, -1, OBI_STR, 0, 1, ID_COLUMN, ID_INDEXER, "Ids", true) < 0) + if (obi_view_add_column(view, ID_COLUMN, -1, OBI_STR, 0, 1, ID_COLUMN, "", "Ids", true) < 0) { obidebug(1, "Error adding an obligatory column in a nucleotide sequences view"); return NULL; } // Adding definition column - if (obi_view_add_column(view, DEFINITION_COLUMN, -1, OBI_STR, 0, 1, DEFINITION_COLUMN, DEFINITION_INDEXER, "Definitions", true) < 0) + if (obi_view_add_column(view, DEFINITION_COLUMN, -1, OBI_STR, 0, 1, DEFINITION_COLUMN, "", "Definitions", true) < 0) { obidebug(1, "Error adding an obligatory column in a nucleotide sequences view"); return NULL; diff --git a/src/obiview.h b/src/obiview.h index 052bffd..319b8d5 100644 --- a/src/obiview.h +++ b/src/obiview.h @@ -44,21 +44,12 @@ #define NUC_SEQUENCE_COLUMN "NUC_SEQ" /**< The name of the column containing the nucleotide sequences * in NUC_SEQS_VIEW views. */ -#define NUC_SEQUENCE_INDEXER "NUC_SEQ_INDEXER" /**< The name of the indexer containing the nucleotide sequences - * in NUC_SEQS_VIEW views. - */ #define ID_COLUMN "ID" /**< The name of the column containing the sequence identifiers * in NUC_SEQS_VIEW views. */ -#define ID_INDEXER "ID_INDEXER" /**< The name of the indexer containing the sequence identifiers - * in NUC_SEQS_VIEW views. - */ #define DEFINITION_COLUMN "DEFINITION" /**< The name of the column containing the sequence definitions * in NUC_SEQS_VIEW views. */ -#define DEFINITION_INDEXER "DEFINITION_INDEXER" /**< The name of the indexer containing the sequence definitions - * in NUC_SEQS_VIEW views. - */ /**