Files
obitools3/src/obidms.c

1188 lines
30 KiB
C
Raw Normal View History

/********************************************************************
* OBIDMS functions *
********************************************************************/
/**
* @file obidms.c
* @author Eric Coissac (eric.coissac@metabarcoding.org)
* @date 23 May 2015
* @brief OBIDMS functions.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <libgen.h> /* <EC> : Added July 28th 2017 to include basename */
#include "obidms.h"
#include "obierrno.h"
#include "obidebug.h"
#include "obidmscolumn.h"
#include "obiview.h"
#include "obiblob_indexer.h"
#include "utils.h"
#include "obilittlebigman.h"
#define DEBUG_LEVEL 0 // TODO has to be defined somewhere else (cython compil flag?)
// Initialize global list of opened DMS
OBIDMS_p global_opened_dms_list[MAX_NB_OPENED_DMS+1] = { 0 };
/**************************************************************************
*
* 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 OBIDMS directory name from an OBIDMS name.
*
2015-06-10 15:19:02 +02:00
* The function builds the directory name corresponding to an OBIDMS.
* It also checks that the name is not too long.
*
* @warning The returned pointer has to be freed by the caller.
*
* @param dms_name The name of the OBIDMS.
*
* @returns A pointer to the directory name.
* @retval NULL if an error occurred.
*
* @since May 2015
* @author Eric Coissac (eric.coissac@metabarcoding.org)
*/
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);
/**
* Internal function adding a DMS in the global list of DMS opened by a program.
*
* @param dms A pointer on the DMS to add.
*
* @retval 0 if the operation was successfully completed.
* @retval -1 if an error occurred.
*
* @since October 2017
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
static int list_dms(OBIDMS_p dms);
/**
* Internal function removing a DMS from the global list of DMS opened by a program.
*
* @param dms A pointer on the DMS to remove.
*
* @since October 2017
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
static void unlist_dms(OBIDMS_p dms);
/************************************************************************
*
* 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_directory_name(const char* dms_name)
{
char* directory_name;
// Build the database directory name
2016-03-21 11:33:06 +01:00
directory_name = (char*) malloc((strlen(dms_name) + 8)*sizeof(char));
if (sprintf(directory_name, "%s.obidms", dms_name) < 0)
{
obi_set_errno(OBIDMS_MEMORY_ERROR);
obidebug(1, "\nProblem building an OBIDMS directory name");
return NULL;
}
// Test if the database name is not too long
if (strlen(directory_name) >= OBIDMS_MAX_NAME)
{
obi_set_errno(OBIDMS_LONG_NAME_ERROR);
obidebug(1, "\nProblem building an OBIDMS directory name");
free(directory_name);
return NULL;
}
return directory_name;
}
2015-06-10 15:19:02 +02:00
static char* build_infos_file_name(const char* dms_name)
{
char* file_name;
// Build file name
2016-03-21 11:33:06 +01:00
file_name = (char*) malloc((strlen(dms_name) + 7)*sizeof(char));
if (sprintf(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
if (close(infos_file_descriptor) < 0)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError closing a DMS information file");
return -1;
}
return 0;
}
static int list_dms(OBIDMS_p dms)
{
int i = 0;
while (global_opened_dms_list[i] != NULL)
i++;
if (i == (MAX_NB_OPENED_DMS-1))
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError opening a DMS: maximum number of DMS opened by a program reached");
return -1;
}
global_opened_dms_list[i] = dms;
return 0;
}
static void unlist_dms(OBIDMS_p dms)
{
int i = 0;
while (global_opened_dms_list[i] != dms)
i++;
while (global_opened_dms_list[i] != NULL)
{
global_opened_dms_list[i] = global_opened_dms_list[i+1];
i++;
}
}
/**********************************************************************
*
* 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
*
**********************************************************************/
int obi_dms_exists(const char* dms_path)
{
struct stat buffer;
2016-02-18 10:38:51 +01:00
char* directory_name;
int check_dir;
// Build and check the directory name
directory_name = build_directory_name(dms_path);
if (directory_name == NULL)
return -1;
check_dir = stat(directory_name, &buffer);
free(directory_name);
if (check_dir == 0)
return 1;
else
return 0;
}
OBIDMS_p obi_create_dms(const char* dms_path)
{
char* directory_name;
DIR* dms_dir;
int dms_file_descriptor;
// Build and check the directory name
directory_name = build_directory_name(dms_path);
if (directory_name == NULL)
return NULL;
// Try to create the directory
if (mkdir(directory_name, 00777) < 0)
{
if (errno == EEXIST)
{
obi_set_errno(OBIDMS_EXIST_ERROR);
obidebug(1, "\nAn OBIDMS directory with the same name already exists in this directory.");
}
else
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nProblem creating an OBIDMS directory");
free(directory_name);
return NULL;
}
// Get file descriptor of DMS directory to create other directories
dms_dir = opendir(directory_name);
if (dms_dir == NULL)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nProblem opening a newly created OBIDMS directory");
free(directory_name);
return NULL;
}
free(directory_name);
dms_file_descriptor = dirfd(dms_dir);
if (dms_file_descriptor < 0)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nProblem getting the file descriptor of a newly created OBIDMS directory");
return NULL;
}
2016-04-12 14:53:33 +02:00
// Create the indexer directory
if (mkdirat(dms_file_descriptor, INDEXER_DIR_NAME, 00777) < 0)
{
2016-04-12 14:53:33 +02:00
obi_set_errno(OBI_INDEXER_ERROR);
obidebug(1, "\nProblem creating the indexer directory");
return NULL;
}
// Create the view directory
if (mkdirat(dms_file_descriptor, VIEW_DIR_NAME, 00777) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nProblem creating the view directory");
return NULL;
}
// Create the taxonomy directory
if (mkdirat(dms_file_descriptor, TAXONOMY_DIR_NAME, 00777) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nProblem creating the taxonomy directory");
return NULL;
}
/*
// Isolate the dms name
j = 0;
for (i=0; i<strlen(dms_path); i++)
{
if (dms_path[i] == '/')
j = i+1;
i++;
}
*/
// Create the informations file
2017-08-20 17:25:58 +02:00
if (create_dms_infos_file(dms_file_descriptor, basename((char*)dms_path)) < 0)
return NULL;
return obi_open_dms(dms_path);
}
2015-06-10 15:19:02 +02:00
OBIDMS_p obi_open_dms(const char* dms_path)
{
OBIDMS_p dms;
2016-08-30 11:09:45 +02:00
char* complete_dms_path;
char* infos_file_name;
int infos_file_descriptor;
bool little_endian_dms;
bool little_endian_platform;
dms = NULL;
// Allocate the data structure
dms = (OBIDMS_p) malloc(sizeof(OBIDMS_t));
if (dms == NULL)
{
obi_set_errno(OBIDMS_MEMORY_ERROR);
obidebug(1, "\nError allocating the memory for the OBIDMS structure");
return NULL;
}
/*
// Isolate and store the dms name
j = 0;
for (i=0; i<strlen(dms_path); i++)
{
if (dms_path[i] == '/')
j = i+1;
i++;
}
*/
2017-08-20 17:25:58 +02:00
strcpy(dms->dms_name, basename((char*)dms_path));
2016-08-30 11:09:45 +02:00
// Build and check the directory name including the relative path
complete_dms_path = build_directory_name(dms_path);
if (complete_dms_path == NULL)
{
free(dms);
return NULL;
}
2016-08-30 11:09:45 +02:00
// Get and store the absolute path to the DMS directory
if (realpath(complete_dms_path, dms->directory_path) == NULL)
{
2016-08-30 11:09:45 +02:00
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError getting the absolute path to the DMS directory (DMS does not exist)");
2016-08-30 11:09:45 +02:00
free(complete_dms_path);
return NULL;
}
2016-08-30 11:09:45 +02:00
free(complete_dms_path);
// Try to open the directory
dms->directory = opendir(dms->directory_path);
if (dms->directory == NULL)
{
switch (errno)
{
case ENOENT:
obi_set_errno(OBIDMS_NOT_EXIST_ERROR);
break;
case EACCES:
obi_set_errno(OBIDMS_ACCESS_ERROR);
break;
case ENOMEM:
obi_set_errno(OBIDMS_MEMORY_ERROR);
break;
default:
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
}
obidebug(1, "\nCan't open OBIDMS directory");
free(dms);
return NULL;
}
// Get and store file descriptor of DMS directory to open the informations file
dms->dir_fd = dirfd(dms->directory);
if (dms->dir_fd < 0)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError getting the file descriptor for a newly created OBIDMS directory");
closedir(dms->directory);
free(dms);
return NULL;
}
// Open informations file to check endianness
infos_file_name = build_infos_file_name(dms->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;
}
if (close(infos_file_descriptor) < 0)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError closing a DMS information file");
return NULL;
}
dms->little_endian = little_endian_dms;
2016-04-12 14:53:33 +02:00
// Open the indexer directory
dms->indexer_directory = opendir_in_dms(dms, INDEXER_DIR_NAME);
if (dms->indexer_directory == NULL)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
2016-04-12 14:53:33 +02:00
obidebug(1, "\nError opening the indexer directory");
closedir(dms->directory);
free(dms);
return NULL;
}
2016-04-12 14:53:33 +02:00
// Store the indexer directory's file descriptor
dms->indexer_dir_fd = dirfd(dms->indexer_directory);
if (dms->indexer_dir_fd < 0)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
2016-04-12 14:53:33 +02:00
obidebug(1, "\nError getting the file descriptor of the indexer directory");
closedir(dms->indexer_directory);
closedir(dms->directory);
free(dms);
return NULL;
}
// Open the view directory
dms->view_directory = opendir_in_dms(dms, VIEW_DIR_NAME);
if (dms->view_directory == NULL)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError opening the view directory");
closedir(dms->indexer_directory);
closedir(dms->directory);
free(dms);
return NULL;
}
// Store the view directory's file descriptor
dms->view_dir_fd = dirfd(dms->view_directory);
if (dms->view_dir_fd < 0)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError getting the file descriptor of the view directory");
closedir(dms->view_directory);
closedir(dms->directory);
free(dms);
return NULL;
}
// Open the taxonomy directory
dms->tax_directory = opendir_in_dms(dms, TAXONOMY_DIR_NAME);
if (dms->tax_directory == NULL)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError opening the taxonomy directory");
closedir(dms->indexer_directory);
closedir(dms->view_directory);
closedir(dms->directory);
free(dms);
return NULL;
}
// Store the taxonomy directory's file descriptor
dms->tax_dir_fd = dirfd(dms->tax_directory);
if (dms->tax_dir_fd < 0)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError getting the file descriptor of the taxonomy directory");
closedir(dms->indexer_directory);
closedir(dms->tax_directory);
closedir(dms->view_directory);
closedir(dms->directory);
free(dms);
return NULL;
}
// Clean unfinished views
if (obi_clean_unfinished_views(dms) < 0)
{
obidebug(1, "\nError cleaning unfinished views when opening an OBIDMS");
closedir(dms->indexer_directory);
closedir(dms->tax_directory);
closedir(dms->view_directory);
closedir(dms->directory);
free(dms);
return NULL;
}
// Clean unfinished columns
if (obi_clean_unfinished_columns(dms) < 0)
{
obidebug(1, "\nError cleaning unfinished columns when opening an OBIDMS");
closedir(dms->indexer_directory);
closedir(dms->tax_directory);
closedir(dms->view_directory);
closedir(dms->directory);
free(dms);
return NULL;
}
// Initialize the list of opened columns
dms->opened_columns = (Opened_columns_list_p) malloc(sizeof(Opened_columns_list_t));
(dms->opened_columns)->nb_opened_columns = 0;
// Initialize the list of opened indexers
2016-04-12 14:53:33 +02:00
dms->opened_indexers = (Opened_indexers_list_p) malloc(sizeof(Opened_indexers_list_t));
(dms->opened_indexers)->nb_opened_indexers = 0;
// Add in the global list of opened DMS
list_dms(dms);
return dms;
}
2015-06-10 15:19:02 +02:00
OBIDMS_p obi_test_open_dms(const char* dms_name)
{
int exists;
exists = obi_dms_exists(dms_name);
switch (exists)
{
case 0:
return NULL;
case 1:
return obi_open_dms(dms_name);
};
obidebug(1, "\nError checking if an OBIDMS directory exists");
return NULL;
}
OBIDMS_p obi_dms(const char* dms_name)
{
int exists;
exists = obi_dms_exists(dms_name);
switch (exists)
{
case 0:
return obi_create_dms(dms_name);
case 1:
return obi_open_dms(dms_name);
};
obidebug(1, "\nError checking if an OBIDMS directory exists");
return NULL;
}
int obi_close_dms(OBIDMS_p dms)
{
if (dms != NULL)
{
// Close all columns
while ((dms->opened_columns)->nb_opened_columns > 0)
obi_close_column(*((dms->opened_columns)->columns));
// Close dms, and view, indexer and taxonomy directories
if (closedir(dms->indexer_directory) < 0)
{
2016-04-12 14:53:33 +02:00
obi_set_errno(OBI_INDEXER_ERROR);
obidebug(1, "\nError closing an indexer directory");
free(dms);
return -1;
}
if (closedir(dms->view_directory) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError closing a view directory");
free(dms);
return -1;
}
if (closedir(dms->tax_directory) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError closing a taxonomy directory");
free(dms);
return -1;
}
if (closedir(dms->directory) < 0)
{
obi_set_errno(OBIDMS_MEMORY_ERROR);
obidebug(1, "\nError closing an OBIDMS directory");
free(dms);
return -1;
}
// Remove DMS from global list of opened DMS
unlist_dms(dms);
free(dms);
}
return 0;
}
OBIDMS_column_p obi_dms_get_column_from_list(OBIDMS_p dms, const char* column_name, obiversion_t version)
{
int i;
for (i=0; i < ((dms->opened_columns)->nb_opened_columns); i++)
{
if (!strcmp(((*(((dms->opened_columns)->columns)+i))->header)->name, column_name)
&& (((*(((dms->opened_columns)->columns)+i))->header)->version == version))
{ // Found the column already opened, return it
return *(((dms->opened_columns)->columns)+i);
}
}
// Didn't find the column
return NULL;
}
void obi_dms_list_column(OBIDMS_p dms, OBIDMS_column_p column) // TODO add check if column already in list?
{
*(((dms->opened_columns)->columns)+((dms->opened_columns)->nb_opened_columns)) = column;
((dms->opened_columns)->nb_opened_columns)++;
}
int obi_dms_unlist_column(OBIDMS_p dms, OBIDMS_column_p column)
{
int i;
Opened_columns_list_p columns_list;
columns_list = dms->opened_columns;
for (i=0; i < columns_list->nb_opened_columns; i++)
{
if (!strcmp(((*((columns_list->columns)+i))->header)->name, (column->header)->name)
&& (((*((columns_list->columns)+i))->header)->version == (column->header)->version))
{ // Found the column. Rearrange list
(columns_list->nb_opened_columns)--;
(columns_list->columns)[i] = (columns_list->columns)[columns_list->nb_opened_columns];
return 0;
}
}
obidebug(1, "\nCould not find the column to delete from list of open columns");
return -1;
}
Obi_indexer_p obi_dms_get_indexer_from_list(OBIDMS_p dms, const char* indexer_name)
{
int i;
Opened_indexers_list_p indexers_list;
indexers_list = dms->opened_indexers;
for (i=0; i < (indexers_list->nb_opened_indexers); i++)
{
if (!strcmp(obi_indexer_get_name((indexers_list->indexers)[i]), indexer_name))
{ // Found the indexer already opened, return it
return (indexers_list->indexers)[i];
}
}
// Didn't find the indexer
return NULL;
}
void obi_dms_list_indexer(OBIDMS_p dms, Obi_indexer_p indexer) // TODO add check if indexer already in list?
{
*(((dms->opened_indexers)->indexers)+((dms->opened_indexers)->nb_opened_indexers)) = indexer;
((dms->opened_indexers)->nb_opened_indexers)++;
}
int obi_dms_unlist_indexer(OBIDMS_p dms, Obi_indexer_p indexer)
{
int i;
Opened_indexers_list_p indexers_list;
indexers_list = dms->opened_indexers;
for (i=0; i < indexers_list->nb_opened_indexers; i++)
{
if (!strcmp(obi_indexer_get_name((indexers_list->indexers)[i]), indexer->name))
{ // Found the indexer. Rearrange list
(indexers_list->nb_opened_indexers)--;
(indexers_list->indexers)[i] = (indexers_list->indexers)[indexers_list->nb_opened_indexers];
return 0;
}
}
obidebug(1, "\nCould not find the indexer to delete from list of open indexers");
return -1;
}
char* obi_dms_get_dms_path(OBIDMS_p dms)
{
char* full_path;
full_path = (char*) malloc((MAX_PATH_LEN)*sizeof(char));
if (full_path == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for the char* path to a file or directory");
return NULL;
}
strcpy(full_path, dms->directory_path);
return full_path;
}
char* obi_dms_get_full_path(OBIDMS_p dms, const char* path_name)
{
char* full_path;
full_path = obi_dms_get_dms_path(dms);
strcat(full_path, "/");
strcat(full_path, path_name);
return full_path;
}
DIR* opendir_in_dms(OBIDMS_p dms, const char* path_name)
{
char* full_path;
DIR* directory;
full_path = obi_dms_get_full_path(dms, path_name);
if (full_path == NULL)
return NULL;
directory = opendir(full_path);
if (directory == NULL)
{
obi_set_errno(OBI_UTILS_ERROR);
obidebug(1, "\nError opening a directory");
}
free(full_path);
return directory;
}
// TODO move somewhere else maybe
// TODO discuss arguments
obiversion_t obi_import_column(const char* dms_path_1, const char* dms_path_2, const char* column_name, obiversion_t version_number)
{
OBIDMS_p dms_1;
OBIDMS_p dms_2;
OBIDMS_column_p column_1;
OBIDMS_column_p column_2;
OBIDMS_column_header_p header_1;
OBIDMS_column_header_p header_2;
int avl_exists;
const char* avl_name;
char* new_avl_name;
obiversion_t new_version;
int i;
int avl_count;
char* avl_name_1;
char* avl_name_2;
char* avl_file_path_1;
char* avl_file_path_2;
char* avl_data_file_path_1;
char* avl_data_file_path_2;
char* complete_avl_name;
Obi_indexer_p avl_group;
dms_1 = obi_open_dms(dms_path_1);
if (dms_1 == NULL)
{
obidebug(1, "\nError opening a DMS to import a column from it");
return -1;
}
dms_2 = obi_dms(dms_path_2);
if (dms_2 == NULL)
{
obidebug(1, "\nError opening or creating a DMS to import a column into it");
return -1;
}
column_1 = obi_open_column(dms_1, column_name, version_number);
if (column_1 == NULL)
{
obidebug(1, "\nError opening a column to import in another DMS");
return -1;
}
header_1 = column_1->header;
// Check if associated indexer exists BEFORE creating the new column as that will automatically create it if it doesn't already exist
avl_name = header_1->indexer_name;
avl_exists = obi_indexer_exists(dms_2, avl_name);
if (avl_exists == -1)
{
obidebug(1, "\nError checking if an indexer exists while importing a column");
return -1;
}
if (avl_exists)
// Use automatic name
new_avl_name = NULL;
else
// Name can stay the same
new_avl_name = header_1->indexer_name;
// Create new column
column_2 = obi_create_column(dms_2, column_name, header_1->returned_data_type, header_1->line_count,
header_1->nb_elements_per_line, header_1->elements_names, true, header_1->tuples,
new_avl_name, (header_1->associated_column).column_name, (header_1->associated_column).version,
header_1->comments);
if (column_2 == NULL)
{
obidebug(1, "\nError creating the new column while importing a column");
return -1;
}
header_2 = column_2->header;
// Get the new version to return
new_version = header_2->version;
// Copy lines_used informations
header_2->lines_used = header_1->lines_used;
// Copy data TODO check how much time and memory that costs, eventually use write() instead
memcpy(column_2->data, column_1->data, header_1->data_size);
// Copy the AVL files if there are some (overwriting the automatically created files)
if ((header_1->returned_data_type == OBI_STR) || (header_1->returned_data_type == OBI_SEQ) || (header_1->returned_data_type == OBI_QUAL))
{
avl_name_1 = (char*) malloc((strlen(header_1->indexer_name) + 1) * sizeof(char));
if (avl_name_1 == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for an AVL name when importing a column");
return -1;
}
strcpy(avl_name_1, header_1->indexer_name);
avl_name_2 = (char*) malloc((strlen(header_2->indexer_name) + 1) * sizeof(char));
if (avl_name_2 == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for an AVL name when importing a column");
return -1;
}
strcpy(avl_name_2, header_2->indexer_name);
avl_count = (column_1->indexer->last_avl_idx) + 1;
// Close column to manipulate AVL files safely (but not multithreading safe) (TODO not sure how important this is, can't find informations about conflicts when using write() on mmapped files)
if (obi_close_column(column_1) < 0)
{
obidebug(1, "\nError closing an imported column");
return -1;
}
if (obi_close_column(column_2) < 0)
{
obidebug(1, "\nError closing an imported column");
return -1;
}
for (i=0; i < avl_count; i++)
{
avl_file_path_1 = obi_get_full_path_of_avl_file_name(dms_1, avl_name_1, i);
if (avl_file_path_1 == NULL)
{
obidebug(1, "\nError getting an AVL file path while importing a column");
return -1;
}
avl_data_file_path_1 = obi_get_full_path_of_avl_data_file_name(dms_1, avl_name_1, i);
if (avl_data_file_path_1 == NULL)
{
obidebug(1, "\nError getting an AVL file path while importing a column");
return -1;
}
avl_file_path_2 = obi_get_full_path_of_avl_file_name(dms_2, avl_name_2, i);
if (avl_file_path_2 == NULL)
{
obidebug(1, "\nError getting an AVL file path while importing a column");
return -1;
}
avl_data_file_path_2 = obi_get_full_path_of_avl_data_file_name(dms_2, avl_name_2, i);
if (avl_data_file_path_2 == NULL)
{
obidebug(1, "\nError getting an AVL file path while importing a column");
return -1;
}
// Copy AVL file
if (copy_file(avl_file_path_1, avl_file_path_2) < 0)
{
obidebug(1, "\nError copying an AVL file while importing a column");
return -1;
}
// Copy AVL data file
if (copy_file(avl_data_file_path_1, avl_data_file_path_2) < 0)
{
obidebug(1, "\nError copying a data AVL file while importing a column");
return -1;
}
free(avl_file_path_1);
free(avl_file_path_2);
free(avl_data_file_path_1);
free(avl_data_file_path_2);
}
// Update AVL names in headers
avl_group = obi_open_indexer(dms_2, avl_name_2);
for (i=0; i < avl_count; i++)
{
complete_avl_name = obi_build_avl_name_with_idx(avl_name_2, i);
strcpy((((avl_group->sub_avls)[i])->header)->avl_name, complete_avl_name);
strcpy(((((avl_group->sub_avls)[i])->data)->header)->avl_name, complete_avl_name);
free(complete_avl_name);
}
free(avl_name_1);
free(avl_name_2);
}
else
{
if (obi_close_column(column_1) < 0)
{
obidebug(1, "\nError closing an imported column");
return -1;
}
if (obi_close_column(column_2) < 0)
{
obidebug(1, "\nError closing an imported column");
return -1;
}
}
// Copy associated column (update version)
//new_associated_col_version = import_column(dms_path_1, dms_path_2, header_1->associated_column_name, header_1->associated_column_version);
// TODO no? because if iterating over all columns in a view etc.... iterate and change associated columns version refs afterwards?
// Close the DMS
obi_close_dms(dms_1);
obi_close_dms(dms_2);
return new_version;
}
// TODO move somewhere else maybe
// TODO discuss arguments
int obi_import_view(const char* dms_path_1, const char* dms_path_2, const char* view_name_1, const char* view_name_2)
{
OBIDMS_p dms_1;
OBIDMS_p dms_2;
Obiview_p view_1;
Obiview_p view_2;
obiversion_t new_version;
int i;
dms_1 = obi_open_dms(dms_path_1);
if (dms_1 == NULL)
{
obidebug(1, "\nError opening a DMS to import a view from it");
return -1;
}
dms_2 = obi_dms(dms_path_2);
if (dms_2 == NULL)
{
obidebug(1, "\nError opening or creating a DMS to import a view into it");
return -1;
}
// Open view to import
view_1 = obi_open_view(dms_1, view_name_1);
// Create new view
if (strcmp((view_1->infos)->view_type, VIEW_TYPE_NUC_SEQS) == 0)
view_2 = obi_new_view_nuc_seqs(dms_2, view_name_2, NULL, NULL, (view_1->infos)->comments, false);
else // Non-typed view
view_2 = obi_new_view(dms_2, view_name_2, NULL, NULL, (view_1->infos)->comments);
// Import line count
view_2->infos->line_count = view_1->infos->line_count;
// Import the line selection column if there is one
if (! view_1->infos->all_lines)
{
view_2->infos->all_lines = false;
new_version = obi_import_column(dms_path_1, dms_path_2, ((view_1->infos)->line_selection).column_name, ((view_1->infos)->line_selection).version);
if (new_version == -1)
{
obidebug(1, "\nError importing a line selection column while importing a view");
return -1;
}
strcpy(((view_2->infos)->line_selection).column_name, ((view_1->infos)->line_selection).column_name);
((view_2->infos)->line_selection).version = new_version;
view_2->line_selection = obi_open_column(dms_2, ((view_2->infos)->line_selection).column_name, ((view_2->infos)->line_selection).version);
if (view_2->line_selection == NULL)
{
obidebug(1, "\nError opening a line selection column while importing a view");
return -1;
}
}
// Import each column and update with the new version number
for (i=0; i < (view_1->infos->column_count); i++)
{
new_version = obi_import_column(dms_path_1, dms_path_2, ((((view_1->infos)->column_references)[i]).column_refs).column_name, ((((view_1->infos)->column_references)[i]).column_refs).version);
if (new_version == -1)
{
obidebug(1, "\nError importing a column while importing a view");
return -1;
}
if (obi_view_add_column(view_2,
((((view_1->infos)->column_references)[i]).column_refs).column_name,
new_version,
(((view_1->infos)->column_references)[i]).alias,
0,
0,
0,
NULL,
false,
NULL,
NULL,
-1,
NULL,
false) < 0)
{
obidebug(1, "\nError adding a column to a view while importing it");
return -1;
}
}
// Close the views
if (obi_save_and_close_view(view_1) < 0)
{
obidebug(1, "\nError closing a view after importing from it");
return -1;
}
if (obi_save_and_close_view(view_2) < 0)
{
obidebug(1, "\nError closing a view after importing it");
return -1;
}
// Close the DMS
obi_close_dms(dms_1);
obi_close_dms(dms_2);
return 0;
}
void obi_close_atexit()
{
int i=0;
while (global_opened_dms_list[i] != NULL)
{
obi_close_dms(global_opened_dms_list[i]);
i++;
}
}