diff --git a/python/obitools3/dms/capi/obiview.pxd b/python/obitools3/dms/capi/obiview.pxd index c6accd3..056da0e 100755 --- a/python/obitools3/dms/capi/obiview.pxd +++ b/python/obitools3/dms/capi/obiview.pxd @@ -60,7 +60,7 @@ cdef extern from "obiview.h" nogil: ctypedef Obiview_t* Obiview_p - Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const_char_p view_name, Obiview_p view_to_clone, index_t* line_selection, const_char_p comments, bint quality_column) + Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const_char_p view_name, Obiview_p view_to_clone, index_t* line_selection, const_char_p comments, bint quality_column, bint create_default_columns) Obiview_p obi_new_view(OBIDMS_p dms, const_char_p view_name, Obiview_p view_to_clone, index_t* line_selection, const_char_p comments) @@ -113,6 +113,8 @@ cdef extern from "obiview.h" nogil: int obi_rollback_view(Obiview_p view) + int obi_delete_view(OBIDMS_p dms, const char* view_name) + # OBI_INT int obi_set_int_with_elt_name_and_col_p_in_view(Obiview_p view, diff --git a/python/obitools3/dms/view/typed_view/view_NUC_SEQS.pyx b/python/obitools3/dms/view/typed_view/view_NUC_SEQS.pyx index c29670c..cafcab2 100755 --- a/python/obitools3/dms/view/typed_view/view_NUC_SEQS.pyx +++ b/python/obitools3/dms/view/typed_view/view_NUC_SEQS.pyx @@ -43,7 +43,8 @@ cdef class View_NUC_SEQS(View): NULL, NULL, comments_b, - quality) + quality, + True) if pointer == NULL : message = "Error : Cannot create view %s" % bytes2str(view_name_b) diff --git a/python/obitools3/dms/view/view.pyx b/python/obitools3/dms/view/view.pyx index c5c6ac5..fb12838 100755 --- a/python/obitools3/dms/view/view.pyx +++ b/python/obitools3/dms/view/view.pyx @@ -15,7 +15,8 @@ from ..capi.obiview cimport Alias_column_pair_p, \ obi_view_get_pointer_on_column_in_view, \ obi_view_delete_column, \ obi_view_create_column_alias, \ - obi_view_write_comments + obi_view_write_comments, \ + obi_delete_view from ..capi.obidmscolumn cimport OBIDMS_column_p from ..capi.obidms cimport OBIDMS_p @@ -66,7 +67,13 @@ cdef class View(OBIWrapper) : def import_view(object dms_1, object dms_2, object view_name_1, object view_name_2): if obi_import_view(tobytes(dms_1), tobytes(dms_2), tobytes(view_name_1), tobytes(view_name_2)) < 0 : raise Exception("Error importing a view") - + + + @staticmethod + def delete_view(DMS dms, object view_name): + if (obi_delete_view(dms.pointer(), tobytes(view_name)) < 0): + raise Exception("Error deleting a view") + @staticmethod def new(DMS dms, @@ -533,6 +540,8 @@ cdef class View(OBIWrapper) : for i in range(len(element.comments[b"input_dms_name"])) : if element.comments[b"input_dms_name"][i] == element.dms.name and b"/" not in element.comments[b"input_view_name"][i]: # Same DMS and not a special element like a taxonomy top_level.append(element.dms[element.comments[b"input_view_name"][i]]) + else: + top_level.append(None) else: top_level.append(None) level_dict[tuple(element.comments[b"input_str"])] = {} diff --git a/src/obi_ecopcr.c b/src/obi_ecopcr.c index 1e4cbc4..72952d5 100755 --- a/src/obi_ecopcr.c +++ b/src/obi_ecopcr.c @@ -765,7 +765,7 @@ int obi_ecopcr(const char* i_dms_name, } // Create output view - o_view = obi_new_view_nuc_seqs(o_dms, o_view_name, NULL, NULL, o_view_comments, false); + o_view = obi_new_view_nuc_seqs(o_dms, o_view_name, NULL, NULL, o_view_comments, false, true); if (o_view == NULL) { obidebug(1, "\nError creating the output view"); diff --git a/src/obiview.c b/src/obiview.c index 19e669b..15bb284 100755 --- a/src/obiview.c +++ b/src/obiview.c @@ -97,6 +97,21 @@ static char* build_unfinished_obiview_file_name(const char* view_name); static bool view_exists(OBIDMS_p dms, const char* view_name); +/** + * Internal function checking if a view is finished. + * + * @param dms The DMS. + * @param view_name The name of the view. + * + * @returns A boolean value indicating whether the view is finished or not. + * @retval -1 if the view does not exist or if an error occurred. + * + * @since October 2018 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +static bool view_is_finished(OBIDMS_p dms, const char* view_name); + + /** * Internal function calculating the initial size of the file where the informations about an obiview are stored. * @@ -586,6 +601,55 @@ static bool view_exists(OBIDMS_p dms, const char* view_name) } +static bool view_is_finished(OBIDMS_p dms, const char* view_name) +{ + struct dirent* dp; + char* file_name; + + // Check finished views + // Create file name + file_name = build_obiview_file_name(view_name); + if (file_name == NULL) + return -1; + + rewinddir(dms->view_directory); + while ((dp = readdir(dms->view_directory)) != NULL) + { + if ((dp->d_name)[0] == '.') + continue; + if (strcmp(dp->d_name, file_name) == 0) + { + free(file_name); + return true; + } + } + + free(file_name); + + // Check unfinished views + // Create file name + file_name = build_unfinished_obiview_file_name(view_name); + if (file_name == NULL) + return -1; + + rewinddir(dms->view_directory); + while ((dp = readdir(dms->view_directory)) != NULL) + { + if ((dp->d_name)[0] == '.') + continue; + if (strcmp(dp->d_name, file_name) == 0) + { + free(file_name); + return false; + } + } + + free(file_name); + + return -1; +} + + static size_t get_platform_view_file_size() { size_t obiview_size; @@ -746,7 +810,6 @@ static int update_column_refs(Obiview_p view) obidebug(1, "\nError getting a column from the linked list of column pointers of a view"); return -1; } - strcpy(((((view->infos)->column_references)[i]).column_refs).column_name, (column->header)->name); ((((view->infos)->column_references)[i]).column_refs).version = (column->header)->version; } @@ -1757,7 +1820,7 @@ Obiview_p obi_new_view_cloned_from_name(OBIDMS_p dms, const char* view_name, con } -Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments, bool quality_column) +Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments, bool quality_column, bool create_default_columns) { Obiview_p view; OBIDMS_column_p associated_nuc_column; @@ -1784,7 +1847,7 @@ Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p v strcpy((view->infos)->view_type, VIEW_TYPE_NUC_SEQS); - if (view_to_clone == NULL) + if ((view_to_clone == NULL) && create_default_columns) { // Adding sequence column if (obi_view_add_column(view, NUC_SEQUENCE_COLUMN, -1, NULL, OBI_SEQ, 0, 1, NULL, false, false, false, NULL, NULL, -1, "Nucleotide sequences", true) < 0) // discuss using same indexer "NUC_SEQ_INDEXER" @@ -1856,7 +1919,7 @@ Obiview_p obi_new_view_nuc_seqs_cloned_from_name(OBIDMS_p dms, const char* view_ view_to_clone = obi_open_view(dms, view_to_clone_name); if (view_to_clone == NULL) return NULL; - view = obi_new_view_nuc_seqs(dms, view_name, view_to_clone, line_selection, comments, false); + view = obi_new_view_nuc_seqs(dms, view_name, view_to_clone, line_selection, comments, false, false); close_view(view_to_clone); @@ -1874,7 +1937,7 @@ Obiview_p obi_clone_view(OBIDMS_p dms, Obiview_p view_to_clone, const char* view } if (strcmp((view_to_clone->infos)->view_type, VIEW_TYPE_NUC_SEQS) == 0) - return obi_new_view_nuc_seqs(dms, view_name, view_to_clone, line_selection, comments, false); + return obi_new_view_nuc_seqs(dms, view_name, view_to_clone, line_selection, comments, false, false); else // Non-typed view return obi_new_view(dms, view_name, view_to_clone, line_selection, comments); } @@ -2002,7 +2065,7 @@ int obi_view_unmap_file(OBIDMS_p dms, Obiview_infos_p view_infos) if (obiview_file_descriptor < 0) { obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError opening an obiview file"); + obidebug(1, "\nError opening an obiview file (%s) >%s<", file_name, dms->dms_name); free(file_name); return -1; } @@ -2230,7 +2293,7 @@ int obi_view_add_column(Obiview_p view, column = obi_open_column(view->dms, column_name, version_number); if (column == NULL) { - obidebug(1, "\nError opening a column to add to a view"); + obidebug(1, "\nError opening a column to add to a view: %s, version %d", column_name, version_number); return -1; } // - If there is a line selection: @@ -2285,10 +2348,10 @@ int obi_view_add_column(Obiview_p view, return -1; } -// // Print dict + // Print dict // for (i=0; i<((view->infos)->column_count); i++) // { -// fprintf(stderr, "\n\nalias: %s", (((view->infos)->column_references)[i]).alias); +// fprintf(stderr, "\n\n2305 alias: %s", (((view->infos)->column_references)[i]).alias); // fprintf(stderr, "\npointer: %x\n", obi_view_get_column(view, (((view->infos)->column_references)[i]).alias)); // } @@ -2775,6 +2838,63 @@ int obi_rollback_view(Obiview_p view) } +int obi_delete_view(OBIDMS_p dms, const char* view_name) +{ + char* view_file_name; + char* view_relative_path; + char* view_full_path; + struct dirent* dp; + + // Check that the view exists + if (view_exists(dms, view_name) == false) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to delete a view: view '%s' does not exist", view_name); + return -1; + } + + // Check that the view is finished + if (view_is_finished(dms, view_name) == false) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to delete a view: view '%s' is not finished", view_name); + return -1; + } + + // Delete view file + view_file_name = (char*) malloc(strlen(view_name) + strlen(".obiview") + 1); + if (view_file_name == NULL) + { + obi_set_errno(OBI_MALLOC_ERROR); + obidebug(1, "\nError allocating memory for a view file name"); + return -1; + } + + strcpy(view_file_name, view_name); + strcat(view_file_name, ".obiview"); + rewinddir(dms->view_directory); + while ((dp = readdir(dms->view_directory)) != NULL) + { + if ((dp->d_name)[0] == '.') + continue; + if (strcmp(dp->d_name, view_file_name) == 0) + { + view_relative_path = (char*) malloc(strlen(VIEW_DIR_NAME) + strlen(view_file_name) + 2); + strcpy(view_relative_path, VIEW_DIR_NAME); + strcat(view_relative_path, "/"); + strcat(view_relative_path, view_file_name); + view_full_path = obi_dms_get_full_path(dms, view_relative_path); + remove(view_full_path); + free(view_relative_path); + free(view_full_path); + } + } + free(view_file_name); + + return 0; +} + + int obi_create_auto_count_column(Obiview_p view) { index_t i; diff --git a/src/obiview.h b/src/obiview.h index b3dd49c..7b4b052 100755 --- a/src/obiview.h +++ b/src/obiview.h @@ -203,6 +203,7 @@ Obiview_p obi_new_view_cloned_from_name(OBIDMS_p dms, const char* view_name, con * if there is one. NULL if there is no line selection or no view to clone. * @param comments Eventually, comments to associate with the view. NULL if not. * @param quality_column Whether or not a sequence quality column is associated with the view. + * @param create_default_columns Whether to create the default columns associated with the view type (false when importing all columns from a view for example). * * @returns A pointer to the newly created view structure. * @retval NULL if an error occurred. @@ -210,7 +211,7 @@ Obiview_p obi_new_view_cloned_from_name(OBIDMS_p dms, const char* view_name, con * @since February 2016 * @author Celine Mercier (celine.mercier@metabarcoding.org) */ -Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments, bool quality_column); +Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments, bool quality_column, bool create_default_columns); /** @@ -579,6 +580,29 @@ int obi_clean_unfinished_views(OBIDMS_p dms); int obi_rollback_view(Obiview_p view); +/** + * @brief Deletes a finished view file. + * + * Only the view informations file is deleted. + * This function should only be used to delete 'temporary views' not meant to appear in the DMS history. + * + * @warning The view needs to be closed. The function checks that the view exists and is finished, but not that it is closed. + * If it was not closed, memory errors will be generated when the system tries to read the deleted file. + * // TODO maybe take opened view as argument in order to close it? but doesn't guarantee that it isn't open elsewhere. + * + * @param dms A pointer on the DMS to which the view belongs. + * @param view_name The name of the view to delete. + * + * @returns A value indicating the success of the operation. + * @retval 0 if the operation was successfully completed. + * @retval -1 if an error occurred. + * + * @since October 2018 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_delete_view(OBIDMS_p dms, const char* view_name); + + /** * @brief Creates an OBI_INT column with the line count of the view it belongs to, and sets all lines to 1. *