/******************************************************************** * Obiview functions * ********************************************************************/ /** * @file obiview.c * @author Celine Mercier (celine.mercier@metabarcoding.org) * @date 16 December 2015 * @brief Obiview functions. */ // TODO #include #include #include #include #include #include "obidms.h" #include "obiview.h" #include "obierrno.h" #include "obidebug.h" #include "obidmscolumn.h" #include "utils.h" #include "obilittlebigman.h" #include "obidmscolumn_idx.h" #define DEBUG_LEVEL 0 // TODO has to be defined somewhere else (cython compil flag?) /************************************************************************** * * D E C L A R A T I O N O F T H E P R I V A T E F U N C T I O N S * **************************************************************************/ /** * Internal function building the file name where obiviews are stored. * * @warning The returned pointer has to be freed by the caller. * * @returns A pointer to the file name. * @retval NULL if an error occurred. * * @param dms_name The name of the OBIDMS. * * @since December 2015 * @author Celine Mercier (celine.mercier@metabarcoding.org) */ static char* build_obiview_file_name(); /** TODO public * Internal function creating the file containing basic informations on the OBIDMS. * * This file contains: * - The endianness of the platform * * @warning The returned pointer has to be freed by the caller. * * @param dms_file_descriptor The file descriptor for the OBIDMS directory. * @param dms_name The name of the OBIDMS. * * @retval 0 if the operation was successfully completed. * @retval -1 if an error occurred. * * @since November 2015 * @author Celine Mercier (celine.mercier@metabarcoding.org) */ int create_obiview_file(int dms_file_descriptor); /************************************************************************ * * D E F I N I T I O N O F T H E P R I V A T E F U N C T I O N S * ************************************************************************/ static char* build_obiview_file_name() { char* file_name; // Build file name file_name = (char*) malloc((strlen(OBIVIEW_FILE_NAME) + 1)*sizeof(char)); if (sprintf(file_name, OBIVIEW_FILE_NAME) < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nProblem building an obiview file name"); return NULL; } return file_name; } size_t get_platform_header_size() { size_t header_size; size_t rounded_header_size; double multiple; header_size = sizeof(Obiviews_header_t); multiple = ceil((double) header_size / (double) getpagesize()); rounded_header_size = multiple * getpagesize(); return rounded_header_size; } size_t get_platform_views_size(int nb_of_views) { size_t obiview_size; size_t rounded_obiview_size; double multiple; obiview_size = sizeof(Obiview_infos_t); multiple = ceil((double) (obiview_size*nb_of_views) / (double) getpagesize()); rounded_obiview_size = multiple * getpagesize(); return rounded_obiview_size; } int create_obiview_file(int dms_file_descriptor) { char* file_name; int obiview_file_descriptor; size_t header_size; // size_t view_size; size_t file_size; Obiviews_header_p header; // Create file name file_name = build_obiview_file_name(); if (file_name == NULL) return -1; // Create file obiview_file_descriptor = openat(dms_file_descriptor, file_name, O_RDWR | O_CREAT | O_EXCL, 0777); if (obiview_file_descriptor < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError creating an obiview file"); free(file_name); return -1; } free(file_name); // Truncate file to the right size header_size = get_platform_header_size(); //view_size = get_platform_views_size(1); file_size = header_size; // + view_size; if (ftruncate(obiview_file_descriptor, file_size) < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError truncating an obiview file to the right size"); close(obiview_file_descriptor); return -1; } // Map the header header = mmap(NULL, header_size, PROT_READ | PROT_WRITE, MAP_SHARED, obiview_file_descriptor, 0 ); if (header == MAP_FAILED) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError mmapping an obiview file header"); close(obiview_file_descriptor); return -1; } // Initialize the header header->header_size = header_size; header->views_size = 0; header->view_count = 0; // Unmap the header if (munmap(header, header_size) < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError munmapping an obiview file header"); close(obiview_file_descriptor); return -1; } close(obiview_file_descriptor); return 0; } /********************************************************************** * * D E F I N I T I O N O F T H E P U B L I C F U N C T I O N S * **********************************************************************/ 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) { Obiview_p view; if (view_to_clone != NULL) { // TODO check that the view to clone is already a NUC_SEQS view (discuss possibility of transforming type of a view) if (strcmp(view_to_clone->view_type, VIEW_TYPE_NUC_SEQS)) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "Trying to clone a non-NUC SEQS view to create a NUC SEQS view"); return NULL; } } view = obi_new_view(dms, view_name, view_to_clone, line_selection, comments); if (view== NULL) return NULL; strcpy(view->view_type, VIEW_TYPE_NUC_SEQS); if (view_to_clone == NULL) { // 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) { 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) { obidebug(1, "Error adding an obligatory column in a nucleotide sequences view"); return NULL; } // Adding description column if (obi_view_add_column(view, DESCRIPTION_COLUMN, -1, OBI_STR, 0, 1, DESCRIPTION_COLUMN, DESCRIPTION_INDEXER, "Descriptions", true) < 0) { obidebug(1, "Error adding an obligatory column in a nucleotide sequences view"); return NULL; } } return view; } Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments) { Obiview_p view; int i; index_t line_nb; Obiviews_infos_all_p views_infos; // Check uniqueness of name TODO but problem if view not written yet has the same name views_infos = obi_read_views(dms); if (views_infos != NULL) { for (i=0; i<((views_infos->header)->view_count); i++) { if (strcmp(((views_infos->view_infos)+i)->name, view_name) == 0) // TODO discuss what to do { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nView name already exists for a previous view"); obi_unmap_read_views(views_infos); return NULL; } } obi_unmap_read_views(views_infos); } view = (Obiview_p) malloc(sizeof(Obiview_t)); if (view == NULL) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError allocating memory for a view"); return NULL; } // Clone view to clone if there is one if (view_to_clone != NULL) { if (!(view_to_clone->read_only)) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nA view can not be cloned if it is not read-only"); free(view); return NULL; } view->dms = dms; view->column_count = view_to_clone->column_count; if ((view_to_clone->line_selection != NULL) && (line_selection == NULL)) // reorder conditions { view->line_selection = obi_open_column(dms, ((view_to_clone->line_selection)->header)->name, ((view_to_clone->line_selection)->header)->version); if (view->line_selection == NULL) return NULL; view->line_count = view_to_clone->line_count; } else if (line_selection != NULL) { view->line_selection = obi_create_column(view->dms, LINES_COLUMN_NAME, OBI_IDX, 0, 1, LINES_COLUMN_NAME, NULL, NULL); if ((view->line_selection) == NULL) { obidebug(1, "\nError creating a column corresponding to a line selection"); return NULL; } view->line_count = 0; i = 0; for (i=0; line_selection[i] != -1; i++) { line_nb = line_selection[i]; if (line_nb > view_to_clone->line_count) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError trying to select a line for a new view that is beyond the line count of the view to clone"); obi_close_column(view->line_selection); free(view); return NULL; } if (view_to_clone->line_selection != NULL) line_nb = obi_column_get_index(view_to_clone->line_selection, line_nb); if (obi_column_set_index(view->line_selection, ((view->line_selection)->header)->lines_used, line_nb) < 0) { obi_close_column(view->line_selection); free(view); return NULL; } // Update view line count (view->line_count)++; } } else { view->line_selection = NULL; view->line_count = view_to_clone->line_count; } for (i=0; i<(view_to_clone->column_count); i++) { (view->columns)[i] = obi_open_column(dms, (((view_to_clone->columns)[i])->header)->name, (((view_to_clone->columns)[i])->header)->version); if ((view->columns)[i] == NULL) { obi_close_column(view->line_selection); free(view); return NULL; } } strcpy(view->view_type, view_to_clone->view_type); strcpy(view->created_from, view_to_clone->name); view->new_line_selection = NULL; } // Else, fill empty view structure else { view->dms = dms; view->column_count = 0; view->line_count = 0; view->line_selection = NULL; view->new_line_selection = NULL; (view->created_from)[0] = '\0'; (view->view_type)[0] = '\0'; //view->columns = NULL; TODO } strcpy(view->name, view_name); strcpy(view->comments, comments); view->read_only = 0; return view; } Obiview_p obi_new_view_cloned_from_name(OBIDMS_p dms, const char* view_name, const char* view_to_clone_name, index_t* line_selection, const char* comments) { Obiview_p view; Obiview_p view_to_clone; view_to_clone = obi_open_view(dms, view_to_clone_name); if (view_to_clone == NULL) return NULL; view = obi_new_view(dms, view_name, view_to_clone, line_selection, comments); obi_close_view(view_to_clone); return view; } Obiview_p obi_new_view_nuc_seqs_cloned_from_name(OBIDMS_p dms, const char* view_name, const char* view_to_clone_name, index_t* line_selection, const char* comments) { Obiview_p view; Obiview_p view_to_clone; 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); obi_close_view(view_to_clone); return view; } Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name) { Obiview_p view; bool first_view; char* view_file_name; int obiview_file_descriptor; size_t header_size; Obiviews_header_p header; Obiview_infos_p views; Obiview_infos_p view_infos; OBIDMS_column_p column; int i; int view_number; // Check if 1st view : view file doesn't exist first_view = 0; view_file_name = build_obiview_file_name(); if (view_file_name == NULL) return NULL; // Open view file, read header size and map header and views obiview_file_descriptor = openat(dms->dir_fd, view_file_name, O_RDWR, 0777); if (obiview_file_descriptor < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError opening an obiview file"); free(view_file_name); return NULL; } free(view_file_name); // Read the header size if (read(obiview_file_descriptor, &header_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t))) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError reading the header size of an obiview file (trying to open a view when there are none?)"); close(obiview_file_descriptor); return NULL; } // Map the header header = mmap(NULL, header_size, PROT_READ | PROT_WRITE, MAP_SHARED, obiview_file_descriptor, 0 ); if (header == MAP_FAILED) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError mmapping an obiview file header"); close(obiview_file_descriptor); return NULL; } // Map the views views = mmap(NULL, header->views_size, PROT_READ | PROT_WRITE, MAP_SHARED, obiview_file_descriptor, header_size ); if (views == MAP_FAILED) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError mmapping the views from an obiview file"); munmap(header, header_size); close(obiview_file_descriptor); return NULL; } // Find and open view that should be read with the line selection associated view_number = -1; if (view_name == NULL) // If view name is NULL, open the latest view TODO discuss view_number = (header->view_count) - 1; else { for (i=0; i<(header->view_count); i++) { if (!strcmp((views+i)->name, view_name)) { // Found the view to open view_number = i; } } } if (view_number == -1) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError: the view '%s' to open was not found", view_name); munmap(views, header->views_size); munmap(header, header_size); close(obiview_file_descriptor); return NULL; } view_infos = views + view_number; view = (Obiview_p) malloc(sizeof(Obiview_t)); if (view == NULL) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError allocating memory for a view"); munmap(views, header->views_size); munmap(header, header_size); close(obiview_file_descriptor); return NULL; } if (view_infos->all_lines) view->line_selection = NULL; else { view->line_selection = obi_open_column(dms, (view_infos->line_selection).column_name, (view_infos->line_selection).version); if (view->line_selection == NULL) { munmap(views, header->views_size); munmap(header, header_size); close(obiview_file_descriptor); return NULL; } } view->dms = dms; view->new_line_selection = NULL; view->read_only = 1; view->column_count = 0; view->line_count = view_infos->line_count; strcpy(view->created_from, view_infos->created_from); strcpy(view->name, view_infos->name); strcpy(view->view_type, view_infos->view_type); strcpy(view->comments, view_infos->comments); // Open the columns to read for (i=0; i<(view_infos->column_count); i++) { column = obi_open_column(dms, ((view_infos->column_references)+i)->column_name, ((view_infos->column_references)+i)->version); if (column == NULL) { obidebug(1, "\nError opening a column for a view: column %d: %s, version %d", i, ((view_infos->column_references)+i)->column_name, ((view_infos->column_references)+i)->version); munmap(views, header->views_size); munmap(header, header_size); close(obiview_file_descriptor); return NULL; } // Store column in the view (view->columns)[view->column_count] = column; view->column_count++; } // Munmap and close things TODO munmap(views, header->views_size); munmap(header, header_size); close(obiview_file_descriptor); return view; } Obiviews_infos_all_p obi_read_views(OBIDMS_p dms) { char* view_file_name; int obiview_file_descriptor; size_t header_size; Obiviews_header_p header; Obiview_infos_p view_infos; Obiviews_infos_all_p views; view_file_name = build_obiview_file_name(); if (view_file_name == NULL) return NULL; // Open view file, read header size and map header and views obiview_file_descriptor = openat(dms->dir_fd, view_file_name, O_RDWR, 0777); if (obiview_file_descriptor < 0) { // No views yet free(view_file_name); return NULL; } free(view_file_name); // Read the header size if (read(obiview_file_descriptor, &header_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t))) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError reading the header size of an obiview file (trying to open a view when there are none?)"); close(obiview_file_descriptor); return NULL; } // Map the header header = mmap(NULL, header_size, PROT_READ | PROT_WRITE, MAP_SHARED, obiview_file_descriptor, 0 ); if (header == MAP_FAILED) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError mmapping an obiview file header"); close(obiview_file_descriptor); return NULL; } // Map the views view_infos = mmap(NULL, header->views_size, PROT_READ | PROT_WRITE, MAP_SHARED, obiview_file_descriptor, header_size ); if (view_infos == MAP_FAILED) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError mmapping the views from an obiview file"); munmap(header, header_size); close(obiview_file_descriptor); return NULL; } views = (Obiviews_infos_all_p) malloc(sizeof(Obiviews_infos_all_t)); if (views == NULL) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError mmapping the views from an obiview file"); munmap(view_infos, header->views_size); munmap(header, header_size); close(obiview_file_descriptor); return NULL; } views->header = header; views->view_infos = view_infos; close(obiview_file_descriptor); return views; } int obi_unmap_read_views(Obiviews_infos_all_p views) { if (munmap(views->view_infos, (views->header)->views_size) < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError unmapping the views of an obiview file"); free(views); return -1; } if (munmap(views->header, (views->header)->header_size) < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError unmapping the header of an obiview file"); free(views); return -1; } free(views); return 0; } int obi_view_add_column(Obiview_p view, const char* column_name, obiversion_t version_number, OBIType_t data_type, index_t nb_lines, index_t nb_elements_per_line, const char* elements_names, const char* indexer_name, const char* comments, bool create) // all infos for creation or open { OBIDMS_column_p column; // Check that the view is not read-only if (view->read_only) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError trying to add a column in a read-only view"); return -1; } if (view->line_count > nb_lines) nb_lines = view->line_count; else if (nb_lines > view->line_count) obi_view_update_lines(view, nb_lines); // Open or create the column if (create) { // Create column column = obi_create_column(view->dms, column_name, data_type, nb_lines, nb_elements_per_line, elements_names, indexer_name, comments); } else { // Open column column = obi_open_column(view->dms, column_name, version_number); } if (column == NULL) { obidebug(1, "\nError creating or opening a column to add to a view"); return -1; } // Store column in the view (view->columns)[view->column_count] = column; view->column_count++; if (view->column_count == 1) // first column in the view view->line_count = (column->header)->lines_used; return 0; } OBIDMS_column_p obi_view_clone_column(Obiview_p view, const char* column_name) { int i; OBIDMS_column_p current_line_selection = NULL; OBIDMS_column_p column; OBIDMS_column_p column_buffer; // Check that the view is not read-only if (view->read_only) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError trying to delete a column in a read-only view"); return NULL; } if (view->new_line_selection != NULL) // TODO Probably shouldn't happen current_line_selection = view->new_line_selection; else current_line_selection = view->line_selection; for (i=0; i<(view->column_count); i++) { if ((current_line_selection != NULL) || (!(strcmp((((view->columns)[i])->header)->name, column_name)))) { // Clone with the right line selection and replace column_buffer = (view->columns)[i]; (view->columns)[i] = obi_clone_column(view->dms, current_line_selection, (((view->columns)[i])->header)->name, (((view->columns)[i])->header)->version, 1); if ((view->columns)[i] == NULL) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError cloning a column to replace in a view"); return NULL; } // Found the column to return if (!(strcmp((((view->columns)[i])->header)->name, column_name))) column = (view->columns)[i]; else obi_truncate_and_close_column(column_buffer); // TODO weird closing after cloning but can't think of cleaner yet } } if (view->line_selection != NULL) { obi_truncate_and_close_column(view->line_selection); view->line_selection = NULL; } if (view->new_line_selection != NULL) { obi_truncate_and_close_column(view->new_line_selection); view->new_line_selection = NULL; } return column; } int obi_view_delete_column(Obiview_p view, const char* column_name) { int i; bool found; // TODO check that not deleting an obligatory column? // Check that the view is not read-only if (view->read_only) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError trying to delete a column in a read-only view"); return -1; } found = 0; for (i=0; i<(view->column_count); i++) { if (!strcmp((((view->columns)[i])->header)->name, column_name)) { obi_truncate_and_close_column((view->columns)[i]); found = 1; } if (found) { if (i != ((view->column_count) - 1)) // not the last one (view->columns)[i] = (view->columns)[i+1]; else // Last column (view->columns)[i] = NULL; } } if (!found) return -1; (view->column_count)--; return 0; } int obi_select_line(Obiview_p view, index_t line_nb) { // Check that the view is not read-only if (view->read_only) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError trying to select a line in a read-only view"); return -1; } // If column for line selection doesn't already exists, create it and store its informations if ((view->new_line_selection) == NULL) { view->new_line_selection = obi_create_column(view->dms, LINES_COLUMN_NAME, OBI_IDX, 0, 1, LINES_COLUMN_NAME, NULL, NULL); if ((view->new_line_selection) == NULL) { obidebug(1, "\nError creating a column corresponding to a line selection"); return -1; } } // If we are already working on a line selection, get the pointed line number if (view->line_selection) line_nb = obi_column_get_index(view->line_selection, line_nb); if (obi_column_set_index(view->new_line_selection, ((view->new_line_selection)->header)->lines_used, line_nb) < 0) return -1; return 0; } int obi_select_lines(Obiview_p view, index_t* line_nbs) { int i; index_t line_nb; // Check that the view is not read-only if (view->read_only) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError trying to select a line in a read-only view"); return -1; } // If column for line selection doesn't already exists, create it and store its informations if ((view->new_line_selection) == NULL) { view->new_line_selection = obi_create_column(view->dms, LINES_COLUMN_NAME, OBI_IDX, 0, 1, LINES_COLUMN_NAME, NULL, NULL); if ((view->new_line_selection) == NULL) { obidebug(1, "\nError creating a column corresponding to a line selection"); return -1; } } for (i=0; line_nbs[i] != -1; i++) { line_nb = line_nbs[i]; // If we are already working on a line selection, get the pointed line number if (view->line_selection) line_nb = obi_column_get_index(view->line_selection, line_nb); if (obi_column_set_index(view->new_line_selection, ((view->new_line_selection)->header)->lines_used, line_nb) < 0) return -1; } return 0; } int obi_view_update_lines(Obiview_p view, index_t line_count) { int i; for (i=0; i<(view->column_count); i++) { while (line_count > (((view->columns)[i])->header)->line_count) { // Enlarge the column if (obi_enlarge_column((view->columns)[i]) < 0) return -1; } } view->line_count = line_count; return 0; } OBIDMS_column_p obi_view_get_column(Obiview_p view, const char* column_name) { int i; for (i=0; i<(view->column_count); i++) { if (!(strcmp((((view->columns)[i])->header)->name, column_name))) return (view->columns)[i]; } return NULL; } OBIDMS_column_p* obi_view_get_pointer_on_column_in_view(Obiview_p view, const char* column_name) { int i; for (i=0; i<(view->column_count); i++) { if (!(strcmp((((view->columns)[i])->header)->name, column_name))) return ((view->columns)+i); } return NULL; } int obi_save_view(Obiview_p view) { int i; struct stat buffer; char* view_file_name; char* full_path; int check_file; int obiview_file_descriptor; size_t header_size; size_t views_size; size_t file_size; Obiviews_header_p header; Obiview_infos_p views; Obiview_infos_p view_infos; OBIDMS_column_p current_line_selection; // Check that the view is not read-only if (view->read_only) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError trying to save a read-only view"); return -1; } view_file_name = build_obiview_file_name(); if (view_file_name == NULL) return -1; // Get the full path for the column directory full_path = get_full_path(view->dms, view_file_name); if (full_path == NULL) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError getting the full path of an obiview file"); free(view_file_name); return -1; } check_file = stat(full_path, &buffer); if (check_file < 0) { // 1st view: create view file if (create_obiview_file((view->dms)->dir_fd) < 0) return -1; } // Open view file, read header size and map header and views obiview_file_descriptor = openat((view->dms)->dir_fd, view_file_name, O_RDWR, 0777); if (obiview_file_descriptor < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError opening an obiview file"); free(view_file_name); return -1; } free(view_file_name); // Read the header size if (read(obiview_file_descriptor, &header_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t))) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError reading the header size of an obiview file"); close(obiview_file_descriptor); return -1; } // Map the header header = mmap(NULL, header_size, PROT_READ | PROT_WRITE, MAP_SHARED, obiview_file_descriptor, 0 ); if (header == MAP_FAILED) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError mmapping an obiview file header"); close(obiview_file_descriptor); return -1; } // Truncate file to the right size to add a new view // TODO lock for multithreading views_size = get_platform_views_size((header->view_count)+1); file_size = header_size + views_size; if (ftruncate(obiview_file_descriptor, file_size) < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError truncating an obiview file to the right size"); munmap(header, header_size); close(obiview_file_descriptor); return -1; } header->views_size = views_size; // Map the views views = mmap(NULL, header->views_size, PROT_READ | PROT_WRITE, MAP_SHARED, obiview_file_descriptor, header_size ); if (views == MAP_FAILED) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError mmapping the views from an obiview file"); munmap(header, header_size); close(obiview_file_descriptor); return -1; } // Write view infos view_infos = views + (header->view_count); view_infos->view_number = (header->view_count); view_infos->column_count = view->column_count; view_infos->creation_date = time(NULL); strcpy(view_infos->created_from, view->created_from); strcpy(view_infos->name, view->name); strcpy(view_infos->view_type, view->view_type); strcpy(view_infos->comments, view->comments); // Store reference for the line selection associated with that view if (view->new_line_selection != NULL) { view_infos->line_count = ((view->new_line_selection)->header)->lines_used; current_line_selection = view->new_line_selection; } else { view_infos->line_count = view->line_count; current_line_selection = view->line_selection; } if (current_line_selection != NULL) { view_infos->all_lines = 0; strcpy((view_infos->line_selection).column_name, (current_line_selection->header)->name); (view_infos->line_selection).version = (current_line_selection->header)->version; } else { view_infos->all_lines = 1; ((view_infos->line_selection).column_name)[0] = '\0'; (view_infos->line_selection).version = -1; } for (i=0; icolumn_count; i++) { strcpy(((view_infos->column_references)+i)->column_name, (((view->columns)[i])->header)->name); ((view_infos->column_references)+i)->version = (((view->columns)[i])->header)->version; } // Increment view count (header->view_count)++; // Unmap and close file munmap(views, header->views_size); munmap(header, header_size); close(obiview_file_descriptor); return 0; } int obi_close_view(Obiview_p view) { int i; for (i=0; i < (view->column_count); i++) { obi_close_column((view->columns)[i]); } free(view); return 0; } int obi_save_and_close_view(Obiview_p view) { if (!(view->read_only)) // TODO discuss { if (obi_save_view(view) < 0) return -1; } if (obi_close_view(view) < 0) return -1; return 0; }