Skip to content

Commit f2d2bab

Browse files
committed
Merge branch 'issue_201' into release_2_4
2 parents 50dbee3 + 721a153 commit f2d2bab

File tree

8 files changed

+175
-41
lines changed

8 files changed

+175
-41
lines changed

src/backup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2225,7 +2225,7 @@ parse_filelist_filenames(parray *files, const char *root)
22252225
if (S_ISREG(file->mode) && file->tblspcOid != 0 &&
22262226
file->name && file->name[0])
22272227
{
2228-
if (file->forkName == INIT)
2228+
if (file->forkName == init)
22292229
{
22302230
/*
22312231
* Do not backup files of unlogged relations.

src/data.c

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -861,13 +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;
869870

870-
for (i = parray_num(parent_chain) - 1; i >= 0; i--)
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;
879+
880+
// for (i = parray_num(parent_chain) - 1; i >= 0; i--)
881+
// for (i = 0; i < parray_num(parent_chain); i++)
882+
while (backup_seq >= 0 && backup_seq < parray_num(parent_chain))
871883
{
872884
char from_root[MAXPGPATH];
873885
char from_fullpath[MAXPGPATH];
@@ -876,7 +888,12 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out, const char
876888
pgFile **res_file = NULL;
877889
pgFile *tmp_file = NULL;
878890

879-
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--;
880897

881898
/* lookup file in intermediate backup */
882899
res_file = parray_bsearch(backup->files, dest_file, pgFileCompareRelPathWithExternal);
@@ -923,20 +940,29 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out, const char
923940
*/
924941
total_write_len += restore_data_file_internal(in, out, tmp_file,
925942
parse_program_version(backup->program_version),
926-
from_fullpath, to_fullpath, dest_file->n_blocks);
943+
from_fullpath, to_fullpath, dest_file->n_blocks,
944+
use_bitmap ? &(dest_file)->pagemap : NULL);
927945

928946
if (fclose(in) != 0)
929947
elog(ERROR, "Cannot close file \"%s\": %s", from_fullpath,
930948
strerror(errno));
949+
950+
// datapagemap_print_debug(&(dest_file)->pagemap);
931951
}
932952
pg_free(in_buf);
933953

934954
return total_write_len;
935955
}
936956

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+
*/
937962
size_t
938963
restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_version,
939-
const char *from_fullpath, const char *to_fullpath, int nblocks)
964+
const char *from_fullpath, const char *to_fullpath, int nblocks,
965+
datapagemap_t *map)
940966
{
941967
BackupPageHeader header;
942968
BlockNumber blknum = 0;
@@ -994,9 +1020,9 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
9941020
}
9951021

9961022
/* sanity? */
997-
if (header.block < blknum)
998-
elog(ERROR, "Backup is broken at block %u of \"%s\"",
999-
blknum, from_fullpath);
1023+
// if (header.block < blknum)
1024+
// elog(ERROR, "Backup is broken at block %u of \"%s\"",
1025+
// blknum, from_fullpath);
10001026

10011027
blknum = header.block;
10021028

@@ -1044,6 +1070,16 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
10441070
if (compressed_size > BLCKSZ)
10451071
elog(ERROR, "Size of a blknum %i exceed BLCKSZ", blknum);
10461072

1073+
/* if this page is marked as already restored, then skip it */
1074+
if (map && datapagemap_is_set(map, blknum))
1075+
{
1076+
/* skip to the next page */
1077+
if (fseek(in, MAXALIGN(compressed_size), SEEK_CUR) != 0)
1078+
elog(ERROR, "Cannot seek block %u of '%s': %s",
1079+
blknum, from_fullpath, strerror(errno));
1080+
continue;
1081+
}
1082+
10471083
/* read a page from file */
10481084
read_len = fread(page.data, 1, MAXALIGN(compressed_size), in);
10491085

@@ -1099,6 +1135,9 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
10991135

11001136
write_len += BLCKSZ;
11011137
cur_pos = write_pos + BLCKSZ; /* update current write position */
1138+
1139+
if (map)
1140+
datapagemap_add(map, blknum);
11021141
}
11031142

11041143
elog(VERBOSE, "Copied file \"%s\": %lu bytes", from_fullpath, write_len);
@@ -1152,7 +1191,7 @@ size_t
11521191
restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
11531192
pgFile *dest_file, FILE *out, const char *to_fullpath)
11541193
{
1155-
int i;
1194+
// int i;
11561195
char from_root[MAXPGPATH];
11571196
char from_fullpath[MAXPGPATH];
11581197
FILE *in = NULL;
@@ -1175,12 +1214,11 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
11751214
* Full copy is latest possible destination file with size equal or
11761215
* greater than zero.
11771216
*/
1178-
for (i = 1; i < parray_num(parent_chain); i++)
1217+
tmp_backup = dest_backup->parent_backup_link;
1218+
while (tmp_backup)
11791219
{
11801220
pgFile **res_file = NULL;
11811221

1182-
tmp_backup = (pgBackup *) parray_get(parent_chain, i);
1183-
11841222
/* lookup file in intermediate backup */
11851223
res_file = parray_bsearch(tmp_backup->files, dest_file, pgFileCompareRelPathWithExternal);
11861224
tmp_file = (res_file) ? *res_file : NULL;
@@ -1203,6 +1241,8 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
12031241
/* Full copy is found */
12041242
if (tmp_file->write_size > 0)
12051243
break;
1244+
1245+
tmp_backup = tmp_backup->parent_backup_link;
12061246
}
12071247
}
12081248

