1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-12-13 11:53:59 +02:00

Add extra directories remapping on restore

This commit is contained in:
Sergey Cherkashin 2018-12-25 02:42:55 +03:00
parent da20711987
commit 91c4572bbd
4 changed files with 106 additions and 2 deletions

View File

@ -124,10 +124,13 @@ static void dir_list_file_internal(parray *files, const char *root,
static void list_data_directories(parray *files, const char *path, bool is_root,
bool exclude);
static void free_extra_remap_list(void *cell);
/* Tablespace mapping */
static TablespaceList tablespace_dirs = {NULL, NULL};
static TablespaceCreatedList tablespace_created_dirs = {NULL, NULL};
/* Extra directories mapping */
static parray *extra_remap_list = NULL;
/*
* Create directory, also create parent directories if necessary.
@ -949,6 +952,57 @@ opt_tablespace_map(ConfigOption *opt, const char *arg)
tablespace_dirs.tail = cell;
}
void
opt_extradir_map(ConfigOption *opt, const char *arg)
{
TablespaceListCell *cell = pgut_new(TablespaceListCell);
char *dst;
char *dst_ptr;
const char *arg_ptr;
extra_remap_list = parray_new();
dst_ptr = dst = cell->old_dir;
for (arg_ptr = arg; *arg_ptr; arg_ptr++)
{
if (dst_ptr - dst >= MAXPGPATH)
elog(ERROR, "directory name too long");
if (*arg_ptr == '\\' && *(arg_ptr + 1) == '=')
; /* skip backslash escaping = */
else if (*arg_ptr == '=' && (arg_ptr == arg || *(arg_ptr - 1) != '\\'))
{
if (*cell->new_dir)
elog(ERROR, "multiple \"=\" signs in extra directory mapping\n");
else
dst = dst_ptr = cell->new_dir;
}
else
*dst_ptr++ = *arg_ptr;
}
if (!*cell->old_dir || !*cell->new_dir)
elog(ERROR, "invalid extra directory mapping format \"%s\", "
"must be \"OLDDIR=NEWDIR\"", arg);
/*
* This check isn't absolutely necessary. But all tablespaces are created
* with absolute directories, so specifying a non-absolute path here would
* just never match, possibly confusing users. It's also good to be
* consistent with the new_dir check.
*/
if (!is_absolute_path(cell->old_dir))
elog(ERROR, "old directory is not an absolute path "
"in extra directory mapping: %s\n",
cell->old_dir);
if (!is_absolute_path(cell->new_dir))
elog(ERROR, "new directory is not an absolute path "
"in extra directory mapping: %s\n",
cell->new_dir);
parray_append(extra_remap_list, cell);
}
/*
* Create backup directories from **backup_dir** to **data_dir**. Doesn't raise
* an error if target directories exist.
@ -1219,6 +1273,43 @@ check_tablespace_mapping(pgBackup *backup)
parray_free(links);
}
char *
check_extra_dir_mapping(char *current_dir)
{
if (!extra_remap_list)
return current_dir;
for (int i = 0; i < parray_num(extra_remap_list); i++)
{
TablespaceListCell *cell = parray_get(extra_remap_list, i);
char *old_dir = cell->old_dir;
if (strcmp(old_dir, current_dir) == 0)
return cell->new_dir;
}
return current_dir;
}
static void
free_extra_remap_list(void *cell)
{
TablespaceListCell *cell_ptr;
if (cell == NULL)
return;
cell_ptr = (TablespaceListCell *)cell;
pfree(cell_ptr);
}
void
clean_extra_dirs_remap_list(void)
{
if (extra_remap_list)
{
parray_walk(extra_remap_list, free_extra_remap_list);
parray_free(extra_remap_list);
}
}
/*
* Print backup content list.
*/

View File

@ -137,7 +137,8 @@ static ConfigOption cmd_options[] =
{ 's', 'S', "slot", &replication_slot, SOURCE_CMD_STRICT },
{ 'b', 134, "delete-wal", &delete_wal, SOURCE_CMD_STRICT },
{ 'b', 135, "delete-expired", &delete_expired, SOURCE_CMD_STRICT },
{ 's', 155, "extra-directory", &extradir, SOURCE_CMD_STRICT },
{ 's', 155, "extra-directory", &extradir, SOURCE_CMD_STRICT },
{ 'f', 'E', "extra-mapping", opt_extradir_map, SOURCE_CMD_STRICT },
/* TODO not completed feature. Make it unavailiable from user level
{ 'b', 18, "remote", &is_remote_backup, SOURCE_CMD_STRICT, }, */
/* restore options */

View File

@ -509,7 +509,10 @@ extern void create_data_directories(const char *data_dir,
extern void read_tablespace_map(parray *files, const char *backup_dir);
extern void opt_tablespace_map(ConfigOption *opt, const char *arg);
extern void opt_extradir_map(ConfigOption *opt, const char *arg);
extern void check_tablespace_mapping(pgBackup *backup);
extern char* check_extra_dir_mapping(char *current_dir);
extern void clean_extra_dirs_remap_list(void);
extern void print_file_list(FILE *out, const parray *files, const char *root,
const char *extra_prefix, parray *extra_list);

View File

@ -463,7 +463,9 @@ restore_backup(pgBackup *backup, const char *extra_dir_str)
requested_extra_dirs = make_extra_directory_list(extra_dir_str);
for (int i = 0; i < parray_num(requested_extra_dirs); i++)
{
dir_create_dir(parray_get(requested_extra_dirs, i), DIR_PERMISSION);
char *extra_path = parray_get(requested_extra_dirs, i);
extra_path = check_extra_dir_mapping(extra_path);
dir_create_dir(extra_path, DIR_PERMISSION);
}
}
@ -504,6 +506,8 @@ restore_backup(pgBackup *backup, const char *extra_dir_str)
if (backup_contains_extra(extra_path, requested_extra_dirs))
{
char container_dir[MAXPGPATH];
extra_path = check_extra_dir_mapping(extra_path);
makeExtraDirPathByNum(container_dir, extra_prefix,
file->extra_dir_num);
dir_name = GetRelativePath(file->path, container_dir);
@ -554,6 +558,8 @@ restore_backup(pgBackup *backup, const char *extra_dir_str)
parray_walk(files, pgFileFree);
parray_free(files);
clean_extra_dirs_remap_list();
if (logger_config.log_level_console <= LOG ||
logger_config.log_level_file <= LOG)
elog(LOG, "restore %s backup completed", base36enc(backup->start_time));
@ -693,7 +699,10 @@ restore_files(void *arg)
char *extra_path = parray_get(arguments->cur_extra_dirs,
file->extra_dir_num - 1);
if (backup_contains_extra(extra_path, arguments->req_extra_dirs))
{
extra_path = check_extra_dir_mapping(extra_path);
copy_file(arguments->extra_prefix, extra_path, file);
}
}
else
copy_file(from_root, instance_config.pgdata, file);