1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-12-14 12:00:13 +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, static void list_data_directories(parray *files, const char *path, bool is_root,
bool exclude); bool exclude);
static void free_extra_remap_list(void *cell);
/* Tablespace mapping */ /* Tablespace mapping */
static TablespaceList tablespace_dirs = {NULL, NULL}; static TablespaceList tablespace_dirs = {NULL, NULL};
static TablespaceCreatedList tablespace_created_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. * Create directory, also create parent directories if necessary.
@ -949,6 +952,57 @@ opt_tablespace_map(ConfigOption *opt, const char *arg)
tablespace_dirs.tail = cell; 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 * Create backup directories from **backup_dir** to **data_dir**. Doesn't raise
* an error if target directories exist. * an error if target directories exist.
@ -1219,6 +1273,43 @@ check_tablespace_mapping(pgBackup *backup)
parray_free(links); 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. * Print backup content list.
*/ */

View File

@ -138,6 +138,7 @@ static ConfigOption cmd_options[] =
{ 'b', 134, "delete-wal", &delete_wal, SOURCE_CMD_STRICT }, { 'b', 134, "delete-wal", &delete_wal, SOURCE_CMD_STRICT },
{ 'b', 135, "delete-expired", &delete_expired, 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 /* TODO not completed feature. Make it unavailiable from user level
{ 'b', 18, "remote", &is_remote_backup, SOURCE_CMD_STRICT, }, */ { 'b', 18, "remote", &is_remote_backup, SOURCE_CMD_STRICT, }, */
/* restore options */ /* 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 read_tablespace_map(parray *files, const char *backup_dir);
extern void opt_tablespace_map(ConfigOption *opt, const char *arg); 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 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, extern void print_file_list(FILE *out, const parray *files, const char *root,
const char *extra_prefix, parray *extra_list); 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); requested_extra_dirs = make_extra_directory_list(extra_dir_str);
for (int i = 0; i < parray_num(requested_extra_dirs); i++) 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)) if (backup_contains_extra(extra_path, requested_extra_dirs))
{ {
char container_dir[MAXPGPATH]; char container_dir[MAXPGPATH];
extra_path = check_extra_dir_mapping(extra_path);
makeExtraDirPathByNum(container_dir, extra_prefix, makeExtraDirPathByNum(container_dir, extra_prefix,
file->extra_dir_num); file->extra_dir_num);
dir_name = GetRelativePath(file->path, container_dir); 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_walk(files, pgFileFree);
parray_free(files); parray_free(files);
clean_extra_dirs_remap_list();
if (logger_config.log_level_console <= LOG || if (logger_config.log_level_console <= LOG ||
logger_config.log_level_file <= LOG) logger_config.log_level_file <= LOG)
elog(LOG, "restore %s backup completed", base36enc(backup->start_time)); elog(LOG, "restore %s backup completed", base36enc(backup->start_time));
@ -693,8 +699,11 @@ restore_files(void *arg)
char *extra_path = parray_get(arguments->cur_extra_dirs, char *extra_path = parray_get(arguments->cur_extra_dirs,
file->extra_dir_num - 1); file->extra_dir_num - 1);
if (backup_contains_extra(extra_path, arguments->req_extra_dirs)) 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); copy_file(arguments->extra_prefix, extra_path, file);
} }
}
else else
copy_file(from_root, instance_config.pgdata, file); copy_file(from_root, instance_config.pgdata, file);