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:
parent
da20711987
commit
91c4572bbd
91
src/dir.c
91
src/dir.c
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user