Files
obitools3/src/obiview.c

1470 lines
42 KiB
C
Raw Normal View History

2016-02-18 10:38:51 +01:00
/********************************************************************
* Obiview functions *
********************************************************************/
/**
* @file obiview.c
* @author Celine Mercier (celine.mercier@metabarcoding.org)
* @date 16 December 2015
* @brief Obiview functions.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "obiview.h"
#include "obidms.h"
2016-02-18 10:38:51 +01:00
#include "obidmscolumn.h"
#include "obidmscolumn_idx.h"
#include "obidmscolumn_bool.h"
#include "obidmscolumn_char.h"
#include "obidmscolumn_float.h"
#include "obidmscolumn_int.h"
#include "obidmscolumn_qual.h"
#include "obidmscolumn_seq.h"
#include "obidmscolumn_str.h"
#include "obierrno.h"
#include "obidebug.h"
#include "obilittlebigman.h"
#include "utils.h"
2016-02-18 10:38:51 +01:00
#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 the informations about an obiview are stored.
2016-02-18 10:38:51 +01:00
*
* @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 view_name The name of the view.
2016-02-18 10:38:51 +01:00
*
* @since June 2016
2016-02-18 10:38:51 +01:00
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
static char* build_obiview_file_name(const char* view_name); // TODO delete after discussion
2016-02-18 10:38:51 +01:00
/**
* @brief Internal function creating a file containing all the informations on a view.
2016-02-18 10:38:51 +01:00
*
* The file is named with the name of the view.
2016-02-18 10:38:51 +01:00
*
* @param dms The DMS to which the view belongs.
* @param view_name The name of the view.
2016-02-18 10:38:51 +01:00
*
* @retval 0 if the operation was successfully completed.
* @retval -1 if an error occurred.
*
* @since June 2016
2016-02-18 10:38:51 +01:00
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
int create_obiview_file(OBIDMS_p dms, const char* view_name);
/**
* @brief Internal function to update the column references of a view.
*
* The column references stored in the mapped view infos structures are updated
* to match the columns opened in the opened view structure.
*
* @param view A pointer on the view.
*
* @since June 2016
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
void update_column_refs(Obiview_p view);
2016-02-18 10:38:51 +01:00
/**
* @brief Internal function to update the line count in the context of a view.
*
* All columns of the view are enlarged to contain at least the new line count.
*
* @warning The view must be writable.
*
* @param view A pointer on the view.
* @param line_count The new line count.
*
* @returns A value indicating the success of the operation.
* @retval 0 if the operation was successfully completed.
* @retval -1 if an error occurred.
*
* @since February 2016
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
int update_lines(Obiview_p view, index_t line_count);
/**
* @brief Internal function to clone a column in the context of a view.
*
* Clones with the right line selection and replaces the cloned columns with the new ones in the view.
* If there is a line selection, all columns have to be cloned, otherwise only the column of interest is cloned.
*
* @param view A pointer on the view.
* @param column_name The name of the column in the view that should be cloned.
*
* @returns A pointer on the new column.
* @retval NULL if an error occurred.
*
* @since February 2016
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_name);
/**
* Internal function preparing to set a value in a column, in the context of a view.
*
* The function checks that the view is not read-only, clones the column or all columns if needed,
* and updates the line count if needed.
*
* @param view The view.
* @param column_pp A pointer on the pointer on the column, to allow replacing the column if it is cloned.
* @param line_nb_p A pointer on the index of the line that will be modified, to allow replacing it if needed.
*
* @retval 0 if the operation was successfully completed.
* @retval -1 if an error occurred.
*
* @since April 2016
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
int prepare_to_set_value_in_column(Obiview_p view, OBIDMS_column_p* column_pp, index_t* line_nb_p);
/**
* Internal function preparing to get a value from a column, in the context of a view.
*
* The function checks that the line index is not beyond the current line count of the view,
* and modifies it if there is a line selection associated with the view.
*
* @param view The view.
* @param line_nb_p A pointer on the index of the line, to allow replacing it if needed.
*
* @retval 0 if the operation was successfully completed.
* @retval -1 if an error occurred.
*
* @since April 2016
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
int prepare_to_get_value_from_column(Obiview_p view, index_t* line_nb_p);
2016-02-18 10:38:51 +01:00
/************************************************************************
*
* 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
*
************************************************************************/
// TODO
//static char* build_obiview_file_name(const char* view_name)
//{
// char* file_name;
//
// // Build file name
// file_name = (char*) malloc((strlen(view_name) + 1)*sizeof(char));
// if (file_name == NULL)
// {
// obi_set_errno(OBI_MALLOC_ERROR);
// obidebug(1, "\nError allocating memory for a view file name");
// return NULL;
// }
// if (sprintf(file_name, view_name) < 0)
// {
// obi_set_errno(OBIVIEW_ERROR);
// obidebug(1, "\nProblem building an obiview file name");
// return NULL;
// }
//
// return file_name;
//}
size_t get_platform_view_file_size()
2016-02-18 10:38:51 +01:00
{
size_t obiview_size;
size_t rounded_obiview_size;
double multiple;
obiview_size = sizeof(Obiview_infos_t);
multiple = ceil((double) (obiview_size) / (double) getpagesize());
2016-02-18 10:38:51 +01:00
rounded_obiview_size = multiple * getpagesize();
return rounded_obiview_size;
}
int create_obiview_file(OBIDMS_p dms, const char* view_name)
2016-02-18 10:38:51 +01:00
{
// char* file_name;
2016-02-18 10:38:51 +01:00
int obiview_file_descriptor;
size_t file_size;
// TODO
// // Create file name
// file_name = build_obiview_file_name(view_name);
// if (file_name == NULL)
// return -1;
2016-02-18 10:38:51 +01:00
// Create file
obiview_file_descriptor = openat(dms->view_dir_fd, view_name, O_RDWR | O_CREAT | O_EXCL, 0777);
2016-02-18 10:38:51 +01:00
if (obiview_file_descriptor < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError creating an obiview file");
// free(file_name); TODO
2016-02-18 10:38:51 +01:00
return -1;
}
//free(file_name); TODO
2016-02-18 10:38:51 +01:00
// Truncate file to the right size
file_size = get_platform_view_file_size();
2016-02-18 10:38:51 +01:00
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;
}
close(obiview_file_descriptor);
2016-02-18 10:38:51 +01:00
return 0;
}
2016-02-18 10:38:51 +01:00
void update_column_refs(Obiview_p view)
{
int i;
for (i=0; i < (view->infos)->column_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;
}
2016-02-18 10:38:51 +01:00
}
int update_lines(Obiview_p view, index_t line_count)
{
int i;
for (i=0; i<((view->infos)->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;
2016-06-16 11:26:54 +02:00
(((view->columns)[i])->header)->lines_used = line_count;
}
}
(view->infos)->line_count = line_count;
return 0;
}
OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_name)
{
int i;
OBIDMS_column_p current_line_selection = NULL;
OBIDMS_column_p column = NULL;
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, trigger error?
current_line_selection = view->new_line_selection;
else
current_line_selection = view->line_selection;
for (i=0; i<((view->infos)->column_count); i++)
{
if ((current_line_selection != NULL) || (!(strcmp((((view->columns)[i])->header)->name, column_name))))
{ // Clone with the right line selection and replace (for all columns if there is a line selection)
// Save pointer to close column after cloning
column_buffer = (view->columns)[i];
// Clone and replace the column in the view
(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;
}
// Close old cloned column
obi_close_column(column_buffer);
if (!(strcmp((((view->columns)[i])->header)->name, column_name)))
{ // Found the column to return
column = (view->columns)[i];
}
}
}
// Close old line selections
if (view->line_selection != NULL)
{
obi_close_column(view->line_selection);
view->line_selection = NULL;
// Update line selection reference
(((view->infos)->line_selection).column_name)[0] = '\0';
((view->infos)->line_selection).version = -1;
}
if (view->new_line_selection != NULL)
{
obi_close_column(view->new_line_selection);
view->new_line_selection = NULL;
}
// Update column references in view infos
update_column_refs(view);
return column;
}
int prepare_to_set_value_in_column(Obiview_p view, OBIDMS_column_p* column_pp, index_t* line_nb_p)
{
char* column_name;
// Check that the view is not read-only
if (view->read_only)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError trying to set a value in a column in a read-only view");
return -1;
}
// If there is a line selection associated with the view or if the column
// is read-only, all columns or this column respectively must be cloned
if ((view->line_selection != NULL) || (!((*column_pp)->writable)))
{
// Get the right line number
if (view->line_selection != NULL)
(*line_nb_p) = *(((index_t*) ((view->line_selection)->data)) + (*line_nb_p));
column_name = (char*) malloc(strlen(((*column_pp)->header)->name) * sizeof(char));
if (column_name == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError trying to allocate memory for a column name");
return -1;
}
strcpy(column_name, ((*column_pp)->header)->name);
(*column_pp) = clone_column_in_view(view, column_name);
if ((*column_pp) == NULL)
{
obidebug(1, "\nError trying to clone a column to modify it");
return -1;
}
free(column_name);
}
if (((*line_nb_p)+1) > (view->infos)->line_count)
{
if (update_lines(view, ((*line_nb_p)+1)) < 0)
return -1;
}
return 0;
}
int prepare_to_get_value_from_column(Obiview_p view, index_t* line_nb_p)
{
if (((*line_nb_p)+1) > ((view->infos)->line_count))
{
obi_set_errno(OBICOL_UNKNOWN_ERROR);
obidebug(1, "\nError trying to get a value that is beyond the current line count of the view");
return -1;
}
if (view->line_selection)
(*line_nb_p) = *(((index_t*) ((view->line_selection)->data)) + (*line_nb_p));
return 0;
}
2016-02-18 10:38:51 +01:00
/**********************************************************************
*
* 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
*
**********************************************************************/
2016-02-29 17:56:55 +01:00
Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments)
2016-02-18 10:38:51 +01:00
{
Obiview_p view;
int i;
index_t line_nb;
struct dirent* dp;
// Check uniqueness of name
while ((dp = readdir(dms->view_directory)) != NULL)
{
if ((dp->d_name)[0] == '.')
continue;
if (strcmp(dp->d_name, view_name) == 0) // TODO change if view name building changes
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nName of new view already exists");
return NULL;
}
}
2016-02-18 10:38:51 +01:00
// Allocate memory for view structure
2016-02-18 10:38:51 +01:00
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;
}
view->dms = dms;
// Create view file
if (create_obiview_file(dms, view_name) < 0)
{
free(view);
return NULL;
}
// Map view file
view->infos = obi_view_map_file(dms, view_name);
if (view->infos == NULL)
{
obidebug(1, "\nError mapping the informations of a new view");
free(view);
return NULL;
}
2016-02-18 10:38:51 +01:00
// 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");
obi_view_unmap_file(view->dms, view->infos);
2016-02-18 10:38:51 +01:00
free(view);
return NULL;
}
// If the view to clone has an associated line selection and there is no new line selection, open the associated line selection
if ((view_to_clone->line_selection != NULL) && (line_selection == NULL))
2016-02-18 10:38:51 +01:00
{
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)
{
obi_view_unmap_file(view->dms, view->infos);
free(view);
2016-02-18 10:38:51 +01:00
return NULL;
}
(view->infos)->line_count = (view_to_clone->infos)->line_count;
2016-02-18 10:38:51 +01:00
}
// If there is a new line selection, build it by combining it with the one from the view to clone if there is one
2016-02-18 10:38:51 +01:00
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");
obi_view_unmap_file(view->dms, view->infos);
free(view);
2016-02-18 10:38:51 +01:00
return NULL;
}
(view->infos)->all_lines = false;
(view->infos)->line_count = 0;
2016-02-18 10:38:51 +01:00
i = 0;
for (i=0; line_selection[i] != -1; i++)
{
line_nb = line_selection[i];
if (line_nb > (view_to_clone->infos)->line_count)
2016-02-18 10:38:51 +01:00
{
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);
obi_view_unmap_file(view->dms, view->infos);
2016-02-18 10:38:51 +01:00
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);
obi_view_unmap_file(view->dms, view->infos);
2016-02-18 10:38:51 +01:00
free(view);
return NULL;
}
// Update view line count
((view->infos)->line_count)++;
2016-02-18 10:38:51 +01:00
}
}
else // If there is no line selection associated with the view to clone or the new view
2016-02-18 10:38:51 +01:00
{
view->line_selection = NULL;
(view->infos)->all_lines = true;
(view->infos)->line_count = (view_to_clone->infos)->line_count;
2016-02-18 10:38:51 +01:00
}
for (i=0; i<((view_to_clone->infos)->column_count); i++)
2016-02-18 10:38:51 +01:00
{
(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)
{
if (view->line_selection != NULL)
obi_close_column(view->line_selection);
obi_view_unmap_file(view->dms, view->infos);
2016-02-18 10:38:51 +01:00
free(view);
return NULL;
}
}
(view->infos)->column_count = (view_to_clone->infos)->column_count;
strcpy((view->infos)->view_type, (view_to_clone->infos)->view_type);
strcpy((view->infos)->created_from, (view_to_clone->infos)->name);
2016-02-18 10:38:51 +01:00
view->new_line_selection = NULL;
}
// Else, fill empty view structure
else
{
(view->infos)->column_count = 0;
(view->infos)->line_count = 0;
(view->infos)->all_lines = true;
view->line_selection = NULL;
view->new_line_selection = NULL;
((view->infos)->created_from)[0] = '\0';
((view->infos)->view_type)[0] = '\0';
//view->columns = NULL; // TODO
2016-02-18 10:38:51 +01:00
}
strcpy((view->infos)->name, view_name);
strcpy((view->infos)->comments, comments);
(view->infos)->creation_date = time(NULL);
2016-02-18 10:38:51 +01:00
view->read_only = 0;
// Store reference for line selection
if (view->line_selection == NULL)
{
(((view->infos)->line_selection).column_name)[0] = '\0';
((view->infos)->line_selection).version = -1;
}
else
{
strcpy(((view->infos)->line_selection).column_name, ((view->line_selection)->header)->name);
((view->infos)->line_selection).version = ((view->line_selection)->header)->version;
}
// Store references for columns
update_column_refs(view);
2016-02-18 10:38:51 +01:00
return view;
}
2016-02-29 17:56:55 +01:00
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)
2016-02-18 10:38:51 +01:00
{
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;
2016-02-29 17:56:55 +01:00
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(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)
{ // Check that the view to clone is already a NUC_SEQS view (TODO discuss possibility of transforming type of a view)
if (strcmp((view_to_clone->infos)->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->infos)->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, "", "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, "", "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, "", "Definitions", true) < 0)
{
obidebug(1, "Error adding an obligatory column in a nucleotide sequences view");
return NULL;
}
// Adding quality column
if (obi_view_add_column(view, QUALITY_COLUMN, -1, OBI_QUAL, 0, 1, QUALITY_COLUMN, "", "Sequence qualities", true) < 0)
{
obidebug(1, "Error adding an obligatory column in a nucleotide sequences view");
return NULL;
}
}
return view;
}
2016-02-29 17:56:55 +01:00
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;
2016-02-29 17:56:55 +01:00
view = obi_new_view_nuc_seqs(dms, view_name, view_to_clone, line_selection, comments);
obi_close_view(view_to_clone);
2016-02-18 10:38:51 +01:00
return view;
}
Obiview_infos_p obi_view_map_file(OBIDMS_p dms, const char* view_name)
2016-02-18 10:38:51 +01:00
{
// char* file_name;
Obiview_infos_p view_infos;
2016-02-18 10:38:51 +01:00
int obiview_file_descriptor;
size_t file_size;
2016-02-18 10:38:51 +01:00
// TODO
// // Create file name
// file_name = build_obiview_file_name(view_name);
// if (file_name == NULL)
// return -1;
2016-02-18 10:38:51 +01:00
// Open view file
obiview_file_descriptor = openat(dms->view_dir_fd, view_name, O_RDWR, 0777);
2016-02-18 10:38:51 +01:00
if (obiview_file_descriptor < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError opening an obiview file");
// free(file_name); TODO
2016-02-18 10:38:51 +01:00
return NULL;
}
//free(file_name); TODO
2016-02-18 10:38:51 +01:00
// Map the view infos structure
file_size = get_platform_view_file_size();
view_infos = mmap(NULL,
file_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
obiview_file_descriptor,
0
);
if (view_infos == NULL)
2016-02-18 10:38:51 +01:00
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError mapping an obiview file");
2016-02-18 10:38:51 +01:00
return NULL;
}
close(obiview_file_descriptor);
2016-02-18 10:38:51 +01:00
return view_infos;
}
2016-02-18 10:38:51 +01:00
int obi_view_unmap_file(OBIDMS_p dms, Obiview_infos_p view_infos)
{
// char* file_name;
int obiview_file_descriptor;
size_t file_size;
// TODO
// // Get file name
// file_name = build_obiview_file_name(view_name);
// if (file_name == NULL)
// return -1;
// Open view file
obiview_file_descriptor = openat(dms->view_dir_fd, view_infos->name, O_RDWR, 0777);
if (obiview_file_descriptor < 0)
2016-02-18 10:38:51 +01:00
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError opening an obiview file");
// free(file_name); TODO
return -1;
}
//free(file_name); TODO
// Unmap the view infos structure
file_size = get_platform_view_file_size();
if (munmap(view_infos, file_size) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError unmapping an obiview file");
close(obiview_file_descriptor);
return -1;
2016-02-18 10:38:51 +01:00
}
close(obiview_file_descriptor);
return 0;
}
Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name)
{
Obiview_p view;
int i;
2016-02-18 10:38:51 +01:00
// Alllocate the memory for the view structure
2016-02-18 10:38:51 +01:00
view = (Obiview_p) malloc(sizeof(Obiview_t));
if (view == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
2016-02-18 10:38:51 +01:00
obidebug(1, "\nError allocating memory for a view");
return NULL;
}
// Map view file
view->infos = obi_view_map_file(dms, view_name);
// Open the line selection associated with the view
if ((view->infos)->all_lines)
2016-02-18 10:38:51 +01:00
view->line_selection = NULL;
else
{
view->line_selection = obi_open_column(dms, ((view->infos)->line_selection).column_name, ((view->infos)->line_selection).version);
2016-02-18 10:38:51 +01:00
if (view->line_selection == NULL)
{
obidebug(1, "\nError opening a line selection for a view");
obi_view_unmap_file(view->dms, view->infos);
free(view);
2016-02-18 10:38:51 +01:00
return NULL;
}
}
// Open the columns to read
for (i=0; i < ((view->infos)->column_count); i++)
2016-02-18 10:38:51 +01:00
{
(view->columns)[i] = obi_open_column(dms, (((view->infos)->column_references)+i)->column_name, (((view->infos)->column_references)+i)->version);
if ((view->columns)[i] == NULL)
2016-02-18 10:38:51 +01:00
{
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);
obi_close_view(view);
2016-02-18 10:38:51 +01:00
return NULL;
}
}
view->dms = dms;
view->new_line_selection = NULL;
view->read_only = true;
2016-02-18 10:38:51 +01:00
return view;
}
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,
2016-04-12 14:53:33 +02:00
const char* indexer_name,
2016-02-18 10:38:51 +01:00
const char* comments,
bool create) // all infos for creation or open
{
int i;
2016-02-18 10:38:51 +01:00
OBIDMS_column_p column;
OBIDMS_column_p column_buffer;
OBIDMS_column_p current_line_selection;
2016-02-18 10:38:51 +01:00
// 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 there is a line selection, clone the columns to delete it
if (view->new_line_selection != NULL) // TODO Probably shouldn't happen, trigger error?
current_line_selection = view->new_line_selection;
else
current_line_selection = view->line_selection;
if (current_line_selection != NULL)
{
for (i=0; i<((view->infos)->column_count); i++)
{
{ // Clone with the right line selection and replace for all columns
// Save pointer to close column after cloning
column_buffer = (view->columns)[i];
// Clone and replace the column in the view
(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 -1;
}
// Close old cloned column
obi_close_column(column_buffer);
}
}
}
// Close old line selections
if (view->line_selection != NULL)
{
obi_close_column(view->line_selection);
view->line_selection = NULL;
// Update line selection reference
(((view->infos)->line_selection).column_name)[0] = '\0';
((view->infos)->line_selection).version = -1;
}
if (view->new_line_selection != NULL)
{
obi_close_column(view->new_line_selection);
view->new_line_selection = NULL;
}
// Update the line count
if ((view->infos)->line_count > nb_lines)
nb_lines = (view->infos)->line_count;
else if (nb_lines > (view->infos)->line_count)
update_lines(view, nb_lines);
2016-02-18 10:38:51 +01:00
// Open or create the column
if (create)
{ // Create column
2016-04-12 14:53:33 +02:00
column = obi_create_column(view->dms, column_name, data_type, nb_lines, nb_elements_per_line, elements_names, indexer_name, comments);
2016-02-18 10:38:51 +01:00
}
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->infos)->column_count] = column;
(view->infos)->column_count++;
if ((view->infos)->column_count == 1) // first column in the view
(view->infos)->line_count = (column->header)->lines_used;
// Update reference in view infos
update_column_refs(view);
2016-02-18 10:38:51 +01:00
return 0;
}
int obi_view_delete_column(Obiview_p view, const char* column_name)
{
int i;
bool found;
// TODO check that not deleting an obligatory column?
2016-02-18 10:38:51 +01:00
// 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->infos)->column_count); i++)
2016-02-18 10:38:51 +01:00
{
if (!strcmp((((view->columns)[i])->header)->name, column_name))
{
obi_close_column((view->columns)[i]);
2016-02-18 10:38:51 +01:00
found = 1;
}
if (found)
{
if (i != (((view->infos)->column_count) - 1)) // not the last one
2016-02-18 10:38:51 +01:00
(view->columns)[i] = (view->columns)[i+1];
else // Last column
(view->columns)[i] = NULL;
}
}
if (!found)
return -1;
((view->infos)->column_count)--;
// Update reference in view infos
update_column_refs(view);
2016-02-18 10:38:51 +01:00
return 0;
}
OBIDMS_column_p obi_view_get_column(Obiview_p view, const char* column_name)
{
int i;
for (i=0; i<((view->infos)->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) // TODO delete?
{
int i;
for (i=0; i<((view->infos)->column_count); i++)
{
if (!(strcmp((((view->columns)[i])->header)->name, column_name)))
return ((view->columns)+i);
}
return NULL;
}
2016-02-18 10:38:51 +01:00
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 the column for line selection doesn't already exists, create it and store its informations
2016-02-18 10:38:51 +01:00
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_save_view(Obiview_p view)
{
// 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;
}
// Store reference for the line selection associated with that view if there is one
2016-02-18 10:38:51 +01:00
if (view->new_line_selection != NULL)
{
(view->infos)->line_count = ((view->new_line_selection)->header)->lines_used;
strcpy(((view->infos)->line_selection).column_name, ((view->new_line_selection)->header)->name);
((view->infos)->line_selection).version = ((view->new_line_selection)->header)->version;
(view->infos)->all_lines = false;
2016-02-18 10:38:51 +01:00
}
else if (view->line_selection != NULL) // Unnecessary in theory
2016-02-18 10:38:51 +01:00
{
strcpy(((view->infos)->line_selection).column_name, ((view->line_selection)->header)->name);
((view->infos)->line_selection).version = ((view->line_selection)->header)->version;
(view->infos)->all_lines = false;
2016-02-18 10:38:51 +01:00
}
else // Necessary because line selection could have been deleted if a column was cloned
2016-02-18 10:38:51 +01:00
{
(((view->infos)->line_selection).column_name)[0] = '\0';
((view->infos)->line_selection).version = -1;
(view->infos)->all_lines = true;
2016-02-18 10:38:51 +01:00
}
update_column_refs(view);
2016-02-18 10:38:51 +01:00
return 0;
}
int obi_close_view(Obiview_p view)
{
int i;
int ret_value;
2016-02-18 10:38:51 +01:00
ret_value = 0;
for (i=0; i < ((view->infos)->column_count); i++)
{
if (obi_close_column((view->columns)[i]) < 0)
{
obidebug(1, "\nError closing a column while closing a view");
ret_value = -1;
}
}
// Close line selections if they exist
if (view->line_selection != NULL)
{
if (obi_close_column(view->line_selection) < 0)
{
obidebug(1, "\nError closing a line selection while closing a view");
ret_value = -1;
}
}
if (view->new_line_selection != NULL)
{
if (obi_close_column(view->new_line_selection) < 0)
{
obidebug(1, "\nError closing a new line selection while closing a view");
ret_value = -1;
}
}
// Unmap view file
if (obi_view_unmap_file(view->dms, view->infos) < 0)
{
obidebug(1, "\nError unmaping a view file while closing a view");
ret_value = -1;
}
free(view);
return ret_value;
}
int obi_save_and_close_view(Obiview_p view)
{
if (!(view->read_only))
{
if (obi_save_view(view) < 0)
return -1;
}
if (obi_close_view(view) < 0)
return -1;
return 0;
}
/*********** FOR BOOL COLUMNS ***********/
int obi_column_set_obibool_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obibool_t value)
{
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
return -1;
return obi_column_set_obibool_with_elt_idx(column, line_nb, element_idx, value);
}
obibool_t obi_column_get_obibool_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
{
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
return OBIBool_NA;
return obi_column_get_obibool_with_elt_idx(column, line_nb, element_idx);
}
int obi_column_set_obibool_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obibool_t value)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return -1;
return obi_column_set_obibool_with_elt_idx_in_view(view, column, line_nb, element_idx, value);
}
obibool_t obi_column_get_obibool_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return OBIBool_NA;
return obi_column_get_obibool_with_elt_idx_in_view(view, column, line_nb, element_idx);
}
/****************************************/
/*********** FOR CHAR COLUMNS ***********/
int obi_column_set_obichar_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obichar_t value)
{
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
return -1;
return obi_column_set_obichar_with_elt_idx(column, line_nb, element_idx, value);
}
obichar_t obi_column_get_obichar_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
{
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
return OBIChar_NA;
return obi_column_get_obichar_with_elt_idx(column, line_nb, element_idx);
}
int obi_column_set_obichar_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obichar_t value)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return -1;
return obi_column_set_obichar_with_elt_idx_in_view(view, column, line_nb, element_idx, value);
}
obichar_t obi_column_get_obichar_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return OBIChar_NA;
return obi_column_get_obichar_with_elt_idx_in_view(view, column, line_nb, element_idx);
}
/****************************************/
/*********** FOR FLOAT COLUMNS ***********/
int obi_column_set_obifloat_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obifloat_t value)
{
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
return -1;
return obi_column_set_obifloat_with_elt_idx(column, line_nb, element_idx, value);
}
obifloat_t obi_column_get_obifloat_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
{
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
return OBIFloat_NA;
return obi_column_get_obifloat_with_elt_idx(column, line_nb, element_idx);
}
int obi_column_set_obifloat_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obifloat_t value)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return -1;
return obi_column_set_obifloat_with_elt_idx_in_view(view, column, line_nb, element_idx, value);
}
obifloat_t obi_column_get_obifloat_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return OBIFloat_NA;
return obi_column_get_obifloat_with_elt_idx_in_view(view, column, line_nb, element_idx);
}
/****************************************/
/*********** FOR INT COLUMNS ***********/
int obi_column_set_obiint_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obiint_t value)
{
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
return -1;
return obi_column_set_obiint_with_elt_idx(column, line_nb, element_idx, value);
}
obiint_t obi_column_get_obiint_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
{
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
return OBIInt_NA;
return obi_column_get_obiint_with_elt_idx(column, line_nb, element_idx);
}
int obi_column_set_obiint_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obiint_t value)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return -1;
return obi_column_set_obiint_with_elt_idx_in_view(view, column, line_nb, element_idx, value);
}
obiint_t obi_column_get_obiint_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return OBIInt_NA;
return obi_column_get_obiint_with_elt_idx_in_view(view, column, line_nb, element_idx);
}
/****************************************/
/*********** FOR QUAL COLUMNS ***********/
int obi_column_set_obiqual_char_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, const char* value)
{
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
return -1;
return obi_column_set_obiqual_char_with_elt_idx(column, line_nb, element_idx, value);
}
int obi_column_set_obiqual_int_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, const uint8_t* value, int value_length)
{
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
return -1;
return obi_column_set_obiqual_int_with_elt_idx(column, line_nb, element_idx, value, value_length);
}
char* obi_column_get_obiqual_char_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
{
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
return OBIQual_char_NA;
return obi_column_get_obiqual_char_with_elt_idx(column, line_nb, element_idx);
}
const uint8_t* obi_column_get_obiqual_int_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, int* value_length)
{
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
return OBIQual_int_NA;
return obi_column_get_obiqual_int_with_elt_idx(column, line_nb, element_idx, value_length);
}
int obi_column_set_obiqual_char_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, const char* value)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return -1;
return obi_column_set_obiqual_char_with_elt_idx_in_view(view, column, line_nb, element_idx, value);
}
int obi_column_set_obiqual_int_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, const uint8_t* value, int value_length)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return -1;
return obi_column_set_obiqual_int_with_elt_idx_in_view(view, column, line_nb, element_idx, value, value_length);
}
char* obi_column_get_obiqual_char_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return OBIQual_char_NA;
return obi_column_get_obiqual_char_with_elt_idx_in_view(view, column, line_nb, element_idx);
}
const uint8_t* obi_column_get_obiqual_int_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, int* value_length)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return OBIQual_int_NA;
return obi_column_get_obiqual_int_with_elt_idx_in_view(view, column, line_nb, element_idx, value_length);
}
/****************************************/
/*********** FOR SEQ COLUMNS ***********/
int obi_column_set_obiseq_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, const char* value)
{
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
return -1;
return obi_column_set_obiseq_with_elt_idx(column, line_nb, element_idx, value);
}
char* obi_column_get_obiseq_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
{
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
return OBISeq_NA;
return obi_column_get_obiseq_with_elt_idx(column, line_nb, element_idx);
}
int obi_column_set_obiseq_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, const char* value)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return -1;
return obi_column_set_obiseq_with_elt_idx_in_view(view, column, line_nb, element_idx, value);
}
char* obi_column_get_obiseq_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return OBISeq_NA;
return obi_column_get_obiseq_with_elt_idx_in_view(view, column, line_nb, element_idx);
}
/****************************************/
/*********** FOR STR COLUMNS ***********/
int obi_column_set_obistr_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, const char* value)
{
if (prepare_to_set_value_in_column(view, &column, &line_nb) < 0)
return -1;
return obi_column_set_obistr_with_elt_idx(column, line_nb, element_idx, value);
}
const char* obi_column_get_obistr_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx)
{
if (prepare_to_get_value_from_column(view, &line_nb) < 0)
return OBIStr_NA;
return obi_column_get_obistr_with_elt_idx(column, line_nb, element_idx);
}
int obi_column_set_obistr_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, const char* value)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return -1;
return obi_column_set_obistr_with_elt_idx_in_view(view, column, line_nb, element_idx, value);
}
const char* obi_column_get_obistr_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name)
{
index_t element_idx = obi_column_get_element_index_from_name(column, element_name);
if (element_idx == OBIIdx_NA)
return OBIStr_NA;
return obi_column_get_obistr_with_elt_idx_in_view(view, column, line_nb, element_idx);
}
/****************************************/