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:
parent
9f227cc78f
commit
f5e7e335c4
28
src/data.c
28
src/data.c
@ -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));
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user