diff --git a/src/backup.c b/src/backup.c index 15ca8bf3..ff672546 100644 --- a/src/backup.c +++ b/src/backup.c @@ -991,8 +991,11 @@ do_backup(time_t start_time) sizeof(current.program_version)); /* Save list of extra directories */ - if(extradir) - current.extra_dir_str = extradir; + if (instance_config.extra_dir_str && + strcmp(instance_config.extra_dir_str, "none") != 0) + { + current.extra_dir_str = instance_config.extra_dir_str; + } /* Create backup directory and BACKUP_CONTROL_FILE */ if (pgBackupCreateDir(¤t)) diff --git a/src/configure.c b/src/configure.c index a9c80922..b2077588 100644 --- a/src/configure.c +++ b/src/configure.c @@ -61,6 +61,11 @@ ConfigOption instance_options[] = OPTION_INSTANCE_GROUP, 0, option_get_value }, #endif + { + 's', 'E', "extra-directory", + &instance_config.extra_dir_str, SOURCE_CMD, 0, + OPTION_INSTANCE_GROUP, 0, option_get_value + }, /* Connection options */ { 's', 'd', "pgdatabase", diff --git a/src/dir.c b/src/dir.c index 24e8d5a4..b37fcab6 100644 --- a/src/dir.c +++ b/src/dir.c @@ -116,6 +116,8 @@ typedef struct TablespaceCreatedList TablespaceCreatedListCell *tail; } TablespaceCreatedList; +static int BlackListCompare(const void *str1, const void *str2); + static bool dir_check_file(const char *root, pgFile *file); static void dir_list_file_internal(parray *files, const char *root, pgFile *parent, bool exclude, @@ -124,13 +126,12 @@ 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; +parray *extra_remap_list = NULL; /* * Create directory, also create parent directories if necessary. @@ -405,8 +406,7 @@ pgFileCompareSize(const void *f1, const void *f2) return 0; } -/* Compare two strings */ -int +static int BlackListCompare(const void *str1, const void *str2) { return strcmp(*(char **) str1, *(char **) str2); @@ -724,8 +724,6 @@ dir_list_file_internal(parray *files, const char *root, pgFile *parent, continue; } - /* If it is extra dir, remember it */ - /* We add the directory anyway */ if (S_ISDIR(file->mode)) parray_append(files, file); @@ -960,7 +958,9 @@ opt_extradir_map(ConfigOption *opt, const char *arg) char *dst_ptr; const char *arg_ptr; - extra_remap_list = parray_new(); + memset(cell, 0, sizeof(TablespaceListCell)); + if (!extra_remap_list) + extra_remap_list = parray_new(); dst_ptr = dst = cell->old_dir; for (arg_ptr = arg; *arg_ptr; arg_ptr++) { @@ -1284,7 +1284,7 @@ check_extra_dir_mapping(char *current_dir) return current_dir; } -static void +void free_extra_remap_list(void *cell) { TablespaceListCell *cell_ptr; @@ -1294,16 +1294,6 @@ free_extra_remap_list(void *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. */ @@ -1657,14 +1647,16 @@ make_extra_directory_list(const char *colon_separated_dirs) parray *list = parray_new(); char *tmp = palloc(strlen(colon_separated_dirs) + 1); - /* TODO: Add path validation */ strcpy(tmp, colon_separated_dirs); p = strtok(tmp,":"); while(p!=NULL) { char * dir = (char *)palloc(strlen(p) + 1); strcpy(dir,p); - parray_append(list, dir); + if (is_absolute_path(dir)) + parray_append(list, dir); + else + elog(ERROR, "Extra directory \"%s\" is not an absolute path", dir); p=strtok(NULL,":"); } pfree(tmp); diff --git a/src/help.c b/src/help.c index 6b2cd929..578ef289 100644 --- a/src/help.c +++ b/src/help.c @@ -119,18 +119,18 @@ help_pg_probackup(void) printf(_(" [--master-port=port] [--master-user=user_name]\n")); printf(_(" [--replica-timeout=timeout]\n")); printf(_(" [--skip-block-validation]\n")); - printf(_(" [--extra-directory]\n")); + printf(_(" [--extra-directory=extra-directory-path]\n")); printf(_("\n %s restore -B backup-path --instance=instance_name\n"), PROGRAM_NAME); printf(_(" [-D pgdata-path] [-i backup-id] [--progress]\n")); printf(_(" [--time=time|--xid=xid|--lsn=lsn [--inclusive=boolean]]\n")); printf(_(" [--timeline=timeline] [-T OLDDIR=NEWDIR]\n")); + printf(_(" [--extra-mapping=OLDDIR=NEWDIR]\n")); printf(_(" [--immediate] [--recovery-target-name=target-name]\n")); printf(_(" [--recovery-target-action=pause|promote|shutdown]\n")); printf(_(" [--restore-as-replica]\n")); printf(_(" [--no-validate]\n")); printf(_(" [--skip-block-validation]\n")); - printf(_(" [-E OLDDIR=NEWDIR]\n")); printf(_("\n %s validate -B backup-path [--instance=instance_name]\n"), PROGRAM_NAME); printf(_(" [-i backup-id] [--progress]\n")); @@ -209,7 +209,8 @@ help_backup(void) printf(_(" [--master-db=db_name] [--master-host=host_name]\n")); printf(_(" [--master-port=port] [--master-user=user_name]\n")); printf(_(" [--replica-timeout=timeout]\n")); - printf(_(" [--skip-block-validation]\n\n")); + printf(_(" [--skip-block-validation]\n")); + printf(_(" [-E extra-directory=extra-directory-path]\n\n")); printf(_(" -B, --backup-path=backup-path location of the backup storage area\n")); printf(_(" -b, --backup-mode=backup-mode backup mode=FULL|PAGE|DELTA|PTRACK\n")); @@ -221,7 +222,9 @@ help_backup(void) printf(_(" -j, --threads=NUM number of parallel threads\n")); printf(_(" --archive-timeout=timeout wait timeout for WAL segment archiving (default: 5min)\n")); printf(_(" --progress show progress\n")); - printf(_(" --skip-block-validation set to validate only file-level checksum\n")); + printf(_(" --skip-block-validation sextra-directoryet to validate only file-level checksum\n")); + printf(_(" -E --extra-directory=extra-directory-path\n")); + printf(_(" backup some directory not from pgdata \n")); printf(_("\n Logging options:\n")); printf(_(" --log-level-console=log-level-console\n")); @@ -283,9 +286,10 @@ help_restore(void) printf(_(" [-D pgdata-path] [-i backup-id] [--progress]\n")); printf(_(" [--time=time|--xid=xid|--lsn=lsn [--inclusive=boolean]]\n")); printf(_(" [--timeline=timeline] [-T OLDDIR=NEWDIR]\n")); + printf(_(" [--extra-mapping=OLDDIR=NEWDIR]\n")); printf(_(" [--immediate] [--recovery-target-name=target-name]\n")); printf(_(" [--recovery-target-action=pause|promote|shutdown]\n")); - printf(_(" [--restore-as-replica] [--no-validate]\n\n")); + printf(_(" [--restore-as-replica] [--no-validate]\n")); printf(_(" [--skip-block-validation]\n\n")); printf(_(" -B, --backup-path=backup-path location of the backup storage area\n")); @@ -302,6 +306,8 @@ help_restore(void) printf(_(" --timeline=timeline recovering into a particular timeline\n")); printf(_(" -T, --tablespace-mapping=OLDDIR=NEWDIR\n")); printf(_(" relocate the tablespace from directory OLDDIR to NEWDIR\n")); + printf(_(" --extra-mapping=OLDDIR=NEWDIR\n")); + printf(_(" relocate the extra directory from OLDDIR to NEWDIR\n")); printf(_(" --immediate end recovery as soon as a consistent state is reached\n")); printf(_(" --recovery-target-name=target-name\n")); @@ -490,11 +496,14 @@ help_set_config(void) printf(_(" [-d dbname] [-h host] [-p port] [-U username]\n")); printf(_(" [--master-db=db_name] [--master-host=host_name]\n")); printf(_(" [--master-port=port] [--master-user=user_name]\n")); - printf(_(" [--replica-timeout=timeout]\n\n")); - printf(_(" [--archive-timeout=timeout]\n\n")); + printf(_(" [--replica-timeout=timeout]\n")); + printf(_(" [--archive-timeout=timeout]\n")); + printf(_(" [-E extra-directory=extra-directory-path]\n\n")); printf(_(" -B, --backup-path=backup-path location of the backup storage area\n")); printf(_(" --instance=instance_name name of the instance\n")); + printf(_(" -E --extra-directory=extra-directory-path\n")); + printf(_(" backup some directory not from pgdata \n")); printf(_("\n Logging options:\n")); printf(_(" --log-level-console=log-level-console\n")); @@ -560,11 +569,14 @@ static void help_add_instance(void) { printf(_("%s add-instance -B backup-path -D pgdata-path\n"), PROGRAM_NAME); - printf(_(" --instance=instance_name\n\n")); + printf(_(" --instance=instance_name\n")); + printf(_(" -E extra-directory=extra-directory-path\n\n")); printf(_(" -B, --backup-path=backup-path location of the backup storage area\n")); printf(_(" -D, --pgdata=pgdata-path location of the database storage area\n")); printf(_(" --instance=instance_name name of the new instance\n")); + printf(_(" -E --extra-directory=extra-directory-path\n")); + printf(_(" backup some directory not from pgdata \n")); } static void diff --git a/src/pg_probackup.c b/src/pg_probackup.c index fe88840f..c76bed66 100644 --- a/src/pg_probackup.c +++ b/src/pg_probackup.c @@ -137,8 +137,6 @@ 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 }, - { '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 */ @@ -147,6 +145,7 @@ static ConfigOption cmd_options[] = { 's', 138, "inclusive", &target_inclusive, SOURCE_CMD_STRICT }, { 'u', 139, "timeline", &target_tli, SOURCE_CMD_STRICT }, { 'f', 'T', "tablespace-mapping", opt_tablespace_map, SOURCE_CMD_STRICT }, + { 'f', 155, "extra-mapping", opt_extradir_map, SOURCE_CMD_STRICT }, { 'b', 140, "immediate", &target_immediate, SOURCE_CMD_STRICT }, { 's', 141, "recovery-target-name", &target_name, SOURCE_CMD_STRICT }, { 's', 142, "recovery-target-action", &target_action, SOURCE_CMD_STRICT }, diff --git a/src/pg_probackup.h b/src/pg_probackup.h index 670d852d..ef988610 100644 --- a/src/pg_probackup.h +++ b/src/pg_probackup.h @@ -180,6 +180,7 @@ typedef struct InstanceConfig uint32 xlog_seg_size; char *pgdata; + char *extra_dir_str; const char *pgdatabase; const char *pghost; const char *pgport; @@ -352,9 +353,6 @@ extern char *backup_path; extern char backup_instance_path[MAXPGPATH]; extern char arclog_path[MAXPGPATH]; -/* extra directory to backup */ -extern char *extradir; - /* common options */ extern int num_threads; extern bool stream_wal; @@ -396,6 +394,7 @@ extern pgBackup current; /* in dir.c */ /* exclude directory list for $PGDATA file listing */ extern const char *pgdata_exclude_dir[]; +extern parray *extra_remap_list; /* in backup.c */ extern int do_backup(time_t start_time); @@ -522,6 +521,7 @@ extern void free_dir_list(parray *list); extern void makeExtraDirPathByNum(char *ret_path, const char *pattern_path, const int dir_num); extern bool backup_contains_extra(const char *dir, parray *dirs_list); +extern void free_extra_remap_list(void *cell); extern int dir_create_dir(const char *path, mode_t mode); extern bool dir_is_empty(const char *path); @@ -540,7 +540,6 @@ extern int pgFileComparePathWithExtra(const void *f1, const void *f2); extern int pgFileComparePathDesc(const void *f1, const void *f2); extern int pgFileCompareLinked(const void *f1, const void *f2); extern int pgFileCompareSize(const void *f1, const void *f2); -extern int BlackListCompare(const void *str1, const void *str2); /* in data.c */ extern bool backup_data_file(backup_files_arg* arguments, diff --git a/src/restore.c b/src/restore.c index 43133ff4..1148f26f 100644 --- a/src/restore.c +++ b/src/restore.c @@ -407,6 +407,11 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt, /* cleanup */ parray_walk(backups, pgBackupFree); parray_free(backups); + if (extra_remap_list) + { + parray_walk(extra_remap_list, free_extra_remap_list); + parray_free(extra_remap_list); + } elog(INFO, "%s of backup %s completed.", action, base36enc(dest_backup->start_time)); @@ -558,8 +563,6 @@ 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));