New C functions to import a column and a view from a DMS to another DMS

This commit is contained in:
Celine Mercier
2017-08-03 16:33:12 +02:00
parent a3e81930c2
commit 4b86aa67a8
2 changed files with 362 additions and 1 deletions

View File

@ -19,12 +19,13 @@
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <libgen.h> /* <EC> : Addted the 28 july 2017 to include basename */
#include <libgen.h> /* <EC> : Added July 28th 2017 to include basename */
#include "obidms.h"
#include "obierrno.h"
#include "obidebug.h"
#include "obidmscolumn.h"
#include "obiview.h"
#include "obiblob_indexer.h"
#include "utils.h"
#include "obilittlebigman.h"
@ -770,3 +771,321 @@ DIR* opendir_in_dms(OBIDMS_p dms, const char* path_name)
return directory;
}
// TODO move somewhere else maybe
// TODO discuss arguments
obiversion_t obi_import_column(const char* dms_path_1, const char* dms_path_2, const char* column_name, obiversion_t version_number)
{
OBIDMS_p dms_1;
OBIDMS_p dms_2;
OBIDMS_column_p column_1;
OBIDMS_column_p column_2;
OBIDMS_column_header_p header_1;
OBIDMS_column_header_p header_2;
int avl_exists;
const char* avl_name;
char* new_avl_name;
obiversion_t new_version;
int i;
int avl_count;
char* avl_name_1;
char* avl_name_2;
char* avl_file_path_1;
char* avl_file_path_2;
char* avl_data_file_path_1;
char* avl_data_file_path_2;
char* complete_avl_name;
Obi_indexer_p avl_group;
dms_1 = obi_open_dms(dms_path_1);
if (dms_1 == NULL)
{
obidebug(1, "\nError opening a DMS to import a column from it");
return -1;
}
dms_2 = obi_dms(dms_path_2);
if (dms_2 == NULL)
{
obidebug(1, "\nError opening or creating a DMS to import a column into it");
return -1;
}
column_1 = obi_open_column(dms_1, column_name, version_number);
if (column_1 == NULL)
{
obidebug(1, "\nError opening a column to import in another DMS");
return -1;
}
header_1 = column_1->header;
// Check if associated indexer exists BEFORE creating the new column as that will automatically create it if it doesn't already exist
avl_name = header_1->indexer_name;
avl_exists = obi_indexer_exists(dms_2, avl_name);
if (avl_exists == -1)
{
obidebug(1, "\nError checking if an indexer exists while importing a column");
return -1;
}
if (avl_exists)
// Use automatic name
new_avl_name = NULL;
else
// Name can stay the same
new_avl_name = header_1->indexer_name;
// Create new column
column_2 = obi_create_column(dms_2, column_name, header_1->returned_data_type, header_1->line_count,
header_1->nb_elements_per_line, header_1->elements_names, true,
new_avl_name, (header_1->associated_column).column_name, (header_1->associated_column).version,
header_1->comments);
if (column_2 == NULL)
{
obidebug(1, "\nError creating the new column while importing a column");
return -1;
}
header_2 = column_2->header;
// Get the new version to return
new_version = header_2->version;
// Copy lines_used informations
header_2->lines_used = header_1->lines_used;
// Copy data TODO check how much time and memory that costs, eventually use write() instead
memcpy(column_2->data, column_1->data, header_1->data_size);
// Copy the AVL files if there are some (overwriting the automatically created files)
if ((header_1->returned_data_type == OBI_STR) || (header_1->returned_data_type == OBI_SEQ) || (header_1->returned_data_type == OBI_QUAL))
{
avl_name_1 = (char*) malloc((strlen(header_1->indexer_name) + 1) * sizeof(char));
if (avl_name_1 == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for an AVL name when importing a column");
return -1;
}
strcpy(avl_name_1, header_1->indexer_name);
avl_name_2 = (char*) malloc((strlen(header_2->indexer_name) + 1) * sizeof(char));
if (avl_name_2 == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for an AVL name when importing a column");
return -1;
}
strcpy(avl_name_2, header_2->indexer_name);
avl_count = (column_1->indexer->last_avl_idx) + 1;
// Close column to manipulate AVL files safely (but not multithreading safe) (TODO not sure how important this is, can't find informations about conflicts when using write() on mmapped files)
if (obi_close_column(column_1) < 0)
{
obidebug(1, "\nError closing an imported column");
return -1;
}
if (obi_close_column(column_2) < 0)
{
obidebug(1, "\nError closing an imported column");
return -1;
}
for (i=0; i < avl_count; i++)
{
avl_file_path_1 = obi_get_full_path_of_avl_file_name(dms_1, avl_name_1, i);
if (avl_file_path_1 == NULL)
{
obidebug(1, "\nError getting an AVL file path while importing a column");
return -1;
}
avl_data_file_path_1 = obi_get_full_path_of_avl_data_file_name(dms_1, avl_name_1, i);
if (avl_data_file_path_1 == NULL)
{
obidebug(1, "\nError getting an AVL file path while importing a column");
return -1;
}
avl_file_path_2 = obi_get_full_path_of_avl_file_name(dms_2, avl_name_2, i);
if (avl_file_path_2 == NULL)
{
obidebug(1, "\nError getting an AVL file path while importing a column");
return -1;
}
avl_data_file_path_2 = obi_get_full_path_of_avl_data_file_name(dms_2, avl_name_2, i);
if (avl_data_file_path_2 == NULL)
{
obidebug(1, "\nError getting an AVL file path while importing a column");
return -1;
}
// Copy AVL file
if (copy_file(avl_file_path_1, avl_file_path_2) < 0)
{
obidebug(1, "\nError copying an AVL file while importing a column");
return -1;
}
// Copy AVL data file
if (copy_file(avl_data_file_path_1, avl_data_file_path_2) < 0)
{
obidebug(1, "\nError copying a data AVL file while importing a column");
return -1;
}
free(avl_file_path_1);
free(avl_file_path_2);
free(avl_data_file_path_1);
free(avl_data_file_path_2);
}
// Update AVL names in headers
avl_group = obi_open_indexer(dms_2, avl_name_2);
for (i=0; i < avl_count; i++)
{
complete_avl_name = obi_build_avl_name_with_idx(avl_name_2, i);
strcpy((((avl_group->sub_avls)[i])->header)->avl_name, complete_avl_name);
strcpy(((((avl_group->sub_avls)[i])->data)->header)->avl_name, complete_avl_name);
free(complete_avl_name);
}
free(avl_name_1);
free(avl_name_2);
}
else
{
if (obi_close_column(column_1) < 0)
{
obidebug(1, "\nError closing an imported column");
return -1;
}
if (obi_close_column(column_2) < 0)
{
obidebug(1, "\nError closing an imported column");
return -1;
}
}
// Copy associated column (update version)
//new_associated_col_version = import_column(dms_path_1, dms_path_2, header_1->associated_column_name, header_1->associated_column_version);
// 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);
return new_version;
}
// TODO move somewhere else maybe
// TODO discuss arguments
int obi_import_view(const char* dms_path_1, const char* dms_path_2, const char* view_name_1, const char* view_name_2)
{
OBIDMS_p dms_1;
OBIDMS_p dms_2;
Obiview_p view_1;
Obiview_p view_2;
obiversion_t new_version;
int i;
dms_1 = obi_open_dms(dms_path_1);
if (dms_1 == NULL)
{
obidebug(1, "\nError opening a DMS to import a view from it");
return -1;
}
dms_2 = obi_dms(dms_path_2);
if (dms_2 == NULL)
{
obidebug(1, "\nError opening or creating a DMS to import a view into it");
return -1;
}
// Open view to import
view_1 = obi_open_view(dms_1, view_name_1);
// Create new view
if (strcmp((view_1->infos)->view_type, VIEW_TYPE_NUC_SEQS) == 0)
view_2 = obi_new_view_nuc_seqs(dms_2, view_name_2, NULL, NULL, (view_1->infos)->comments, false);
else // Non-typed view
view_2 = obi_new_view(dms_2, view_name_2, NULL, NULL, (view_1->infos)->comments);
// Import line count
view_2->infos->line_count = view_1->infos->line_count;
// Import the line selection column if there is one
if (! view_1->infos->all_lines)
{
view_2->infos->all_lines = false;
new_version = obi_import_column(dms_path_1, dms_path_2, ((view_1->infos)->line_selection).column_name, ((view_1->infos)->line_selection).version);
if (new_version == -1)
{
obidebug(1, "\nError importing a line selection column while importing a view");
return -1;
}
strcpy(((view_2->infos)->line_selection).column_name, ((view_1->infos)->line_selection).column_name);
((view_2->infos)->line_selection).version = new_version;
view_2->line_selection = obi_open_column(dms_2, ((view_2->infos)->line_selection).column_name, ((view_2->infos)->line_selection).version);
if (view_2->line_selection == NULL)
{
obidebug(1, "\nError opening a line selection column while importing a view");
return -1;
}
}
// Import each column and update with the new version number
for (i=0; i < (view_1->infos->column_count); i++)
{
new_version = obi_import_column(dms_path_1, dms_path_2, ((((view_1->infos)->column_references)[i]).column_refs).column_name, ((((view_1->infos)->column_references)[i]).column_refs).version);
if (new_version == -1)
{
obidebug(1, "\nError importing a column while importing a view");
return -1;
}
if (obi_view_add_column(view_2,
((((view_1->infos)->column_references)[i]).column_refs).column_name,
new_version,
(((view_1->infos)->column_references)[i]).alias,
0,
0,
0,
NULL,
NULL,
NULL,
-1,
NULL,
false) < 0)
{
obidebug(1, "\nError adding a column to a view while importing it");
return -1;
}
}
// Close the views
if (obi_save_and_close_view(view_1) < 0)
{
obidebug(1, "\nError closing a view after importing from it");
return -1;
}
if (obi_save_and_close_view(view_2) < 0)
{
obidebug(1, "\nError closing a view after importing it");
return -1;
}
// Close the DMS
obi_close_dms(dms_1);
obi_close_dms(dms_2);
return 0;
}

