1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-18 04:58:51 +02:00

Add checksum delta for incremental backups.

Use checksums rather than timestamps to determine if files have changed.  This is useful in cases where the timestamps may not be trustworthy, e.g. when performing an incremental after failing over to a standby.

If checksum delta is enabled then checksums will be used for verification of resumed backups, even if they are full.  Resumes have always used checksums to verify the files in the repository, enabling delta performs checksums on the database files as well.

Note that the user must manually enable this feature in cases were it would be useful or just keep in enabled all the time.  A future commit will address automatically enabling the feature in cases where it seems likely to be useful.

Contributed by Cynthia Shang.
This commit is contained in:
Cynthia Shang 2018-09-19 11:12:45 -04:00 committed by David Steele
parent bf0691576a
commit 880fbb5e57
25 changed files with 2356 additions and 913 deletions

View File

@ -1108,13 +1108,12 @@ my %hConfigDefine =
{
&CFGDEF_SECTION => CFGDEF_SECTION_GLOBAL,
&CFGDEF_TYPE => CFGDEF_TYPE_BOOLEAN,
&CFGDEF_DEFAULT => false,
&CFGDEF_COMMAND =>
{
&CFGCMD_RESTORE =>
{
&CFGDEF_DEFAULT => false,
}
}
&CFGCMD_BACKUP => {},
&CFGCMD_RESTORE => {},
},
},
&CFGOPT_COMPRESS =>

View File

@ -164,6 +164,17 @@
<example>600</example>
</config-key>
<!-- CONFIG - GENERAL SECTION - DELTA OPTION -->
<config-key id="delta" name="Delta">
<summary>Restore or backup using checksums.</summary>
<text>During a restore, by default the <postgres/> data and tablespace directories are expected to be present but empty. This option performs a delta restore using checksums.
During a backup, this option will use checksums instead of the timestamps to determine if files will be copied.</text>
<example>y</example>
</config-key>
<!-- CONFIG - GENERAL SECTION - LOCK-PATH KEY -->
<config-key id="lock-path" name="Lock Path">
<summary>Path where lock files are stored.</summary>
@ -677,15 +688,6 @@
<example>db_main</example>
</config-key>
<!-- CONFIG - RESTORE SECTION - DELTA OPTION -->
<config-key id="delta" name="Delta">
<summary>Restore using delta.</summary>
<text>By default the <postgres/> data and tablespace directories are expected to be present but empty. This option performs a delta restore using checksums.</text>
<example>y</example>
</config-key>
<!-- CONFIG - RESTORE SECTION - LINK-ALL KEY -->
<config-key id="link-all" name="Link All">
<summary>Restore all symlinks.</summary>

View File

@ -28,6 +28,16 @@
</release-item>
</release-bug-list>
<release-feature-list>
<release-item>
<release-item-contributor-list>
<release-item-contributor id="cynthia.shang"/>
</release-item-contributor-list>
<p>Add checksum delta for incremental backups which uses checksums rather than timestamps to determine if files have changed.</p>
</release-item>
</release-feature-list>
<release-improvement-list>
<release-item>
<p>Ignore all files in a linked tablespace directory except the subdirectory for the current version of <postgres/>. Previously an error would be generated if other files were present and not owned by the <postgres/> user.</p>

View File

@ -117,7 +117,7 @@ sub resumeClean
# Else if a file
elsif ($cType eq 'f')
{
# If the original backup was compressed the remove the extension before checking the manifest
# If the original backup was compressed then remove the extension before checking the manifest
my $strFile = $strName;
if ($bCompressed)
@ -132,11 +132,16 @@ sub resumeClean
# To be preserved the checksum must be defined
my $strChecksum = $oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_CHECKSUM, false);
# If the size and timestamp match OR if the size matches and the delta option is set, then keep the file.
# In the latter case, if the timestamp had changed then rather than removing and recopying the file, the file
# will be tested in backupFile to see if the db/repo checksum still matches: if so, it is not necessary to recopy,
# else it will need to be copied to the new backup.
if (defined($strChecksum) &&
$oManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP) ==
$oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP) &&
$oManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE) ==
$oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE))
$oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE) &&
(cfgOption(CFGOPT_DELTA) ||
$oManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP) ==
$oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP)))
{
$oManifest->set(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksum);
@ -285,30 +290,20 @@ sub processManifest
sprintf("%016d-%s", $oBackupManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $a, MANIFEST_SUBKEY_SIZE), $a)}
($oBackupManifest->keys(MANIFEST_SECTION_TARGET_FILE, INI_SORT_NONE)))
{
# If the file has a reference it does not need to be copied since it can be retrieved from the referenced backup.
# However, if hard-linking is turned on the link will need to be created
# If the file has a reference it does not need to be copied since it can be retrieved from the referenced backup - unless
# the option to checksum all files is set. However, if hardlinking is enabled the link will need to be created
my $strReference = $oBackupManifest->get(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_REFERENCE, false);
if (defined($strReference))
{
# If hardlinking is turned on then create a hardlink for files that have not changed since the last backup
if ($bHardLink)
# If the delta option to checksum all files is not set or it is set and the file size of the referenced file is zero
# then skip checking/copying this file
if (!cfgOption(CFGOPT_DELTA) ||
$oBackupManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_SIZE) == 0)
{
&log(DETAIL, "hardlink ${strRepoFile} to ${strReference}");
storageRepo()->linkCreate(
STORAGE_REPO_BACKUP . "/${strReference}/${strRepoFile}" . ($bCompress ? qw{.} . COMPRESS_EXT : ''),
STORAGE_REPO_BACKUP . "/${strBackupLabel}/${strRepoFile}" . ($bCompress ? qw{.} . COMPRESS_EXT : ''),
{bHard => true});
# This file will not need to be copied
next;
}
# Else log the reference
else
{
logDebugMisc($strOperation, "reference ${strRepoFile} to ${strReference}");
}
# This file will not need to be copied
next;
}
# By default put everything into a single queue
@ -352,7 +347,8 @@ sub processManifest
cfgOption(CFGOPT_CHECKSUM_PAGE) ? isChecksumPage($strRepoFile) : false, $strBackupLabel, $bCompress,
cfgOption(CFGOPT_COMPRESS_LEVEL), $oBackupManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile,
MANIFEST_SUBKEY_TIMESTAMP, false), $bIgnoreMissing,
cfgOption(CFGOPT_CHECKSUM_PAGE) && isChecksumPage($strRepoFile) ? $hStartLsnParam : undef],
cfgOption(CFGOPT_CHECKSUM_PAGE) && isChecksumPage($strRepoFile) ? $hStartLsnParam : undef,
cfgOption(CFGOPT_DELTA), defined($strReference) ? true : false],
{rParamSecure => $oBackupManifest->cipherPassSub() ? [$oBackupManifest->cipherPassSub()] : undef});
# Size and checksum will be removed and then verified later as a sanity check
@ -403,6 +399,33 @@ sub processManifest
protocolKeepAlive();
}
foreach my $strFile ($oBackupManifest->keys(MANIFEST_SECTION_TARGET_FILE))
{
# If the file has a reference, then it was not copied since it can be retrieved from the referenced backup. However, if
# hardlinking is enabled the link will need to be created.
my $strReference = $oBackupManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_REFERENCE, false);
if ($strReference)
{
# If hardlinking is enabled then create a hardlink for files that have not changed since the last backup
if ($bHardLink)
{
&log(DETAIL, "hardlink ${strFile} to ${strReference}");
storageRepo()->linkCreate(
STORAGE_REPO_BACKUP . "/${strReference}/${strFile}" . ($bCompress ? qw{.} . COMPRESS_EXT : ''),
STORAGE_REPO_BACKUP . "/${strBackupLabel}/${strFile}" . ($bCompress ? qw{.} . COMPRESS_EXT : ''),
{bHard => true});
}
# Else log the reference. With delta, it is possible that references may have been removed if a file needed to be
# recopied.
else
{
logDebugMisc($strOperation, "reference ${strFile} to ${strReference}");
}
}
}
# Validate the manifest
$oBackupManifest->validate();
@ -803,7 +826,11 @@ sub process
# Build the manifest
$oBackupManifest->build($oStorageDbMaster, $strDbMasterPath, $oLastManifest, cfgOption(CFGOPT_ONLINE),
$hTablespaceMap, $hDatabaseMap, cfgOption(CFGOPT_EXCLUDE, false));
cfgOption(CFGOPT_DELTA), $hTablespaceMap, $hDatabaseMap, cfgOption(CFGOPT_EXCLUDE, false));
# Set the delta option.
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_DELTA, undef, cfgOption(CFGOPT_DELTA));
&log(TEST, TEST_MANIFEST_BUILD);
# If resuming from an aborted backup

View File