@@ -1214,6 +1254,11 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
12141254
if (!tmp_file)
12151255
elog(ERROR, "Failed to locate a full copy of non-data file \"%s\"", to_fullpath);
12161256

1257+
if (tmp_file->write_size <= 0)
1258+
elog(ERROR, "Full copy of non-data file has invalid size. "
1259+
"Metadata corruption in backup %s in file: \"%s\"",
1260+
base36enc(tmp_backup->start_time), to_fullpath);
1261+
12171262
if (tmp_file->external_dir_num == 0)
12181263
join_path_components(from_root, tmp_backup->root_dir, DATABASE_DIR);
12191264
else

src/dir.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -720,22 +720,22 @@ dir_check_file(pgFile *file)
720720
{
721721
/* Auxiliary fork of the relfile */
722722
if (strcmp(fork_name, "vm") == 0)
723-
file->forkName = VM;
723+
file->forkName = vm;
724724

725725
else if (strcmp(fork_name, "fsm") == 0)
726-
file->forkName = FSM;
726+
file->forkName = fsm;
727727

728728
else if (strcmp(fork_name, "cfm") == 0)
729-
file->forkName = CFM;
730-
731-
else if (strcmp(fork_name, "init") == 0)
732-
file->forkName = INIT;
729+
file->forkName = cfm;
733730

734731
else if (strcmp(fork_name, "ptrack") == 0)
735-
file->forkName = PTRACK;
732+
file->forkName = ptrack;
733+
734+
else if (strcmp(fork_name, "init") == 0)
735+
file->forkName = init;
736736

737737
/* Do not backup ptrack files */
738-
if (file->forkName == PTRACK)
738+
if (file->forkName == ptrack)
739739
return CHECK_FALSE;
740740
}
741741
else

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: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,11 @@ typedef enum CompressAlg
124124

125125
typedef enum ForkName
126126
{
127-
VM,
128-
FSM,
129-
CFM,
130-
INIT,
131-
PTRACK
127+
vm,
128+
fsm,
129+
cfm,
130+
init,
131+
ptrack
132132
} ForkName;
133133

134134
#define INIT_FILE_CRC32(use_crc32c, crc) \
@@ -935,9 +935,10 @@ 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,
940-
const char *from_fullpath, const char *to_fullpath, int nblocks);
940+
const char *from_fullpath, const char *to_fullpath, int nblocks,
941+
datapagemap_t *map);
941942
extern size_t restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
942943
pgFile *dest_file, FILE *out, const char *to_fullpath);
943944
extern void restore_non_data_file_internal(FILE *in, FILE *out, pgFile *file,
@@ -1056,4 +1057,10 @@ extern void get_header_errormsg(Page page, char **errormsg);
10561057
extern void get_checksum_errormsg(Page page, char **errormsg,
10571058
BlockNumber absolute_blkno);
10581059

1060+
extern bool
1061+
datapagemap_is_set(datapagemap_t *map, BlockNumber blkno);
1062+
1063+
extern void
1064+
datapagemap_print_debug(datapagemap_t *map);
1065+
10591066
#endif /* PG_PROBACKUP_H */

src/restore.c

Lines changed: 22 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,17 @@ 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+
572+
/* There is no point in bitmap restore, when restoring a single FULL backup */
573+
if (parray_num(parent_chain) == 1)
574+
use_bitmap = false;
575+
563576
/*
564577
* Restore dest_backup internal directories.
565578
*/
@@ -645,6 +658,7 @@ restore_chain(pgBackup *dest_backup, parray *parent_chain,
645658
arg->dbOid_exclude_list = dbOid_exclude_list;
646659
arg->skip_external_dirs = params->skip_external_dirs;
647660
arg->to_root = pgdata_path;
661+
arg->use_bitmap = use_bitmap;
648662
threads_args[i].restored_bytes = 0;
649663
/* By default there are some error */
650664
threads_args[i].ret = 1;
@@ -859,7 +873,8 @@ restore_files(void *arg)
859873
setvbuf(out, out_buf, _IOFBF, STDIO_BUFSIZE);
860874
/* Destination file is data file */
861875
arguments->restored_bytes += restore_data_file(arguments->parent_chain,
862-
dest_file, out, to_fullpath);
876+
dest_file, out, to_fullpath,
877+
arguments->use_bitmap);
863878
}
864879
else
865880
{
@@ -871,6 +886,9 @@ restore_files(void *arg)
871886
arguments->dest_backup, dest_file, out, to_fullpath);
872887
}
873888

889+
/* free pagemap used for restore optimization */
890+
pg_free(dest_file->pagemap.bitmap);
891+
874892
done:
875893
/* close file */
876894
if (fio_fclose(out) != 0)
@@ -973,6 +991,9 @@ create_recovery_conf(time_t backup_id,
973991
elog(ERROR, "cannot open file \"%s\": %s", path,
974992
strerror(errno));
975993

994+
if (fio_chmod(path, FILE_PERMISSION, FIO_DB_HOST) == -1)
995+
elog(ERROR, "Cannot change mode of \"%s\": %s", path, strerror(errno));
996+
976997
#if PG_VERSION_NUM >= 120000
977998
fio_fprintf(fp, "# probackup_recovery.conf generated by pg_probackup %s\n",
978999
PROGRAM_VERSION);

0 commit comments

Comments
 (0)