C sources modified to add the handling of OBIDM columns with the type

OBI_INT, and the handling of multiple types in general
This commit is contained in:
celinemercier
2015-07-31 18:03:48 +02:00
parent a6abc74500
commit 5f62cd8526
6 changed files with 684 additions and 10 deletions

View File

@ -3,7 +3,7 @@
****************************************************************************/
/**
* @file OBIDMS_column.h
* @file obidmscolumn.c
* @author Celine Mercier
* @date 22 May 2015
* @brief Functions for the shared elements of all the OBIColumn structures.
@ -12,6 +12,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
@ -27,6 +28,11 @@
#include "obidebug.h"
#include "obilittlebigman.h"
#include "obidmscolumn_int.h"
#define DEBUG_LEVEL 0
/**************************************************************************
*
@ -115,13 +121,28 @@ static obiversion_t obi_get_new_version_number(OBIDMS_column_directory_p column_
static int create_version_file(OBIDMS_column_directory_p column_directory);
/**
* @brief Internal function setting the elements names of the lines of a
* column in the header of the OBIDMS column structure.
*
* @param column a pointer as returned by obi_create_column()
* @param elements_names the names of the elements with ';' as separator
*
* @return 0 if the operation was successfully completed
* @retvalue -1 if an error occurred
*
* @since July 2015
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
int obi_column_set_elements_names(OBIDMS_column_p column, const char* elements_names);
/************************************************************************
*
* 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
*
************************************************************************/
#define DEBUG_LEVEL 0
static char *build_column_file_name(const char *column_name, obiversion_t version_number)
{
@ -423,6 +444,16 @@ static int create_version_file(OBIDMS_column_directory_p column_directory)
}
int obi_column_set_elements_names(OBIDMS_column_p column, const char* elements_names)
{
(column->header)->elements_names = malloc(strlen(elements_names)*sizeof(char) + 1);
if ((column->header)->elements_names == NULL)
return -1;
strcpy((column->header)->elements_names, elements_names);
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
@ -521,6 +552,32 @@ obiversion_t obi_get_latest_version_number(OBIDMS_column_directory_p column_dire
}
obiversion_t obi_column_get_latest_version_from_name(OBIDMS_p dms, const char* column_name)
{
OBIDMS_column_directory_p column_directory;
obiversion_t latest_version;
// Get the column directory structure associated to the column
column_directory = obi_open_column_directory(dms, column_name);
if (column_directory == NULL)
{
obidebug(1, "\nProblem opening column directory");
return -1;
}
// Get the latest version number
latest_version = obi_get_latest_version_number(column_directory);
if (latest_version < 0)
{
obidebug(1, "\nProblem getting the latest version number");
obi_close_column_directory(column_directory);
return -1;
}
return latest_version;
}
size_t obi_get_platform_header_size()
{
return getpagesize() * 1;
@ -547,6 +604,8 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms,
new_column = NULL;
// TODO check that informations are not NULL/invalid
// Get the column directory structure associated to the column
column_directory = obi_column_directory(dms, column_name);
if (column_directory == NULL)
@ -673,8 +732,7 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms,
header->version = version_number;
header->comments[0] = 0x0;
header->elements_names = malloc(strlen(elements_names)*sizeof(char) + 1);
strcpy(header->elements_names, elements_names);
obi_column_set_elements_names(new_column, elements_names);
strncpy(header->name, column_name, OBIDMS_MAX_COLNAME);
@ -683,3 +741,316 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms,
return new_column;
}
OBIDMS_column_p obi_open_column(OBIDMS_p dms, const char* column_name, obiversion_t version_number)
{
OBIDMS_column_p column;
OBIDMS_column_directory_p column_directory;
char* column_file_name;
int column_file_descriptor;
int column_dir_file_descriptor;
size_t header_size;
size_t data_size;
column = NULL;
// Get the column directory structure associated to the column
column_directory = obi_open_column_directory(dms, column_name);
if (column_directory == NULL)
{
obidebug(1, "\nProblem opening column directory");
return NULL;
}
// Get the file descriptor associated to the column directory
column_dir_file_descriptor = dirfd(column_directory->directory);
if (column_dir_file_descriptor < 0)
{
obidebug(1, "\nProblem opening column directory");
obi_set_errno(OBICOLDIR_UNKNOWN_ERROR);
obi_close_column_directory(column_directory);
return NULL;
}
// Calculate the header size
header_size = obi_get_platform_header_size();
// Get the latest version number if it has the value -1 (not given by user)
if (version_number == -1)
{
version_number = obi_get_latest_version_number(column_directory);
if (version_number < 0)
{
obidebug(1, "\nProblem getting the latest version number");
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
return NULL;
}
}
// Get the column file name
column_file_name = build_column_file_name(column_name, version_number);
if (column_file_name == NULL)
{
obidebug(1, "Problem building column file name");
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
return NULL;
}
// Open the column file, ALWAYS READ-ONLY
column_file_descriptor = openat(column_dir_file_descriptor, column_file_name, O_RDONLY);
if (column_file_descriptor < 0)
{
obidebug(1, "\nCan't open column file");
obi_set_errno(OBICOL_UNKNOWN_ERROR);
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
free(column_file_name);
return NULL;
}
// Allocate the memory for the column structure
column = (OBIDMS_column_p) malloc(sizeof(OBIDMS_column_t));
if (column == NULL)
{
obi_set_errno(OBICOL_UNKNOWN_ERROR);
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
close(column_file_descriptor);
free(column_file_name);
return NULL;
}
// Fill the column structure
column->dms = dms;
column->column_directory = column_directory;
column->header = mmap(NULL,
header_size,
PROT_READ,
MAP_SHARED,
column_file_descriptor,
0
);
if (column->header == MAP_FAILED)
{
obi_set_errno(OBICOL_UNKNOWN_ERROR);
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
close(column_file_descriptor);
free(column_file_name);
free(column);
return NULL;
}
// Check endianness?
// Compute data size from the informations in the header
data_size = ((column->header)->line_count) * sizeof((column->header)->data_type); // TODO line_count for tests, change to lines_used later
column->data = mmap(NULL,
data_size,
PROT_READ,
MAP_SHARED,
column_file_descriptor,
header_size
);
if (column->data == MAP_FAILED)
{
munmap(column->header, header_size);
obi_set_errno(OBICOL_UNKNOWN_ERROR);
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
close(column_file_descriptor);
free(column_file_name);
free(column);
return NULL;
}
column->writable = false;
free(column_file_name);
close(column_file_descriptor);
return column;
}
int obi_close_column(OBIDMS_column_p column)
{
//munmap?
free(column);
return 0;
}
void obi_column_make_unwritable(OBIDMS_column_p column)
{
column->writable = false;
}
size_t obi_column_get_line_count(OBIDMS_column_p column)
{
return (column->header)->line_count;
}
OBIType_t obi_column_get_data_type(OBIDMS_column_p column)
{
return (column->header)->data_type;
}
OBIType_t obi_column_get_data_type_from_name(OBIDMS_p dms, const char* column_name)
{
OBIDMS_column_header_p header;
OBIDMS_column_directory_p column_directory;
char* column_file_name;
int column_file_descriptor;
int column_dir_file_descriptor;
size_t header_size;
OBIType_t data_type;
obiversion_t version_number;
// Get the column directory structure associated to the column
column_directory = obi_open_column_directory(dms, column_name);
if (column_directory == NULL)
{
obidebug(1, "\nProblem opening column directory");
return -1;
}
// Get the file descriptor associated to the column directory
column_dir_file_descriptor = dirfd(column_directory->directory);
if (column_dir_file_descriptor < 0)
{
obidebug(1, "\nProblem opening column directory");
obi_set_errno(OBICOLDIR_UNKNOWN_ERROR);
obi_close_column_directory(column_directory);
return -1;
}
// Calculate the header size
header_size = obi_get_platform_header_size();
// Get the latest version number
version_number = obi_get_latest_version_number(column_directory);
if (version_number < 0)
{
obidebug(1, "\nProblem getting the latest version number");
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
return -1;
}
// Get the column file name
column_file_name = build_column_file_name(column_name, version_number);
if (column_file_name == NULL)
{
obidebug(1, "Problem building column file name");
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
return -1;
}
// Open the column file (READ-ONLY)
column_file_descriptor = openat(column_dir_file_descriptor, column_file_name, O_RDONLY);
if (column_file_descriptor < 0)
{
obidebug(1, "\nCan't open column file");
obi_set_errno(OBICOL_UNKNOWN_ERROR);
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
free(column_file_name);
return -1;
}
// Fill the header structure
header = mmap(NULL,
header_size,
PROT_READ,
MAP_SHARED,
column_file_descriptor,
0
);
if (header == MAP_FAILED)
{
obi_set_errno(OBICOL_UNKNOWN_ERROR);
obi_close_column_directory(column_directory);
close(column_dir_file_descriptor);
close(column_file_descriptor);
free(column_file_name);
free(header);
return -1;
}
// Check endianness?
data_type = header->data_type;
free(column_file_name);
close(column_file_descriptor);
munmap(header, header_size);
return data_type;
}
const char* obi_column_get_elements_names(OBIDMS_column_p column)
{
return (column->header)->elements_names;
}
// to be rewritten in an optimized and safe way
size_t obi_column_get_element_index_from_name(OBIDMS_column_p column, const char* element_name)
{
char* elements_names;
char* name;
size_t element_index;
elements_names = strdup((column->header)->elements_names);
if (elements_names == NULL)
{
obidebug(1, "\nError strdup-ing the elements names");
return -1;
}
element_index = 0;
name = strtok (elements_names, ";"); // not thread safe, see strtok_r maybe
if (strcmp(element_name, name) == 0)
{
free(elements_names);
return element_index;
}
element_index++;
while (name != NULL)
{
name = strtok (NULL, ";"); // not thread safe, see strtok_r maybe
if (strcmp(element_name, name) == 0)
{
free(elements_names);
return element_index;
}
element_index++;
}
obidebug(1, "\nCan't find element name");
free(elements_names);
return -1;
}
size_t obi_column_get_nb_elements_per_line(OBIDMS_column_p column)
{
return (column->header)->nb_elements_per_line;
}