View File

@ -361,4 +361,46 @@ char* obi_dms_get_full_path(OBIDMS_p dms, const char* path_name);
DIR* opendir_in_dms(OBIDMS_p dms, const char* path_name);
/**
* @brief Imports a column, copying it from a DMS to another DMS, and returns the version of the column in the destination DMS.
*
* The eventual associated indexers are imported too. If an indexer with the same name already exists in the destination DMS,
* they are not merged, the imported indexer is renamed.
*
* @warning The eventual associated column is not imported and needs to be imported separately.
*
* @param dms_path_1 The path to the source DMS (without the '.obidms' extension).
* @param dms_path_2 The path to the destination DMS (without the '.obidms' extension). It is created if it doesn't already exist.
* @param column_name The name of the column to import.
* @param version_number The version of the column to import.
*
* @returns The new version of the column in the destination DMS.
* @retval -1 if an error occurred.
*
* @since August 2017
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
obiversion_t obi_import_column(const char* dms_path_1, const char* dms_path_2, const char* column_name, obiversion_t version_number);
/**
* @brief Imports a view, copying it and all its associated columns from a DMS to another DMS.
*
* All the columns and the eventual associated indexers are imported. If an indexer with the same name already exists in the destination DMS,
* they are not merged, the imported indexer is renamed.
*
* @param dms_path_1 The path to the source DMS (without the '.obidms' extension).
* @param dms_path_2 The path to the destination DMS (without the '.obidms' extension). It is created if it doesn't already exist.
* @param view_name_1 The name of the view to import.
* @param view_name_2 The name of the imported view in the destination DMS.
*
* @retval 0 on success.
* @retval -1 if an error occurred.
*
* @since August 2017
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
int obi_import_view(const char* dms_path_1, const char* dms_path_2, const char* view_name_1, const char* view_name_2);
#endif /* OBIDMS_H_ */