@ -36,6 +36,8 @@ use constant BACKUP_FILE_RECOPY => 2;
push @EXPORT, qw(BACKUP_FILE_RECOPY);
use constant BACKUP_FILE_SKIP => 3;
push @EXPORT, qw(BACKUP_FILE_SKIP);
use constant BACKUP_FILE_NOOP => 4;
push @EXPORT, qw(BACKUP_FILE_NOOP);
####################################################################################################################################
# backupFile
@ -57,7 +59,10 @@ sub backupFile
$lModificationTime, # File modification time
$bIgnoreMissing, # Is it OK if the file is missing?
$hExtraParam, # Parameter to pass to the extra function
$strCipherPass, # Passphrase to access the repo file (undefined if repo not encrypted)
$bDelta, # Is the delta option on?
$bHasReference, # Does the file exist in the repo in a prior backup in the set?
$strCipherPass, # Passphrase to access the repo file (undefined if repo not encrypted). This
# parameter must always be last in the parameter list to this function.
) =
logDebugParam
(
@ -73,6 +78,8 @@ sub backupFile
{name => 'lModificationTime', trace => true},
{name => 'bIgnoreMissing', default => true, trace => true},
{name => 'hExtraParam', required => false, trace => true},
{name => 'bDelta', trace => true},
{name => 'bHasReference', trace => true},
{name => 'strCipherPass', required => false, trace => true},
);
@ -86,29 +93,71 @@ sub backupFile
# Add compression suffix if needed
my $strFileOp = $strRepoFile . ($bCompress ? '.' . COMPRESS_EXT : '');
# If checksum is defined then the file already exists but needs to be checked
my $bCopy = true;
# If checksum is defined then the file needs to be checked. If delta option then check the DB and possibly the repo, else just
# check the repo.
if (defined($strChecksum))
{
# Add decompression
my $rhyFilter;
if ($bCompress)
# If delta, then check the DB checksum and possibly the repo. If the checksum does not match in either case then recopy.
if ($bDelta)
{
push(@{$rhyFilter}, {strClass => STORAGE_FILTER_GZIP, rxyParam => [{strCompressType => STORAGE_DECOMPRESS}]});
($strCopyChecksum, $lCopySize) = storageDb()->hashSize($strDbFile, {bIgnoreMissing => $bIgnoreMissing});
# If the DB file exists, then check the checksum
if (defined($strCopyChecksum))
{
$bCopy = !($strCopyChecksum eq $strChecksum && $lCopySize == $lSizeFile);
# If the database file checksum and size are same and the file is in a prior backup, then no need to copy. If the
# checksum/size do not match, that is OK, just leave the copy result as COPY so the file will be copied to this
# backup.
if (!$bCopy && $bHasReference)
{
$iCopyResult = BACKUP_FILE_NOOP;
}
}
# Else the source file is missing from the database so skip this file
else
{
$iCopyResult = BACKUP_FILE_SKIP;
$bCopy = false;
}
}
# Get the checksum
($strCopyChecksum, $lCopySize) = $oStorageRepo->hashSize(
$oStorageRepo->openRead(STORAGE_REPO_BACKUP . "/${strBackupLabel}/${strFileOp}",
{rhyFilter => $rhyFilter, strCipherPass => $strCipherPass}));
# If this is not a delta backup or it is and the file exists and the checksum from the DB matches, then also test the
# checksum of the file in the repo (unless it is in a prior backup) and if the checksum doesn't match, then there may be
# corruption in the repo, so recopy
if (!$bDelta || !$bHasReference)
{
# If this is a delta backup and the file is missing from the DB, then remove it from the repo (backupManifestUpdate will
# remove it from the manifest)
if ($iCopyResult == BACKUP_FILE_SKIP)
{
$oStorageRepo->remove(STORAGE_REPO_BACKUP . "/${strBackupLabel}/${strFileOp}");
}
elsif (!$bDelta || !$bCopy)
{
# Add decompression
my $rhyFilter;
# Determine if the file needs to be recopied
$bCopy = !($strCopyChecksum eq $strChecksum && $lCopySize == $lSizeFile);
if ($bCompress)
{
push(@{$rhyFilter}, {strClass => STORAGE_FILTER_GZIP, rxyParam => [{strCompressType => STORAGE_DECOMPRESS}]});
}
# Set copy result
$iCopyResult = $bCopy ? BACKUP_FILE_RECOPY : BACKUP_FILE_CHECKSUM;
# Get the checksum
($strCopyChecksum, $lCopySize) = $oStorageRepo->hashSize(
$oStorageRepo->openRead(STORAGE_REPO_BACKUP . "/${strBackupLabel}/${strFileOp}",
{rhyFilter => $rhyFilter, strCipherPass => $strCipherPass}));
# Determine if the file needs to be recopied
$bCopy = !($strCopyChecksum eq $strChecksum && $lCopySize == $lSizeFile);
# Set copy result
$iCopyResult = $bCopy ? BACKUP_FILE_RECOPY : BACKUP_FILE_CHECKSUM;
}
}
}
# Copy the file
@ -241,121 +290,144 @@ sub backupManifestUpdate
# Increment current backup progress
$lSizeCurrent += $lSize;
# Log invalid checksum
if ($iCopyResult == BACKUP_FILE_RECOPY)
# If the file is in a prior backup and nothing changed, then nothing needs to be done
if ($iCopyResult == BACKUP_FILE_NOOP)
{
&log(
WARN,
"resumed backup file ${strRepoFile} does not have expected checksum ${strChecksum}. The file will be recopied and" .
" backup will continue but this may be an issue unless the resumed backup path in the repository is known to be" .
" corrupted.\n" .
"NOTE: this does not indicate a problem with the PostgreSQL page checksums.");
}
# If copy was successful store the checksum and size
if ($iCopyResult == BACKUP_FILE_COPY || $iCopyResult == BACKUP_FILE_RECOPY || $iCopyResult == BACKUP_FILE_CHECKSUM)
{
# Log copy or checksum
&log($iCopyResult == BACKUP_FILE_CHECKSUM ? DETAIL : INFO,
($iCopyResult == BACKUP_FILE_CHECKSUM ?
'checksum resumed file ' : 'backup file ' . (defined($strHost) ? "${strHost}:" : '')) .
"${strDbFile} (" . fileSizeFormat($lSizeCopy) .
', ' . int($lSizeCurrent * 100 / $lSizeTotal) . '%)' .
($lSizeCopy != 0 ? " checksum ${strChecksumCopy}" : ''), undef, undef, undef, $iLocalId);
# File copy was not needed so just restore the size and checksum to the manifest
$oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_SIZE, $lSizeCopy);
$oManifest->set(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksumCopy);
if ($lSizeRepo != $lSizeCopy)
&log(DETAIL,
'match file from prior backup ' . (defined($strHost) ? "${strHost}:" : '') . "${strDbFile} (" .
fileSizeFormat($lSizeCopy) . ', ' . int($lSizeCurrent * 100 / $lSizeTotal) . '%)' .
($lSizeCopy != 0 ? " checksum ${strChecksumCopy}" : ''),
undef, undef, undef, $iLocalId);
}
# Else process the results
else
{
# Log invalid checksum
if ($iCopyResult == BACKUP_FILE_RECOPY)
{
$oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_REPO_SIZE, $lSizeRepo);
&log(
WARN,
"resumed backup file ${strRepoFile} does not have expected checksum ${strChecksum}. The file will be recopied and" .
" backup will continue but this may be an issue unless the resumed backup path in the repository is known to be" .
" corrupted.\n" .
"NOTE: this does not indicate a problem with the PostgreSQL page checksums.");
}
if ($lSizeCopy > 0)
# If copy was successful store the checksum and size
if ($iCopyResult == BACKUP_FILE_COPY || $iCopyResult == BACKUP_FILE_RECOPY || $iCopyResult == BACKUP_FILE_CHECKSUM)
{
$oManifest->set(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksumCopy);
}
# Log copy or checksum
&log($iCopyResult == BACKUP_FILE_CHECKSUM ? DETAIL : INFO,
($iCopyResult == BACKUP_FILE_CHECKSUM ?
'checksum resumed file ' : 'backup file ' . (defined($strHost) ? "${strHost}:" : '')) .
"${strDbFile} (" . fileSizeFormat($lSizeCopy) .
', ' . int($lSizeCurrent * 100 / $lSizeTotal) . '%)' .
($lSizeCopy != 0 ? " checksum ${strChecksumCopy}" : ''), undef, undef, undef, $iLocalId);
# If the file had page checksums calculated during the copy
if ($bChecksumPage)
{
# The valid flag should be set
if (defined($rExtra->{bValid}))
$oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_SIZE, $lSizeCopy);
if ($lSizeRepo != $lSizeCopy)
{
# Store the valid flag
$oManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM_PAGE, $rExtra->{bValid});
$oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_REPO_SIZE, $lSizeRepo);
}
# If the page was not valid
if (!$rExtra->{bValid})
if ($lSizeCopy > 0)
{
$oManifest->set(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksumCopy);
}
# If the file was copied, then remove any reference to the file's existence in a prior backup.
if ($iCopyResult == BACKUP_FILE_COPY || $iCopyResult == BACKUP_FILE_RECOPY)
{
$oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_REFERENCE);
}
# If the file had page checksums calculated during the copy
if ($bChecksumPage)
{
# The valid flag should be set
if (defined($rExtra->{bValid}))
{
# Check for a page misalignment
if ($lSizeCopy % PG_PAGE_SIZE != 0)
# Store the valid flag
$oManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM_PAGE, $rExtra->{bValid});
# If the page was not valid
if (!$rExtra->{bValid})
{
# Make sure the align flag was set, otherwise there is a bug
if (!defined($rExtra->{bAlign}) || $rExtra->{bAlign})
# Check for a page misalignment
if ($lSizeCopy % PG_PAGE_SIZE != 0)
{
confess &log(ASSERT, 'bAlign flag should have been set for misaligned page');
}
# Emit a warning so the user knows something is amiss
&log(WARN,
'page misalignment in file ' . (defined($strHost) ? "${strHost}:" : '') .
"${strDbFile}: file size ${lSizeCopy} is not divisible by page size " . PG_PAGE_SIZE);
}
# Else process the page check errors
else
{
$oManifest->set(
MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR,
dclone($rExtra->{iyPageError}));
# Build a pretty list of the page errors
my $strPageError;
my $iPageErrorTotal = 0;
foreach my $iyPage (@{$rExtra->{iyPageError}})
{
$strPageError .= (defined($strPageError) ? ', ' : '');
# If a range of pages
if (ref($iyPage))
# Make sure the align flag was set, otherwise there is a bug
if (!defined($rExtra->{bAlign}) || $rExtra->{bAlign})
{
$strPageError .= $$iyPage[0] . '-' . $$iyPage[1];
$iPageErrorTotal += ($$iyPage[1] - $$iyPage[0]) + 1;
confess &log(ASSERT, 'bAlign flag should have been set for misaligned page');
}
# Else a single page
else
{
$strPageError .= $iyPage;
$iPageErrorTotal += 1;
}
}
# There should be at least one page in the error list
if ($iPageErrorTotal == 0)
# Emit a warning so the user knows something is amiss
&log(WARN,
'page misalignment in file ' . (defined($strHost) ? "${strHost}:" : '') .
"${strDbFile}: file size ${lSizeCopy} is not divisible by page size " . PG_PAGE_SIZE);
}
# Else process the page check errors
else
{
confess &log(ASSERT, 'page checksum error list should have at least one entry');
}
$oManifest->set(
MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR,
dclone($rExtra->{iyPageError}));
# Emit a warning so the user knows something is amiss
&log(WARN,
'invalid page checksum' . ($iPageErrorTotal > 1 ? 's' : '') .
' found in file ' . (defined($strHost) ? "${strHost}:" : '') . "${strDbFile} at page" .
($iPageErrorTotal > 1 ? 's' : '') . " ${strPageError}");
# Build a pretty list of the page errors
my $strPageError;
my $iPageErrorTotal = 0;
foreach my $iyPage (@{$rExtra->{iyPageError}})
{
$strPageError .= (defined($strPageError) ? ', ' : '');
# If a range of pages
if (ref($iyPage))
{
$strPageError .= $$iyPage[0] . '-' . $$iyPage[1];
$iPageErrorTotal += ($$iyPage[1] - $$iyPage[0]) + 1;
}
# Else a single page
else
{
$strPageError .= $iyPage;
$iPageErrorTotal += 1;
}
}
# There should be at least one page in the error list
if ($iPageErrorTotal == 0)
{
confess &log(ASSERT, 'page checksum error list should have at least one entry');
}
# Emit a warning so the user knows something is amiss
&log(WARN,
'invalid page checksum' . ($iPageErrorTotal > 1 ? 's' : '') .
' found in file ' . (defined($strHost) ? "${strHost}:" : '') . "${strDbFile} at page" .
($iPageErrorTotal > 1 ? 's' : '') . " ${strPageError}");
}
}
}
}
# If it's not set that's a bug in the code
elsif (!$oManifest->test(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM_PAGE))
{
confess &log(ASSERT, "${strDbFile} should have calculated page checksums");
# If it's not set that's a bug in the code
elsif (!$oManifest->test(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM_PAGE))
{
confess &log(ASSERT, "${strDbFile} should have calculated page checksums");
}
}
}
}
# Else the file was removed during backup so remove from manifest
elsif ($iCopyResult == BACKUP_FILE_SKIP)
{
&log(DETAIL, 'skip file removed by database ' . (defined($strHost) ? "${strHost}:" : '') . $strDbFile);
$oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strRepoFile);
# Else the file was removed during backup so remove from manifest
elsif ($iCopyResult == BACKUP_FILE_SKIP)
{
&log(DETAIL, 'skip file removed by database ' . (defined($strHost) ? "${strHost}:" : '') . $strDbFile);
$oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strRepoFile);
}
}
# Determine whether to save the manifest

View File

@ -97,7 +97,7 @@ sub process
$oBackupManifest->build(
storageDb({iRemoteIdx => $iRemoteIdx}), cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)), undef,
cfgOptionValid(CFGOPT_ONLINE) && cfgOption(CFGOPT_ONLINE), $oDb->tablespaceMapGet());
cfgOptionValid(CFGOPT_ONLINE) && cfgOption(CFGOPT_ONLINE), false, $oDb->tablespaceMapGet());
return true;
}

View File

@ -109,6 +109,8 @@ use constant MANIFEST_KEY_COMPRESS => 'option-'
push @EXPORT, qw(MANIFEST_KEY_COMPRESS);
use constant MANIFEST_KEY_ONLINE => 'option-' . cfgOptionName(CFGOPT_ONLINE);
push @EXPORT, qw(MANIFEST_KEY_ONLINE);
use constant MANIFEST_KEY_DELTA => 'option-' . cfgOptionName(CFGOPT_DELTA);
push @EXPORT, qw(MANIFEST_KEY_DELTA);
# Information about the database that was backed up
use constant MANIFEST_KEY_DB_ID => 'db-id';
@ -571,6 +573,7 @@ sub build
$strPath,
$oLastManifest,
$bOnline,
$bDelta,
$hTablespaceMap,
$hDatabaseMap,
$rhExclude,
@ -587,6 +590,7 @@ sub build
{name => 'strPath'},
{name => 'oLastManifest', required => false},
{name => 'bOnline'},
{name => 'bDelta'},
{name => 'hTablespaceMap', required => false},
{name => 'hDatabaseMap', required => false},
{name => 'rhExclude', required => false},
@ -930,7 +934,7 @@ sub build
}
$self->build(
$oStorageDbMaster, $strLinkDestination, undef, $bOnline, $hTablespaceMap, $hDatabaseMap, $rhExclude, $strFile,
$oStorageDbMaster, $strLinkDestination, undef, $bOnline, $bDelta, $hTablespaceMap, $hDatabaseMap, $rhExclude, $strFile,
$bTablespace, dirname("${strPath}/${strName}"), $strFilter, $iLevel + 1);
}
}
@ -984,13 +988,17 @@ sub build
$self->set(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_FUTURE, 'y');
}
}
# Else check if modification time and size are unchanged since last backup
# Else check if the size and timestamp match OR if the size matches and the delta option is set, then keep the file.
# In the latter case, if there had been a timestamp change then rather than removing and recopying the file, the file
# will be tested in backupFile to see if the db/repo checksum still matches: if so, it is not necessary to recopy,
# else it will need to be copied to the new backup. For zero sized files, the reference will be set and copying
# will be skipped later.
elsif (defined($oLastManifest) && $oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName) &&
$self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) ==
$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) &&
($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) == 0 ||
$oLastManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) &&
($bDelta || ($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) == 0 ||
$self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP) ==
$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP)))
$oLastManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP))))
{
# Copy reference from previous backup if possible
if ($oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REFERENCE))
@ -1005,14 +1013,14 @@ sub build
$oLastManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL));
}
# Copy the checksum from previous manifest
# Copy the checksum from previous manifest (if it exists - zero sized files don't have checksums)
if ($oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM))
{
$self->set(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM,
$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM));
}
# Copy repo size from the previous manifest
# Copy repo size from the previous manifest (if it exists)
if ($oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REPO_SIZE))
{
$self->set(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REPO_SIZE,

View File

@ -981,27 +981,25 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
CFGDEFDATA_OPTION_SECURE(false)
CFGDEFDATA_OPTION_HELP_SECTION("restore")
CFGDEFDATA_OPTION_HELP_SUMMARY("Restore using delta.")
CFGDEFDATA_OPTION_HELP_SECTION("general")
CFGDEFDATA_OPTION_HELP_SUMMARY("Restore or backup using checksums.")
CFGDEFDATA_OPTION_HELP_DESCRIPTION
(
"By default the PostgreSQL data and tablespace directories are expected to be present but empty. This option performs "
"a delta restore using checksums."
"During a restore, by default the PostgreSQL data and tablespace directories are expected to be present but empty. "
"This option performs a delta restore using checksums.\n"
"\n"
"During a backup, this option will use checksums instead of the timestamps to determine if files will be copied."
)
CFGDEFDATA_OPTION_COMMAND_LIST
(
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdBackup)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRestore)
)
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_COMMAND_OVERRRIDE
(
CFGDEFDATA_OPTION_OPTIONAL_COMMAND(cfgDefCmdRestore)
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("0")
)
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("0")
)
)

