Made the handling of listing and unlisting opened columns and indexers

functions in the obidms files.
This commit is contained in:
Celine Mercier
2016-04-15 10:49:12 +02:00
parent 73d64e5aff
commit 71492ad229
8 changed files with 323 additions and 215 deletions

View File

@ -969,7 +969,7 @@ int add_new_avl_in_group(OBIDMS_avl_group_p avl_group)
(avl_group->current_avl_idx)++;
// Create the new AVL
(avl_group->sub_avls)[avl_group->current_avl_idx] = obi_create_avl(avl_group->dms, avl_group->avl_name, avl_group->current_avl_idx);
(avl_group->sub_avls)[avl_group->current_avl_idx] = obi_create_avl(avl_group->dms, avl_group->name, avl_group->current_avl_idx);
if ((avl_group->sub_avls)[avl_group->current_avl_idx] == NULL)
{
obidebug(1, "\nError creating a new AVL tree in a group");
@ -1611,11 +1611,6 @@ OBIDMS_avl_p obi_create_avl(OBIDMS_p dms, const char* avl_name, int avl_idx)
// Bloom filter
bloom_init(&((avl->header)->bloom_filter), MAX_NODE_COUNT_PER_AVL);
// Add in the list of opened AVL trees
*(((dms->opened_indexers)->indexers)+((dms->opened_indexers)->nb_opened_indexers)) = avl;
((dms->opened_indexers)->nb_opened_indexers)++;
avl->counter = 1;
if (avl_idx >= 0)
free(complete_avl_name);
@ -1636,7 +1631,6 @@ OBIDMS_avl_p obi_open_avl(OBIDMS_p dms, const char* avl_name, int avl_idx)
int avl_dir_file_descriptor;
OBIDMS_avl_data_p avl_data;
OBIDMS_avl_p avl;
size_t i;
// Get complete name of AVL if index
if (avl_idx >= 0)
@ -1657,18 +1651,6 @@ OBIDMS_avl_p obi_open_avl(OBIDMS_p dms, const char* avl_name, int avl_idx)
strcpy(complete_avl_name, avl_name);
}
// Check if the AVL tree is already in the list of opened AVL trees
for (i=0; i < ((dms->opened_indexers)->nb_opened_indexers); i++)
{
if (!strcmp(((*(((dms->opened_indexers)->indexers)+i))->header)->avl_name, complete_avl_name))
{ // Found the AVL tree already opened
((*(((dms->opened_indexers)->indexers)+i))->counter)++;
if (avl_idx >= 0)
free(complete_avl_name);
return *(((dms->opened_indexers)->indexers)+i);
}
}
// Open the AVL directory
avl_dir_name = get_full_path_of_avl_dir(dms, avl_name);
if (avl_dir_name == NULL)
@ -1877,11 +1859,6 @@ OBIDMS_avl_p obi_open_avl(OBIDMS_p dms, const char* avl_name, int avl_idx)
avl->dir_fd = avl_dir_file_descriptor;
avl->avl_fd = avl_file_descriptor;
// Add in the list of opened AVL trees
*(((dms->opened_indexers)->indexers)+((dms->opened_indexers)->nb_opened_indexers)) = avl;
((dms->opened_indexers)->nb_opened_indexers)++;
avl->counter = 1;
if (avl_idx >= 0)
free(complete_avl_name);
@ -1929,10 +1906,16 @@ OBIDMS_avl_group_p obi_create_avl_group(OBIDMS_p dms, const char* avl_name)
}
avl_group->current_avl_idx = 0;
strcpy(avl_group->avl_name, avl_name);
strcpy(avl_group->name, avl_name);
avl_group->dms = dms;
// Add in the list of open indexers
obi_dms_list_indexer(dms, avl_group);
// Set counter to 1
avl_group->counter = 1;
return avl_group;
}
@ -1944,7 +1927,14 @@ OBIDMS_avl_group_p obi_open_avl_group(OBIDMS_p dms, const char* avl_name)
int avl_count;
int i;
// TODO check that the group isn't already open
// Check if the group isn't already open
avl_group = obi_dms_get_indexer_from_list(dms, avl_name);
if (avl_group != NULL) // Found it
{
// Increment counter
(avl_group->counter)++;
return avl_group;
}
avl_group = (OBIDMS_avl_group_p) malloc(sizeof(OBIDMS_avl_group_t));
if (avl_group == NULL)
@ -1973,10 +1963,16 @@ OBIDMS_avl_group_p obi_open_avl_group(OBIDMS_p dms, const char* avl_name)
return NULL;
}
avl_group->current_avl_idx = avl_count-1; // TODO latest. discuss
strcpy(avl_group->avl_name, avl_name);
strcpy(avl_group->name, avl_name);
avl_group->dms = dms;
// Add in the list of open indexers
obi_dms_list_indexer(dms, avl_group);
// Set counter to 1
avl_group->counter = 1;
return avl_group;
}
@ -1984,51 +1980,29 @@ OBIDMS_avl_group_p obi_open_avl_group(OBIDMS_p dms, const char* avl_name)
int obi_close_avl(OBIDMS_avl_p avl)
{
int ret_val = 0;
size_t i;
Opened_indexers_list_p indexers_list;
OBIDMS_p dms;
dms = avl->dms;
ret_val = close_avl_data(avl->data);
indexers_list = dms->opened_indexers;
ret_val = truncate_avl_to_size_used(avl);
(avl->counter)--;
if (avl->counter == 0)
if (munmap(avl->tree, (((avl->header)->nb_items_max) * sizeof(AVL_node_t))) < 0)
{
// Delete from the list of opened avls
for (i=0; i < (indexers_list->nb_opened_indexers); i++)
{
if (!strcmp(((*((indexers_list->indexers)+i))->header)->avl_name, (avl->header)->avl_name))
{ // Found the avl. Rearrange list
(indexers_list->nb_opened_indexers)--;
(indexers_list->indexers)[i] = (indexers_list->indexers)[indexers_list->nb_opened_indexers];
}
}
ret_val = close_avl_data(avl->data);
ret_val = truncate_avl_to_size_used(avl);
if (munmap(avl->tree, (((avl->header)->nb_items_max) * sizeof(AVL_node_t))) < 0)
{
obi_set_errno(OBI_AVL_ERROR);
obidebug(1, "\nError munmapping the tree of an AVL tree file");
ret_val = -1;
}
if (munmap(avl->header, (avl->header)->header_size) < 0)
{
obi_set_errno(OBI_AVL_ERROR);
obidebug(1, "\nError munmapping the header of an AVL tree file");
ret_val = -1;
}
close(avl->avl_fd);
free(avl);
obi_set_errno(OBI_AVL_ERROR);
obidebug(1, "\nError munmapping the tree of an AVL tree file");
ret_val = -1;
}
if (munmap(avl->header, (avl->header)->header_size) < 0)
{
obi_set_errno(OBI_AVL_ERROR);
obidebug(1, "\nError munmapping the header of an AVL tree file");
ret_val = -1;
}
close(avl->avl_fd);
free(avl);
return ret_val;
}
@ -2040,10 +2014,21 @@ int obi_close_avl_group(OBIDMS_avl_group_p avl_group)
ret_val = 0;
for (i=0; i < (avl_group->current_avl_idx); i++)
if (obi_close_avl((avl_group->sub_avls)[i]) < 0)
ret_val = -1;
free(avl_group);
(avl_group->counter)--;
if (avl_group->counter == 0)
{
// Delete from the list of opened indexers
ret_val = obi_dms_unlist_indexer(avl_group->dms, avl_group);
// Close each AVL of the group
for (i=0; i < (avl_group->current_avl_idx); i++)
if (obi_close_avl((avl_group->sub_avls)[i]) < 0)
ret_val = -1;
free(avl_group);
}
return ret_val;
}

