View files now have a dynamic size to allow unlimited comments size

This commit is contained in:
Celine Mercier
2016-08-18 17:57:03 +02:00
parent e4129610cf
commit 7b780ffb28
2 changed files with 173 additions and 19 deletions

View File

@ -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);
}
}

View File

@ -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;