View File

@ -2098,12 +2098,13 @@ static const EmbeddedModule embeddedModule[] =
"{\n"
"\n"
"my $strChecksum = $oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_CHECKSUM, false);\n"
"\n"
"\n\n\n\n\n"
"if (defined($strChecksum) &&\n"
"$oManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP) ==\n"
"$oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP) &&\n"
"$oManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE) ==\n"
"$oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE))\n"
"$oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE) &&\n"
"(cfgOption(CFGOPT_DELTA) ||\n"
"$oManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP) ==\n"
"$oAbortedManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP)))\n"
"{\n"
"$oManifest->set(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksum);\n"
"\n\n"
@ -2239,24 +2240,14 @@ static const EmbeddedModule embeddedModule[] =
"\n"
"if (defined($strReference))\n"
"{\n"
"\n"
"if ($bHardLink)\n"
"{\n"
"&log(DETAIL, \"hardlink ${strRepoFile} to ${strReference}\");\n"
"\n"
"storageRepo()->linkCreate(\n"
"STORAGE_REPO_BACKUP . \"/${strReference}/${strRepoFile}\" . ($bCompress ? qw{.} . COMPRESS_EXT : ''),\n"
"STORAGE_REPO_BACKUP . \"/${strBackupLabel}/${strRepoFile}\" . ($bCompress ? qw{.} . COMPRESS_EXT : ''),\n"
"{bHard => true});\n"
"}\n"
"\n"
"else\n"
"{\n"
"logDebugMisc($strOperation, \"reference ${strRepoFile} to ${strReference}\");\n"
"}\n"
"\n\n"
"if (!cfgOption(CFGOPT_DELTA) ||\n"
"$oBackupManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_SIZE) == 0)\n"
"{\n"
"\n"
"next;\n"
"}\n"
"}\n"
"\n\n"
"my $strQueueKey = MANIFEST_TARGET_PGDATA;\n"
"\n\n"
@ -2292,7 +2283,8 @@ static const EmbeddedModule embeddedModule[] =
"cfgOption(CFGOPT_CHECKSUM_PAGE) ? isChecksumPage($strRepoFile) : false, $strBackupLabel, $bCompress,\n"
"cfgOption(CFGOPT_COMPRESS_LEVEL), $oBackupManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile,\n"
"MANIFEST_SUBKEY_TIMESTAMP, false), $bIgnoreMissing,\n"
"cfgOption(CFGOPT_CHECKSUM_PAGE) && isChecksumPage($strRepoFile) ? $hStartLsnParam : undef],\n"
"cfgOption(CFGOPT_CHECKSUM_PAGE) && isChecksumPage($strRepoFile) ? $hStartLsnParam : undef,\n"
"cfgOption(CFGOPT_DELTA), defined($strReference) ? true : false],\n"
"{rParamSecure => $oBackupManifest->cipherPassSub() ? [$oBackupManifest->cipherPassSub()] : undef});\n"
"\n\n"
"$oBackupManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_SIZE);\n"
@ -2333,6 +2325,31 @@ static const EmbeddedModule embeddedModule[] =
"\n\n\n"
"protocolKeepAlive();\n"
"}\n"
"\n"
"foreach my $strFile ($oBackupManifest->keys(MANIFEST_SECTION_TARGET_FILE))\n"
"{\n"
"\n\n"
"my $strReference = $oBackupManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_REFERENCE, false);\n"
"\n"
"if ($strReference)\n"
"{\n"
"\n"
"if ($bHardLink)\n"
"{\n"
"&log(DETAIL, \"hardlink ${strFile} to ${strReference}\");\n"
"\n"
"storageRepo()->linkCreate(\n"
"STORAGE_REPO_BACKUP . \"/${strReference}/${strFile}\" . ($bCompress ? qw{.} . COMPRESS_EXT : ''),\n"
"STORAGE_REPO_BACKUP . \"/${strBackupLabel}/${strFile}\" . ($bCompress ? qw{.} . COMPRESS_EXT : ''),\n"
"{bHard => true});\n"
"}\n"
"\n\n"
"else\n"
"{\n"
"logDebugMisc($strOperation, \"reference ${strFile} to ${strReference}\");\n"
"}\n"
"}\n"
"}\n"
"\n\n"
"$oBackupManifest->validate();\n"
"\n\n"
@ -2676,7 +2693,10 @@ static const EmbeddedModule embeddedModule[] =
"$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_CHECKSUM_PAGE, undef, cfgOption(CFGOPT_CHECKSUM_PAGE));\n"
"\n\n"
"$oBackupManifest->build($oStorageDbMaster, $strDbMasterPath, $oLastManifest, cfgOption(CFGOPT_ONLINE),\n"
"$hTablespaceMap, $hDatabaseMap, cfgOption(CFGOPT_EXCLUDE, false));\n"
"cfgOption(CFGOPT_DELTA), $hTablespaceMap, $hDatabaseMap, cfgOption(CFGOPT_EXCLUDE, false));\n"
"\n\n"
"$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_DELTA, undef, cfgOption(CFGOPT_DELTA));\n"
"\n"
"&log(TEST, TEST_MANIFEST_BUILD);\n"
"\n\n"
"if (defined($oAbortedManifest))\n"
@ -3100,6 +3120,8 @@ static const EmbeddedModule embeddedModule[] =
"push @EXPORT, qw(BACKUP_FILE_RECOPY);\n"
"use constant BACKUP_FILE_SKIP => 3;\n"
"push @EXPORT, qw(BACKUP_FILE_SKIP);\n"
"use constant BACKUP_FILE_NOOP => 4;\n"
"push @EXPORT, qw(BACKUP_FILE_NOOP);\n"
"\n\n\n\n"
"sub backupFile\n"
"{\n"
@ -3118,7 +3140,10 @@ static const EmbeddedModule embeddedModule[] =
"$lModificationTime,\n"
"$bIgnoreMissing,\n"
"$hExtraParam,\n"
"$bDelta,\n"
"$bHasReference,\n"
"$strCipherPass,\n"
"\n"
") =\n"
"logDebugParam\n"
"(\n"
@ -3134,6 +3159,8 @@ static const EmbeddedModule embeddedModule[] =
"{name => 'lModificationTime', trace => true},\n"
"{name => 'bIgnoreMissing', default => true, trace => true},\n"
"{name => 'hExtraParam', required => false, trace => true},\n"
"{name => 'bDelta', trace => true},\n"
"{name => 'bHasReference', trace => true},\n"
"{name => 'strCipherPass', required => false, trace => true},\n"
");\n"
"\n"
@ -3145,12 +3172,43 @@ static const EmbeddedModule embeddedModule[] =
"my $lRepoSize;\n"
"\n\n"
"my $strFileOp = $strRepoFile . ($bCompress ? '.' . COMPRESS_EXT : '');\n"
"\n\n"
"my $bCopy = true;\n"
"\n"
"my $bCopy = true;\n"
"\n\n\n"
"if (defined($strChecksum))\n"
"{\n"
"\n"
"if ($bDelta)\n"
"{\n"
"($strCopyChecksum, $lCopySize) = storageDb()->hashSize($strDbFile, {bIgnoreMissing => $bIgnoreMissing});\n"
"\n\n"
"if (defined($strCopyChecksum))\n"
"{\n"
"$bCopy = !($strCopyChecksum eq $strChecksum && $lCopySize == $lSizeFile);\n"
"\n\n\n\n"
"if (!$bCopy && $bHasReference)\n"
"{\n"
"$iCopyResult = BACKUP_FILE_NOOP;\n"
"}\n"
"}\n"
"\n"
"else\n"
"{\n"
"$iCopyResult = BACKUP_FILE_SKIP;\n"
"$bCopy = false;\n"
"}\n"
"}\n"
"\n\n\n\n"
"if (!$bDelta || !$bHasReference)\n"
"{\n"
"\n\n"
"if ($iCopyResult == BACKUP_FILE_SKIP)\n"
"{\n"
"$oStorageRepo->remove(STORAGE_REPO_BACKUP . \"/${strBackupLabel}/${strFileOp}\");\n"
"}\n"
"elsif (!$bDelta || !$bCopy)\n"
"{\n"
"\n"
"my $rhyFilter;\n"
"\n"
"if ($bCompress)\n"
@ -3166,6 +3224,8 @@ static const EmbeddedModule embeddedModule[] =
"\n\n"
"$iCopyResult = $bCopy ? BACKUP_FILE_RECOPY : BACKUP_FILE_CHECKSUM;\n"
"}\n"
"}\n"
"}\n"
"\n\n"
"if ($bCopy)\n"
"{\n"
@ -3280,6 +3340,22 @@ static const EmbeddedModule embeddedModule[] =
"\n\n"
"$lSizeCurrent += $lSize;\n"
"\n\n"
"if ($iCopyResult == BACKUP_FILE_NOOP)\n"
"{\n"
"\n"
"$oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_SIZE, $lSizeCopy);\n"
"$oManifest->set(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksumCopy);\n"
"\n"
"&log(DETAIL,\n"
"'match file from prior backup ' . (defined($strHost) ? \"${strHost}:\" : '') . \"${strDbFile} (\" .\n"
"fileSizeFormat($lSizeCopy) . ', ' . int($lSizeCurrent * 100 / $lSizeTotal) . '%)' .\n"
"($lSizeCopy != 0 ? \" checksum ${strChecksumCopy}\" : ''),\n"
"undef, undef, undef, $iLocalId);\n"
"}\n"
"\n"
"else\n"
"{\n"
"\n"
"if ($iCopyResult == BACKUP_FILE_RECOPY)\n"
"{\n"
"&log(\n"
@ -3312,6 +3388,11 @@ static const EmbeddedModule embeddedModule[] =
"$oManifest->set(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksumCopy);\n"
"}\n"
"\n\n"
"if ($iCopyResult == BACKUP_FILE_COPY || $iCopyResult == BACKUP_FILE_RECOPY)\n"
"{\n"
"$oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_REFERENCE);\n"
"}\n"
"\n\n"
"if ($bChecksumPage)\n"
"{\n"
"\n"
@ -3387,6 +3468,7 @@ static const EmbeddedModule embeddedModule[] =
"&log(DETAIL, 'skip file removed by database ' . (defined($strHost) ? \"${strHost}:\" : '') . $strDbFile);\n"
"$oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strRepoFile);\n"
"}\n"
"}\n"
"\n\n"
"$lManifestSaveCurrent += $lSize;\n"
"\n"
@ -4535,7 +4617,7 @@ static const EmbeddedModule embeddedModule[] =
"\n"
"$oBackupManifest->build(\n"
"storageDb({iRemoteIdx => $iRemoteIdx}), cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)), undef,\n"
"cfgOptionValid(CFGOPT_ONLINE) && cfgOption(CFGOPT_ONLINE), $oDb->tablespaceMapGet());\n"
"cfgOptionValid(CFGOPT_ONLINE) && cfgOption(CFGOPT_ONLINE), false, $oDb->tablespaceMapGet());\n"
"\n"
"return true;\n"
"}\n"
@ -11649,6 +11731,8 @@ static const EmbeddedModule embeddedModule[] =
"push @EXPORT, qw(MANIFEST_KEY_COMPRESS);\n"
"use constant MANIFEST_KEY_ONLINE => 'option-' . cfgOptionName(CFGOPT_ONLINE);\n"
"push @EXPORT, qw(MANIFEST_KEY_ONLINE);\n"
"use constant MANIFEST_KEY_DELTA => 'option-' . cfgOptionName(CFGOPT_DELTA);\n"
"push @EXPORT, qw(MANIFEST_KEY_DELTA);\n"
"\n\n"
"use constant MANIFEST_KEY_DB_ID => 'db-id';\n"
"push @EXPORT, qw(MANIFEST_KEY_DB_ID);\n"
@ -12028,6 +12112,7 @@ static const EmbeddedModule embeddedModule[] =
"$strPath,\n"
"$oLastManifest,\n"
"$bOnline,\n"
"$bDelta,\n"
"$hTablespaceMap,\n"
"$hDatabaseMap,\n"
"$rhExclude,\n"
@ -12044,6 +12129,7 @@ static const EmbeddedModule embeddedModule[] =
"{name => 'strPath'},\n"
"{name => 'oLastManifest', required => false},\n"
"{name => 'bOnline'},\n"
"{name => 'bDelta'},\n"
"{name => 'hTablespaceMap', required => false},\n"
"{name => 'hDatabaseMap', required => false},\n"
"{name => 'rhExclude', required => false},\n"
@ -12347,7 +12433,7 @@ static const EmbeddedModule embeddedModule[] =
"}\n"
"\n"
"$self->build(\n"
"$oStorageDbMaster, $strLinkDestination, undef, $bOnline, $hTablespaceMap, $hDatabaseMap, $rhExclude, $strFile,\n"
"$oStorageDbMaster, $strLinkDestination, undef, $bOnline, $bDelta, $hTablespaceMap, $hDatabaseMap, $rhExclude, $strFile,\n"
"$bTablespace, dirname(\"${strPath}/${strName}\"), $strFilter, $iLevel + 1);\n"
"}\n"
"}\n"
@ -12390,13 +12476,13 @@ static const EmbeddedModule embeddedModule[] =
"$self->set(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_FUTURE, 'y');\n"
"}\n"
"}\n"
"\n"
"\n\n\n\n\n"
"elsif (defined($oLastManifest) && $oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName) &&\n"
"$self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) ==\n"
"$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) &&\n"
"($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) == 0 ||\n"
"$oLastManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) &&\n"
"($bDelta || ($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) == 0 ||\n"
"$self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP) ==\n"
"$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP)))\n"
"$oLastManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP))))\n"
"{\n"
"\n"
"if ($oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REFERENCE))\n"

