OBIDMS: Opened DMS now have a counter associated so that DMS are not

actually opened several times by the same program, which triggers the
cleaning of unfinished views and columns (to discuss)
This commit is contained in:
Celine Mercier
2017-11-24 17:58:47 +01:00
parent ee5d647d0d
commit 9e3ac477eb
4 changed files with 167 additions and 54 deletions

View File

@ -34,8 +34,10 @@
#define DEBUG_LEVEL 0 // TODO has to be defined somewhere else (cython compil flag?)
// Initialize global list of opened DMS
// Initialize global list of opened DMS and their associated counters
OBIDMS_p global_opened_dms_list[MAX_NB_OPENED_DMS+1] = { 0 };
int global_opened_dms_counter_list[MAX_NB_OPENED_DMS+1] = { 0 };
/**************************************************************************
@ -120,11 +122,44 @@ 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.
* @param force Whether the DMS should be unlisted even if it is opened more than once.
*
* @retval 0 if the operation was successfully completed.
* @retval -1 if the DMS was not found.
*
* @since October 2017
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
static void unlist_dms(OBIDMS_p dms);
static int unlist_dms(OBIDMS_p dms, bool force);
/**
* Internal function checking if a DMS is already in the global list of DMS opened by the program.
*
* @param full_dms_path The absolute path to the DMS directory.
*
* @returns A pointer on the DMS if it is already opened, or NULL if it was not opened.
*
* @since November 2017
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
static OBIDMS_p check_if_dms_in_list(const char* full_dms_path);
/**
* Internal function returning the count for an opened DMS (how many times the DMS is opened) in the global list of DMS opened by the program.
*
* @param dms A pointer on the DMS.
*
* @returns The count indicating how many times the DMS has been opened by the program.
*
* @retval -1 if the DMS was not found.
*
* @since November 2017
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
static int dms_count_in_list(OBIDMS_p dms);
/************************************************************************
@ -238,7 +273,7 @@ int create_dms_infos_file(int dms_file_descriptor, const char* dms_name)
static int list_dms(OBIDMS_p dms)
{
int i = 0;
while (global_opened_dms_list[i] != NULL)
while ((global_opened_dms_list[i] != NULL) && (global_opened_dms_list[i] != dms))
i++;
if (i == (MAX_NB_OPENED_DMS-1))
{
@ -246,21 +281,63 @@ static int list_dms(OBIDMS_p dms)
obidebug(1, "\nError opening a DMS: maximum number of DMS opened by a program reached");
return -1;
}
global_opened_dms_list[i] = dms;
if (global_opened_dms_list[i] == NULL)
{ // new dms
global_opened_dms_list[i] = dms;
global_opened_dms_counter_list[i] = 0;
}
else
{ // already opened dms
(global_opened_dms_counter_list[i])++;
}
return 0;
}
static void unlist_dms(OBIDMS_p dms)
static int unlist_dms(OBIDMS_p dms, bool force)
{
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];
while ((global_opened_dms_list[i] != dms) && (i <= MAX_NB_OPENED_DMS))
i++;
if (i == MAX_NB_OPENED_DMS)
return -1; // DMS not found
// If opened more than once, and the unlisting is not forced, decrement counter
if ((global_opened_dms_counter_list[i] > 1) && (! force))
(global_opened_dms_counter_list[i])--;
else
{ // If opened once or forced unlisting, delete and unlist by shifting the list
while (global_opened_dms_list[i] != NULL)
{
global_opened_dms_list[i] = global_opened_dms_list[i+1];
i++;
}
}
return 0;
}
static OBIDMS_p check_if_dms_in_list(const char* full_dms_path)
{
int i = 0;
while ((i <= MAX_NB_OPENED_DMS) && (global_opened_dms_list[i] != NULL) && (strcmp(global_opened_dms_list[i]->directory_path, full_dms_path) != 0))
i++;
if (i == MAX_NB_OPENED_DMS)
return NULL; // DMS not found
if (global_opened_dms_list[i] != NULL)
return global_opened_dms_list[i];
return NULL;
}
static int dms_count_in_list(OBIDMS_p dms)
{
int i = 0;
while ((i <= MAX_NB_OPENED_DMS) && (global_opened_dms_list[i] != dms))
i++;
if (i == MAX_NB_OPENED_DMS)
return -1; // DMS not found
return global_opened_dms_counter_list[i];
}
@ -384,7 +461,8 @@ OBIDMS_p obi_create_dms(const char* dms_path)
OBIDMS_p obi_open_dms(const char* dms_path)
{
OBIDMS_p dms;
char* complete_dms_path;
char* relative_dms_path;
char* absolute_dms_path;
char* infos_file_name;
int infos_file_descriptor;
bool little_endian_dms;
@ -392,6 +470,32 @@ OBIDMS_p obi_open_dms(const char* dms_path)
dms = NULL;
// Build and check the directory name including the relative path
relative_dms_path = build_directory_name(dms_path);
if (relative_dms_path == NULL)
return NULL;
// Get and store the absolute path to the DMS directory
absolute_dms_path = realpath(relative_dms_path, NULL);
if (absolute_dms_path == NULL)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError getting the absolute path to the DMS directory (DMS does not exist)");
free(relative_dms_path);
return NULL;
}
free(relative_dms_path);
// Check if the DMS is already opened
dms = check_if_dms_in_list(absolute_dms_path);
if (dms != NULL)
{
list_dms(dms);
free(absolute_dms_path);
return dms;
}
// Allocate the data structure
dms = (OBIDMS_p) malloc(sizeof(OBIDMS_t));
if (dms == NULL)
@ -401,36 +505,8 @@ OBIDMS_p obi_open_dms(const char* dms_path)
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++;
}
*/
strcpy(dms->dms_name, basename((char*)dms_path));
// 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;
}
// Get and store the absolute path to the DMS directory
if (realpath(complete_dms_path, dms->directory_path) == NULL)
{
obi_set_errno(OBIDMS_UNKNOWN_ERROR);
obidebug(1, "\nError getting the absolute path to the DMS directory (DMS does not exist)");
free(complete_dms_path);
return NULL;
}
free(complete_dms_path);
strcpy(dms->directory_path, absolute_dms_path);
// Try to open the directory
dms->directory = opendir(dms->directory_path);
@ -620,7 +696,18 @@ OBIDMS_p obi_open_dms(const char* dms_path)
(dms->opened_indexers)->nb_opened_indexers = 0;
// Add in the global list of opened DMS
list_dms(dms);
if (list_dms(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->opened_columns);
free(dms->opened_indexers);
free(dms);
return NULL;
}
return dms;
}
@ -664,8 +751,27 @@ OBIDMS_p obi_dms(const char* dms_name)
}
int obi_close_dms(OBIDMS_p dms)
int obi_close_dms(OBIDMS_p dms, bool force)
{
int dms_counter;
if (!force)
{
dms_counter = dms_count_in_list(dms);
if (dms_counter < 0)
obidebug(1, "\nError checking the counter of an OBIDMS in the global list of opened OBIDMS");
if (dms_counter > 1) // Don't close if the DMS is opened more than once
{
if (unlist_dms(dms, force) < 0)
{
obidebug(1, "\nError decrementing the counter of an OBIDMS in the global list of opened OBIDMS");
return -1;
}
return 0;
}
}
if (dms != NULL)
{
// Close all columns
@ -703,7 +809,12 @@ int obi_close_dms(OBIDMS_p dms)
}
// Remove DMS from global list of opened DMS
unlist_dms(dms);
if (unlist_dms(dms, force) < 0)
{
obidebug(1, "\nError removing an OBIDMS from the global list of opened OBIDMS when closing it");
free(dms);
return -1;
}
free(dms);
}
@ -1060,8 +1171,8 @@ obiversion_t obi_import_column(const char* dms_path_1, const char* dms_path_2, c
// 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);
obi_close_dms(dms_1, false);
obi_close_dms(dms_2, false);
return new_version;
}
@ -1167,8 +1278,8 @@ int obi_import_view(const char* dms_path_1, const char* dms_path_2, const char*
}
// Close the DMS
obi_close_dms(dms_1);
obi_close_dms(dms_2);
obi_close_dms(dms_1, false);
obi_close_dms(dms_2, false);
return 0;
}
@ -1180,7 +1291,7 @@ void obi_close_atexit()
while (global_opened_dms_list[i] != NULL)
{
obi_close_dms(global_opened_dms_list[i]);
obi_close_dms(global_opened_dms_list[i], true);
i++;
}
}