Skip to content

Commit 8aa5231

Browse files
committed
[Issue #201] fix restore of files from versions older than 2.3.0
1 parent eea727d commit 8aa5231

File tree

4 files changed

+57
-13
lines changed

4 files changed

+57
-13
lines changed

src/data.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -861,14 +861,25 @@ backup_non_data_file(pgFile *file, pgFile *prev_file,
861861
* Apply changed blocks to destination file from every backup in parent chain.
862862
*/
863863
size_t
864-
restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out, const char *to_fullpath)
864+
restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out,
865+
const char *to_fullpath, bool use_bitmap)
865866
{
866-
int i;
867867
size_t total_write_len = 0;
868868
char *in_buf = pgut_malloc(STDIO_BUFSIZE);
869+
int backup_seq = 0;
870+
871+
// FULL -> INCR -> DEST
872+
// 2 1 0
873+
if (use_bitmap)
874+
/* start with dest backup */
875+
backup_seq = 0;
876+
else
877+
/* start with full backup */
878+
backup_seq = parray_num(parent_chain) - 1;
869879

870880
// for (i = parray_num(parent_chain) - 1; i >= 0; i--)
871-
for (i = 0; i < parray_num(parent_chain); i++)
881+
// for (i = 0; i < parray_num(parent_chain); i++)
882+
while (backup_seq >= 0 && backup_seq < parray_num(parent_chain))
872883
{
873884
char from_root[MAXPGPATH];
874885
char from_fullpath[MAXPGPATH];
@@ -877,7 +888,12 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out, const char
877888
pgFile **res_file = NULL;
878889
pgFile *tmp_file = NULL;
879890

880-
pgBackup *backup = (pgBackup *) parray_get(parent_chain, i);
891+
pgBackup *backup = (pgBackup *) parray_get(parent_chain, backup_seq);
892+
893+
if (use_bitmap)
894+
backup_seq++;
895+
else
896+
backup_seq--;
881897

882898
/* lookup file in intermediate backup */
883899
res_file = parray_bsearch(backup->files, dest_file, pgFileCompareRelPathWithExternal);
@@ -925,7 +941,7 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out, const char
925941
total_write_len += restore_data_file_internal(in, out, tmp_file,
926942
parse_program_version(backup->program_version),
927943
from_fullpath, to_fullpath, dest_file->n_blocks,
928-
&(dest_file)->pagemap);
944+
use_bitmap ? &(dest_file)->pagemap : NULL);
929945

930946
if (fclose(in) != 0)
931947
elog(ERROR, "Cannot close file \"%s\": %s", from_fullpath,
@@ -938,6 +954,11 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out, const char
938954
return total_write_len;
939955
}
940956

957+
/* Restore block from "in" file to "out" file.
958+
* If "nblocks" is greater than zero, then skip restoring blocks,
959+
* whose position if greater than "nblocks".
960+
* If map is NULL, then page bitmap cannot be used for restore optimization
961+
*/
941962
size_t
942963
restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_version,
943964
const char *from_fullpath, const char *to_fullpath, int nblocks,
@@ -1050,7 +1071,7 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
10501071
elog(ERROR, "Size of a blknum %i exceed BLCKSZ", blknum);
10511072

10521073
/* if this page is marked as already restored, then skip it */
1053-
if (datapagemap_is_set(map, blknum))
1074+
if (map && datapagemap_is_set(map, blknum))
10541075
{
10551076
/* skip to the next page */
10561077
if (fseek(in, MAXALIGN(compressed_size), SEEK_CUR) != 0)
@@ -1115,7 +1136,8 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
11151136
write_len += BLCKSZ;
11161137
cur_pos = write_pos + BLCKSZ; /* update current write position */
11171138

1118-
datapagemap_add(map, blknum);
1139+
if (map)
1140+
datapagemap_add(map, blknum);
11191141
}
11201142

11211143
elog(VERBOSE, "Copied file \"%s\": %lu bytes", from_fullpath, write_len);
@@ -1191,6 +1213,7 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
11911213
* full copy of destination file.
11921214
* Full copy is latest possible destination file with size equal or
11931215
* greater than zero.
1216+
* TODO: rewrite to use parent_link of dest backup.
11941217
*/
11951218
for (i = 1; i < parray_num(parent_chain); i++)
11961219
{

src/merge.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ typedef struct
2828
// size_t in_place_merge_bytes;
2929
bool compression_match;
3030
bool program_version_match;
31+
bool use_bitmap;
3132

3233
/*
3334
* Return value from the thread.
@@ -47,7 +48,7 @@ get_external_index(const char *key, const parray *list);
4748
static void
4849
merge_data_file(parray *parent_chain, pgBackup *full_backup,
4950
pgBackup *dest_backup, pgFile *dest_file,
50-
pgFile *tmp_file, const char *to_root);
51+
pgFile *tmp_file, const char *to_root, bool use_bitmap);
5152

5253
static void
5354
merge_non_data_file(parray *parent_chain, pgBackup *full_backup,
@@ -439,6 +440,7 @@ merge_chain(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup)
439440
*dest_externals = NULL;
440441

441442
parray *result_filelist = NULL;
443+
bool use_bitmap = true;
442444
// size_t total_in_place_merge_bytes = 0;
443445

444446
pthread_t *threads = NULL;
@@ -601,6 +603,9 @@ merge_chain(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup)
601603
if (full_externals && dest_externals)
602604
reorder_external_dirs(full_backup, full_externals, dest_externals);
603605

606+
if (parse_program_version(dest_backup->program_version) < 20300)
607+
use_bitmap = false;
608+
604609
/* Setup threads */
605610
for (i = 0; i < parray_num(dest_backup->files); i++)
606611
{
@@ -639,6 +644,7 @@ merge_chain(parray *parent_chain, pgBackup *full_backup, pgBackup *dest_backup)
639644

640645
arg->compression_match = compression_match;
641646
arg->program_version_match = program_version_match;
647+
arg->use_bitmap = use_bitmap;
642648
/* By default there are some error */
643649
arg->ret = 1;
644650

@@ -1028,7 +1034,8 @@ merge_files(void *arg)
10281034
arguments->full_backup,
10291035
arguments->dest_backup,
10301036
dest_file, tmp_file,
1031-
arguments->full_database_dir);
1037+
arguments->full_database_dir,
1038+
arguments->use_bitmap);
10321039
else
10331040
merge_non_data_file(arguments->parent_chain,
10341041
arguments->full_backup,
@@ -1128,7 +1135,7 @@ reorder_external_dirs(pgBackup *to_backup, parray *to_external,
11281135
void
11291136
merge_data_file(parray *parent_chain, pgBackup *full_backup,
11301137
pgBackup *dest_backup, pgFile *dest_file, pgFile *tmp_file,
1131-
const char *full_database_dir)
1138+
const char *full_database_dir, bool use_bitmap)
11321139
{
11331140
FILE *out = NULL;
11341141
char *buffer = pgut_malloc(STDIO_BUFSIZE);
@@ -1154,7 +1161,7 @@ merge_data_file(parray *parent_chain, pgBackup *full_backup,
11541161
setvbuf(out, buffer, _IOFBF, STDIO_BUFSIZE);
11551162

11561163
/* restore file into temp file */
1157-
tmp_file->size = restore_data_file(parent_chain, dest_file, out, to_fullpath_tmp1);
1164+
tmp_file->size = restore_data_file(parent_chain, dest_file, out, to_fullpath_tmp1, use_bitmap);
11581165
fclose(out);
11591166
pg_free(buffer);
11601167

src/pg_probackup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -935,7 +935,7 @@ extern void backup_non_data_file_internal(const char *from_fullpath,
935935
bool missing_ok);
936936

937937
extern size_t restore_data_file(parray *parent_chain, pgFile *dest_file,
938-
FILE *out, const char *to_fullpath);
938+
FILE *out, const char *to_fullpath, bool use_bitmap);
939939
extern size_t restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_version,
940940
const char *from_fullpath, const char *to_fullpath, int nblocks,
941941
datapagemap_t *map);

src/restore.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ typedef struct
2727
bool skip_external_dirs;
2828
const char *to_root;
2929
size_t restored_bytes;
30+
bool use_bitmap;
3031

3132
/*
3233
* Return value from the thread.
@@ -501,6 +502,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
501502
pthread_t *threads;
502503
restore_files_arg *threads_args;
503504
bool restore_isok = true;
505+
bool use_bitmap = true;
504506

505507
/* fancy reporting */
506508
char pretty_dest_bytes[20];
@@ -560,6 +562,13 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
560562
parray_qsort(backup->files, pgFileCompareRelPathWithExternal);
561563
}
562564

565+
/* If dest backup version is older than 2.3.0, then bitmap optimization
566+
* is impossible to use, because bitmap restore rely on pgFile.n_blocks,
567+
* which is not always available in old backups.
568+
*/
569+
if (parse_program_version(dest_backup->program_version) < 20300)
570+
use_bitmap = false;
571+
563572
/*
564573
* Restore dest_backup internal directories.
565574
*/
@@ -645,6 +654,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
645654
arg->dbOid_exclude_list = dbOid_exclude_list;
646655
arg->skip_external_dirs = params->skip_external_dirs;
647656
arg->to_root = pgdata_path;
657+
arg->use_bitmap = use_bitmap;
648658
threads_args[i].restored_bytes = 0;
649659
/* By default there are some error */
650660
threads_args[i].ret = 1;
@@ -859,7 +869,8 @@ restore_files(void *arg)
859869
setvbuf(out, out_buf, _IOFBF, STDIO_BUFSIZE);
860870
/* Destination file is data file */
861871
arguments->restored_bytes += restore_data_file(arguments->parent_chain,
862-
dest_file, out, to_fullpath);
872+
dest_file, out, to_fullpath,
873+
arguments->use_bitmap);
863874
}
864875
else
865876
{
@@ -976,6 +987,9 @@ create_recovery_conf(time_t backup_id,
976987
elog(ERROR, "cannot open file \"%s\": %s", path,
977988
strerror(errno));
978989

990+
if (fio_chmod(path, FILE_PERMISSION, FIO_DB_HOST) == -1)
991+
elog(ERROR, "Cannot change mode of \"%s\": %s", path, strerror(errno));
992+
979993
#if PG_VERSION_NUM >= 120000
980994
fio_fprintf(fp, "# probackup_recovery.conf generated by pg_probackup %s\n",
981995
PROGRAM_VERSION);

0 commit comments

Comments
 (0)