View File

@ -152,8 +152,6 @@ typedef struct OBIDMS_avl {
*/
int avl_fd; /**< The file descriptor of the file containing the AVL tree.
*/
size_t counter; /**< Indicates by how many threads/programs (TODO) the AVL tree is used.
*/
} OBIDMS_avl_t, *OBIDMS_avl_p;
@ -165,10 +163,12 @@ typedef struct OBIDMS_avl_group {
*/
int current_avl_idx; /**< Index in the sub_avls array of the AVL tree currently being filled.
*/
char avl_name[AVL_MAX_NAME+1]; /**< Base name of the AVL group. The AVL trees in it have names of the form basename_idx.
char name[AVL_MAX_NAME+1]; /**< Base name of the AVL group. The AVL trees in it have names of the form basename_idx.
*/
OBIDMS_p dms; /**< Pointer to the OBIDMS structure to which the AVL group belongs.
*/
size_t counter; /**< Indicates by how many threads/programs (TODO) the AVL group is used.
*/
} OBIDMS_avl_group_t, *OBIDMS_avl_group_p;

View File

@ -27,7 +27,9 @@
*/
typedef OBIDMS_avl_group_p Obi_indexer_p; /**< Typedef to refer to the used indexer structure.
typedef struct OBIDMS_avl_group Obi_indexer; /**< Typedef to refer to the used indexer structure.
*/
typedef OBIDMS_avl_group_p Obi_indexer_p; /**< Typedef to refer to the pointer of the used indexer structure.
*/