View File

@ -655,6 +655,13 @@ unit:
coverage:
Backup/Info: partial
# ----------------------------------------------------------------------------------------------------------------------------
- name: file-unit-perl
total: 2
coverage:
Backup/File: partial
# ********************************************************************************************************************************
- name: manifest

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -167,6 +167,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=false
option-hardlink=false
option-online=false
@ -250,7 +251,7 @@ db-version="9.4"
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
full backup - resume (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --force --checksum-page --type=full --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --force --checksum-page --delta --type=full --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
------------------------------------------------------------------------------------------------------------------------------------
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
@ -349,6 +350,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=true
option-hardlink=false
option-online=false
@ -362,25 +364,27 @@ pg_data/postgresql.conf={"file":"postgresql.conf","path":"../pg_config","type":"
cipher-pass=[CIPHER-PASS-3]
[target:file]
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","mode":"0660","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_hba.conf={"checksum":"dd4cea0cae348309f9de28ad4ded8ee2cc2e6d5b","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"mode":"0660","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"238a131a3e8eb98d1fc5b27d882ca40b7618fd2a","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_hba.conf={"checksum":"dd4cea0cae348309f9de28ad4ded8ee2cc2e6d5b","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
[target:file:default]
group="[GROUP-1]"
master=false
master=true
mode="0600"
user="[USER-1]"
@ -634,6 +638,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=false
option-hardlink=false
option-online=false
@ -645,28 +650,30 @@ pg_tblspc/1={"path":"[TEST_PATH]/db-master/db/tablespace/ts1","tablespace-id":"1
cipher-pass=[CIPHER-PASS-3]
[target:file]
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/1/[TS_PATH-1]/16384/tablespace1.txt={"checksum":"14c44cef6287269b08d41de489fd492bb9fc795d","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"238a131a3e8eb98d1fc5b27d882ca40b7618fd2a","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/1/[TS_PATH-1]/16384/tablespace1.txt={"checksum":"14c44cef6287269b08d41de489fd492bb9fc795d","checksum-page":false,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
[target:file:default]
group="[GROUP-1]"
master=false
master=true
mode="0600"
user="[USER-1]"
@ -722,7 +729,7 @@ db-version="9.4"
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
incr backup - resume and add tablespace 2 (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --process-max=1 --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --process-max=1 --delta --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
------------------------------------------------------------------------------------------------------------------------------------
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
@ -730,8 +737,6 @@ P00 WARN: backup [BACKUP-INCR-1] missing in repository removed from backup.inf
P00 WARN: incr backup cannot alter 'checksum-page' option to 'false', reset to 'true' from [BACKUP-FULL-2]
P00 WARN: aborted backup [BACKUP-INCR-2] of same type exists, will be cleaned to remove invalid files and resumed
P00 TEST: PgBaCkReStTeSt-BACKUP-RESUME-PgBaCkReStTeSt
P00 WARN: resumed backup file pg_data/badchecksum.txt does not have expected checksum bogus. The file will be recopied and backup will continue but this may be an issue unless the resumed backup path in the repository is known to be corrupted.
NOTE: this does not indicate a problem with the PostgreSQL page checksums.
P00 WARN: page misalignment in file db-master:[TEST_PATH]/db-master/db/base/pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt: file size 7 is not divisible by page size 8192
P00 WARN: page misalignment in file db-master:[TEST_PATH]/db-master/db/base/pg_tblspc/1/[TS_PATH-1]/16384/tablespace1.txt: file size 7 is not divisible by page size 8192
@ -826,6 +831,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=true
option-hardlink=false
option-online=false
@ -839,29 +845,31 @@ pg_tblspc/2={"path":"[TEST_PATH]/db-master/db/tablespace/ts2","tablespace-id":"2
cipher-pass=[CIPHER-PASS-3]
[target:file]
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/1/[TS_PATH-1]/16384/tablespace1.txt={"checksum":"d85de07d6421d90aa9191c11c889bfde43680f0f","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/1/[TS_PATH-1]/16384/tablespace1.txt={"checksum":"d85de07d6421d90aa9191c11c889bfde43680f0f","checksum-page":false,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","checksum-page":false,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
[target:file:default]
group="[GROUP-1]"
master=false
master=true
mode="0600"
user="[USER-1]"
@ -924,7 +932,7 @@ db-version="9.4"
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
diff backup - cannot resume - new diff (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --log-level-console=warn --process-max=1 --type=diff --stanza=db backup --test --test-delay=0.2 --test-point=backup-noresume=y
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --log-level-console=warn --process-max=1 --delta --type=diff --stanza=db backup --test --test-delay=0.2 --test-point=backup-noresume=y
------------------------------------------------------------------------------------------------------------------------------------
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
@ -1026,6 +1034,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=true
option-hardlink=false
option-online=false
@ -1038,28 +1047,31 @@ pg_tblspc/2={"path":"[TEST_PATH]/db-master/db/tablespace/ts2","tablespace-id":"2
cipher-pass=[CIPHER-PASS-3]
[target:file]
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/1/[TS_PATH-1]/16384/tablespace1.txt={"checksum":"d85de07d6421d90aa9191c11c889bfde43680f0f","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/1/[TS_PATH-1]/16384/tablespace1.txt={"checksum":"d85de07d6421d90aa9191c11c889bfde43680f0f","checksum-page":false,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","checksum-page":false,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
[target:file:default]
group="[GROUP-1]"
master=false
master=true
mode="0600"
user="[USER-1]"
@ -1119,7 +1131,7 @@ db-version="9.4"
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
diff backup - cannot resume - disabled / no repo link (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --no-resume --log-level-console=warn --process-max=1 --type=diff --stanza=db backup --test --test-delay=0.2 --test-point=backup-noresume=y
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --no-resume --log-level-console=warn --process-max=1 --delta --type=diff --stanza=db backup --test --test-delay=0.2 --test-point=backup-noresume=y
------------------------------------------------------------------------------------------------------------------------------------
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
@ -1221,6 +1233,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=true
option-hardlink=false
option-online=false
@ -1233,28 +1246,31 @@ pg_tblspc/2={"path":"[TEST_PATH]/db-master/db/tablespace/ts2","tablespace-id":"2
cipher-pass=[CIPHER-PASS-3]
[target:file]
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/1/[TS_PATH-1]/16384/tablespace1.txt={"checksum":"d85de07d6421d90aa9191c11c889bfde43680f0f","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"e0101dd8ffb910c9c202ca35b5f828bcb9697bed","checksum-page":false,"checksum-page-error":[1],"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/1/[TS_PATH-1]/16384/tablespace1.txt={"checksum":"d85de07d6421d90aa9191c11c889bfde43680f0f","checksum-page":false,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","checksum-page":false,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
[target:file:default]
group="[GROUP-1]"
master=false
master=true
mode="0600"
user="[USER-1]"
@ -1438,6 +1454,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=false
option-hardlink=false
option-online=false
@ -1460,6 +1477,9 @@ pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/base2.txt={"checksum":"09b5e31766be1dba1ec27de82f975c1b6eea2a92","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","master":true,"reference":"[BACKUP-DIFF-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","master":true,"reference":"[BACKUP-DIFF-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
@ -1655,6 +1675,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=false
option-hardlink=false
option-online=false
@ -1677,6 +1698,9 @@ pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/base2.txt={"checksum":"09b5e31766be1dba1ec27de82f975c1b6eea2a92","checksum-page":false,"reference":"[BACKUP-INCR-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","master":true,"reference":"[BACKUP-DIFF-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","master":true,"reference":"[BACKUP-DIFF-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
@ -1746,7 +1770,7 @@ db-version="9.4"
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
diff backup - updates since last full (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --log-level-console=warn --process-max=1 --type=diff --stanza=db backup
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --log-level-console=warn --process-max=1 --delta --type=diff --stanza=db backup
------------------------------------------------------------------------------------------------------------------------------------
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
@ -1851,6 +1875,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=true
option-hardlink=false
option-online=false
@ -1873,6 +1898,9 @@ pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/base2.txt={"checksum":"09b5e31766be1dba1ec27de82f975c1b6eea2a92","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
@ -2046,6 +2074,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=false
option-hardlink=false
option-online=false
@ -2068,6 +2097,9 @@ pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/base2.txt={"checksum":"09b5e31766be1dba1ec27de82f975c1b6eea2a92","checksum-page":false,"reference":"[BACKUP-DIFF-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","master":true,"reference":"[BACKUP-DIFF-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","master":true,"reference":"[BACKUP-DIFF-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
@ -2139,7 +2171,7 @@ db-version="9.4"
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
diff backup - remove files during backup (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --log-level-console=warn --process-max=1 --type=diff --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --log-level-console=warn --process-max=1 --delta --type=diff --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
------------------------------------------------------------------------------------------------------------------------------------
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.
@ -2244,6 +2276,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=true
option-compress=false
option-delta=true
option-hardlink=false
option-online=false
@ -2255,27 +2288,30 @@ pg_tblspc/2={"path":"[TEST_PATH]/db-master/db/tablespace/ts2-2","tablespace-id":
cipher-pass=[CIPHER-PASS-3]
[target:file]
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"master":true,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2c.txt={"checksum":"dfcb8679956b734706cf87259d50c88f83e80e66","checksum-page":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"mode":"0660","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","checksum-page":true,"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","checksum-page":false,"checksum-page-error":[0,[3,5],7],"master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"reference":"[BACKUP-FULL-2]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","checksum-page":false,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2c.txt={"checksum":"dfcb8679956b734706cf87259d50c88f83e80e66","checksum-page":false,"master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
[target:file:default]
group="[GROUP-1]"
master=false
master=true
mode="0600"
user="[USER-1]"
@ -2435,6 +2471,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=false
option-compress=true
option-delta=false
option-hardlink=false
option-online=false
@ -2446,28 +2483,31 @@ pg_tblspc/2={"path":"[TEST_PATH]/db-master/db/tablespace/ts2-2","tablespace-id":
cipher-pass=[CIPHER-PASS-4]
[target:file]
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","mode":"0660","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"7579ada0808d7f98087a0a586d0df9de009cdc33","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"master":true,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2c.txt={"checksum":"dfcb8679956b734706cf87259d50c88f83e80e66","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/badchecksum.txt={"checksum":"f927212cd08d11a42a666b2f04235398e9ceeb51","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/12000={"checksum":"22c98d248ff548311eda88559e4a8405ed77c003","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/1/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"mode":"0660","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/17000={"checksum":"7579ada0808d7f98087a0a586d0df9de009cdc33","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/16384/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000={"checksum":"4a383e4fb8b5cd2a4e8fab91ef63dce48e532a2f","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c2ec5","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/special-@!#$^&*()-_+~`{}[]\|:;"<>',.?%={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zero_from_start={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/zerosize.txt={"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2.txt={"checksum":"dc7f76e43c46101b47acc55ae4d593a9e6983578","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_tblspc/2/[TS_PATH-1]/32768/tablespace2c.txt={"checksum":"dfcb8679956b734706cf87259d50c88f83e80e66","master":false,"repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
[target:file:default]
group="[GROUP-1]"
master=false
master=true
mode="0600"
user="[USER-1]"
@ -2542,55 +2582,55 @@ stanza: db
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 160KB, backup size: 160KB
repository size: 160.4KB, repository backup size: 160.4KB
repository size: 160.5KB, repository backup size: 160.5KB
diff backup: [BACKUP-DIFF-2]
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 160KB, backup size: 25B
repository size: 160.5KB, repository backup size: 128B
database size: 160KB, backup size: 41B
repository size: 160.6KB, repository backup size: 192B
backup reference list: [BACKUP-FULL-2]
incr backup: [BACKUP-INCR-3]
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 160KB, backup size: 13B
repository size: 160.6KB, repository backup size: 64B
repository size: 160.7KB, repository backup size: 64B
backup reference list: [BACKUP-FULL-2], [BACKUP-DIFF-2]
incr backup: [BACKUP-INCR-4]
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 144KB, backup size: 8B
repository size: 144.6KB, repository backup size: 32B
repository size: 144.7KB, repository backup size: 32B
backup reference list: [BACKUP-FULL-2], [BACKUP-DIFF-2], [BACKUP-INCR-3]
diff backup: [BACKUP-DIFF-3]
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 144KB, backup size: 39B
repository size: 144.6KB, repository backup size: 192B
database size: 144KB, backup size: 55B
repository size: 144.7KB, repository backup size: 256B
backup reference list: [BACKUP-FULL-2]
incr backup: [BACKUP-INCR-5]
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 144KB, backup size: 0B
repository size: 144.6KB, repository backup size: 0B
repository size: 144.7KB, repository backup size: 0B
backup reference list: [BACKUP-FULL-2], [BACKUP-DIFF-3]
diff backup: [BACKUP-DIFF-4]
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 144KB, backup size: 30B
repository size: 144.5KB, repository backup size: 128B
database size: 144KB, backup size: 46B
repository size: 144.6KB, repository backup size: 192B
backup reference list: [BACKUP-FULL-2]
full backup: [BACKUP-FULL-3]
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 144KB, backup size: 144KB
repository size: 2.3KB, repository backup size: 2.3KB
repository size: 2.5KB, repository backup size: 2.5KB
info db stanza - normal output (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --log-level-console=warn --stanza=db --output=json info
@ -2987,6 +3027,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=false
option-compress=true
option-delta=false
option-hardlink=false
option-online=false
@ -3009,6 +3050,9 @@ pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/base2.txt={"checksum":"cafac3c59553f2cfde41ce2e62e7662295f108c0","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
@ -3128,13 +3172,13 @@ stanza: db
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 144KB, backup size: 144KB
repository size: 2.3KB, repository backup size: 2.3KB
repository size: 2.5KB, repository backup size: 2.5KB
diff backup: [BACKUP-DIFF-5]
timestamp start/stop: [TIMESTAMP-STR]
wal start/stop: n/a
database size: 144KB, backup size: 9B
repository size: 2.4KB, repository backup size: 48B
database size: 144.1KB, backup size: 9B
repository size: 2.5KB, repository backup size: 48B
backup reference list: [BACKUP-FULL-3]
info all stanzas - normal output (db-master host)
@ -3360,6 +3404,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=false
option-compress=true
option-delta=false
option-hardlink=false
option-online=false
@ -3382,6 +3427,9 @@ pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/base2.txt={"checksum":"cafac3c59553f2cfde41ce2e62e7662295f108c0","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
@ -3558,6 +3606,7 @@ option-archive-copy=true
option-backup-standby=false
option-checksum-page=false
option-compress=true
option-delta=false
option-hardlink=false
option-online=false
@ -3580,6 +3629,9 @@ pg_data/base/32768/33000.32767={"checksum":"21e2c7c1a326682c07053b7d6a5a40dbd49c
pg_data/base/32768/33001={"checksum":"6bf316f11d28c28914ea9be92c00de9bea6d9a6b","reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/32768/PG_VERSION={"checksum":"184473f470864e067ee3a22e64b47b0a1c356f29","reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/base/base2.txt={"checksum":"cafac3c59553f2cfde41ce2e62e7662295f108c0","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changecontent.txt={"checksum":"a094d94583e209556d03c3c5da33131a065f1689","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changesize.txt={"checksum":"3905d5be2ec8d67f41435dab5e0dcda3ae47455d","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-1]}
pg_data/changetime.txt={"checksum":"88087292ed82e26f3eb824d0bffc05ccf7a30f8d","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/global/pg_control={"checksum":"b4a3adade1e81ebfc7e9a27bca0887a347d81522","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/pg_stat/global.stat={"checksum":"e350d5ce0153f3e22d5db21cf2a4eff00f3ee877","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}
pg_data/postgresql.conf={"checksum":"6721d92c9fcdf4248acff1f9a1377127d9064807","master":true,"reference":"[BACKUP-FULL-3]","repo-size":[SIZE],"size":[SIZE],"timestamp":[TIMESTAMP-2]}

View File

@ -128,7 +128,7 @@ incr backup - fail on archive_mode=always (db-master host)
------------------------------------------------------------------------------------------------------------------------------------
incr backup - update during backup (db-master host)
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stop-auto --buffer-size=32768 --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stop-auto --buffer-size=32768 --delta --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
------------------------------------------------------------------------------------------------------------------------------------
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf

View File

@ -161,7 +161,7 @@ check db - verify check command on standby (db-standby host)
------------------------------------------------------------------------------------------------------------------------------------
incr backup - update during backup (db-master host)
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stop-auto --buffer-size=32768 --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stop-auto --buffer-size=32768 --delta --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
------------------------------------------------------------------------------------------------------------------------------------
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf

View File

@ -161,7 +161,7 @@ check db - confirm standby manifest->build executed (db-standby host)
------------------------------------------------------------------------------------------------------------------------------------
incr backup - update during backup (db-standby host)
> [CONTAINER-EXEC] db-standby [BACKREST-BIN] --config=[TEST_PATH]/db-standby/pgbackrest.conf --stop-auto --buffer-size=32768 --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
> [CONTAINER-EXEC] db-standby [BACKREST-BIN] --config=[TEST_PATH]/db-standby/pgbackrest.conf --stop-auto --buffer-size=32768 --delta --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
------------------------------------------------------------------------------------------------------------------------------------
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf

View File

@ -169,7 +169,7 @@ start all stanzas (db-master host)
------------------------------------------------------------------------------------------------------------------------------------
incr backup - update during backup (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stop-auto --buffer-size=32768 --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stop-auto --buffer-size=32768 --delta --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
------------------------------------------------------------------------------------------------------------------------------------
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf

View File

@ -223,7 +223,7 @@ check db - verify check command on standby (db-standby host)
------------------------------------------------------------------------------------------------------------------------------------
incr backup - update during backup (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stop-auto --buffer-size=32768 --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stop-auto --buffer-size=32768 --delta --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
------------------------------------------------------------------------------------------------------------------------------------
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf

View File

@ -168,7 +168,7 @@ archive-copy=y
start-fast=y
incr backup - update during backup (backup host)
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stop-auto --buffer-size=32768 --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stop-auto --buffer-size=32768 --delta --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
------------------------------------------------------------------------------------------------------------------------------------
+ supplemental file: [TEST_PATH]/db-master/pgbackrest.conf

View File

@ -476,6 +476,10 @@ sub backupCompare
$oActualManifest->get(INI_SECTION_CIPHER, INI_KEY_CIPHER_PASS);
}
# Update the expected manifest with whether the --delta option was used or not to perform the backup.
$oExpectedManifest->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_DELTA} =
$oActualManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_DELTA) ? INI_TRUE : INI_FALSE;
my $strSectionPath = $oActualManifest->get(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_PATH);
foreach my $strFileKey ($oActualManifest->keys(MANIFEST_SECTION_TARGET_FILE))
@ -1752,6 +1756,10 @@ sub restoreCompare
'/'. FILE_MANIFEST),
{strCipherPass => $oHostBackup->cipherPassManifest()});
# Get the --delta option from the backup manifest so the actual manifest can be built the same way for comparison
$$oExpectedManifestRef{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_DELTA} =
$oExpectedManifest->get(MANIFEST_SECTION_BACKUP_OPTION, &MANIFEST_KEY_DELTA);
$oLastManifest =
new pgBackRest::Manifest(
storageRepo()->pathGet(
@ -1815,7 +1823,11 @@ sub restoreCompare
iDbCatalogVersion => $oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG},
oStorage => storageTest()});
$oActualManifest->build(storageTest(), $strDbClusterPath, $oLastManifest, false, $oTablespaceMap);
# Build the actual manifest using the delta setting that was actually used by the latest backup if one exists
$oActualManifest->build(storageTest(), $strDbClusterPath, $oLastManifest, false,
$oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_DELTA}, $oTablespaceMap);
$oActualManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_DELTA, undef,
$oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_DELTA});
my $strSectionPath = $oActualManifest->get(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_PATH);
@ -1877,17 +1889,37 @@ sub restoreCompare
{
my $oStat = storageTest()->info($oActualManifest->dbPathGet($strSectionPath, $strName));
# When performing a selective restore, the files for the database(s) that are not restored are still copied but as empty
# sparse files (blocks == 0). If the file is not a sparse file or is a link, then get the actual checksum for comparison
if ($oStat->blocks > 0 || S_ISLNK($oStat->mode))
{
my ($strHash) = storageTest()->hashSize($oActualManifest->dbPathGet($strSectionPath, $strName));
$oActualManifest->set(
MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM, $strHash);
# If the delta option was set, it is possible that the checksum on the file changed from the last manifest. If so,
# then the file was expected to be copied by the backup and therefore the reference would have been removed.
if ($oExpectedManifestRef->{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_DELTA})
{
# If the actual checksum and last manifest checksum don't match, remove the reference
if (defined($oLastManifest) &&
$oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM) &&
$strHash ne $oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM))
{
$oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REFERENCE);
}
}
}
else
{
# If there is a sparse file, remove the checksum and reference since they may or may not match. In this case, it is
# not important to check them since it is known that the file was intentionally not restored.
$oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM);
delete(${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_CHECKSUM});
$oActualManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REFERENCE);
delete(${$oExpectedManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strName}{&MANIFEST_SUBKEY_REFERENCE});
}
}
}
@ -1912,6 +1944,8 @@ sub restoreCompare
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_HARDLINK});
$oActualManifest->set(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ONLINE});
$oActualManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_DELTA, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_DELTA});
$oActualManifest->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef,
${$oExpectedManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION});

View File

@ -0,0 +1,691 @@
####################################################################################################################################
# Tests for Backup File module
####################################################################################################################################
package pgBackRestTest::Module::Backup::BackupFileUnitPerlTest;
use parent 'pgBackRestTest::Env::HostEnvTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use File::Basename qw(dirname);
use Storable qw(dclone);
use pgBackRest::Backup::File;
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Common::Wait;
use pgBackRest::Config::Config;
use pgBackRest::DbVersion;
use pgBackRest::Manifest;
use pgBackRest::Protocol::Helper;
use pgBackRest::Protocol::Storage::Helper;
use pgBackRest::Storage::Helper;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::RunTest;
use pgBackRestTest::Env::Host::HostBackupTest;
####################################################################################################################################
# initModule
####################################################################################################################################
sub initModule
{
my $self = shift;
$self->{strDbPath} = $self->testPath() . '/db';
$self->{strRepoPath} = $self->testPath() . '/repo';
$self->{strBackupPath} = "$self->{strRepoPath}/backup/" . $self->stanza();
$self->{strPgControl} = $self->{strDbPath} . '/' . DB_FILE_PGCONTROL;
# Create backup path
storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true});
# Generate pg_control file
storageTest()->pathCreate($self->{strDbPath} . '/' . DB_PATH_GLOBAL, {bCreateParent => true});
$self->controlGenerate($self->{strDbPath}, PG_VERSION_94);
}
####################################################################################################################################
# run
####################################################################################################################################
sub run
{
my $self = shift;
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
$self->optionTestSet(CFGOPT_PG_PATH, $self->{strDbPath});
$self->optionTestSet(CFGOPT_REPO_PATH, $self->{strRepoPath});
$self->optionTestSet(CFGOPT_LOG_PATH, $self->testPath());
$self->optionTestSetBool(CFGOPT_ONLINE, false);
$self->optionTestSet(CFGOPT_DB_TIMEOUT, 5);
$self->optionTestSet(CFGOPT_PROTOCOL_TIMEOUT, 6);
$self->optionTestSet(CFGOPT_COMPRESS_LEVEL, 3);
$self->configTestLoad(CFGCMD_BACKUP);
# Repo
my $strRepoBackupPath = storageRepo()->pathGet(STORAGE_REPO_BACKUP);
my $strBackupLabel = "20180724-182750F";
# File
my $strFileName = "12345";
my $strFileDb = $self->{strDbPath} . "/$strFileName";
my $strFileHash = '1c7e00fd09b9dd11fc2966590b3e3274645dd031';
my $strFileRepo = storageRepo()->pathGet(
STORAGE_REPO_BACKUP . "/$strBackupLabel/" . MANIFEST_TARGET_PGDATA . "/$strFileName");
my $strRepoFile = MANIFEST_TARGET_PGDATA . "/$strFileName";
my $strRepoPgControl = MANIFEST_FILE_PGCONTROL;
my $strPgControlRepo = storageRepo()->pathGet(STORAGE_REPO_BACKUP . "/$strBackupLabel/$strRepoPgControl");
my $strPgControlHash = 'b4a3adade1e81ebfc7e9a27bca0887a347d81522';
# Copy file to db path
executeTest('cp ' . $self->dataPath() . "/filecopy.archive2.bin ${strFileDb}");
# Get size and data info for the files in the db path
my $hManifest = storageDb()->manifest($self->{strDbPath});
my $lFileSize = $hManifest->{$strFileName}{size} + 0;
my $lFileTime = $hManifest->{$strFileName}{modification_time} + 0;
my $lPgControlSize = $hManifest->{&DB_FILE_PGCONTROL}{size} + 0;
my $lPgControlTime = $hManifest->{&DB_FILE_PGCONTROL}{modification_time} + 0;
my $lRepoFileCompressSize = 3646899;
my $strBackupPath = $self->{strBackupPath} . "/$strBackupLabel";
my $strHost = "host";
my $iLocalId = 1;
# Initialize the manifest
my $oBackupManifest = new pgBackRest::Manifest("$strBackupPath/" . FILE_MANIFEST,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => 201409291});
$oBackupManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
# Set the initial size values for backupManifestUpdate - running size and size for when to save the file
my $lSizeCurrent = 0;
my $lSizeTotal = 16785408;
my $lManifestSaveCurrent = 0;
my $lManifestSaveSize = int($lSizeTotal / 100);
# Result variables
my $iResultCopyResult;
my $lResultCopySize;
my $lResultRepoSize;
my $strResultCopyChecksum;
my $rResultExtra;
################################################################################################################################
if ($self->begin('backupFile(), backupManifestUpdate()'))
{
#---------------------------------------------------------------------------------------------------------------------------
# Copy pg_control and confirm manifestUpdate does not save the manifest yet
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($self->{strPgControl}, MANIFEST_FILE_PGCONTROL, $lPgControlSize, undef, false, $strBackupLabel, false,
cfgOption(CFGOPT_COMPRESS_LEVEL), $lPgControlTime, true, undef, false, false, undef);
$self->testResult(sub {storageTest()->exists($strPgControlRepo)}, true, 'pg_control file exists in repo');
$self->testResult(($iResultCopyResult == BACKUP_FILE_COPY && $strResultCopyChecksum eq $strPgControlHash &&
$lResultCopySize == $lPgControlSize && $lResultRepoSize == $lPgControlSize), true,
'pg_control file copied to repo successfully');
($lSizeCurrent, $lManifestSaveCurrent) = backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
$self->{strPgControl},
$strRepoPgControl,
$lPgControlSize,
undef,
false,
$iResultCopyResult,
$lResultCopySize,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent);
# Accumulators should be same size as pg_control
$self->testResult(($lSizeCurrent == $lPgControlSize && $lManifestSaveCurrent == $lPgControlSize), true,
"file size in repo and repo size equal pg_control size");
$self->testResult(sub {$oBackupManifest->test(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL,
MANIFEST_SUBKEY_CHECKSUM, $strPgControlHash)}, true, "manifest updated for pg_control");
# Neither backup.manifest nor backup.manifest.copy written because size threshold not met
$self->testException(sub {storageRepo()->openRead("$strBackupPath/" . FILE_MANIFEST . INI_COPY_EXT)}, ERROR_FILE_MISSING,
"unable to open '$strBackupPath/" . FILE_MANIFEST . INI_COPY_EXT . "': No such file or directory");
$self->testException(sub {storageRepo()->openRead("$strBackupPath/" . FILE_MANIFEST)}, ERROR_FILE_MISSING,
"unable to open '$strBackupPath/" . FILE_MANIFEST . "': No such file or directory");
#---------------------------------------------------------------------------------------------------------------------------
# No prior checksum, no compression, no page checksum, no extra, no delta, no hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($strFileDb, $strRepoFile, $lFileSize, undef, false, $strBackupLabel, false,
cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, false, false, undef);
$self->testResult(sub {storageTest()->exists($strFileRepo)}, true, 'non-compressed file exists in repo');
$self->testResult(($iResultCopyResult == BACKUP_FILE_COPY && $strResultCopyChecksum eq $strFileHash &&
$lResultCopySize == $lFileSize && $lResultRepoSize == $lFileSize), true,
'file copied to repo successfully');
$self->testException(sub {storageRepo()->openRead("$strFileRepo.gz")}, ERROR_FILE_MISSING,
"unable to open '$strFileRepo.gz': No such file or directory");
($lSizeCurrent, $lManifestSaveCurrent) = backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
false,
$iResultCopyResult,
$lResultCopySize,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent);
# Accumulator includes size of pg_control and file. Manifest saved so ManifestSaveCurrent returns to 0
$self->testResult(($lSizeCurrent == ($lPgControlSize + $lFileSize) && $lManifestSaveCurrent == 0), true,
"repo size increased and ManifestSaveCurrent returns to 0");
$self->testResult(sub {$oBackupManifest->test(MANIFEST_SECTION_TARGET_FILE, $strRepoFile,
MANIFEST_SUBKEY_CHECKSUM, $strFileHash)}, true, "manifest updated for $strRepoFile");
# Backup.manifest not written but backup.manifest.copy written because size threshold met
$self->testResult(sub {storageTest()->exists("$strBackupPath/" . FILE_MANIFEST . INI_COPY_EXT)}, true,
'backup.manifest.copy exists in repo');
$self->testException(sub {storageRepo()->openRead("$strBackupPath/" . FILE_MANIFEST)}, ERROR_FILE_MISSING,
"unable to open '$strBackupPath/" . FILE_MANIFEST . "': No such file or directory");
storageTest()->remove($strFileRepo);
storageTest()->remove($strPgControlRepo);
#---------------------------------------------------------------------------------------------------------------------------
# No prior checksum, yes compression, yes page checksum, no extra, no delta, no hasReference
$self->testException(sub {backupFile($strFileDb, $strRepoFile, $lFileSize, undef, true,
$strBackupLabel, true, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, false, false, undef)}, ERROR_ASSERT,
"iWalId is required in Backup::Filter::PageChecksum->new");
# Build the lsn start parameter to pass to the extra function
my $hStartLsnParam =
{
iWalId => 0xFFFF,
iWalOffset => 0xFFFF,
};
#---------------------------------------------------------------------------------------------------------------------------
# No prior checksum, yes compression, yes page checksum, yes extra, no delta, no hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($strFileDb, $strRepoFile, $lFileSize, undef, true, $strBackupLabel, true,
cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, $hStartLsnParam, false, false, undef);
$self->testResult(sub {storageTest()->exists("$strFileRepo.gz")}, true, 'compressed file exists in repo');
$self->testResult(($iResultCopyResult == BACKUP_FILE_COPY && $strResultCopyChecksum eq $strFileHash &&
$lResultRepoSize == $lRepoFileCompressSize && $rResultExtra->{bValid}), true, 'file copied to repo successfully');
# Only the compressed version of the file exists
$self->testException(sub {storageRepo()->openRead("$strFileRepo")}, ERROR_FILE_MISSING,
"unable to open '$strFileRepo': No such file or directory");
($lSizeCurrent, $lManifestSaveCurrent) = backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
true,
$iResultCopyResult,
$lResultCopySize,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent);
# File is compressed in repo so make sure repo-size added to manifest
$self->testResult(sub {$oBackupManifest->test(
MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_REPO_SIZE, $lResultRepoSize)},
true, "repo-size set");
$self->testResult(sub {$oBackupManifest->test(
MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM_PAGE, $rResultExtra->{bValid})},
true, "checksum page set");
# Save the compressed file for later test
executeTest('mv ' . "$strFileRepo.gz $strFileRepo.gz.SAVE");
#---------------------------------------------------------------------------------------------------------------------------
# Add a segment number for bChecksumPage code coverage
executeTest('cp ' . "$strFileDb $strFileDb.1");
# No prior checksum, no compression, yes page checksum, yes extra, no delta, no hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile("$strFileDb.1", "$strRepoFile.1", $lFileSize, undef, true, $strBackupLabel, false,
cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, $hStartLsnParam, false, false, undef);
$self->testResult(sub {storageTest()->exists("$strFileRepo.1")}, true, 'non-compressed segment file exists in repo');
$self->testResult(($iResultCopyResult == BACKUP_FILE_COPY && $strResultCopyChecksum eq $strFileHash &&
$lResultRepoSize == $lFileSize && $rResultExtra->{bValid}), true, 'segment file copied to repo successfully');
# Set a section in the manifest to ensure it is removed in the next test
$oBackupManifest->set(
MANIFEST_SECTION_TARGET_FILE, "$strRepoFile.1", MANIFEST_SUBKEY_CHECKSUM, $strResultCopyChecksum);
$self->testResult(sub {$oBackupManifest->test(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . "/$strFileName.1")},
true, MANIFEST_TARGET_PGDATA . "/$strFileName.1 section exists in manifest");
#---------------------------------------------------------------------------------------------------------------------------
# Remove the db file and try to back it up
storageTest()->remove("$strFileDb.1");
# No prior checksum, no compression, no page checksum, no extra, No delta, no hasReference, no db file
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile("$strFileDb.1", "$strRepoFile.1", $lFileSize, undef, false, $strBackupLabel,
false, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, false, false, undef);
$self->testResult(($iResultCopyResult == BACKUP_FILE_SKIP && !defined($strResultCopyChecksum) &&
!defined($lResultRepoSize) && !defined($lResultCopySize)), true, "db file missing - $strRepoFile.1 file skipped");
# Delta not set so file still exists in repo
$self->testResult(sub {storageTest()->exists("$strFileRepo.1")}, true, ' delta not set - file exists in repo');
($lSizeCurrent, $lManifestSaveCurrent) = backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
"$strFileDb.1",
"$strRepoFile.1",
$lFileSize,
$strFileHash,
false,
$iResultCopyResult,
$lResultCopySize,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent);
$self->testResult(sub {$oBackupManifest->test(MANIFEST_SECTION_TARGET_FILE, "$strRepoFile.1")},
false, " $strRepoFile.1 section removed from manifest");
# Yes prior checksum, no compression, no page checksum, no extra, yes delta, no hasReference, no db file
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile("$strFileDb.1", MANIFEST_TARGET_PGDATA . "/$strFileName.1", $lFileSize, $strFileHash, false, $strBackupLabel,
false, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, true, false, undef);
$self->testResult(($iResultCopyResult == BACKUP_FILE_SKIP && !defined($strResultCopyChecksum) &&
!defined($lResultRepoSize)), true, "db file missing - delta $strRepoFile.1 file skipped");
$self->testResult(sub {storageTest()->exists("$strFileRepo.1")}, false, ' delta set - file removed from repo');
# Code path for host not defined for logged message of skipped file
($lSizeCurrent, $lManifestSaveCurrent) = backupManifestUpdate(
$oBackupManifest,
undef,
$iLocalId,
"$strFileDb.1",
MANIFEST_TARGET_PGDATA . "/$strFileName.1",
$lFileSize,
$strFileHash,
false,
$iResultCopyResult,
$lResultCopySize,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent);
# Yes prior checksum, no compression, no page checksum, no extra, yes delta, no hasReference, no db file,
# do not ignoreMissing
$self->testException(sub {backupFile("$strFileDb.1", "$strRepoFile.1", $lFileSize, $strFileHash,
false, $strBackupLabel, false, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, false, undef, true, false, undef)},
ERROR_FILE_MISSING, "unable to open '$strFileDb.1': No such file or directory");
#---------------------------------------------------------------------------------------------------------------------------
# Restore the compressed file
executeTest('mv ' . "$strFileRepo.gz.SAVE $strFileRepo.gz");
# Yes prior checksum, yes compression, no page checksum, no extra, yes delta, no hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($strFileDb, $strRepoFile, $lFileSize, $strFileHash, false, $strBackupLabel,
true, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, true, false, undef);
$self->testResult(($iResultCopyResult == BACKUP_FILE_CHECKSUM && $strResultCopyChecksum eq $strFileHash &&
$lResultCopySize == $lFileSize), true, 'db checksum and repo same - no copy file');
#---------------------------------------------------------------------------------------------------------------------------
# DB Checksum mismatch
storageTest()->remove("$strFileRepo", {bIgnoreMissing => true});
# Save the compressed file for later test
executeTest('mv ' . "$strFileRepo.gz $strFileRepo.gz.SAVE");
# Yes prior checksum, no compression, no page checksum, no extra, yes delta, no hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($strFileDb, $strRepoFile, $lFileSize, $strFileHash . "ff", false,
$strBackupLabel, false, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, true, false, undef);
$self->testResult(($iResultCopyResult == BACKUP_FILE_COPY && $strResultCopyChecksum eq $strFileHash &&
$lResultCopySize == $lFileSize && $lResultRepoSize == $lFileSize), true, 'db checksum mismatch - copy file');
#---------------------------------------------------------------------------------------------------------------------------
# DB file size mismatch
# Yes prior checksum, no compression, no page checksum, no extra, yes delta, no hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($strFileDb, $strRepoFile, $lFileSize + 1, $strFileHash, false, $strBackupLabel, false,
cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, true, false, undef);
$self->testResult(($iResultCopyResult == BACKUP_FILE_COPY && $strResultCopyChecksum eq $strFileHash &&
$lResultCopySize == $lFileSize && $lResultRepoSize == $lFileSize), true, 'db file size mismatch - copy file');
#---------------------------------------------------------------------------------------------------------------------------
# Repo mismatch
# Restore the compressed file as if non-compressed so checksum won't match
executeTest('cp ' . "$strFileRepo.gz.SAVE $strFileRepo");
# Yes prior checksum, no compression, no page checksum, no extra, yes delta, no hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($strFileDb, $strRepoFile, $lFileSize, $strFileHash, false, $strBackupLabel, false,
cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, true, false, undef);
$self->testResult(($iResultCopyResult == BACKUP_FILE_RECOPY && $strResultCopyChecksum eq $strFileHash &&
$lResultCopySize == $lFileSize && $lResultRepoSize == $lFileSize), true, 'repo checksum mismatch - recopy file');
# Restore the compressed file
executeTest('mv ' . "$strFileRepo.gz.SAVE $strFileRepo.gz");
# Yes prior checksum, yes compression, no page checksum, no extra, no delta, no hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($strFileDb, $strRepoFile, $lFileSize + 1, $strFileHash, false,
$strBackupLabel, true, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, false, false, undef);
$self->testResult(($iResultCopyResult == BACKUP_FILE_RECOPY && $strResultCopyChecksum eq $strFileHash &&
$lResultCopySize == $lFileSize), true, 'repo size mismatch - recopy file');
#---------------------------------------------------------------------------------------------------------------------------
# Has reference
# Set a reference in the manifest to ensure it is removed after backupManifestUpdate
$oBackupManifest->set(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_REFERENCE, BOGUS);
$self->testResult(sub {$oBackupManifest->test(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_REFERENCE,
BOGUS)}, true, "$strRepoFile reference section exists in manifest");
# Yes prior checksum, no compression, no page checksum, no extra, yes delta, yes hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($strFileDb, $strRepoFile, $lFileSize + 1, $strFileHash, false,
$strBackupLabel, false, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, true, true, undef);
$self->testResult(($iResultCopyResult == BACKUP_FILE_COPY && $strResultCopyChecksum eq $strFileHash &&
$lResultCopySize == $lFileSize && $lResultRepoSize == $lFileSize), true, 'db file size mismatch has reference - copy');
# Code path to ensure reference is removed
($lSizeCurrent, $lManifestSaveCurrent) = backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
false,
$iResultCopyResult,
$lResultCopySize,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent);
# Confirm reference to prior backup removed
$self->testResult(sub {$oBackupManifest->test(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . "/$strFileName.",
MANIFEST_SUBKEY_REFERENCE)},
false, "reference to prior backup in manifest removed");
#---------------------------------------------------------------------------------------------------------------------------
# BACKUP_FILE_NOOP
# Yes prior checksum, no compression, no page checksum, no extra, yes delta, yes hasReference
($iResultCopyResult, $lResultCopySize, $lResultRepoSize, $strResultCopyChecksum, $rResultExtra) =
backupFile($strFileDb, $strRepoFile, $lFileSize, $strFileHash, false,
$strBackupLabel, false, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, true, true, undef);
$self->testResult(($iResultCopyResult == BACKUP_FILE_NOOP && $strResultCopyChecksum eq $strFileHash &&
$lResultCopySize == $lFileSize), true, 'db file same has reference - noop');
# Calculate running counts
my $lSizeCurrentAfter = $lSizeCurrent + $lFileSize;
my $lManifestSaveCurrentAfter = $lManifestSaveCurrent + $lFileSize;
# Increase manifest save size, so manifest will not be saved so counts can be tested
$lManifestSaveSize = $lFileSize * 2;
($lSizeCurrent, $lManifestSaveCurrent) = backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
false,
$iResultCopyResult,
$lResultCopySize,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent);
$self->testResult(($lSizeCurrent ==$lSizeCurrentAfter && $lManifestSaveCurrent == $lManifestSaveCurrentAfter),
true, ' running counts updated');
#---------------------------------------------------------------------------------------------------------------------------
# Remove file from repo. No reference so should hard error since this means sometime between the building of the manifest
# for the aborted backup, the file went missing from the aborted backup dir.
storageTest()->remove("$strFileRepo", {bIgnoreMissing => true});
$self->testException(sub {backupFile($strFileDb, $strRepoFile, $lFileSize, $strFileHash,
false, $strBackupLabel, false, cfgOption(CFGOPT_COMPRESS_LEVEL), $lFileTime, true, undef, true, false, undef)},
ERROR_FILE_MISSING, "unable to open '$strFileRepo': No such file or directory");
}
################################################################################################################################
# This section for for code coverage that is not covered in the above tests
if ($self->begin('backupManifestUpdate()'))
{
$oBackupManifest = new pgBackRest::Manifest("$strBackupPath/" . FILE_MANIFEST,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => 201409291});
#---------------------------------------------------------------------------------------------------------------------------
# Check BACKUP_FILE_RECOPY warning
$iResultCopyResult = BACKUP_FILE_RECOPY;
$lResultCopySize = 0;
$lResultRepoSize = $lResultCopySize + 1;
$strResultCopyChecksum = $strFileHash;
$lSizeCurrent = 0;
$lManifestSaveSize = $lFileSize * 2;
$lManifestSaveCurrent = 0;
$self->testResult(sub {backupManifestUpdate(
$oBackupManifest,
undef,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
false,
$iResultCopyResult,
$lResultCopySize,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent)}, "($lFileSize, $lFileSize)",
'backup file recopy warning', {strLogExpect =>
"WARN: resumed backup file $strRepoFile does not have expected checksum $strFileHash. The file will be recopied and" .
" backup will continue but this may be an issue unless the resumed backup path in the repository is known to be" .
" corrupted.\n" .
"NOTE: this does not indicate a problem with the PostgreSQL page checksums."});
# Check size code paths
$self->testResult(
$oBackupManifest->test(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_SIZE, $lResultCopySize),
true, " copy size set");
$self->testResult(
$oBackupManifest->test(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_REPO_SIZE, $lResultRepoSize),
true, " repo size set");
$self->testResult(
$oBackupManifest->test(MANIFEST_SECTION_TARGET_FILE, $strRepoFile, MANIFEST_SUBKEY_CHECKSUM, $strResultCopyChecksum),
false, " checksum not set since copy size 0");
#---------------------------------------------------------------------------------------------------------------------------
# Checkum page exception
$iResultCopyResult = BACKUP_FILE_COPY;
$self->testException(sub {backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
true,
$iResultCopyResult,
$lResultCopySize,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent)},
ERROR_ASSERT, "$strFileDb should have calculated page checksums");
$rResultExtra->{bValid} = false;
$self->testException(sub {backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
true,
$iResultCopyResult,
$lResultCopySize + 1,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent)},
ERROR_ASSERT, "bAlign flag should have been set for misaligned page");
$rResultExtra->{bAlign} = true;
$self->testException(sub {backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
true,
$iResultCopyResult,
$lResultCopySize + 1,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent)},
ERROR_ASSERT, "bAlign flag should have been set for misaligned page");
$rResultExtra->{bAlign} = false;
$self->testResult(sub {backupManifestUpdate(
$oBackupManifest,
$strHost,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
true,
$iResultCopyResult,
$lResultCopySize + 1,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent)},
"($lFileSize, $lFileSize)",
'page misalignment warning - host defined', {strLogExpect =>
"WARN: page misalignment in file $strHost:$strFileDb: file size " . ($lResultCopySize + 1) .
" is not divisible by page size " . PG_PAGE_SIZE});
$self->testResult(sub {backupManifestUpdate(
$oBackupManifest,
undef,
$iLocalId,
$strFileDb,
$strRepoFile,
$lFileSize,
$strFileHash,
true,
$iResultCopyResult,
$lResultCopySize + 1,
$lResultRepoSize,
$strResultCopyChecksum,
$rResultExtra,
$lSizeTotal,
$lSizeCurrent,
$lManifestSaveSize,
$lManifestSaveCurrent)},
"($lFileSize, $lFileSize)",
'page misalignment warning - host not defined', {strLogExpect =>
"WARN: page misalignment in file $strFileDb: file size " . ($lResultCopySize + 1) .
" is not divisible by page size " . PG_PAGE_SIZE});
}
}
1;

