1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-11-28 09:33:54 +02:00

[Issue #228]: add strict mode to get_data_file_headers()

This commit is contained in:
Grigory Smolkin 2020-06-21 13:54:29 +03:00
parent ac1ff37ada
commit 73a6915161
4 changed files with 52 additions and 20 deletions

View File

@ -823,10 +823,11 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out,
/* get headers for this file */
if (use_headers && tmp_file->n_headers > 0)
headers = get_data_file_headers(&(backup->hdr_map), tmp_file,
parse_program_version(backup->program_version));
parse_program_version(backup->program_version),
true);
if (use_headers && !headers && tmp_file->n_headers > 0)
elog(ERROR, "Failed to get headers for file \"%s\"", from_fullpath);
elog(ERROR, "Failed to get page headers for file \"%s\"", from_fullpath);
/*
* Restore the file.
@ -1599,10 +1600,13 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
elog(ERROR, "Cannot open file \"%s\": %s",
fullpath, strerror(errno));
headers = get_data_file_headers(hdr_map, file, backup_version);
headers = get_data_file_headers(hdr_map, file, backup_version, false);
if (!headers && file->n_headers > 0)
elog(ERROR, "Failed to get headers for file \"%s\"", fullpath);
{
elog(WARNING, "Cannot get page headers for file \"%s\"", fullpath);
return false;
}
/* calc CRC of backup file */
INIT_FILE_CRC32(use_crc32c, crc);
@ -2124,8 +2128,9 @@ send_pages(ConnectionArgs* conn_arg, const char *to_fullpath, const char *from_f
* array of headers.
*/
BackupPageHeader2*
get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version)
get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version, bool strict)
{
bool success = false;
FILE *in = NULL;
size_t read_len = 0;
pg_crc32 hdr_crc;
@ -2145,13 +2150,19 @@ get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version)
in = fopen(hdr_map->path, PG_BINARY_R);
if (!in)
elog(ERROR, "Cannot open header file \"%s\": %s", hdr_map->path, strerror(errno));
{
elog(strict ? ERROR : WARNING, "Cannot open header file \"%s\": %s", hdr_map->path, strerror(errno));
return NULL;
}
/* disable buffering for header file */
setvbuf(in, NULL, _IONBF, BUFSIZ);
if (fseek(in, file->hdr_off, SEEK_SET))
elog(ERROR, "Cannot seek to position %lu in page header map \"%s\": %s",
{
elog(strict ? ERROR : WARNING, "Cannot seek to position %lu in page header map \"%s\": %s",
file->hdr_off, hdr_map->path, strerror(errno));
goto cleanup;
}
/*
* The actual number of headers in header file is n+1, last one is a dummy header,
@ -2159,28 +2170,35 @@ get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version)
*/
read_len = (file->n_headers+1) * sizeof(BackupPageHeader2);
/* allocate memory for compressed and uncompressed headers */
headers = pgut_malloc(read_len);
memset(headers, 0, read_len);
/* allocate memory for compressed headers */
zheaders = pgut_malloc(file->hdr_size);
memset(zheaders, 0, file->hdr_size);
if (fread(zheaders, 1, file->hdr_size, in) != file->hdr_size)
elog(ERROR, "Cannot read header file at offset: %li len: %i \"%s\": %s",
{
elog(strict ? ERROR : WARNING, "Cannot read header file at offset: %li len: %i \"%s\": %s",
file->hdr_off, file->hdr_size, hdr_map->path, strerror(errno));
goto cleanup;
}
// elog(INFO, "zsize: %i, size: %i", file->hdr_size, read_len);
/* allocate memory for uncompressed headers */
headers = pgut_malloc(read_len);
memset(headers, 0, read_len);
z_len = do_decompress(headers, read_len, zheaders, file->hdr_size,
ZLIB_COMPRESS, &errormsg);
if (z_len <= 0)
{
if (errormsg)
elog(ERROR, "An error occured during metadata decompression for file \"%s\": %s",
elog(strict ? ERROR : WARNING, "An error occured during metadata decompression for file \"%s\": %s",
file->rel_path, errormsg);
else
elog(ERROR, "An error occured during metadata decompression for file \"%s\": %i",
elog(strict ? ERROR : WARNING, "An error occured during metadata decompression for file \"%s\": %i",
file->rel_path, z_len);
goto cleanup;
}
/* validate checksum */
@ -2189,13 +2207,26 @@ get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version)
FIN_FILE_CRC32(true, hdr_crc);
if (hdr_crc != file->hdr_crc)
elog(ERROR, "Header map for file \"%s\" crc mismatch \"%s\" offset: %lu, len: %lu, current: %u, expected: %u",
{
elog(strict ? ERROR : WARNING, "Header map for file \"%s\" crc mismatch \"%s\" "
"offset: %lu, len: %lu, current: %u, expected: %u",
file->rel_path, hdr_map->path, file->hdr_off, read_len, hdr_crc, file->hdr_crc);
goto cleanup;
}
if (fclose(in))
elog(ERROR, "Cannot close file \"%s\"", hdr_map->path);
success = true;
cleanup:
pg_free(zheaders);
if (in && fclose(in))
elog(ERROR, "Cannot close file \"%s\"", hdr_map->path);
if (!success)
{
pg_free(headers);
headers = NULL;
}
return headers;
}

View File

@ -1082,7 +1082,8 @@ merge_files(void *arg)
/* Copy header metadata from old map into a new one */
tmp_file->n_headers = file->n_headers;
headers = get_data_file_headers(&(arguments->full_backup->hdr_map), file,
parse_program_version(arguments->full_backup->program_version));
parse_program_version(arguments->full_backup->program_version),
true);
/* sanity */
if (!headers && file->n_headers > 0)

View File

@ -1020,7 +1020,7 @@ extern pid_t check_postmaster(const char *pgdata);
extern bool validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
uint32 checksum_version, uint32 backup_version, HeaderMap *hdr_map);
extern BackupPageHeader2* get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version);
extern BackupPageHeader2* get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version, bool strict);
extern void write_page_headers(BackupPageHeader2 *headers, pgFile *file, HeaderMap *hdr_map, bool is_merge);
extern void init_header_map(pgBackup *backup);
extern void cleanup_header_map(HeaderMap *hdr_map);

View File

@ -1144,7 +1144,7 @@ restore_files(void *arg)
/* Restore destination file */
if (dest_file->is_datafile && !dest_file->is_cfs)
{
/* enable stdio buffering for local destination non-data file */
/* enable stdio buffering for local destination data file */
if (!fio_is_remote_file(out))
setvbuf(out, out_buf, _IOFBF, STDIO_BUFSIZE);
/* Destination file is data file */
@ -1155,7 +1155,7 @@ restore_files(void *arg)
}
else
{
/* disable stdio buffering for local destination data file */
/* 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 */