View files now have a dynamic size to allow unlimited comments size
This commit is contained in:
183
src/obiview.c
183
src/obiview.c
@ -44,9 +44,9 @@
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Internal function calculating the size of the file where the informations about an obiview are stored.
|
||||
* Internal function calculating the initial size of the file where the informations about an obiview are stored.
|
||||
*
|
||||
* @returns The size of the file in bytes.
|
||||
* @returns The initial size of the file in bytes, rounded to a multiple of page size.
|
||||
*
|
||||
* @since June 2016
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
@ -54,16 +54,49 @@
|
||||
size_t get_platform_view_file_size();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Internal function enlarging a view file.
|
||||
*
|
||||
* @param view A pointer on the view.
|
||||
* @param new_size The new size needed, in bytes (not necessarily rounded to a page size multiple).
|
||||
*
|
||||
* @retval 0 if the operation was successfully completed.
|
||||
* @retval -1 if an error occurred.
|
||||
*
|
||||
* @since August 2016
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
int enlarge_view_file(Obiview_p view, size_t new_size);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Internal function writing new comments in a view file.
|
||||
*
|
||||
* The new comments are concatenated to the pre-existing ones.
|
||||
* The view file is enlarged if necessary.
|
||||
*
|
||||
* @param view A pointer on the view.
|
||||
* @param comments The new comments that should be added.
|
||||
*
|
||||
* @retval 0 if the operation was successfully completed.
|
||||
* @retval -1 if an error occurred.
|
||||
*
|
||||
* @since August 2016
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
int write_comments_to_view_file(Obiview_p view, const char* comments);
|
||||
|
||||
|
||||
/**
|
||||
* Internal function building the file name where the informations about an obiview are stored.
|
||||
*
|
||||
* @warning The returned pointer has to be freed by the caller.
|
||||
*
|
||||
* @param view_name The name of the view.
|
||||
*
|
||||
* @returns A pointer to the file name.
|
||||
* @retval NULL if an error occurred.
|
||||
*
|
||||
* @param view_name The name of the view.
|
||||
*
|
||||
* @since June 2016
|
||||
* @author Celine Mercier (celine.mercier@metabarcoding.org)
|
||||
*/
|
||||
@ -409,6 +442,101 @@ size_t get_platform_view_file_size()
|
||||
}
|
||||
|
||||
|
||||
int enlarge_view_file(Obiview_p view, size_t new_size)
|
||||
{
|
||||
int obiview_file_descriptor;
|
||||
double multiple;
|
||||
size_t rounded_new_size;
|
||||
|
||||
// TODO if file name changes
|
||||
// // Create file name
|
||||
// file_name = build_obiview_file_name(view_name);
|
||||
// if (file_name == NULL)
|
||||
// return -1;
|
||||
|
||||
// Open view file
|
||||
obiview_file_descriptor = openat((view->dms)->view_dir_fd, (view->infos)->name, O_RDWR, 0777);
|
||||
if (obiview_file_descriptor < 0)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError opening a view file");
|
||||
// free(file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//free(file_name);
|
||||
|
||||
// Round new size to a multiple of page size // TODO make function in utils
|
||||
multiple = ceil((double) new_size / (double) getpagesize());
|
||||
rounded_new_size = multiple * getpagesize();
|
||||
|
||||
|
||||
// Enlarge the file
|
||||
if (ftruncate(obiview_file_descriptor, rounded_new_size) < 0)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError enlarging a view file");
|
||||
close(obiview_file_descriptor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Unmap and remap the file
|
||||
if (munmap(view->infos, (view->infos)->file_size) < 0)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError munmapping a view file when enlarging");
|
||||
close(obiview_file_descriptor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
view->infos = mmap(NULL,
|
||||
rounded_new_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
obiview_file_descriptor,
|
||||
0
|
||||
);
|
||||
if (view->infos == MAP_FAILED)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError re-mmapping a view file after enlarging the file");
|
||||
close(obiview_file_descriptor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set new size
|
||||
(view->infos)->file_size = rounded_new_size;
|
||||
|
||||
close(obiview_file_descriptor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int write_comments_to_view_file(Obiview_p view, const char* comments)
|
||||
{
|
||||
size_t new_size;
|
||||
|
||||
if (comments == NULL)
|
||||
return 0; // TODO or error? discuss
|
||||
|
||||
new_size = (view->infos)->used_size + strlen(comments);
|
||||
|
||||
// Check if the file has to be enlarged
|
||||
if (new_size >= (view->infos)->file_size)
|
||||
{
|
||||
if (enlarge_view_file(view, new_size) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcat((view->infos)->comments, comments);
|
||||
|
||||
(view->infos)->used_size = new_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int create_obiview_file(OBIDMS_p dms, const char* view_name)
|
||||
{
|
||||
// char* file_name;
|
||||
@ -433,7 +561,7 @@ int create_obiview_file(OBIDMS_p dms, const char* view_name)
|
||||
|
||||
//free(file_name);
|
||||
|
||||
// Truncate file to the right size
|
||||
// Truncate file to the initial size
|
||||
file_size = get_platform_view_file_size();
|
||||
|
||||
if (ftruncate(obiview_file_descriptor, file_size) < 0)
|
||||
@ -444,6 +572,15 @@ int create_obiview_file(OBIDMS_p dms, const char* view_name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Write file size
|
||||
if (write(obiview_file_descriptor, &file_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t)))
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError writing the file size in an obiview file");
|
||||
close(obiview_file_descriptor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(obiview_file_descriptor);
|
||||
|
||||
return 0;
|
||||
@ -839,7 +976,7 @@ char* view_check_all_predicates(Obiview_p view)
|
||||
char* all_predicates_string = NULL;
|
||||
char** all_predicates = NULL;
|
||||
|
||||
if (view->nb_predicates == 0)
|
||||
if (view->nb_predicates == 0) // TODO or no error? discuss
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError trying to check predicates of a view with no predicates.");
|
||||
@ -917,10 +1054,10 @@ char* view_check_all_predicates(Obiview_p view)
|
||||
|
||||
Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments)
|
||||
{
|
||||
Obiview_p view;
|
||||
int i;
|
||||
index_t line_nb;
|
||||
struct dirent* dp;
|
||||
Obiview_p view;
|
||||
int i;
|
||||
index_t line_nb;
|
||||
struct dirent* dp;
|
||||
|
||||
// Check uniqueness of name
|
||||
while ((dp = readdir(dms->view_directory)) != NULL)
|
||||
@ -963,6 +1100,9 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Write used size in view file for initial structure
|
||||
(view->infos)->used_size = sizeof(Obiview_infos_t);
|
||||
|
||||
// Clone view to clone if there is one
|
||||
if (view_to_clone != NULL)
|
||||
{
|
||||
@ -1058,11 +1198,17 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl
|
||||
|
||||
// Fill last informations
|
||||
strcpy((view->infos)->name, view_name);
|
||||
strcpy((view->infos)->comments, comments);
|
||||
(view->infos)->creation_date = time(NULL);
|
||||
view->nb_predicates = 0;
|
||||
view->predicate_functions = NULL;
|
||||
|
||||
if (write_comments_to_view_file(view, comments) < 0) // TODO copy comments if cloning view?
|
||||
{
|
||||
obidebug(1, "\nError writing comments when creating a view");
|
||||
obi_close_view(view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Store reference for line selection
|
||||
if (view->line_selection == NULL)
|
||||
{
|
||||
@ -1251,8 +1397,16 @@ Obiview_infos_p obi_view_map_file(OBIDMS_p dms, const char* view_name)
|
||||
|
||||
//free(file_name);
|
||||
|
||||
// Get file size
|
||||
if (read(obiview_file_descriptor, &file_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t)))
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
obidebug(1, "\nError reading the file size in an obiview file");
|
||||
close(obiview_file_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Map the view infos structure
|
||||
file_size = get_platform_view_file_size();
|
||||
view_infos = mmap(NULL,
|
||||
file_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
@ -1298,7 +1452,7 @@ int obi_view_unmap_file(OBIDMS_p dms, Obiview_infos_p view_infos)
|
||||
//free(file_name);
|
||||
|
||||
// Unmap the view infos structure
|
||||
file_size = get_platform_view_file_size();
|
||||
file_size = view_infos->file_size;
|
||||
if (munmap(view_infos, file_size) < 0)
|
||||
{
|
||||
obi_set_errno(OBIVIEW_ERROR);
|
||||
@ -1796,8 +1950,7 @@ int obi_save_and_close_view(Obiview_p view)
|
||||
return -1; // TODO reverse view (delete files)
|
||||
else
|
||||
{
|
||||
// TODO check size and grow file if needed
|
||||
strcat((view->infos)->comments, predicates);
|
||||
write_comments_to_view_file(view, predicates);
|
||||
free(predicates);
|
||||
}
|
||||
}
|
||||
|
@ -30,9 +30,6 @@
|
||||
|
||||
#define OBIVIEW_NAME_MAX_LENGTH (1000) /**< The maximum length of an OBIDMS view name.
|
||||
*/
|
||||
#define OBIVIEW_COMMENTS_MAX_LENGTH (10000) /**< The maximum length of the comments associated
|
||||
* with a view.
|
||||
*/
|
||||
#define VIEW_TYPE_MAX_LENGTH (1024) /**< The maximum length of the type name of a view.
|
||||
*/
|
||||
#define LINES_COLUMN_NAME "LINES" /**< The name of the column containing the line selections
|
||||
@ -73,6 +70,10 @@ typedef struct Alias_column_pair {
|
||||
* Once a view has been written in the view file, it can not be modified and can only be read.
|
||||
*/
|
||||
typedef struct Obiview_infos {
|
||||
size_t file_size; /**< View file size in bytes.
|
||||
*/
|
||||
size_t used_size; /**< Used size in bytes.
|
||||
*/
|
||||
time_t creation_date; /**< Time at which the view was written in the view file.
|
||||
*/
|
||||
char name[OBIVIEW_NAME_MAX_LENGTH+1]; /**< Name of the view, used to identify it.
|
||||
@ -92,7 +93,7 @@ typedef struct Obiview_infos {
|
||||
*/
|
||||
Alias_column_pair_t column_references[MAX_NB_OPENED_COLUMNS]; /**< References (name, version and alias) for all the columns in the view.
|
||||
*/
|
||||
char comments[OBIVIEW_COMMENTS_MAX_LENGTH+1]; /**< Comments, additional informations on the view.
|
||||
char comments[]; /**< Comments, additional informations on the view.
|
||||
*/
|
||||
} Obiview_infos_t, *Obiview_infos_p;
|
||||
|
||||
|
Reference in New Issue
Block a user