1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-11-24 08:52:38 +02:00

[Issue #66] Correctly handle zero-sized nonedata files during incremental restore

This commit is contained in:
Grigory Smolkin 2020-06-23 00:15:37 +03:00
parent 9f227cc78f
commit f5e7e335c4
3 changed files with 37 additions and 20 deletions

View File

@ -711,7 +711,7 @@ backup_non_data_file(pgFile *file, pgFile *prev_file,
}
/*
* If non-data file exists in previous backup
* If nonedata file exists in previous backup
* and its mtime is less than parent backup start time ... */
if (prev_file && file->exists_in_prev &&
file->mtime <= parent_backup_time)
@ -1136,7 +1136,7 @@ restore_non_data_file_internal(FILE *in, FILE *out, pgFile *file,
/* check for interrupt */
if (interrupted || thread_interrupted)
elog(ERROR, "Interrupted during non-data file restore");
elog(ERROR, "Interrupted during nonedata file restore");
read_len = fread(buf, 1, STDIO_BUFSIZE, in);
@ -1165,7 +1165,6 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
pgFile *dest_file, FILE *out, const char *to_fullpath,
bool already_exists)
{
// int i;
char from_root[MAXPGPATH];
char from_fullpath[MAXPGPATH];
FILE *in = NULL;
@ -1203,14 +1202,19 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
*/
if (!tmp_file)
{
elog(ERROR, "Failed to locate non-data file \"%s\" in backup %s",
elog(ERROR, "Failed to locate nonedata file \"%s\" in backup %s",
dest_file->rel_path, base36enc(tmp_backup->start_time));
continue;
}
/* Full copy is found and it is null sized, nothing to do here */
if (tmp_file->write_size == 0)
{
/* In case of incremental restore truncate file just to be safe */
if (already_exists && fio_ftruncate(out, 0))
elog(ERROR, "Cannot truncate file \"%s\": %s", strerror(errno));
return 0;
}
/* Full copy is found */
if (tmp_file->write_size > 0)
@ -1222,14 +1226,14 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
/* sanity */
if (!tmp_backup)
elog(ERROR, "Failed to found a backup containing full copy of non-data file \"%s\"",
elog(ERROR, "Failed to locate a backup containing full copy of nonedata file \"%s\"",
to_fullpath);
if (!tmp_file)
elog(ERROR, "Failed to locate a full copy of non-data file \"%s\"", to_fullpath);
elog(ERROR, "Failed to locate a full copy of nonedata file \"%s\"", to_fullpath);
if (tmp_file->write_size <= 0)
elog(ERROR, "Full copy of non-data file has invalid size. "
elog(ERROR, "Full copy of nonedata file has invalid size. "
"Metadata corruption in backup %s in file: \"%s\"",
base36enc(tmp_backup->start_time), to_fullpath);
@ -1245,6 +1249,10 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
to_fullpath);
return 0;
}
/* Checksum mismatch, truncate file and overwrite it */
if (fio_ftruncate(out, 0))
elog(ERROR, "Cannot truncate file \"%s\": %s", strerror(errno));
}
if (tmp_file->external_dir_num == 0)
@ -1264,7 +1272,7 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
elog(ERROR, "Cannot open backup file \"%s\": %s", from_fullpath,
strerror(errno));
/* disable stdio buffering for non-data files */
/* disable stdio buffering for nonedata files */
setvbuf(in, NULL, _IONBF, BUFSIZ);
/* do actual work */
@ -1793,7 +1801,7 @@ get_checksum_map(const char *fullpath, uint32 checksum_version,
char in_buf[STDIO_BUFSIZE];
/* open file */
in = fopen(fullpath, PG_BINARY_R);
in = fopen(fullpath, "r+");
if (!in)
elog(ERROR, "Cannot open source file \"%s\": %s", fullpath, strerror(errno));
@ -1864,7 +1872,7 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
Assert(shift_lsn > 0);
/* open file */
in = fopen(fullpath, PG_BINARY_R);
in = fopen(fullpath, "r+");
if (!in)
elog(ERROR, "Cannot open source file \"%s\": %s", fullpath, strerror(errno));

View File

@ -1342,7 +1342,7 @@ merge_non_data_file(parray *parent_chain, pgBackup *full_backup,
*/
if (!from_file)
{
elog(ERROR, "Failed to locate non-data file \"%s\" in backup %s",
elog(ERROR, "Failed to locate nonedata file \"%s\" in backup %s",
dest_file->rel_path, base36enc(from_backup->start_time));
continue;
}
@ -1353,11 +1353,11 @@ merge_non_data_file(parray *parent_chain, pgBackup *full_backup,
/* sanity */
if (!from_backup)
elog(ERROR, "Failed to found a backup containing full copy of non-data file \"%s\"",
elog(ERROR, "Failed to found a backup containing full copy of nonedata file \"%s\"",
dest_file->rel_path);
if (!from_file)
elog(ERROR, "Failed to locate a full copy of non-data file \"%s\"", dest_file->rel_path);
elog(ERROR, "Failed to locate a full copy of nonedata file \"%s\"", dest_file->rel_path);
/* set path to source file */
if (from_file->external_dir_num)

View File

@ -470,8 +470,8 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
base36enc(dest_backup->start_time),
(uint32) (redo.lsn >> 32), (uint32) redo.lsn, redo.tli);
else
elog(INFO, "Destination directory redo point %X/%X on tli %i is within reach of "
"backup %s with Stop LSN %X/%X on tli %i, incremental restore in 'lsn' mode is possible",
elog(INFO, "Destination directory redo point %X/%X on tli %i is "
"within reach of backup %s with Stop LSN %X/%X on tli %i",
(uint32) (redo.lsn >> 32), (uint32) redo.lsn, redo.tli,
base36enc(tmp_backup->start_time),
(uint32) (tmp_backup->stop_lsn >> 32), (uint32) tmp_backup->stop_lsn,
@ -1118,11 +1118,20 @@ restore_files(void *arg)
}
}
/* open destination file */
if (already_exists)
out = fio_fopen(to_fullpath, PG_BINARY_R "+", FIO_DB_HOST);
else
/*
* Open dest file and truncate it to zero, if destination
* file already exists and dest file size is zero, or
* if file do not exist
*/
if ((already_exists && dest_file->write_size == 0) || !already_exists)
out = fio_fopen(to_fullpath, PG_BINARY_W, FIO_DB_HOST);
/*
* If file already exists and dest size is not zero,
* then open it for reading and writing.
*/
else
out = fio_fopen(to_fullpath, PG_BINARY_R "+", FIO_DB_HOST);
if (out == NULL)
elog(ERROR, "Cannot open restore target file \"%s\": %s",
to_fullpath, strerror(errno));
@ -1158,7 +1167,7 @@ restore_files(void *arg)
/* disable stdio buffering for local destination nonedata file */
if (!fio_is_remote_file(out))
setvbuf(out, NULL, _IONBF, BUFSIZ);
/* Destination file is non-data file */
/* Destination file is nonedata file */
arguments->restored_bytes += restore_non_data_file(arguments->parent_chain,
arguments->dest_backup, dest_file, out, to_fullpath,
already_exists);