1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/test/lib/pgBackRestTest/Module/Backup/BackupFileUnitPerlTest.pm
David Steele d038b9a029 Support configurable WAL segment size.
PostgreSQL 11 introduces configurable WAL segment sizes, from 1MB to 1GB.

There are two areas that needed to be updated to support this: building the archive-get queue and checking that WAL has been archived after a backup.  Both operations require the WAL segment size to properly build a list.

Checking the archive after a backup is still implemented in Perl and has an active database connection, so just get the WAL segment size from the database.

The archive-get command does not have a connection to the database, so get the WAL segment size from pg_control instead.  This requires a deeper inspection of pg_control than has been done in the past, so it seemed best to copy the relevant data structures from each version of PostgreSQL and build a generic interface layer to address them.  While this approach is a bit verbose, it has the advantage of being relatively simple, and can easily be updated for new versions of PostgreSQL.

Since the integration tests generate pg_control files for testing, teach Perl how to generate files with the correct offsets for both 32-bit and 64-bit architectures.
2018-09-25 10:24:42 +01:00

692 lines
33 KiB
Perl

####################################################################################################################################
# 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 =
$self->archBits() == 32 ? '8107e546c59c72a8c1818fc3610d7cc1e5623660' : '4c77c900f7af0d9ab13fa9982051a42e0b637f6c';
# 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;