Views are now rollbacked if an error occurs, and unfinished views and

columns are deleted when an OBIDMS is opened.
This commit is contained in:
Celine Mercier
2017-10-26 18:58:48 +02:00
parent 1ae634d56b
commit dfd51939a0
11 changed files with 702 additions and 55 deletions

View File

@ -1062,7 +1062,9 @@ static int rename_finished_view(Obiview_p view)
static int finish_view(Obiview_p view)
{
char* predicates;
char* predicates;
int i;
OBIDMS_column_p column;
// Check that the view is not read-only
if (view->read_only)
@ -1111,6 +1113,19 @@ static int finish_view(Obiview_p view)
if (rename_finished_view(view) < 0)
return -1;
// Flag the columns as finished
for (i=0; i < ((view->infos)->column_count); i++)
{
column = *((OBIDMS_column_p*)ll_get(view->columns, i));
if (column == NULL)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError getting a column to flag it as finished when finishing a view");
return -1;
}
(column->header)->finished = true;
}
// Flag the view as finished
(view->infos)->finished = true;
@ -2502,6 +2517,271 @@ int obi_save_and_close_view(Obiview_p view)
}
int obi_clean_unfinished_views(OBIDMS_p dms)
{
struct dirent* dp;
int i;
char* full_path;
char* relative_path;
Obiview_infos_p view_infos;
char* view_name;
int ret_value;
char* to_delete[1000];
int d;
ret_value = 0;
d = 0;
// Look for unfinished views and delete them
while ((dp = readdir(dms->view_directory)) != NULL)
{
if ((dp->d_name)[0] == '.')
continue;
i=0;
while ((dp->d_name)[i] != '.')
i++;
relative_path = (char*) malloc(strlen(VIEW_DIR_NAME) + strlen(dp->d_name) + 2);
strcpy(relative_path, VIEW_DIR_NAME);
strcat(relative_path, "/");
strcat(relative_path, dp->d_name);
full_path = obi_dms_get_full_path(dms, relative_path);
free(relative_path);
if (full_path == NULL)
{
obidebug(1, "\nError getting the full path to a view file when cleaning unfinished views");
ret_value = -1;
continue;
}
if (strcmp((dp->d_name)+i, ".obiview_unfinished") == 0)
{
// Add to the list of files to delete (deleting in loop not safe)
to_delete[d] = full_path;
d++;
}
else if (strcmp((dp->d_name)+i, ".obiview") == 0)
{ // Check if the view was properly flagged as finished
view_name = (char*) malloc((i+1) * sizeof(char));
if (view_name == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for a view name when deleting unfinished views: file %s", dp->d_name);
ret_value = -1;
continue;
}
strncpy(view_name, dp->d_name, i);
view_name[i] = '\0';
view_infos = obi_view_map_file(dms, view_name, true);
if (view_infos == NULL)
{
obidebug(1, "\nError reading a view file when deleting unfinished views: file %s", dp->d_name);
ret_value = -1;
continue;
}
if (view_infos->finished == false)
{
// Add to the list of files to delete (deleting in loop not safe)
to_delete[d] = full_path;
d++;
}
}
for (i=0; i<d; i++)
{
if (remove(to_delete[i]) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError deleting a view file when deleting unfinished views: file %s", to_delete[d]);
ret_value = -1;
}
free(to_delete[d]);
}
}
return 0;
}
int obi_rollback_view(Obiview_p view)
{
int i;
int ret_value;
int n;
struct dirent* dp;
OBIDMS_column_p column;
char* column_file_path;
char* column_dir_name;
char* column_dir_path;
char* view_file_name;
char* view_relative_path;
char* view_full_path;
ret_value = 0;
// Don't rollback if view finished
if (view->read_only)
return ret_value;
for (i=0; i<((view->infos)->column_count); i++)
{
column = *((OBIDMS_column_p*)ll_get(view->columns, i));
if (column == NULL)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError getting a column from the linked list of column pointers of a view when rollbacking the view");
ret_value = -1;
continue;
}
// Delete the column file if it was created by the view (it was if it is writable)
if (column->writable)
{
// Build file and dir paths
column_file_path = obi_column_full_path(view->dms, (column->header)->name, (column->header)->version);
if (column_file_path == NULL)
{
obidebug(1, "\nError getting a column file path when rollbacking a view");
ret_value = -1;
continue;
}
column_dir_name = obi_build_column_directory_name((column->header)->name);
if (column_dir_name == NULL)
{
obidebug(1, "\nError getting a column directory name when rollbacking a view");
ret_value = -1;
}
column_dir_path = obi_dms_get_full_path(view->dms, column_dir_name);
if (column_dir_path == NULL)
{
obidebug(1, "\nError getting a column directory path when rollbacking a view");
ret_value = -1;
}
// Try to close the column (?)
if (obi_close_column(column) < 0)
ret_value = -1;
// Delete the column file
if (remove(column_file_path) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError deleting a column file when rollbacking a view");
ret_value = -1;
}
// Delete column dir if it's empty
n = count_dir(column_dir_path);
if (n == 0)
{
if (remove(column_dir_path) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError deleting a column directory when rollbacking a view");
ret_value = -1;
}
}
free(column_file_path);
free(column_dir_name);
free(column_dir_path);
}
}
// Delete line selection if there is one
if (view->line_selection != NULL)
{
column = view->line_selection;
if (column->writable)
{
// Build file and dir paths
column_file_path = obi_column_full_path(view->dms, (column->header)->name, (column->header)->version);
if (column_file_path == NULL)
{
obidebug(1, "\nError getting a column file path when rollbacking a view");
ret_value = -1;
}
column_dir_name = obi_build_column_directory_name((column->header)->name);
if (column_dir_name == NULL)
{
obidebug(1, "\nError getting a column directory name when rollbacking a view");
ret_value = -1;
}
column_dir_path = obi_dms_get_full_path(view->dms, column_dir_name);
if (column_dir_path == NULL)
{
obidebug(1, "\nError getting a column directory path when rollbacking a view");
ret_value = -1;
}
// Try to close the column (?)
if (obi_close_column(column) < 0)
ret_value = -1;
// Delete the column file
if (remove(column_file_path) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError deleting a column file when rollbacking a view");
ret_value = -1;
}
// Delete column dir if it's empty
n = count_dir(column_dir_path);
if (n == 0)
{
if (remove(column_dir_path) < 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError deleting a column directory when rollbacking a view");
ret_value = -1;
}
}
free(column_file_path);
free(column_dir_name);
free(column_dir_path);
}
}
// Delete view file
view_file_name = (char*) malloc(strlen((view->infos)->name) + strlen(".obiview_unfinished") + 1);
if (view_file_name == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for a view file name");
ret_value = -1;
}
else
{
strcpy(view_file_name, (view->infos)->name);
strcat(view_file_name, ".obiview_unfinished");
while ((dp = readdir((view->dms)->view_directory)) != NULL)
{
if ((dp->d_name)[0] == '.')
continue;
if (strcmp(dp->d_name, view_file_name) == 0)
{
view_relative_path = (char*) malloc(strlen(VIEW_DIR_NAME) + strlen(view_file_name) + 2);
strcpy(view_relative_path, VIEW_DIR_NAME);
strcat(view_relative_path, "/");
strcat(view_relative_path, view_file_name);
view_full_path = obi_dms_get_full_path(view->dms, view_relative_path);
remove(view_full_path);
}
}
free(view_file_name);
free(view_relative_path);
free(view_full_path);
}
// Free the linked list of column pointers
ll_free(view->columns);
// Free the column dictionary
ht_free(view->column_dict);
free(view);
return ret_value;
}
int obi_create_auto_count_column(Obiview_p view)
{
index_t i;