View File

@ -23,6 +23,7 @@
#include "obierrno.h"
#include "obidebug.h"
#include "obidmscolumn.h"
#include "obiblob_indexer.h"
#include "utils.h"
#include "obilittlebigman.h"
@ -417,12 +418,10 @@ OBIDMS_p obi_open_dms(const char* dms_name)
// Initialize the list of opened columns
dms->opened_columns = (Opened_columns_list_p) malloc(sizeof(Opened_columns_list_t));
(dms->opened_columns)->columns = (OBIDMS_column_p*) malloc(MAX_NB_OPENED_COLUMNS*sizeof(OBIDMS_column_p));
(dms->opened_columns)->nb_opened_columns = 0;
// Initialize the list of opened indexers // TODO should be handled somewhere else?
dms->opened_indexers = (Opened_indexers_list_p) malloc(sizeof(Opened_indexers_list_t));
(dms->opened_indexers)->indexers = (OBIDMS_avl_p*) malloc(MAX_NB_OPENED_INDEXERS*sizeof(OBIDMS_avl_p)); // TODO idk how to handle this
(dms->opened_indexers)->nb_opened_indexers = 0;
return dms;
@ -477,3 +476,165 @@ int obi_close_dms(OBIDMS_p dms)
return 0;
}
int obi_dms_is_column_name_in_list(OBIDMS_p dms, const char* column_name)
{
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_name))
{ // Found it
return 0;
}
}
return 1;
}
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)
{
*(((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(((indexers_list->indexers)[i])->name, indexer_name)) // TODO it references something in AVL_group struct
{ // 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)
{
*(((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(((indexers_list->indexers)[i])->name, indexer->name)) // TODO it references something in AVL_group struct
{ // 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* get_full_path(OBIDMS_p dms, const char* path_name)
{
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;
}
if (getcwd(full_path, MAX_PATH_LEN) == NULL)
{
obi_set_errno(OBI_UTILS_ERROR);
obidebug(1, "\nError getting the path to a file or directory");
return NULL;
}
strcat(full_path, "/");
strcat(full_path, dms->directory_name);
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 = 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;
}

View File

@ -23,6 +23,8 @@
#include <stdbool.h>
#include "obierrno.h"
//#include "obidmscolumn.h"
//#include "obiblob_indexer.h"
#define OBIDMS_MAX_NAME (2048) /**< The maximum length of an OBIDMS name.
@ -35,21 +37,31 @@
*/
#define MAX_NB_OPENED_INDEXERS (1000) /**< The maximum number of indexers open at the same time.
*/
#define MAX_PATH_LEN 4096 /**< Maximum length for the character string defining a
* file or directory path.
*/
typedef int32_t obiversion_t; /**< TODO double
*/
struct OBIDMS_column; // TODO
typedef struct OBIDMS_column* OBIDMS_column_p;
typedef struct Opened_columns_list {
size_t nb_opened_columns;
struct OBIDMS_column** columns; // TODO allocate array size here
typedef struct Opened_columns_list { // TODO Handle the problem linked to columns with the same name + means only one version
int nb_opened_columns;
OBIDMS_column_p columns[MAX_NB_OPENED_COLUMNS];
} Opened_columns_list_t, *Opened_columns_list_p;
struct OBIDMS_avl; // TODO
struct OBIDMS_avl_group; // TODO
typedef struct OBIDMS_avl_group* OBIDMS_avl_group_p;
typedef OBIDMS_avl_group_p Obi_indexer_p;
typedef struct Opened_indexers_list {
size_t nb_opened_indexers;
struct OBIDMS_avl** indexers; // TODO indexer but not AVL_group
int nb_opened_indexers;
Obi_indexer_p indexers[MAX_NB_OPENED_INDEXERS];
} Opened_indexers_list_t, *Opened_indexers_list_p;
@ -174,4 +186,60 @@ OBIDMS_p obi_dms(const char* dms_name);
int obi_close_dms(OBIDMS_p dms);
// TODO doc
int obi_dms_is_column_name_in_list(OBIDMS_p dms, const char* column_name);
OBIDMS_column_p obi_dms_get_column_from_list(OBIDMS_p dms, const char* column_name, obiversion_t version);
void obi_dms_list_column(OBIDMS_p dms, OBIDMS_column_p column);
int obi_dms_unlist_column(OBIDMS_p dms, OBIDMS_column_p column);
Obi_indexer_p obi_dms_get_indexer_from_list(OBIDMS_p dms, const char* indexer_name);
void obi_dms_list_indexer(OBIDMS_p dms, Obi_indexer_p indexer);
int obi_dms_unlist_indexer(OBIDMS_p dms, Obi_indexer_p indexer);
/** TODO
* @brief Internal function getting the full path of a file or a directory from its
* path relative to a directory file descriptor.
*
* @warning The returned pointer has to be freed by the caller.
*
* @param directory_file_descriptor The file descriptor for the directory to which
* path_name is relative.
* @param path_name The path name for the file or directory, relative to directory_file_descriptor.
*
* @returns A pointer to the full path.
* @retval NULL if an error occurred.
*
* @since June 2015
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
char* get_full_path(OBIDMS_p dms, const char* path_name);
/**
* @brief Replacement function for opendirat() : open a directory relative to a directory file descriptor.
*
* @param directory_file_descriptor The file descriptor for the directory in which the directory should be opened.
* @param path_name The path name for the directory to be opened, relative to directory_file_descriptor.
*
* @returns The file descriptor of the opened directory.
* @retval NULL if an error occurred.
*
* @since June 2015
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
DIR* opendir_in_dms(OBIDMS_p dms, const char* path_name);
#endif /* OBIDMS_H_ */

View File

@ -745,8 +745,9 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms,
close(column_file_descriptor);
// Add in the list of opened columns
*(((dms->opened_columns)->columns)+((dms->opened_columns)->nb_opened_columns)) = new_column;
((dms->opened_columns)->nb_opened_columns)++;
obi_dms_list_column(dms, new_column);
// Set counter to 1 // TODO Discuss counters
new_column->counter = 1;
return new_column;
@ -762,7 +763,6 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms,
char* column_file_name;
int column_file_descriptor;
size_t header_size;
size_t i;
column = NULL;
@ -786,14 +786,12 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms,
}
// Check if the column is already in the list of opened columns
for (i=0; i < ((dms->opened_columns)->nb_opened_columns); i++)
column = obi_dms_get_column_from_list(dms, column_name, version_number);
// If it's found, increment its counter and return it
if (column != NULL)
{
if (!strcmp(((*(((dms->opened_columns)->columns)+i))->header)->name, column_name)
&& (((*(((dms->opened_columns)->columns)+i))->header)->version == version_number))
{ // Found the column already opened, increase its counter and return the column
((*(((dms->opened_columns)->columns)+i))->counter)++;
return *(((dms->opened_columns)->columns)+i);
}
(column->counter)++;
return column;
}
// Get the column file name
@ -892,9 +890,10 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms,
close(column_file_descriptor);
// Add in the list of opened columns and set column counter to 1
*(((dms->opened_columns)->columns)+((dms->opened_columns)->nb_opened_columns)) = column;
((dms->opened_columns)->nb_opened_columns)++;
// Add in the list of opened columns
obi_dms_list_column(dms, column);
// Set counter to 1
column->counter = 1;
return column;
@ -985,57 +984,35 @@ OBIDMS_column_p obi_clone_column(OBIDMS_p dms,
int obi_close_column(OBIDMS_column_p column)
{
size_t i;
bool close_dir;
Opened_columns_list_p columns_list;
bool close_dir;
int ret_val = 0;
// Truncate the column to the number of lines used if it's not read-only
if (column->writable)
{
if (obi_truncate_column(column) < 0)
return -1;
}
columns_list = (column->dms)->opened_columns;
ret_val = obi_truncate_column(column);
(column->counter)--;
if (column->counter == 0)
{
// Delete from the list of 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];
}
}
if (obi_dms_unlist_column(column->dms, column) < 0)
ret_val = -1;
// Close column directory if it was the last column opened from that directory
close_dir = 1;
for (i=0; i < (columns_list->nb_opened_columns); i++)
{
if (!strcmp(((*((columns_list->columns)+i))->header)->name, (column->header)->name))
{ // Not the last column from that directory
close_dir = 0;
}
}
close_dir = obi_dms_is_column_name_in_list(column->dms, (column->header)->name);
// If the data type is OBI_STR or OBI_SEQ, the associated indexer is closed
if (((column->header)->returned_data_type == OBI_STR) || ((column->header)->returned_data_type == OBI_SEQ))
{
if (obi_close_indexer(column->indexer) < 0)
return -1;
}
ret_val = -1;
// Munmap data
if (munmap(column->data, (column->header)->data_size) < 0)
{
obi_set_errno(OBICOL_UNKNOWN_ERROR);
obidebug(1, "\nError munmapping column data");
return -1;
ret_val = -1;
}
// Munmap header
@ -1043,16 +1020,18 @@ int obi_close_column(OBIDMS_column_p column)
{
obi_set_errno(OBICOL_UNKNOWN_ERROR);
obidebug(1, "\nError munmapping a column header");
return -1;
ret_val = -1;
}
// Close column directory
if (close_dir)
obi_close_column_directory(column->column_directory);
if (obi_close_column_directory(column->column_directory) < 0)
ret_val = -1;
free(column);
}
return 0;
return ret_val;
}

View File

@ -34,55 +34,6 @@
*
**********************************************************************/
char* get_full_path(OBIDMS_p dms, const char* path_name)
{
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;
}
if (getcwd(full_path, MAX_PATH_LEN) == NULL)
{
obi_set_errno(OBI_UTILS_ERROR);
obidebug(1, "\nError getting the path to a file or directory");
return NULL;
}
strcat(full_path, "/");
strcat(full_path, dms->directory_name);
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 = 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;
}
int count_dir(char *dir)
{

View File

@ -22,44 +22,6 @@
#define ONE_IF_ZERO(x) (((x)==0)?1:(x)) /**< If x is equal to 0, x takes the value 1.
*/
#define MAX_PATH_LEN 4096 /**< Maximum length for the character string defining a
* file or directory path.
*/
/**
* @brief Internal function getting the full path of a file or a directory from its
* path relative to a directory file descriptor.
*
* @warning The returned pointer has to be freed by the caller.
*
* @param directory_file_descriptor The file descriptor for the directory to which
* path_name is relative.
* @param path_name The path name for the file or directory, relative to directory_file_descriptor.
*
* @returns A pointer to the full path.
* @retval NULL if an error occurred.
*
* @since June 2015
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
char* get_full_path(OBIDMS_p dms, const char* path_name);
/**
* @brief Replacement function for opendirat() : open a directory relative to a directory file descriptor.
*
* @param directory_file_descriptor The file descriptor for the directory in which the directory should be opened.
* @param path_name The path name for the directory to be opened, relative to directory_file_descriptor.
*
* @returns The file descriptor of the opened directory.
* @retval NULL if an error occurred.
*
* @since June 2015
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
DIR* opendir_in_dms(OBIDMS_p dms, const char* path_name);
/*
* TODO