1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2025-02-03 14:01:57 +02:00

Remove the limit on the number of extra directories.

Save extra directories separately to eliminate name collisions.
This commit is contained in:
Sergey Cherkashin 2018-11-27 16:28:30 +03:00
parent 07c7c14df6
commit 863486be7e
4 changed files with 55 additions and 35 deletions

View File

@ -463,8 +463,7 @@ do_backup_instance(void)
{ {
int i; int i;
char database_path[MAXPGPATH]; char database_path[MAXPGPATH];
char extra_path[MAXPGPATH]; char extra_path[MAXPGPATH]; /* Temp value. Used as template */
char *extradirs[] = { NULL, NULL, NULL, NULL };
char dst_backup_path[MAXPGPATH]; char dst_backup_path[MAXPGPATH];
char label[1024]; char label[1024];
XLogRecPtr prev_backup_start_lsn = InvalidXLogRecPtr; XLogRecPtr prev_backup_start_lsn = InvalidXLogRecPtr;
@ -478,23 +477,22 @@ do_backup_instance(void)
pgBackup *prev_backup = NULL; pgBackup *prev_backup = NULL;
parray *prev_backup_filelist = NULL; parray *prev_backup_filelist = NULL;
parray *backup_list = NULL; parray *backup_list = NULL;
parray *extra_dirs = NULL;
pgFile *pg_control = NULL; pgFile *pg_control = NULL;
elog(LOG, "Database backup start"); elog(LOG, "Database backup start");
i = 0; extra_dirs = parray_new();
/* TODO: Add path validation */
if(extradir) if(extradir)
{ {
p = strtok(extradir,":"); p = strtok(extradir,":");
while(p!=NULL) while(p!=NULL)
{ {
extradirs[i] = (char *)palloc(strlen(p) + 1); char * dir = (char *)palloc(strlen(p) + 1);
strcpy(extradirs[i],p); strcpy(dir,p);
elog(WARNING,"%s",extradirs[i]); parray_append(extra_dirs, dir);
i++;
p=strtok(NULL,":"); p=strtok(NULL,":");
if (i==3)
break;
} }
} }
@ -654,11 +652,10 @@ do_backup_instance(void)
parse_backup_filelist_filenames(backup_files_list, pgdata); parse_backup_filelist_filenames(backup_files_list, pgdata);
/* Append to backup list all files dirictories from extra dirictory option */ /* Append to backup list all files dirictories from extra dirictory option */
for (i = 0; extradirs[i]; i++) for (i = 0; i < parray_num(extra_dirs); i++)
{ /* Extra dirs numeration starts with 1. 0 value is not extra dir */
elog(WARNING,"%s",extradirs[i]); dir_list_file(backup_files_list, (char *) parray_get(extra_dirs, i),
dir_list_file(backup_files_list, extradirs[i], true, true, true, true); true, true, true, i+1);
}
if (current.backup_mode != BACKUP_MODE_FULL) if (current.backup_mode != BACKUP_MODE_FULL)
{ {
@ -714,8 +711,12 @@ do_backup_instance(void)
elog(VERBOSE, "Create directory \"%s\" NAME %s", dir_name, file->name); elog(VERBOSE, "Create directory \"%s\" NAME %s", dir_name, file->name);
if (file->is_extra) if (file->extra_dir_num)
join_path_components(dirpath, extra_path, dir_name); {
char temp[MAXPGPATH];
sprintf(temp, "%s%d", extra_path, file->extra_dir_num);
join_path_components(dirpath, temp, dir_name);
}
else else
join_path_components(dirpath, database_path, dir_name); join_path_components(dirpath, database_path, dir_name);
dir_create_dir(dirpath, DIR_PERMISSION); dir_create_dir(dirpath, DIR_PERMISSION);
@ -783,6 +784,12 @@ do_backup_instance(void)
parray_walk(prev_backup_filelist, pgFileFree); parray_walk(prev_backup_filelist, pgFileFree);
parray_free(prev_backup_filelist); parray_free(prev_backup_filelist);
} }
/* clean extra directories list */
if (extra_dirs)
{
parray_walk(extra_dirs, pfree);
parray_free(extra_dirs);
}
/* In case of backup from replica >= 9.6 we must fix minRecPoint, /* In case of backup from replica >= 9.6 we must fix minRecPoint,
* First we must find pg_control in backup_files_list. * First we must find pg_control in backup_files_list.
@ -2237,10 +2244,12 @@ backup_files(void *arg)
continue; continue;
} }
} }
else if (file->is_extra) else if (file->extra_dir_num)
{ {
char temp[MAXPGPATH];
sprintf(temp, "%s%d", arguments->extra, file->extra_dir_num);
if (!copy_file(file->extradir, if (!copy_file(file->extradir,
arguments->extra, temp,
file)) file))
{ {
file->write_size = BYTES_INVALID; file->write_size = BYTES_INVALID;

View File

@ -406,7 +406,7 @@ pgBackupCreateDir(pgBackup *backup)
{ {
int i; int i;
char path[MAXPGPATH]; char path[MAXPGPATH];
char *subdirs[] = { DATABASE_DIR, EXTRA_DIR, NULL }; char *subdirs[] = { DATABASE_DIR, NULL };
pgBackupGetPath(backup, path, lengthof(path), NULL); pgBackupGetPath(backup, path, lengthof(path), NULL);

View File

@ -120,7 +120,8 @@ static int BlackListCompare(const void *str1, const void *str2);
static bool dir_check_file(const char *root, pgFile *file); static bool dir_check_file(const char *root, pgFile *file);
static void dir_list_file_internal(parray *files, const char *root, static void dir_list_file_internal(parray *files, const char *root,
pgFile *parent, bool exclude, pgFile *parent, bool exclude,
bool omit_symlink, parray *black_list, bool is_extra); bool omit_symlink, parray *black_list,
int extra_dir_num);
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);
@ -156,7 +157,7 @@ dir_create_dir(const char *dir, mode_t mode)
} }
pgFile * pgFile *
pgFileNew(const char *path, bool omit_symlink, bool is_extra) pgFileNew(const char *path, bool omit_symlink, int extra_dir_num)
{ {
struct stat st; struct stat st;
pgFile *file; pgFile *file;
@ -174,7 +175,8 @@ pgFileNew(const char *path, bool omit_symlink, bool is_extra)
file = pgFileInit(path); file = pgFileInit(path);
file->size = st.st_size; file->size = st.st_size;
file->mode = st.st_mode; file->mode = st.st_mode;
file->is_extra = is_extra; file->is_extra = extra_dir_num > 0;
file->extra_dir_num = extra_dir_num;
file->extradir = NULL; file->extradir = NULL;
return file; return file;
@ -374,7 +376,7 @@ BlackListCompare(const void *str1, const void *str2)
*/ */
void void
dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink, dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink,
bool add_root, bool is_extra) bool add_root, int extra_dir_num)
{ {
pgFile *file; pgFile *file;
parray *black_list = NULL; parray *black_list = NULL;
@ -411,7 +413,7 @@ dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink,
parray_qsort(black_list, BlackListCompare); parray_qsort(black_list, BlackListCompare);
} }
file = pgFileNew(root, false, is_extra); file = pgFileNew(root, false, extra_dir_num);
if (file == NULL) if (file == NULL)
return; return;
@ -427,7 +429,8 @@ dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink,
parray_append(files, file); parray_append(files, file);
} }
dir_list_file_internal(files, root, file, exclude, omit_symlink, black_list, is_extra); dir_list_file_internal(files, root, file, exclude, omit_symlink, black_list,
extra_dir_num);
} }
/* /*
@ -615,7 +618,7 @@ dir_check_file(const char *root, pgFile *file)
*/ */
static void static void
dir_list_file_internal(parray *files, const char *root, pgFile *parent, dir_list_file_internal(parray *files, const char *root, pgFile *parent,
bool exclude, bool omit_symlink, parray *black_list, bool is_extra) bool exclude, bool omit_symlink, parray *black_list, int extra_dir_num)
{ {
DIR *dir; DIR *dir;
struct dirent *dent; struct dirent *dent;
@ -644,7 +647,7 @@ dir_list_file_internal(parray *files, const char *root, pgFile *parent,
join_path_components(child, parent->path, dent->d_name); join_path_components(child, parent->path, dent->d_name);
file = pgFileNew(child, omit_symlink, is_extra); file = pgFileNew(child, omit_symlink, extra_dir_num);
if (file == NULL) if (file == NULL)
continue; continue;
@ -677,7 +680,7 @@ dir_list_file_internal(parray *files, const char *root, pgFile *parent,
} }
/* If it is extra dir, remember it */ /* If it is extra dir, remember it */
if (is_extra) if (extra_dir_num)
{ {
file->extradir = pgut_strdup(root); file->extradir = pgut_strdup(root);
dirname(file->extradir); dirname(file->extradir);
@ -705,7 +708,7 @@ dir_list_file_internal(parray *files, const char *root, pgFile *parent,
*/ */
if (S_ISDIR(file->mode)) if (S_ISDIR(file->mode))
dir_list_file_internal(files, root, file, exclude, omit_symlink, dir_list_file_internal(files, root, file, exclude, omit_symlink,
black_list, is_extra); black_list, extra_dir_num);
} }
if (errno && errno != ENOENT) if (errno && errno != ENOENT)
@ -1201,11 +1204,12 @@ print_file_list(FILE *out, const parray *files, const char *root)
fprintf(out, "{\"path\":\"%s\", \"size\":\"" INT64_FORMAT "\", " fprintf(out, "{\"path\":\"%s\", \"size\":\"" INT64_FORMAT "\", "
"\"mode\":\"%u\", \"is_datafile\":\"%u\", " "\"mode\":\"%u\", \"is_datafile\":\"%u\", "
"\"is_cfs\":\"%u\", \"crc\":\"%u\", " "\"is_cfs\":\"%u\", \"crc\":\"%u\", "
"\"compress_alg\":\"%s\", \"is_extra\":\"%u\"", "\"compress_alg\":\"%s\", \"is_extra\":\"%u\""
", \"extra_dir_num\":\"%u\"",
path, file->write_size, file->mode, path, file->write_size, file->mode,
file->is_datafile ? 1 : 0, file->is_cfs ? 1 : 0, file->crc, file->is_datafile ? 1 : 0, file->is_cfs ? 1 : 0, file->crc,
deparse_compress_alg(file->compress_alg), deparse_compress_alg(file->compress_alg),
file->is_extra ? 1 : 0); file->is_extra ? 1 : 0, file->extra_dir_num);
if (file->extradir) if (file->extradir)
fprintf(out, ",\"extradir\":\"%s\"", file->extradir); fprintf(out, ",\"extradir\":\"%s\"", file->extradir);
@ -1399,6 +1403,7 @@ dir_read_file_list(const char *root, const char *extra_path, const char *file_tx
is_datafile, is_datafile,
is_cfs, is_cfs,
is_extra, is_extra,
extra_dir_num,
crc, crc,
segno, segno,
n_blocks; n_blocks;
@ -1412,10 +1417,15 @@ dir_read_file_list(const char *root, const char *extra_path, const char *file_tx
get_control_value(buf, "crc", NULL, &crc, true); get_control_value(buf, "crc", NULL, &crc, true);
get_control_value(buf, "compress_alg", compress_alg_string, NULL, false); get_control_value(buf, "compress_alg", compress_alg_string, NULL, false);
get_control_value(buf, "is_extra", NULL, &is_extra, false); get_control_value(buf, "is_extra", NULL, &is_extra, false);
get_control_value(buf, "extra_dir_num", NULL, &extra_dir_num, false);
if (root) if (root)
if (is_extra) if (extra_dir_num)
join_path_components(filepath, extra_path, path); {
char temp[MAXPGPATH];
sprintf(temp, "%s%ld", extra_path, extra_dir_num);
join_path_components(filepath, temp, path);
}
else else
join_path_components(filepath, root, path); join_path_components(filepath, root, path);
else else

View File

@ -117,6 +117,7 @@ typedef struct pgFile
bool is_cfs; /* Flag to distinguish files compressed by CFS*/ bool is_cfs; /* Flag to distinguish files compressed by CFS*/
bool is_database; bool is_database;
bool is_extra; bool is_extra;
bool extra_dir_num; /* Number of extra directory. 0 if not extra */
char *extradir; /* File from extra directory */ char *extradir; /* File from extra directory */
bool exists_in_prev; /* Mark files, both data and regular, that exists in previous backup */ bool exists_in_prev; /* Mark files, both data and regular, that exists in previous backup */
CompressAlg compress_alg; /* compression algorithm applied to the file */ CompressAlg compress_alg; /* compression algorithm applied to the file */
@ -516,7 +517,7 @@ extern const char* deparse_compress_alg(int alg);
/* in dir.c */ /* in dir.c */
extern void dir_list_file(parray *files, const char *root, bool exclude, extern void dir_list_file(parray *files, const char *root, bool exclude,
bool omit_symlink, bool add_root, bool is_extra); bool omit_symlink, bool add_root, int extra_dir_num);
extern void create_data_directories(const char *data_dir, extern void create_data_directories(const char *data_dir,
const char *backup_dir, const char *backup_dir,
bool extract_tablespaces); bool extract_tablespaces);
@ -534,7 +535,7 @@ extern bool dir_is_empty(const char *path);
extern bool fileExists(const char *path); extern bool fileExists(const char *path);
extern size_t pgFileSize(const char *path); extern size_t pgFileSize(const char *path);
extern pgFile *pgFileNew(const char *path, bool omit_symlink, bool is_extra); extern pgFile *pgFileNew(const char *path, bool omit_symlink, int extra_dir_num);
extern pgFile *pgFileInit(const char *path); extern pgFile *pgFileInit(const char *path);
extern void pgFileDelete(pgFile *file); extern void pgFileDelete(pgFile *file);
extern void pgFileFree(void *file); extern void pgFileFree(void *file);