View File

@ -226,7 +226,7 @@ sub run
# Build error if offline = true and no tablespace path
#---------------------------------------------------------------------------------------------------------------------------
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, false)}, ERROR_FILE_MISSING,
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false)}, ERROR_FILE_MISSING,
"unable to stat '" . $self->{strDbPath} . "/" . MANIFEST_TARGET_PGTBLSPC . "': No such file or directory");
# bOnline = true tests - Compare the base manifest
@ -234,10 +234,10 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestBase, $oManifest)}, "", 'base manifest');
$self->testException(
sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_ASSERT,
sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_ASSERT,
'manifest has already been built');
# Create expected manifest from base
@ -274,7 +274,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'paths/files and different modes');
# Master = false (what can be copied from a standby vs the master)
@ -294,7 +294,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'master false');
# Create pg_config path and postgresql.conf file
@ -370,7 +370,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'link');
# Create a link loop and expect an error
@ -381,7 +381,7 @@ sub run
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$self->testException(
sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_FORMAT,
sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_FORMAT,
'recursion in manifest build exceeds depth of 16: pg_data/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/' .
"pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata\n" .
'HINT: is there a link loop in $PGDATA?');
@ -519,7 +519,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'skip directories/files');
# Unskip code path coverage
@ -551,7 +551,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_93, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_93)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 94 directories');
# Change DB version to 91
@ -572,7 +572,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_91, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_91)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 92 directories');
# Change DB version to 90
@ -636,7 +636,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_90, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_90)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 91 directories');
# Change DB version to 84
@ -675,7 +675,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_84, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_84)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 90 directories');
# Change DB version to 83
@ -696,7 +696,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_83, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_83)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 84 directories');
# Reset Manifest for next tests
@ -731,7 +731,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'manifest reset');
# Tablespaces
@ -745,7 +745,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_LINK_EXPECTED,
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_LINK_EXPECTED,
MANIFEST_TARGET_PGTBLSPC . "/" . BOGUS . " is not a symlink - " . DB_PATH_PGTBLSPC . " should contain only symlinks");
testPathRemove("${strTblSpcPath}/" . BOGUS);
@ -757,7 +757,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_TABLESPACE_IN_PGDATA,
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_TABLESPACE_IN_PGDATA,
'tablespace symlink ../ destination must not be in $PGDATA');
testFileRemove("${strTblSpcPath}/${strTblspcId}");
@ -766,7 +766,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_TABLESPACE_IN_PGDATA,
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_TABLESPACE_IN_PGDATA,
'tablespace symlink .. destination must not be in $PGDATA');
testFileRemove("${strTblSpcPath}/${strTblspcId}");
@ -775,7 +775,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_TABLESPACE_IN_PGDATA,
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_TABLESPACE_IN_PGDATA,
'tablespace symlink ../base destination must not be in $PGDATA');
testFileRemove("${strTblSpcPath}/${strTblspcId}");
@ -785,7 +785,7 @@ sub run
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$self->testException(
sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_TABLESPACE_IN_PGDATA,
sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_TABLESPACE_IN_PGDATA,
"tablespace symlink $self->{strDbPath}/base destination must not be in \$PGDATA");
testFileRemove("${strTblSpcPath}/${strTblspcId}");
@ -794,7 +794,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_ASSERT,
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_ASSERT,
"tablespace with oid ${strTblspcId} not found in tablespace map\n" .
"HINT: was a tablespace created or dropped during the backup?");
testFileRemove("${strTblSpcPath}/${strTblspcId}");
@ -812,7 +812,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, false)}, ERROR_LINK_DESTINATION,
$self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false)}, ERROR_LINK_DESTINATION,
"link '${strTblSpcPath}/${strTblspcId}' -> '$strIntermediateLink' cannot reference another link");
testFileRemove($strIntermediateLink);
@ -901,7 +901,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, false);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'offline with valid tablespace - do not skip database WAL directory and only copy unlogged init file');
@ -920,7 +920,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, $hTablespaceMap, $hDatabaseMap);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false, $hTablespaceMap, $hDatabaseMap);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'offline passing tablespace map and database map');
@ -947,7 +947,7 @@ sub run
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(
storageDb(), $self->{strDbPath}, undef, false, $hTablespaceMap, $hDatabaseMap,
storageDb(), $self->{strDbPath}, undef, false, false, $hTablespaceMap, $hDatabaseMap,
{'postgresql.auto.conf' => true, 'hosts' => true, 'pg_log/' => true, 'global/exclude' => true});
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'check exclusions');
@ -1023,7 +1023,7 @@ sub run
$oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strTempFileOid,
MANIFEST_SUBKEY_MASTER, false);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, $hTablespaceMap, $hDatabaseMap);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false, $hTablespaceMap, $hDatabaseMap);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'tablespace with version < 9.0');
@ -1041,7 +1041,7 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_84, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_84)});
$oManifest->build(storageDb(), $self->{strDbPath}, undef, false);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'undefined user/group');
@ -1248,7 +1248,7 @@ sub run
$lTime + 20000);
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_FUTURE, 'y');
$self->testResult(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, "[undef]",
$self->testResult(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, "[undef]",
'future timestamp warning', {strLogExpect =>
"WARN: some files have timestamps in the future - they will be copied to prevent possible race conditions"});
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'manifest future subkey=y');
@ -1278,11 +1278,11 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$self->testResult(sub {$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true)}, "[undef]",
$self->testResult(sub {$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false)}, "[undef]",
'last manifest future timestamp warning', {strLogExpect =>
"WARN: some files have timestamps in the future - they will be copied to prevent possible race conditions"});
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'last manifest future subkey=y, new manifest future subkey removed');
'last manifest future subkey=y, new manifest future subkey removed');
# File info in last manifest same as current
#---------------------------------------------------------------------------------------------------------------------------
@ -1298,27 +1298,28 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true);
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'reference set to prior backup label');
# Create a new file reference
# Create a new file reference and a zero-sized file reference
my $strTestNew = $strTest . 'new';
my $strZeroFile = 'zero-file';
storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strTestNew,
{strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), $strTestNew);
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_SIZE, length($strTestNew));
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_TIMESTAMP, $lTime);
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_SIZE, length($strTestNew));
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_TIMESTAMP, $lTime);
storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strZeroFile,
{strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), '');
# Change the size on a file
storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strTest,
{strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), $strTest . 'more');
# Set a reference, checksum, repo size, master and page checksum in the last manifest
my $strCheckSum = '1234567890';
my $lRepoSize = 10000;
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_SIZE, length($strTestNew));
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_TIMESTAMP, $lTime);
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_REFERENCE, BOGUS . BOGUS);
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
@ -1329,8 +1330,20 @@ sub run
MANIFEST_SUBKEY_MASTER, false);
$oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_CHECKSUM_PAGE, true);
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_SIZE, 0);
$oLastManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_REPO_SIZE, $lRepoSize);
$oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_MASTER, false);
$oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_CHECKSUM_PAGE, true);
# Update expected manifest
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_SIZE, length($strTestNew));
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_TIMESTAMP, $lTime);
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_REFERENCE, BOGUS . BOGUS);
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
@ -1339,6 +1352,21 @@ sub run
MANIFEST_SUBKEY_REPO_SIZE, $lRepoSize);
$oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_CHECKSUM_PAGE, true);
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_SIZE, 0);
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_TIMESTAMP, $lTime);
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_REFERENCE, BOGUS);
$oManifestExpected->numericSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_REPO_SIZE, $lRepoSize);
$oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_CHECKSUM_PAGE, true);
# Remove the reference for strTest since the size has changed
$oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest,
MANIFEST_SUBKEY_REFERENCE);
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest,
MANIFEST_SUBKEY_SIZE, length($strTest . 'more'));
# Default "master" is flipping because it's not something we read from disk
$oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, false);
@ -1348,35 +1376,88 @@ sub run
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true);
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'updates from last manifest');
# MANIFEST_SUBKEY_CHECKSUM_PAGE = false and MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR set/not set
# Timestamp in the lastManifest is different than built manifest (size and content the same)
#---------------------------------------------------------------------------------------------------------------------------
$oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
# pass delta=true - expected manifest will use the timestamp set for the file on disk ($lTime)
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_TIMESTAMP, $lTime - 10);
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_TIMESTAMP, $lTime - 10);
# Add a file not in the last manifest
storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strTest . '2',
{strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), $strTest);
# Update expected manifest
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest . '2',
MANIFEST_SUBKEY_SIZE, length($strTest));
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest . '2',
MANIFEST_SUBKEY_TIMESTAMP, $lTime);
$oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest . '2',
MANIFEST_SUBKEY_MASTER, true);
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, true);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'delta true, size same, timestamp different');
# With different timestamp in last manifest pass delta=false - the references to the prior backup will be removed for the
# non-zero file but the zero file will still have a reference
$oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_REFERENCE);
$oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_CHECKSUM);
$oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_REPO_SIZE);
$oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
MANIFEST_SUBKEY_CHECKSUM_PAGE);
# Default "master" is flipping because it's not something we read from disk
$oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, true);
$oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_MASTER);
$oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest . '2',
MANIFEST_SUBKEY_MASTER);
$oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_MASTER, false);
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'delta false, size same, timestamp different');
# MANIFEST_SUBKEY_CHECKSUM_PAGE = false and MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR set/not set from last manifest
#---------------------------------------------------------------------------------------------------------------------------
$oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_CHECKSUM_PAGE, false);
$oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
$oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_CHECKSUM_PAGE, false);
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true);
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'checksum-page false, checksum-page-error not set');
my @iyChecksumPageError = (1);
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
$oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR, \@iyChecksumPageError);
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew,
$oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile,
MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR, \@iyChecksumPageError);
$oManifest = new pgBackRest::Manifest(
$strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true);
$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false);
$self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "",
'checksum-page false, checksum-page-error set');
}
@ -1388,7 +1469,7 @@ sub run
iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
my $oManifestExpected = dclone($oManifestBase);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true);
$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false);
# Add a file after building manifest
my $lTimeTest = $lTime + 10;

