1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/test/lib/BackRestTest/ExpireCommonTest.pm

434 lines
16 KiB
Perl

#!/usr/bin/perl
####################################################################################################################################
# ExpireCommonTest.pl - Common code for expire tests
####################################################################################################################################
package BackRestTest::ExpireCommonTest;
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use File::Basename qw(dirname);
use lib dirname($0) . '/../lib';
use BackRest::BackupCommon;
use BackRest::BackupInfo;
use BackRest::Common::Ini;
use BackRest::Common::Log;
use BackRest::Config;
use BackRest::File;
use BackRest::Manifest;
use BackRestTest::CommonTest;
####################################################################################################################################
# Operation constants
####################################################################################################################################
use constant OP_EXPIRE_COMMON_TEST => 'ExpireCommonTest';
use constant OP_EXPIRE_COMMON_TEST_ARCHIVE_CREATE => OP_EXPIRE_COMMON_TEST . "->archiveCreate";
use constant OP_EXPIRE_COMMON_TEST_ARCHIVE_NEXT => OP_EXPIRE_COMMON_TEST . "->archiveNext";
use constant OP_EXPIRE_COMMON_TEST_BACKUP_CREATE => OP_EXPIRE_COMMON_TEST . "->backupCreate";
use constant OP_EXPIRE_COMMON_TEST_NEW => OP_EXPIRE_COMMON_TEST . "->new";
use constant OP_EXPIRE_COMMON_TEST_PROCESS => OP_EXPIRE_COMMON_TEST . "->process";
use constant OP_EXPIRE_COMMON_TEST_STANZA_CREATE => OP_EXPIRE_COMMON_TEST . "->stanzaCreate";
####################################################################################################################################
# new
####################################################################################################################################
sub new
{
my $class = shift; # Class name
# Create the class hash
my $self = {};
bless $self, $class;
# Assign function parameters, defaults, and log debug info
(
my $strOperation,
$self->{oFile}
) =
logDebugParam
(
OP_EXPIRE_COMMON_TEST_NEW, \@_,
{name => 'oFile'}
);
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self}
);
}
####################################################################################################################################
# stanzaCreate
####################################################################################################################################
sub stanzaCreate
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strStanza,
$strDbVersion
) =
logDebugParam
(
OP_EXPIRE_COMMON_TEST_STANZA_CREATE, \@_,
{name => 'strStanza'},
{name => 'strDbVersion'}
);
# Assign variables
my $oStanza = {};
$$oStanza{strDbVersion} = $strDbVersion;
$$oStanza{iDbId} = 1;
# Create the system id
my $strDbVersionTemp = $strDbVersion;
$strDbVersionTemp =~ s/\.//;
$$oStanza{ullDbSysId} = $strDbVersionTemp . '000000000000000' . $$oStanza{iDbId};
$$oStanza{iCatalogVersion} = '20' . $strDbVersionTemp . '0101';
$$oStanza{iControlVersion} = $strDbVersionTemp . '1';
# Create the stanza backup path
my $strBackupClusterPath = BackRestTestCommon_RepoPathGet() . '/backup';
BackRestTestCommon_PathCreate($strBackupClusterPath, undef, true);
$strBackupClusterPath .= "/${strStanza}";
BackRestTestCommon_PathCreate($strBackupClusterPath, undef, true);
$$oStanza{strBackupClusterPath} = $strBackupClusterPath;
# Create the backup info object
my $oBackupInfo = new BackRest::BackupInfo($$oStanza{strBackupClusterPath});
$oBackupInfo->check($$oStanza{strDbVersion}, $$oStanza{iControlVersion}, $$oStanza{iCatalogVersion}, $$oStanza{ullDbSysId});
$oBackupInfo->save();
# Create the stanza archive path
my $strArchiveClusterPath = BackRestTestCommon_RepoPathGet() . '/archive';
BackRestTestCommon_PathCreate($strArchiveClusterPath, undef, true);
$strArchiveClusterPath .= "/${strStanza}";
BackRestTestCommon_PathCreate($strArchiveClusterPath, undef, true);
# Create the archive info object
$$oStanza{oArchiveInfo} = new BackRest::ArchiveInfo($strArchiveClusterPath);
$$oStanza{oArchiveInfo}->check($$oStanza{strDbVersion}, $$oStanza{ullDbSysId});
# Create the stanza archive version path
$strArchiveClusterPath .= '/' . $$oStanza{strDbVersion} . '-' . $$oStanza{iDbId};
BackRestTestCommon_PathCreate($strArchiveClusterPath, undef, true);
$$oStanza{strArchiveClusterPath} = $strArchiveClusterPath;
$self->{oStanzaHash}{$strStanza} = $oStanza;
# Return from function and log return values if any
return logDebugReturn
(
$strOperation
);
}
####################################################################################################################################
# backupCreate
####################################################################################################################################
sub backupCreate
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strStanza,
$strType,
$lTimestamp,
$iArchiveBackupTotal,
$iArchiveBetweenTotal
) =
logDebugParam
(
OP_EXPIRE_COMMON_TEST_BACKUP_CREATE, \@_,
{name => 'strStanza'},
{name => 'strType'},
{name => 'lTimestamp'},
{name => 'iArchiveBackupTotal', default => 3},
{name => 'iArchiveBetweenTotal', default => 3}
);
my $oStanza = $self->{oStanzaHash}{$strStanza};
my ($strArchiveStart, $strArchiveStop) = $self->archiveCreate($strStanza, $iArchiveBackupTotal);
# Create the manifest
my $oLastManifest = $strType ne BACKUP_TYPE_FULL ? $$oStanza{oManifest} : undef;
my $strBackupLabel =
backupLabelFormat($strType,
defined($oLastManifest) ? $oLastManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL) : undef,
$lTimestamp);
my $strBackupClusterSetPath .= "$$oStanza{strBackupClusterPath}/${strBackupLabel}";
BackRestTestCommon_PathCreate($strBackupClusterSetPath);
my $oManifest = new BackRest::Manifest("$strBackupClusterSetPath/" . FILE_MANIFEST, false);
# Store information about the backup into the backup section
$oManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL, undef, $strBackupLabel);
$oManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_CHECK, undef, true);
$oManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_COPY, undef, false);
$oManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_START, undef, $strArchiveStart);
$oManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_STOP, undef, $strArchiveStop);
$oManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_COMPRESS, undef, true);
$oManifest->numericSet(INI_SECTION_BACKREST, INI_KEY_FORMAT, undef, BACKREST_FORMAT);
$oManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_HARDLINK, undef, false);
$oManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_START_STOP, undef, true);
$oManifest->numericSet(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_START, undef, $lTimestamp);
$oManifest->numericSet(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_STOP, undef, $lTimestamp);
$oManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TYPE, undef, $strType);
$oManifest->set(INI_SECTION_BACKREST, INI_KEY_VERSION, undef, BACKREST_VERSION);
if ($strType ne BACKUP_TYPE_FULL)
{
if (!defined($oLastManifest))
{
confess &log(ERROR, "oLastManifest must be defined when strType = ${strType}");
}
push(my @stryReference, $oLastManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL));
$oManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_PRIOR, undef, $stryReference[0]);
}
$oManifest->save();
$$oStanza{oManifest} = $oManifest;
# Add the backup to info
my $oBackupInfo = new BackRest::BackupInfo($$oStanza{strBackupClusterPath});
$oBackupInfo->check($$oStanza{strDbVersion}, $$oStanza{iControlVersion}, $$oStanza{iCatalogVersion}, $$oStanza{ullDbSysId});
$oBackupInfo->add($self->{oFile}, $oManifest);
# Create the backup description string
if (defined($$oStanza{strBackupDescription}))
{
$$oStanza{strBackupDescription} .= "\n";
}
$$oStanza{strBackupDescription} .=
"* ${strType} backup: label = ${strBackupLabel}" .
(defined($oLastManifest) ? ', prior = ' . $oLastManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL) : '') .
", start = ${strArchiveStart}, stop = ${strArchiveStop}";
$self->archiveCreate($strStanza, $iArchiveBetweenTotal);
# Return from function and log return values if any
return logDebugReturn
(
$strOperation
);
}
####################################################################################################################################
# archiveNext
####################################################################################################################################
sub archiveNext
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strArchive,
$bSkipFF
) =
logDebugParam
(
OP_EXPIRE_COMMON_TEST_ARCHIVE_NEXT, \@_,
{name => 'strArchive', trace => true},
{name => 'bSkipFF', trace => true}
);
# Break archive log into components
my $lTimeline = hex(substr($strArchive, 0, 8));
my $lMajor = hex(substr($strArchive, 8, 8));
my $lMinor = hex(substr($strArchive, 16, 8));
# Increment the minor component (and major when needed)
$lMinor += 1;
if ($bSkipFF && $lMinor == 255 || !$bSkipFF && $lMinor == 256)
{
$lMajor += 1;
$lMinor = 0;
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strArchiveNext', value => uc(sprintf("%08x%08x%08x", $lTimeline, $lMajor, $lMinor)), trace => true}
);
}
####################################################################################################################################
# archiveCreate
####################################################################################################################################
sub archiveCreate
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strStanza,
$iArchiveTotal
) =
logDebugParam
(
OP_EXPIRE_COMMON_TEST_ARCHIVE_CREATE, \@_,
{name => 'strStanza'},
{name => 'iArchiveTotal'}
);
my $oStanza = $self->{oStanzaHash}{$strStanza};
my $iArchiveIdx = 0;
my $bSkipFF = $$oStanza{strDbVersion} <= 9.2;
my $strArchive = defined($$oStanza{strArchiveLast}) ? $self->archiveNext($$oStanza{strArchiveLast}, $bSkipFF) :
'000000010000000000000000';
push(my @stryArchive, $strArchive);
do
{
my $strPath = "$$oStanza{strArchiveClusterPath}/" . substr($strArchive, 0, 16);
BackRestTestCommon_PathCreate($strPath, undef, true);
my $strFile = "${strPath}/${strArchive}-0000000000000000000000000000000000000000" . ($iArchiveIdx % 2 == 0 ? '.gz' : '');
BackRestTestCommon_FileCreate($strFile, 'ARCHIVE');
$iArchiveIdx++;
if ($iArchiveIdx < $iArchiveTotal)
{
$strArchive = $self->archiveNext($strArchive, $bSkipFF);
}
}
while ($iArchiveIdx < $iArchiveTotal);
push(@stryArchive, $strArchive);
$$oStanza{strArchiveLast} = $strArchive;
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'stryArchive', value => \@stryArchive}
);
}
####################################################################################################################################
# process
####################################################################################################################################
sub process
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$strStanza,
$iExpireFull,
$iExpireDiff,
$strExpireArchiveType,
$iExpireArchive,
$strDescription
) =
logDebugParam
(
OP_EXPIRE_COMMON_TEST_PROCESS, \@_,
{name => 'strStanza'},
{name => 'iExpireFull'},
{name => 'iExpireDiff'},
{name => 'strExpireArchiveType'},
{name => 'iExpireArchive'},
{name => 'strDescription'}
);
my $oStanza = $self->{oStanzaHash}{$strStanza};
BackRestTestCommon_TestLogAppendFile(BackRestTestCommon_RepoPathGet() .
"/backup/${strStanza}/backup.info", false, $$oStanza{strBackupDescription});
undef($$oStanza{strBackupDescription});
my $strCommand = BackRestTestCommon_CommandMainGet() .
' "--' . OPTION_CONFIG . '=' . BackRestTestCommon_RepoPathGet() . '/pg_backrest.conf"' .
' --' . OPTION_STANZA . '=' . $strStanza .
' --' . OPTION_LOG_LEVEL_CONSOLE . '=' . lc(INFO);
if (defined($iExpireFull))
{
$strCommand .= ' --retention-full=' . $iExpireFull;
}
if (defined($iExpireDiff))
{
$strCommand .= ' --retention-diff=' . $iExpireDiff;
}
if (defined($strExpireArchiveType))
{
$strCommand .= ' --retention-archive-type=' . $strExpireArchiveType .
' --retention-archive=' . $iExpireArchive;
}
$strCommand .= ' expire';
BackRestTestCommon_Execute($strCommand, undef, undef, undef, undef, $strDescription);
# # Check that the correct backups were expired
# my @stryBackupActual = $oFile->list(PATH_BACKUP_CLUSTER);
#
# if (join(",", @stryBackupActual) ne join(",", @{$stryBackupExpectedRef}))
# {
# confess "expected backup list:\n " . join("\n ", @{$stryBackupExpectedRef}) .
# "\n\nbut actual was:\n " . join("\n ", @stryBackupActual) . "\n";
# }
#
# # Check that the correct archive logs were expired
# my @stryArchiveActual = $oFile->list(PATH_BACKUP_ARCHIVE, BackRestTestCommon_DbVersion() . '-1/0000000100000000');
#
# if (join(",", @stryArchiveActual) ne join(",", @{$stryArchiveExpectedRef}))
# {
# confess "expected archive list:\n " . join("\n ", @{$stryArchiveExpectedRef}) .
# "\n\nbut actual was:\n " . join("\n ", @stryArchiveActual) . "\n";
# }
BackRestTestCommon_TestLogAppendFile(BackRestTestCommon_RepoPathGet() .
"/backup/${strStanza}/backup.info", false);
# Return from function and log return values if any
return logDebugReturn
(
$strOperation
);
}
1;