diff --git a/python/obitools3/obidms/_obidms.pyx b/python/obitools3/obidms/_obidms.pyx index 885ba81..db16e98 100644 --- a/python/obitools3/obidms/_obidms.pyx +++ b/python/obitools3/obidms/_obidms.pyx @@ -66,12 +66,12 @@ cdef class OBIDMS : cpdef close(self) : - #TODO close all columns + #TODO close all columns (needs to be discussed) if (obi_close_dms(self.pointer)) < 0 : raise Exception("Problem closing an OBIDMS") - cpdef dict list(self): + cpdef dict list(self): # TDODO This is a temporary function that will be rewritten # Declarations cdef object p @@ -100,13 +100,12 @@ cdef class OBIDMS : data_type = bytes2str(name_data_type(header.data_type)) line_count = header.line_count creation_date = bytes2str(obi_column_format_date(header.creation_date)) - obi_unmap_header(header) # TODO check if error? but C will already warn and there's nothing to do + obi_unmap_header(header) latest_version = obi_column_get_latest_version_from_name(self.pointer, column_name_b) dms[column_name]['data_type'] = data_type dms[column_name]['latest_version'] = latest_version dms[column_name]['line_count'] = line_count dms[column_name]['creation_date'] = creation_date - # TODO : actually get all the informations in the header print("{:<30} {:<12} {:<25} {:<30} {:<40}".format(column_name, data_type, latest_version, line_count, creation_date)) return dms diff --git a/python/obitools3/obidms/capi/obidmscolumn.pxd b/python/obitools3/obidms/capi/obidmscolumn.pxd index d08a2c2..196f310 100644 --- a/python/obitools3/obidms/capi/obidmscolumn.pxd +++ b/python/obitools3/obidms/capi/obidmscolumn.pxd @@ -15,7 +15,6 @@ from ..capi.obitypes cimport const_char_p, \ cdef extern from "obidmscolumn.h" nogil: struct OBIDMS_column_header_t: - bint little_endian size_t header_size size_t data_size index_t line_count diff --git a/src/obidms.c b/src/obidms.c index 06b9ae5..35ae74f 100644 --- a/src/obidms.c +++ b/src/obidms.c @@ -23,6 +23,7 @@ #include "obidebug.h" #include "obidmscolumn.h" #include "private_at_functions.h" +#include "obilittlebigman.h" #define DEBUG_LEVEL 0 // TODO has to be defined somewhere else (cython compil flag?) @@ -54,6 +55,44 @@ static char* build_directory_name(const char* dms_name); +/** + * Internal function building the informations file name from an OBIDMS name. + * + * The function builds the file name for the informations file of an OBIDMS. + * + * @warning The returned pointer has to be freed by the caller. + * + * @param dms_name The name of the OBIDMS. + * + * @returns A pointer to the file name. + * @retval NULL if an error occurred. + * + * @since November 2015 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +static char* build_infos_file_name(const char* dms_name); + + +/** + * 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_dms_infos_file(int dms_file_descriptor, const char* dms_name); + + /************************************************************************ * * 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 @@ -85,6 +124,74 @@ static char* build_directory_name(const char* dms_name) } +static char* build_infos_file_name(const char* dms_name) +{ + char* file_name; + + // Build file name + if (asprintf(&file_name, "%s_infos", dms_name) < 0) + { + obi_set_errno(OBIDMS_MEMORY_ERROR); + obidebug(1, "\nProblem building an informations file name"); + return NULL; + } + + return file_name; +} + + +int create_dms_infos_file(int dms_file_descriptor, const char* dms_name) +{ + char* file_name; + int infos_file_descriptor; + off_t file_size; + bool little_endian; + + file_size = sizeof(bool); + + // Create file name + file_name = build_infos_file_name(dms_name); + if (file_name == NULL) + return -1; + + // Create file + infos_file_descriptor = openat(dms_file_descriptor, file_name, O_RDWR | O_CREAT | O_EXCL, 0777); + if (infos_file_descriptor < 0) + { + obi_set_errno(OBIDMS_UNKNOWN_ERROR); + obidebug(1, "\nError creating an informations file"); + free(file_name); + return -1; + } + + free(file_name); + + // Truncate the infos file to the right size + if (ftruncate(infos_file_descriptor, file_size) < 0) + { + obi_set_errno(OBIDMS_UNKNOWN_ERROR); + obidebug(1, "\nError truncating an informations file"); + close(infos_file_descriptor); + return -1; + } + + // Write endianness + little_endian = obi_is_little_endian(); + if (write(infos_file_descriptor, &little_endian, sizeof(bool)) < ((ssize_t) sizeof(bool))) + { + obi_set_errno(OBIDMS_UNKNOWN_ERROR); + obidebug(1, "\nError writing the endianness in an informations file"); + close(infos_file_descriptor); + return -1; + } + + // Close file + close(infos_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 @@ -116,8 +223,8 @@ int obi_dms_exists(const char* dms_name) OBIDMS_p obi_create_dms(const char* dms_name) { char* directory_name; - DIR* dms_dir; - int dms_file_descriptor; + DIR* dms_dir; + int dms_file_descriptor; // Build and check the directory name directory_name = build_directory_name(dms_name); @@ -160,13 +267,17 @@ OBIDMS_p obi_create_dms(const char* dms_name) } // Create the arrays directory - if (mkdirat(dms_file_descriptor, ARRAY_DIR_NAME, 00777) < 0) + if (mkdirat(dms_file_descriptor, ARRAYS_DIR_NAME, 00777) < 0) { obi_set_errno(OBI_ARRAY_ERROR); obidebug(1, "\nProblem creating an arrays directory"); return NULL; } + // Create the informations file + if (create_dms_infos_file(dms_file_descriptor, dms_name) < 0) + return NULL; + return obi_open_dms(dms_name); } @@ -175,6 +286,10 @@ OBIDMS_p obi_open_dms(const char* dms_name) { OBIDMS_p dms; char* directory_name; + char* infos_file_name; + int infos_file_descriptor; + bool little_endian_dms; + bool little_endian_platform; dms = NULL; @@ -224,7 +339,7 @@ OBIDMS_p obi_open_dms(const char* dms_name) return NULL; } - // Get file descriptor of DMS directory to open the arrays directory + // Get and store file descriptor of DMS directory to open the informations file dms->dir_fd = dirfd(dms->directory); if (dms->dir_fd < 0) { @@ -235,8 +350,45 @@ OBIDMS_p obi_open_dms(const char* dms_name) return NULL; } + // Open informations file to check endianness + infos_file_name = build_infos_file_name(dms_name); + infos_file_descriptor = openat(dms->dir_fd, infos_file_name, O_RDONLY, 0777); + if (infos_file_descriptor < 0) + { + obi_set_errno(OBIDMS_UNKNOWN_ERROR); + obidebug(1, "\nError opening an informations file"); + closedir(dms->directory); + free(dms); + return NULL; + } + + free(infos_file_name); + + // Check endianness of the platform and DMS + little_endian_platform = obi_is_little_endian(); + if (read(infos_file_descriptor, &little_endian_dms, sizeof(bool)) < ((ssize_t) sizeof(bool))) + { + obi_set_errno(OBIDMS_UNKNOWN_ERROR); + obidebug(1, "\nError reading the endianness in an informations file"); + close(infos_file_descriptor); + closedir(dms->directory); + free(dms); + return NULL; + } + if (little_endian_platform != little_endian_dms) + { + obi_set_errno(OBIDMS_BAD_ENDIAN_ERROR); + obidebug(1, "\nError: The DMS and the platform have different endianness"); + close(infos_file_descriptor); + closedir(dms->directory); + free(dms); + return NULL; + } + + close(infos_file_descriptor); + // Open the arrays directory - dms->array_directory = private_opendirat(dms->dir_fd, ARRAY_DIR_NAME); + dms->array_directory = private_opendirat(dms->dir_fd, ARRAYS_DIR_NAME); if (dms->array_directory == NULL) { obi_set_errno(OBIDMS_UNKNOWN_ERROR); @@ -251,9 +403,9 @@ OBIDMS_p obi_open_dms(const char* dms_name) if (dms->array_dir_fd < 0) { obi_set_errno(OBIDMS_UNKNOWN_ERROR); - obidebug(1, "\nError opening the arrays directory"); - closedir(dms->directory); + obidebug(1, "\nError getting the file descriptor of the arrays directory"); closedir(dms->array_directory); + closedir(dms->directory); free(dms); return NULL; } diff --git a/src/obidms.h b/src/obidms.h index 8e371fb..d990e79 100644 --- a/src/obidms.h +++ b/src/obidms.h @@ -26,7 +26,7 @@ #define OBIDMS_MAX_NAME (2048) /**< The maximum length of an OBIDMS name. */ -#define ARRAY_DIR_NAME "arrays" /**< The name of the arrays directory. +#define ARRAYS_DIR_NAME "arrays" /**< The name of the arrays directory. */ diff --git a/src/obidmscolumn.c b/src/obidmscolumn.c index df9d580..5101f68 100644 --- a/src/obidmscolumn.c +++ b/src/obidmscolumn.c @@ -339,7 +339,7 @@ static obiversion_t create_version_file(OBIDMS_column_directory_p column_directo return -1; } - // Position offset to 0 to prepare for writing + // Position offset to 0 to prepare for writing // TODO Unnecessary? if (lseek(version_file_descriptor, 0, SEEK_SET) != 0) { obi_set_errno(OBICOL_UNKNOWN_ERROR); @@ -358,7 +358,7 @@ static obiversion_t create_version_file(OBIDMS_column_directory_p column_directo } // Prepare for unlocking - if (lseek(version_file_descriptor, 0, SEEK_SET) != 0) + if (lseek(version_file_descriptor, 0, SEEK_SET) != 0) // TODO Unnecessary? { obi_set_errno(OBICOL_UNKNOWN_ERROR); obidebug(1, "\nError preparing a version file for unlocking");