View File

@ -64,6 +64,7 @@ sub run
foreach my $bRemote ($bS3 ? (true) : (false, true))
{
my $bRepoEncrypt = $bS3 ? true : false;
my $bDeltaBackup = !$bRemote || ($bRepoEncrypt && $bRemote) ? true : false;
# Increment the run, log, and decide whether this unit test should be run
if (!$self->begin("rmt ${bRemote}, s3 ${bS3}, enc ${bRepoEncrypt}")) {next}
@ -103,6 +104,7 @@ sub run
$oManifest{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_COMPRESS} = JSON::PP::false;
$oManifest{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_HARDLINK} = JSON::PP::false;
$oManifest{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_ONLINE} = JSON::PP::false;
$oManifest{&MANIFEST_SECTION_BACKUP_OPTION}{&MANIFEST_KEY_DELTA} = JSON::PP::false;
if ($bRepoEncrypt)
{
@ -524,10 +526,18 @@ sub run
$oHostDbMaster->manifestFileCreate(\%oManifest, MANIFEST_TARGET_PGDATA, 'zero_from_start', undef,
undef, $lTime, undef, true);
# Add files for testing backups when time changes but content doesn't, and when content changes but time and size don't
$oHostDbMaster->manifestFileCreate(
\%oManifest, MANIFEST_TARGET_PGDATA, 'changetime.txt', 'SIZE', '88087292ed82e26f3eb824d0bffc05ccf7a30f8d', $lTime,
undef, true);
$oHostDbMaster->manifestFileCreate(
\%oManifest, MANIFEST_TARGET_PGDATA, 'changecontent.txt', 'CONTENT', '238a131a3e8eb98d1fc5b27d882ca40b7618fd2a', $lTime,
undef, true);
$strFullBackup = $oHostBackup->backup(
$strType, 'resume',
{oExpectedManifest => \%oManifest, strTest => TEST_BACKUP_RESUME,
strOptionalParam => '--force --' . cfgOptionName(CFGOPT_CHECKSUM_PAGE)});
strOptionalParam => '--force --' . cfgOptionName(CFGOPT_CHECKSUM_PAGE) . ($bDeltaBackup ? ' --delta' : '')});
# Remove postmaster.pid so restore will succeed (the rest will be cleaned up by the delta)
storageDb->remove($oHostDbMaster->dbBasePath() . '/' . DB_FILE_POSTMASTERPID);
@ -956,13 +966,43 @@ sub run
# Also create tablespace 11 to be sure it does not conflict with path of tablespace 1
$oHostDbMaster->manifestTablespaceCreate(\%oManifest, 11);
# Change only the time on a valid file and update the timestamp in the expected manifest
utime($lTime - 100, $lTime - 100, $oHostDbMaster->dbBasePath() . '/changetime.txt')
or confess &log(ERROR, "unable to set time for file ".$oHostDbMaster->dbBasePath() . '/changetime.txt');
$oManifest{&MANIFEST_SECTION_TARGET_FILE}{'pg_data/changetime.txt'}{&MANIFEST_SUBKEY_TIMESTAMP} = $lTime - 100;
# Change the content of the changecontent file to be the same size but not the timestamp on the file
storageDb()->put($oHostDbMaster->dbBasePath() . '/changecontent.txt', 'CHGCONT');
utime($lTime, $lTime, $oHostDbMaster->dbBasePath() . '/changecontent.txt')
or confess &log(ERROR, "unable to set time for file ".$oHostDbMaster->dbBasePath() . '/changecontent.txt');
if ($bDeltaBackup)
{
# With --delta, the changetime file will not be recopied and the reference will remain to the last backup however,
# the changecontent file will be recopied since the checksum has changed so update the checksum and remove the reference
$oManifest{&MANIFEST_SECTION_TARGET_FILE}{'pg_data/changecontent.txt'}{&MANIFEST_SUBKEY_CHECKSUM} =
"a094d94583e209556d03c3c5da33131a065f1689";
delete($oManifest{&MANIFEST_SECTION_TARGET_FILE}{'pg_data/changecontent.txt'}{&MANIFEST_SUBKEY_REFERENCE});
}
else
{
# Without --delta, the changetime reference will be removed since the timestamp has changed but since the timestamp on
# the changecontent did not change even though the contents did, it will still reference the prior backup - this may be
# a rare occurrence and not good but it is one reason to use --delta
delete($oManifest{&MANIFEST_SECTION_TARGET_FILE}{'pg_data/changetime.txt'}{&MANIFEST_SUBKEY_REFERENCE});
$oManifest{&MANIFEST_SECTION_TARGET_FILE}{'pg_data/changetime.txt'}{&MANIFEST_SUBKEY_TIMESTAMP} = $lTime - 100;
}
$strBackup = $oHostBackup->backup(
$strType, 'resume and add tablespace 2',
{oExpectedManifest => \%oManifest, strTest => TEST_BACKUP_RESUME,
strOptionalParam => '--' . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1'});
strOptionalParam => '--' . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1' . ($bDeltaBackup ? ' --delta' : '')});
# Remove the size-changed test file to avoid expect log churn
$oHostDbMaster->manifestFileRemove(\%oManifest, MANIFEST_TARGET_PGDATA, 'changesize.txt');
if (!$bRemote)
{
# Remove the size-changed test file to avoid expect log churn
$oHostDbMaster->manifestFileRemove(\%oManifest, MANIFEST_TARGET_PGDATA, 'changesize.txt');
}
# Resume Diff Backup
#---------------------------------------------------------------------------------------------------------------------------
@ -974,13 +1014,15 @@ sub run
# Create resumable backup from last backup
$strResumePath = storageRepo()->pathGet('backup/' . $self->stanza() . "/${strBackup}");
# Remove the main manifest so the backup appears aborted
# Remove the main manifest from the last backup so the backup appears aborted
forceStorageRemove(storageRepo(), "${strResumePath}/" . FILE_MANIFEST);
# The aborted backup is of a different type so is not resumable and is removed. A differential is created.
$strBackup = $oHostBackup->backup(
$strType, 'cannot resume - new diff',
{oExpectedManifest => \%oManifest, strTest => TEST_BACKUP_NORESUME,
strOptionalParam => "$strLogReduced --" . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1'});
strOptionalParam => "$strLogReduced --" . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1' .
($bDeltaBackup ? ' --delta' : '')});
# Resume Diff Backup
#---------------------------------------------------------------------------------------------------------------------------
@ -992,10 +1034,13 @@ sub run
# Remove the main manifest so the backup appears aborted
forceStorageRemove(storageRepo(), "${strResumePath}/" . FILE_MANIFEST);
# The aborted backup is of the same type so it is resumable but passing --no-resume. Pass --delta same as before to avoid
# expect log churn and to test restore with a --delta manifest.
$strBackup = $oHostBackup->backup(
$strType, 'cannot resume - disabled / no repo link',
{oExpectedManifest => \%oManifest, strTest => TEST_BACKUP_NORESUME,
strOptionalParam => "--no-resume ${strLogReduced} --" . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1'});
strOptionalParam => "--no-resume ${strLogReduced} --" . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1' .
($bDeltaBackup ? ' --delta' : '')});
# Restore
#---------------------------------------------------------------------------------------------------------------------------
@ -1118,7 +1163,8 @@ sub run
$strBackup = $oHostBackup->backup(
$strType, 'updates since last full', {oExpectedManifest => \%oManifest,
strOptionalParam => "$strLogReduced --" . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1'});
strOptionalParam => "$strLogReduced --" . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1' .
($bDeltaBackup ? ' --delta' : '')});
# Incr Backup
#
@ -1166,7 +1212,8 @@ sub run
$oBackupExecute = $oHostBackup->backupBegin(
$strType, 'remove files during backup',
{oExpectedManifest => \%oManifest, strTest => TEST_MANIFEST_BUILD, fTestDelay => 1,
strOptionalParam => "$strLogReduced --" . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1'});
strOptionalParam => "$strLogReduced --" . cfgOptionName(CFGOPT_PROCESS_MAX) . '=1' .
($bDeltaBackup ? ' --delta' : '')});
$oHostDbMaster->manifestFileCreate(
\%oManifest, MANIFEST_TARGET_PGTBLSPC . '/2', '32768/tablespace2c.txt', 'TBLSPCBIGGER',

View File

@ -619,10 +619,12 @@ sub run
$oHostDbMaster->sqlSelectOne("select pg_start_backup('test backup that will be restarted', true)");
}
# Exercise --delta checksum option
$oExecuteBackup = $oHostBackup->backupBegin(
CFGOPTVAL_BACKUP_TYPE_INCR, 'update during backup',
{strTest => TEST_MANIFEST_BUILD, fTestDelay => $fTestDelay,
strOptionalParam => '--' . cfgOptionName(CFGOPT_STOP_AUTO) . ' --' . cfgOptionName(CFGOPT_BUFFER_SIZE) . '=32768'});
strOptionalParam => '--' . cfgOptionName(CFGOPT_STOP_AUTO) . ' --' . cfgOptionName(CFGOPT_BUFFER_SIZE) . '=32768' .
' --delta'});
# Drop a table
$oHostDbMaster->sqlExecute('drop table test_remove');

View File

@ -127,7 +127,6 @@ testRun(void)
"\n"
" --db-include restore only specified databases\n"
" [current=db1, db2]\n"
" --delta restore using delta [default=n]\n"
" --force force a restore [default=n]\n"
" --link-all restore all symlinks [default=n]\n"
" --link-map modify the destination of a symlink\n"
@ -162,6 +161,7 @@ testRun(void)
" files [default=/etc/pgbackrest/conf.d]\n"
" --config-path base path of pgBackRest configuration files\n"
" [default=/etc/pgbackrest]\n"
" --delta restore or backup using checksums [default=n]\n"
" --lock-path path where lock files are stored\n"
" [default=/tmp/pgbackrest]\n"
" --neutral-umask use a neutral umask [default=y]\n"