mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
Allow page header checks to be skipped.
These checks cause false negatives for page checksum verification when the page is encrypted because pd_upper might end up as 0 in the encrypted data. This issue is rare but reproducible given a large enough cluster. Make these checks optional, but leave them enabled by default.
This commit is contained in:
parent
8240eb5da5
commit
f5e6bc2698
@ -17,6 +17,16 @@
|
||||
<release date="XXXX-XX-XX" version="2.46dev" title="UNDER DEVELOPMENT">
|
||||
<release-core-list>
|
||||
<release-improvement-list>
|
||||
<release-item>
|
||||
<release-item-contributor-list>
|
||||
<release-item-ideator id="david.christensen"/>
|
||||
<release-item-contributor id="david.steele"/>
|
||||
<release-item-reviewer id="david.christensen"/>
|
||||
</release-item-contributor-list>
|
||||
|
||||
<p>Allow page header checks to be skipped.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<commit subject="Move error modules to common/error directory."/>
|
||||
<commit subject="Improve retry error messages."/>
|
||||
|
@ -1210,6 +1210,15 @@ option:
|
||||
command-role:
|
||||
main: {}
|
||||
|
||||
page-header-check:
|
||||
section: global
|
||||
type: boolean
|
||||
default: true
|
||||
command:
|
||||
backup: {}
|
||||
command-role:
|
||||
main: {}
|
||||
|
||||
exclude:
|
||||
section: global
|
||||
type: list
|
||||
|
@ -1249,6 +1249,18 @@
|
||||
<example>y</example>
|
||||
</config-key>
|
||||
|
||||
<config-key id="page-header-check" name="Page Header Check">
|
||||
<summary>Check PostgreSQL page headers.</summary>
|
||||
|
||||
<text>
|
||||
<p>Enabled by default, this option adds page header checks.</p>
|
||||
|
||||
<p>Disabling this option should be avoided except when necessary, e.g. if pages are encrypted.</p>
|
||||
</text>
|
||||
|
||||
<example>n</example>
|
||||
</config-key>
|
||||
|
||||
<config-key id="resume" name="Resume">
|
||||
<summary>Allow resume of failed backup.</summary>
|
||||
|
||||
|
@ -1987,6 +1987,7 @@ backupJobCallback(void *const data, const unsigned int clientIdx)
|
||||
pckWriteBoolP(param, !backupProcessFilePrimary(jobData->standbyExp, file.name));
|
||||
pckWriteBinP(param, file.checksumSha1 != NULL ? BUF(file.checksumSha1, HASH_TYPE_SHA1_SIZE) : NULL);
|
||||
pckWriteBoolP(param, file.checksumPage);
|
||||
pckWriteBoolP(param, cfgOptionBool(cfgOptPageHeaderCheck));
|
||||
|
||||
// If block incremental then provide the location of the prior map when available
|
||||
if (blockIncr)
|
||||
|
@ -208,7 +208,8 @@ backupFile(
|
||||
ioFilterGroupAdd(
|
||||
ioReadFilterGroup(storageReadIo(read)),
|
||||
pageChecksumNew(
|
||||
segmentNumber(file->pgFile), PG_SEGMENT_PAGE_DEFAULT, storagePathP(storagePg(), file->pgFile)));
|
||||
segmentNumber(file->pgFile), PG_SEGMENT_PAGE_DEFAULT, file->pgFilePageHeaderCheck,
|
||||
storagePathP(storagePg(), file->pgFile)));
|
||||
}
|
||||
|
||||
// Compress filter
|
||||
|
@ -33,6 +33,7 @@ typedef struct BackupFile
|
||||
bool pgFileCopyExactSize; // Copy only pg expected size
|
||||
const Buffer *pgFileChecksum; // Expected pg file checksum
|
||||
bool pgFileChecksumPage; // Validate page checksums?
|
||||
bool pgFilePageHeaderCheck; // Validate page headers?
|
||||
size_t blockIncrSize; // Perform block incremental on this file?
|
||||
size_t blockIncrChecksumSize; // Block checksum size
|
||||
uint64_t blockIncrSuperSize; // Size of the super block
|
||||
|
@ -21,6 +21,7 @@ typedef struct PageChecksum
|
||||
{
|
||||
unsigned int segmentPageTotal; // Total pages in a segment
|
||||
unsigned int pageNoOffset; // Page number offset for subsequent segments
|
||||
bool headerCheck; // Perform additional header checks?
|
||||
const String *fileName; // Used to load the file to retry pages
|
||||
|
||||
unsigned char *pageBuffer; // Buffer to hold a page while verifying the checksum
|
||||
@ -99,28 +100,29 @@ pageChecksumProcess(THIS_VOID, const Buffer *const input)
|
||||
// Only validate page checksum if the page is complete
|
||||
if (this->align || pageIdx < pageTotal - 1)
|
||||
{
|
||||
// Skip new pages indicated by pd_upper == 0
|
||||
bool pdUpperValid = true;
|
||||
bool pageValid = true;
|
||||
|
||||
if (pageHeader->pd_upper == 0)
|
||||
// Skip new all-zero pages. To speed this up first check pd_upper when header check is enabled or pd_checksum when
|
||||
// header check is disabled. The latter is required when the page is encrypted.
|
||||
if ((this->headerCheck && pageHeader->pd_upper == 0) || (!this->headerCheck && pageHeader->pd_checksum == 0))
|
||||
{
|
||||
// Check that the entire page is zero in case pd_upper is corrupted
|
||||
// Check that the entire page is zero
|
||||
for (unsigned int pageIdx = 0; pageIdx < PG_PAGE_SIZE_DEFAULT / sizeof(size_t); pageIdx++)
|
||||
{
|
||||
if (((size_t *)pageHeader)[pageIdx] != 0)
|
||||
{
|
||||
pdUpperValid = false;
|
||||
pageValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the entire page is zero it is valid
|
||||
if (pdUpperValid)
|
||||
if (pageValid)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only validate the checksum if pd_upper is non-zero to avoid an assertion from pg_checksum_page()
|
||||
if (pdUpperValid)
|
||||
// Only validate the checksum if the page is valid
|
||||
if (pageValid)
|
||||
{
|
||||
// Make a copy of the page since it will be modified by the page checksum function
|
||||
memcpy(this->pageBuffer, pageHeader, PG_PAGE_SIZE_DEFAULT);
|
||||
@ -223,11 +225,13 @@ pageChecksumResult(THIS_VOID)
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN IoFilter *
|
||||
pageChecksumNew(const unsigned int segmentNo, const unsigned int segmentPageTotal, const String *const fileName)
|
||||
pageChecksumNew(
|
||||
const unsigned int segmentNo, const unsigned int segmentPageTotal, const bool headerCheck, const String *const fileName)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||
FUNCTION_LOG_PARAM(UINT, segmentNo);
|
||||
FUNCTION_LOG_PARAM(UINT, segmentPageTotal);
|
||||
FUNCTION_LOG_PARAM(BOOL, headerCheck);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
@ -237,6 +241,7 @@ pageChecksumNew(const unsigned int segmentNo, const unsigned int segmentPageTota
|
||||
{
|
||||
.segmentPageTotal = segmentPageTotal,
|
||||
.pageNoOffset = segmentNo * segmentPageTotal,
|
||||
.headerCheck = headerCheck,
|
||||
.fileName = strDup(fileName),
|
||||
.pageBuffer = bufPtr(bufNew(PG_PAGE_SIZE_DEFAULT)),
|
||||
.valid = true,
|
||||
@ -254,6 +259,7 @@ pageChecksumNew(const unsigned int segmentNo, const unsigned int segmentPageTota
|
||||
|
||||
pckWriteU32P(packWrite, segmentNo);
|
||||
pckWriteU32P(packWrite, segmentPageTotal);
|
||||
pckWriteBoolP(packWrite, headerCheck);
|
||||
pckWriteStrP(packWrite, fileName);
|
||||
pckWriteEndP(packWrite);
|
||||
|
||||
@ -276,9 +282,10 @@ pageChecksumNewPack(const Pack *const paramList)
|
||||
PackRead *const paramListPack = pckReadNew(paramList);
|
||||
const unsigned int segmentNo = pckReadU32P(paramListPack);
|
||||
const unsigned int segmentPageTotal = pckReadU32P(paramListPack);
|
||||
const bool headerCheck = pckReadBoolP(paramListPack);
|
||||
const String *const fileName = pckReadStrP(paramListPack);
|
||||
|
||||
result = ioFilterMove(pageChecksumNew(segmentNo, segmentPageTotal, fileName), memContextPrior());
|
||||
result = ioFilterMove(pageChecksumNew(segmentNo, segmentPageTotal, headerCheck, fileName), memContextPrior());
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
|
@ -16,7 +16,8 @@ Filter type constant
|
||||
/***********************************************************************************************************************************
|
||||
Constructors
|
||||
***********************************************************************************************************************************/
|
||||
FN_EXTERN IoFilter *pageChecksumNew(unsigned int segmentNo, unsigned int segmentPageTotal, const String *fileName);
|
||||
FN_EXTERN IoFilter *pageChecksumNew(
|
||||
unsigned int segmentNo, unsigned int segmentPageTotal, bool headerCheck, const String *fileName);
|
||||
FN_EXTERN IoFilter *pageChecksumNewPack(const Pack *paramList);
|
||||
|
||||
#endif
|
||||
|
@ -49,6 +49,7 @@ backupFileProtocol(PackRead *const param, ProtocolServer *const server)
|
||||
file.pgFileCopyExactSize = pckReadBoolP(param);
|
||||
file.pgFileChecksum = pckReadBinP(param);
|
||||
file.pgFileChecksumPage = pckReadBoolP(param);
|
||||
file.pgFilePageHeaderCheck = pckReadBoolP(param);
|
||||
file.blockIncrSize = (size_t)pckReadU64P(param);
|
||||
|
||||
if (file.blockIncrSize > 0)
|
||||
|
@ -96,6 +96,7 @@ Option constants
|
||||
#define CFGOPT_NEUTRAL_UMASK "neutral-umask"
|
||||
#define CFGOPT_ONLINE "online"
|
||||
#define CFGOPT_OUTPUT "output"
|
||||
#define CFGOPT_PAGE_HEADER_CHECK "page-header-check"
|
||||
#define CFGOPT_PG "pg"
|
||||
#define CFGOPT_PG_VERSION_FORCE "pg-version-force"
|
||||
#define CFGOPT_PROCESS "process"
|
||||
@ -134,7 +135,7 @@ Option constants
|
||||
#define CFGOPT_TYPE "type"
|
||||
#define CFGOPT_VERBOSE "verbose"
|
||||
|
||||
#define CFG_OPTION_TOTAL 166
|
||||
#define CFG_OPTION_TOTAL 167
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Option value constants
|
||||
@ -416,6 +417,7 @@ typedef enum
|
||||
cfgOptNeutralUmask,
|
||||
cfgOptOnline,
|
||||
cfgOptOutput,
|
||||
cfgOptPageHeaderCheck,
|
||||
cfgOptPg,
|
||||
cfgOptPgDatabase,
|
||||
cfgOptPgHost,
|
||||
|
@ -3225,6 +3225,32 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] =
|
||||
), // opt/output
|
||||
), // opt/output
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
PARSE_RULE_OPTION // opt/page-header-check
|
||||
( // opt/page-header-check
|
||||
PARSE_RULE_OPTION_NAME("page-header-check"), // opt/page-header-check
|
||||
PARSE_RULE_OPTION_TYPE(cfgOptTypeBoolean), // opt/page-header-check
|
||||
PARSE_RULE_OPTION_NEGATE(true), // opt/page-header-check
|
||||
PARSE_RULE_OPTION_RESET(true), // opt/page-header-check
|
||||
PARSE_RULE_OPTION_REQUIRED(true), // opt/page-header-check
|
||||
PARSE_RULE_OPTION_SECTION(cfgSectionGlobal), // opt/page-header-check
|
||||
// opt/page-header-check
|
||||
PARSE_RULE_OPTION_COMMAND_ROLE_MAIN_VALID_LIST // opt/page-header-check
|
||||
( // opt/page-header-check
|
||||
PARSE_RULE_OPTION_COMMAND(cfgCmdBackup) // opt/page-header-check
|
||||
), // opt/page-header-check
|
||||
// opt/page-header-check
|
||||
PARSE_RULE_OPTIONAL // opt/page-header-check
|
||||
( // opt/page-header-check
|
||||
PARSE_RULE_OPTIONAL_GROUP // opt/page-header-check
|
||||
( // opt/page-header-check
|
||||
PARSE_RULE_OPTIONAL_DEFAULT // opt/page-header-check
|
||||
( // opt/page-header-check
|
||||
PARSE_RULE_VAL_BOOL_TRUE, // opt/page-header-check
|
||||
), // opt/page-header-check
|
||||
), // opt/page-header-check
|
||||
), // opt/page-header-check
|
||||
), // opt/page-header-check
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
PARSE_RULE_OPTION // opt/pg
|
||||
( // opt/pg
|
||||
PARSE_RULE_OPTION_NAME("pg"), // opt/pg
|
||||
@ -9875,6 +9901,7 @@ static const uint8_t optionResolveOrder[] =
|
||||
cfgOptNeutralUmask, // opt-resolve-order
|
||||
cfgOptOnline, // opt-resolve-order
|
||||
cfgOptOutput, // opt-resolve-order
|
||||
cfgOptPageHeaderCheck, // opt-resolve-order
|
||||
cfgOptPg, // opt-resolve-order
|
||||
cfgOptPgLocal, // opt-resolve-order
|
||||
cfgOptPgPath, // opt-resolve-order
|
||||
|
@ -12,6 +12,7 @@ Modifications need to be made after copying:
|
||||
|
||||
1) Remove `#include "storage/bufpage.h"`.
|
||||
2) Make pg_checksum_page() static.
|
||||
3) Remove Assert(!PageIsNew(&cpage->phdr)).
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
@ -204,9 +205,6 @@ pg_checksum_page(char *page, BlockNumber blkno)
|
||||
uint16 save_checksum;
|
||||
uint32 checksum;
|
||||
|
||||
/* We only calculate the checksum for properly-initialized pages */
|
||||
Assert(!PageIsNew(&cpage->phdr));
|
||||
|
||||
/*
|
||||
* Save pd_checksum and temporarily set it to zero, so that the checksum
|
||||
* calculation isn't affected by the old checksum stored on the page.
|
||||
|
@ -205,14 +205,6 @@ typedef struct PageHeaderData
|
||||
// ---------------------------------------------------------------------------------------------------------------------------------
|
||||
typedef PageHeaderData *PageHeader;
|
||||
|
||||
// PageIsNew macro
|
||||
// ---------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* PageIsNew
|
||||
* returns true iff page has not been initialized (by PageInit)
|
||||
*/
|
||||
#define PageIsNew(page) (((PageHeader) (page))->pd_upper == 0)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Types from src/include/access/transam.h
|
||||
***********************************************************************************************************************************/
|
||||
|
@ -626,7 +626,7 @@ testRun(void)
|
||||
IoWrite *write = ioBufferWriteNew(bufferOut);
|
||||
ioFilterGroupAdd(
|
||||
ioWriteFilterGroup(write),
|
||||
pageChecksumNewPack(ioFilterParamList(pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, STRDEF(BOGUS_STR)))));
|
||||
pageChecksumNewPack(ioFilterParamList(pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, true, STRDEF(BOGUS_STR)))));
|
||||
ioWriteOpen(write);
|
||||
ioWrite(write, buffer);
|
||||
TEST_ERROR(ioWrite(write, buffer), AssertError, "should not be possible to see two misaligned pages in a row");
|
||||
@ -656,7 +656,8 @@ testRun(void)
|
||||
|
||||
write = ioBufferWriteNew(bufferOut);
|
||||
ioFilterGroupAdd(
|
||||
ioWriteFilterGroup(write), pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, storagePathP(storageTest, STRDEF("relation"))));
|
||||
ioWriteFilterGroup(write),
|
||||
pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, true, storagePathP(storageTest, STRDEF("relation"))));
|
||||
ioWriteOpen(write);
|
||||
ioWrite(write, buffer);
|
||||
ioWriteClose(write);
|
||||
@ -3294,9 +3295,27 @@ testRun(void)
|
||||
hrnCfgArgRawZ(argList, cfgOptRepoRetentionFull, "1");
|
||||
hrnCfgArgRawStrId(argList, cfgOptType, backupTypeIncr);
|
||||
hrnCfgArgRawBool(argList, cfgOptDelta, true);
|
||||
hrnCfgArgRawBool(argList, cfgOptPageHeaderCheck, false);
|
||||
hrnCfgArgRawBool(argList, cfgOptRepoHardlink, true);
|
||||
HRN_CFG_LOAD(cfgCmdBackup, argList);
|
||||
|
||||
// File with bad page checksum and header errors that will be ignored
|
||||
Buffer *relation = bufNew(PG_PAGE_SIZE_DEFAULT * 4);
|
||||
memset(bufPtr(relation), 0, bufSize(relation));
|
||||
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0xFF};
|
||||
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x01)) = (PageHeaderData){.pd_upper = 0x00};
|
||||
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x02)) = (PageHeaderData){.pd_upper = 0x00};
|
||||
(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x02))[PG_PAGE_SIZE_DEFAULT - 1] = 0xFF;
|
||||
((PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x02)))->pd_checksum = pgPageChecksum(
|
||||
bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x02), 2);
|
||||
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x03)) = (PageHeaderData){.pd_upper = 0x00};
|
||||
(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x03))[PG_PAGE_SIZE_DEFAULT - 1] = 0xEE;
|
||||
((PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x03)))->pd_checksum = 1;
|
||||
bufUsedSet(relation, bufSize(relation));
|
||||
|
||||
HRN_STORAGE_PUT(storagePgWrite(), PG_PATH_BASE "/1/3", relation, .timeModified = backupTimeStart);
|
||||
const char *rel1_3Sha1 = strZ(strNewEncode(encodingHex, cryptoHashOne(hashTypeSha1, relation)));
|
||||
|
||||
// Run backup. Make sure that the timeline selected converts to hexdecimal that can't be interpreted as decimal.
|
||||
hrnBackupPqScriptP(PG_VERSION_11, backupTimeStart, .timeline = 0x2C, .walTotal = 2);
|
||||
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
|
||||
@ -3308,6 +3327,8 @@ testRun(void)
|
||||
"P00 INFO: check archive for segment 0000002C05DB8EB000000000\n"
|
||||
"P00 WARN: a timeline switch has occurred since the 20191027-181320F backup, enabling delta checksum\n"
|
||||
" HINT: this is normal after restoring from backup or promoting a standby.\n"
|
||||
"P01 DETAIL: backup file " TEST_PATH "/pg1/base/1/3 (32KB, [PCT]) checksum [SHA1]\n"
|
||||
"P00 WARN: invalid page checksums found in file " TEST_PATH "/pg1/base/1/3 at pages 0, 3\n"
|
||||
"P01 DETAIL: backup file " TEST_PATH "/pg1/global/pg_control (8KB, [PCT]) checksum [SHA1]\n"
|
||||
"P01 DETAIL: match file from prior backup " TEST_PATH "/pg1/base/1/1 (8KB, [PCT]) checksum [SHA1]\n"
|
||||
"P01 DETAIL: match file from prior backup " TEST_PATH "/pg1/postgresql.conf (11B, [PCT]) checksum [SHA1]\n"
|
||||
@ -3322,65 +3343,73 @@ testRun(void)
|
||||
"P00 DETAIL: wrote 'tablespace_map' file returned from backup stop function\n"
|
||||
"P00 INFO: check archive for segment(s) 0000002C05DB8EB000000000:0000002C05DB8EB000000001\n"
|
||||
"P00 INFO: new backup label = 20191027-181320F_20191030-014640I\n"
|
||||
"P00 INFO: incr backup size = [SIZE], file total = 7");
|
||||
"P00 INFO: incr backup size = [SIZE], file total = 8");
|
||||
|
||||
TEST_RESULT_STR_Z(
|
||||
TEST_RESULT_STR(
|
||||
testBackupValidateP(storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest")),
|
||||
". {link, d=20191027-181320F_20191030-014640I}\n"
|
||||
"pg_data {path}\n"
|
||||
"pg_data/PG_VERSION.gz {file, s=2}\n"
|
||||
"pg_data/backup_label.gz {file, s=17}\n"
|
||||
"pg_data/base {path}\n"
|
||||
"pg_data/base/1 {path}\n"
|
||||
"pg_data/base/1/1.gz {file, s=8192}\n"
|
||||
"pg_data/global {path}\n"
|
||||
"pg_data/global/pg_control.gz {file, s=8192}\n"
|
||||
"pg_data/pg_tblspc {path}\n"
|
||||
"pg_data/pg_tblspc/32768 {link, d=../../pg_tblspc/32768}\n"
|
||||
"pg_data/pg_wal {path}\n"
|
||||
"pg_data/postgresql.conf.gz {file, s=11}\n"
|
||||
"pg_data/tablespace_map.gz {file, s=19}\n"
|
||||
"pg_tblspc {path}\n"
|
||||
"pg_tblspc/32768 {path}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051 {path}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051/1 {path}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051/1/5.gz {file, s=0}\n"
|
||||
"--------\n"
|
||||
"[backup:target]\n"
|
||||
"pg_data={\"path\":\"" TEST_PATH "/pg1\",\"type\":\"path\"}\n"
|
||||
"pg_tblspc/32768={\"path\":\"../../pg1-tblspc/32768\",\"tablespace-id\":\"32768\""
|
||||
",\"tablespace-name\":\"tblspc32768\",\"type\":\"link\"}\n"
|
||||
"\n"
|
||||
"[target:file]\n"
|
||||
"pg_data/PG_VERSION={\"checksum\":\"17ba0791499db908433b80f37c5fbc89b870084b\",\"reference\":\"20191027-181320F\""
|
||||
",\"size\":2,\"timestamp\":1572200000}\n"
|
||||
"pg_data/backup_label={\"checksum\":\"8e6f41ac87a7514be96260d65bacbffb11be77dc\",\"size\":17"
|
||||
",\"timestamp\":1572400002}\n"
|
||||
"pg_data/base/1/1={\"checksum\":\"0631457264ff7f8d5fb1edc2c0211992a67c73e6\",\"checksum-page\":true"
|
||||
",\"reference\":\"20191027-181320F\",\"size\":8192,\"timestamp\":1572200000}\n"
|
||||
"pg_data/global/pg_control={\"size\":8192,\"timestamp\":1572400000}\n"
|
||||
"pg_data/postgresql.conf={\"checksum\":\"e3db315c260e79211b7b52587123b7aa060f30ab\""
|
||||
",\"reference\":\"20191027-181320F\",\"size\":11,\"timestamp\":1570000000}\n"
|
||||
"pg_data/tablespace_map={\"checksum\":\"87fe624d7976c2144e10afcb7a9a49b071f35e9c\",\"size\":19"
|
||||
",\"timestamp\":1572400002}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051/1/5={\"checksum-page\":true,\"reference\":\"20191027-181320F\",\"size\":0"
|
||||
",\"timestamp\":1572200000}\n"
|
||||
"\n"
|
||||
"[target:link]\n"
|
||||
"pg_data/pg_tblspc/32768={\"destination\":\"../../pg1-tblspc/32768\"}\n"
|
||||
"\n"
|
||||
"[target:path]\n"
|
||||
"pg_data={}\n"
|
||||
"pg_data/base={}\n"
|
||||
"pg_data/base/1={}\n"
|
||||
"pg_data/global={}\n"
|
||||
"pg_data/pg_tblspc={}\n"
|
||||
"pg_data/pg_wal={}\n"
|
||||
"pg_tblspc={}\n"
|
||||
"pg_tblspc/32768={}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051={}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051/1={}\n",
|
||||
strNewFmt(
|
||||
". {link, d=20191027-181320F_20191030-014640I}\n"
|
||||
"pg_data {path}\n"
|
||||
"pg_data/PG_VERSION.gz {file, s=2}\n"
|
||||
"pg_data/backup_label.gz {file, s=17}\n"
|
||||
"pg_data/base {path}\n"
|
||||
"pg_data/base/1 {path}\n"
|
||||
"pg_data/base/1/1.gz {file, s=8192}\n"
|
||||
"pg_data/base/1/3.gz {file, s=32768}\n"
|
||||
"pg_data/global {path}\n"
|
||||
"pg_data/global/pg_control.gz {file, s=8192}\n"
|
||||
"pg_data/pg_tblspc {path}\n"
|
||||
"pg_data/pg_tblspc/32768 {link, d=../../pg_tblspc/32768}\n"
|
||||
"pg_data/pg_wal {path}\n"
|
||||
"pg_data/postgresql.conf.gz {file, s=11}\n"
|
||||
"pg_data/tablespace_map.gz {file, s=19}\n"
|
||||
"pg_tblspc {path}\n"
|
||||
"pg_tblspc/32768 {path}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051 {path}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051/1 {path}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051/1/5.gz {file, s=0}\n"
|
||||
"--------\n"
|
||||
"[backup:target]\n"
|
||||
"pg_data={\"path\":\"" TEST_PATH "/pg1\",\"type\":\"path\"}\n"
|
||||
"pg_tblspc/32768={\"path\":\"../../pg1-tblspc/32768\",\"tablespace-id\":\"32768\""
|
||||
",\"tablespace-name\":\"tblspc32768\",\"type\":\"link\"}\n"
|
||||
"\n"
|
||||
"[target:file]\n"
|
||||
"pg_data/PG_VERSION={\"checksum\":\"17ba0791499db908433b80f37c5fbc89b870084b\""
|
||||
",\"reference\":\"20191027-181320F\",\"size\":2,\"timestamp\":1572200000}\n"
|
||||
"pg_data/backup_label={\"checksum\":\"8e6f41ac87a7514be96260d65bacbffb11be77dc\",\"size\":17"
|
||||
",\"timestamp\":1572400002}\n"
|
||||
"pg_data/base/1/1={\"checksum\":\"0631457264ff7f8d5fb1edc2c0211992a67c73e6\",\"checksum-page\":true"
|
||||
",\"reference\":\"20191027-181320F\",\"size\":8192,\"timestamp\":1572200000}\n"
|
||||
"pg_data/base/1/3={\"checksum\":\"%s\",\"checksum-page\":false,\"checksum-page-error\":[0,3],\"size\":32768"
|
||||
",\"timestamp\":1572400000}\n"
|
||||
"pg_data/global/pg_control={\"size\":8192,\"timestamp\":1572400000}\n"
|
||||
"pg_data/postgresql.conf={\"checksum\":\"e3db315c260e79211b7b52587123b7aa060f30ab\""
|
||||
",\"reference\":\"20191027-181320F\",\"size\":11,\"timestamp\":1570000000}\n"
|
||||
"pg_data/tablespace_map={\"checksum\":\"87fe624d7976c2144e10afcb7a9a49b071f35e9c\",\"size\":19"
|
||||
",\"timestamp\":1572400002}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051/1/5={\"checksum-page\":true,\"reference\":\"20191027-181320F\",\"size\":0"
|
||||
",\"timestamp\":1572200000}\n"
|
||||
"\n"
|
||||
"[target:link]\n"
|
||||
"pg_data/pg_tblspc/32768={\"destination\":\"../../pg1-tblspc/32768\"}\n"
|
||||
"\n"
|
||||
"[target:path]\n"
|
||||
"pg_data={}\n"
|
||||
"pg_data/base={}\n"
|
||||
"pg_data/base/1={}\n"
|
||||
"pg_data/global={}\n"
|
||||
"pg_data/pg_tblspc={}\n"
|
||||
"pg_data/pg_wal={}\n"
|
||||
"pg_tblspc={}\n"
|
||||
"pg_tblspc/32768={}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051={}\n"
|
||||
"pg_tblspc/32768/PG_11_201809051/1={}\n",
|
||||
rel1_3Sha1),
|
||||
"compare file list");
|
||||
|
||||
// Remove test files
|
||||
HRN_STORAGE_REMOVE(storagePgWrite(), "base/1/3", .errorOnMissing = true);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user