mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-14 10:13:05 +02:00
de816a0f57
Integration expect log testing was originally used as a rough-and-ready way to make sure that certain code paths were being executed before the unit tests existed. Now that we have 100% unit test coverage (with expect log testing) the value of the integration expect tests seems minimal at best.
But they do cause numerous issues:
- Maintenance of the expect code and replacements that are required to keep logs reproducible.
- Even a trivial change can cause massive churn in the expect logs, e.g. d9088b2
. These changes should be minutely audited but since the expect logs have little value now it is seldom worth the effort.
- The OS version used to do expect testing (RHEL7) can only be used to test one version of PostgreSQL. This makes it hard to balance the PostgreSQL version testing between OS versions.
- When a commit affects expect logs it is not clear (especially for new developers) how to regenerate them and our contributing guide is silent on the issue.
The goal is to migrate the integration tests to C and expect testing is not part of that plan. It seems best to get rid of them now.
718 lines
27 KiB
Perl
718 lines
27 KiB
Perl
####################################################################################################################################
|
|
# HostDbTest.pm - Database host
|
|
####################################################################################################################################
|
|
package pgBackRestTest::Env::Host::HostDbSyntheticTest;
|
|
use parent 'pgBackRestTest::Env::Host::HostDbCommonTest';
|
|
|
|
####################################################################################################################################
|
|
# Perl includes
|
|
####################################################################################################################################
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
|
|
use Exporter qw(import);
|
|
our @EXPORT = qw();
|
|
use Fcntl ':mode';
|
|
use File::Basename qw(basename dirname);
|
|
use File::stat;
|
|
|
|
use pgBackRestDoc::Common::Exception;
|
|
use pgBackRestDoc::Common::Log;
|
|
use pgBackRestDoc::Common::String;
|
|
use pgBackRestDoc::ProjectInfo;
|
|
|
|
use pgBackRestTest::Common::ContainerTest;
|
|
use pgBackRestTest::Common::DbVersion;
|
|
use pgBackRestTest::Common::FileTest;
|
|
use pgBackRestTest::Common::RunTest;
|
|
use pgBackRestTest::Common::StorageRepo;
|
|
use pgBackRestTest::Common::Wait;
|
|
use pgBackRestTest::Env::Host::HostBackupTest;
|
|
use pgBackRestTest::Env::Host::HostBaseTest;
|
|
use pgBackRestTest::Env::Host::HostDbCommonTest;
|
|
use pgBackRestTest::Env::Manifest;
|
|
|
|
####################################################################################################################################
|
|
# new
|
|
####################################################################################################################################
|
|
sub new
|
|
{
|
|
my $class = shift; # Class name
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$oParam,
|
|
) =
|
|
logDebugParam
|
|
(
|
|
__PACKAGE__ . '->new', \@_,
|
|
{name => 'oParam', required => false, trace => true},
|
|
);
|
|
|
|
my $self = $class->SUPER::new(
|
|
{
|
|
strImage => containerRepo() . ':' . testRunGet()->vm() . "-test",
|
|
bTls => $oParam->{bTls},
|
|
strBackupDestination => $$oParam{strBackupDestination},
|
|
bSynthetic => true,
|
|
bStandby => $$oParam{bStandby},
|
|
bRepoLocal => $oParam->{bRepoLocal},
|
|
bRepoEncrypt => $oParam->{bRepoEncrypt},
|
|
});
|
|
bless $self, $class;
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'self', value => $self, trace => true}
|
|
);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# dbFileCreate
|
|
#
|
|
# Create a file specifying content, mode, and time.
|
|
####################################################################################################################################
|
|
sub dbFileCreate
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strFile = shift;
|
|
my $strContent = shift;
|
|
my $lTime = shift;
|
|
my $strMode = shift;
|
|
|
|
# Check that strTarget is a valid
|
|
my $strPath = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH};
|
|
|
|
if (!defined($strPath))
|
|
{
|
|
confess &log(ERROR, "${strTarget} not a valid target: \n" . Dumper(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}));
|
|
}
|
|
|
|
# Get tablespace path if this is a tablespace
|
|
my $strPgPath;
|
|
|
|
if (index($strTarget, DB_PATH_PGTBLSPC . '/') == 0)
|
|
{
|
|
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
|
|
|
|
$strPgPath = 'PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
|
|
}
|
|
|
|
# Create actual file location
|
|
my $strPathFile = $strPath .
|
|
(defined($strPgPath) ? "/${strPgPath}" : '') . "/${strFile}";
|
|
|
|
if (index($strPathFile, '/') != 0)
|
|
{
|
|
$strPathFile = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} . '/' .
|
|
(defined(dirname($strPathFile)) ? dirname($strPathFile) : '') . "/${strPathFile}";
|
|
}
|
|
|
|
# Create the file
|
|
testFileCreate($strPathFile, $strContent, $lTime, $strMode);
|
|
|
|
# Return path to created file
|
|
return $strPathFile;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# dbFileRemove
|
|
####################################################################################################################################
|
|
sub dbFileRemove
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strFile = shift;
|
|
my $bIgnoreMissing = shift;
|
|
|
|
# Get actual path location
|
|
my $strDbFile = $self->manifestDbPathGet($oManifestRef, $strTarget, $strFile);
|
|
|
|
# Remove the file
|
|
if (!(defined($bIgnoreMissing) && $bIgnoreMissing && !(-e $strDbFile)))
|
|
{
|
|
testFileRemove($strDbFile);
|
|
}
|
|
|
|
return $strDbFile;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# dbLinkCreate
|
|
#
|
|
# Create a file specifying content, mode, and time.
|
|
####################################################################################################################################
|
|
sub dbLinkCreate
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strFile = shift;
|
|
my $strDestination = shift;
|
|
|
|
# Create actual file location
|
|
my $strDbFile = $self->manifestDbPathGet($oManifestRef, $strTarget, $strFile);
|
|
|
|
# Create the file
|
|
testLinkCreate($strDbFile, $strDestination);
|
|
|
|
# Return path to created file
|
|
return $strDbFile;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestDbPathGet
|
|
#
|
|
# Get the db path based on the target and file passed.
|
|
####################################################################################################################################
|
|
sub manifestDbPathGet
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strFile = shift;
|
|
|
|
# Determine the manifest key
|
|
my $strDbPath = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH};
|
|
|
|
# If target is a tablespace
|
|
if (defined(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}))
|
|
{
|
|
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
|
|
|
|
$strDbPath .= '/PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
|
|
}
|
|
|
|
$strDbPath .= defined($strFile) ? "/${strFile}" : '';
|
|
|
|
return $strDbPath;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestFileCreate
|
|
#
|
|
# Create a file specifying content, mode, and time and add it to the manifest.
|
|
####################################################################################################################################
|
|
sub manifestFileCreate
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strFile = shift;
|
|
my $strContent = shift;
|
|
my $strChecksum = shift;
|
|
my $lTime = shift;
|
|
my $strMode = shift;
|
|
my $bPrimary = shift;
|
|
my $strChecksumPageError = shift;
|
|
|
|
# Determine the manifest key
|
|
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strTarget, $strFile);
|
|
|
|
# Create the file
|
|
my $strPathFile = $self->dbFileCreate($oManifestRef, $strTarget, $strFile, $strContent, $lTime, $strMode);
|
|
|
|
# Stat the file
|
|
my $oStat = lstat($strPathFile);
|
|
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_MODE} =
|
|
sprintf('%04o', S_IMODE($oStat->mode));
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_TIMESTAMP} = $oStat->mtime;
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_SIZE} = $oStat->size;
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_REFERENCE});
|
|
|
|
my $bChecksumPage = defined($strChecksumPageError) ? false : (isChecksumPage($strManifestKey) ? true : undef);
|
|
|
|
if (defined($bChecksumPage))
|
|
{
|
|
$oManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_CHECKSUM_PAGE} =
|
|
$bChecksumPage ? JSON::PP::true : JSON::PP::false;
|
|
|
|
if (!$bChecksumPage && $strChecksumPageError ne '0')
|
|
{
|
|
my @iyChecksumPageError = eval($strChecksumPageError);
|
|
|
|
$oManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR} =
|
|
\@iyChecksumPageError;
|
|
}
|
|
else
|
|
{
|
|
delete($oManifestRef->{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR});
|
|
}
|
|
}
|
|
|
|
if (defined($strChecksum))
|
|
{
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{checksum} = $strChecksum;
|
|
}
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestFileRemove
|
|
#
|
|
# Remove a file from disk and (optionally) the manifest.
|
|
####################################################################################################################################
|
|
sub manifestFileRemove
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strFile = shift;
|
|
|
|
# Determine the manifest key
|
|
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strTarget, $strFile);
|
|
|
|
# Remove the file
|
|
$self->dbFileRemove($oManifestRef, $strTarget, $strFile, true);
|
|
|
|
# Remove from manifest
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey});
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestKeyGet
|
|
#
|
|
# Get the manifest key based on the target and file/path/link passed.
|
|
####################################################################################################################################
|
|
sub manifestKeyGet
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strFile = shift;
|
|
|
|
# Determine the manifest key
|
|
my $strManifestKey = $strTarget;
|
|
|
|
# If target is a tablespace
|
|
if (defined(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}))
|
|
{
|
|
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
|
|
|
|
$strManifestKey .= '/PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
|
|
}
|
|
|
|
$strManifestKey .= (defined($strFile) ? "/$strFile" : '');
|
|
|
|
return $strManifestKey;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestLinkCreate
|
|
#
|
|
# Create a link and add it to the manifest.
|
|
####################################################################################################################################
|
|
sub manifestLinkCreate
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strPath = shift;
|
|
my $strFile = shift;
|
|
my $strDestination = shift;
|
|
my $bPrimary = shift;
|
|
|
|
# Determine the manifest key
|
|
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strPath, $strFile);
|
|
|
|
# Load target
|
|
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_PATH} = $strDestination;
|
|
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_TYPE} = MANIFEST_VALUE_LINK;
|
|
|
|
# Create the link
|
|
my $strDbFile = $self->dbLinkCreate($oManifestRef, $strPath, $strFile, $strDestination);
|
|
|
|
# Stat the link
|
|
my $oStat = lstat($strDbFile);
|
|
|
|
# Check for errors in stat
|
|
if (!defined($oStat))
|
|
{
|
|
confess 'unable to stat ${strDbFile}';
|
|
}
|
|
|
|
# Load file into manifest
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strManifestKey}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strManifestKey}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strManifestKey}{&MANIFEST_SUBKEY_DESTINATION} = $strDestination;
|
|
|
|
# Stat what the link is pointing to
|
|
my $strDestinationFile = $strDestination;
|
|
|
|
if (index($strDestinationFile, '/') != 0)
|
|
{
|
|
$strDestinationFile = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{&MANIFEST_TARGET_PGDATA}{&MANIFEST_SUBKEY_PATH} . '/' .
|
|
(defined(dirname($strPath)) ? dirname($strPath) : '') . "/${strDestination}";
|
|
}
|
|
|
|
$oStat = lstat($strDestinationFile);
|
|
|
|
my $strSection = MANIFEST_SECTION_TARGET_PATH;
|
|
|
|
if (S_ISREG($oStat->mode))
|
|
{
|
|
$strSection = MANIFEST_SECTION_TARGET_FILE;
|
|
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_SIZE} = $oStat->size;
|
|
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_TIMESTAMP} = $oStat->mtime;
|
|
(${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_CHECKSUM}) = storageTest()->hashSize($strDestinationFile);
|
|
|
|
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_FILE} =
|
|
basename(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_PATH});
|
|
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_PATH} =
|
|
dirname(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey}{&MANIFEST_SUBKEY_PATH});
|
|
}
|
|
# Allow a link to a link to be created to test that backrest errors out correctly
|
|
elsif (S_ISLNK($oStat->mode))
|
|
{
|
|
$strSection = MANIFEST_SECTION_TARGET_LINK;
|
|
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_DESTINATION} = $strDestination;
|
|
}
|
|
elsif (!S_ISDIR($oStat->mode))
|
|
{
|
|
confess &log(ASSERT, "unrecognized file type for file $strDestinationFile");
|
|
}
|
|
|
|
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
|
|
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
|
|
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_MODE} = sprintf('%04o', S_IMODE($oStat->mode));
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestLinkMap
|
|
#
|
|
# Remap links to new directories/files
|
|
####################################################################################################################################
|
|
sub manifestLinkMap
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strDestination = shift;
|
|
|
|
if ($$oManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TYPE} ne MANIFEST_VALUE_LINK)
|
|
{
|
|
confess "cannot map target ${strTarget} because it is not a link";
|
|
}
|
|
|
|
if (defined($$oManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}))
|
|
{
|
|
confess "tablespace ${strTarget} cannot be remapped with this function";
|
|
}
|
|
|
|
if (defined($strDestination))
|
|
{
|
|
confess "GENERAL LINK REMAP NOT IMPLEMENTED";
|
|
}
|
|
else
|
|
{
|
|
delete($$oManifestRef{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget});
|
|
delete($$oManifestRef{&MANIFEST_SECTION_TARGET_LINK}{$strTarget});
|
|
}
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestLinkRemove
|
|
#
|
|
# Create a link and add it to the manifest.
|
|
####################################################################################################################################
|
|
sub manifestLinkRemove
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strPath = shift;
|
|
my $strFile = shift;
|
|
|
|
# Delete the link
|
|
my $strDbFile = $self->dbFileRemove($oManifestRef, $strPath, $strFile);
|
|
|
|
# Determine the manifest key
|
|
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strPath, $strFile);
|
|
|
|
# Delete from manifest
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strManifestKey});
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strManifestKey});
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey});
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strManifestKey});
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestPathCreate
|
|
#
|
|
# Create a path specifying mode and add it to the manifest.
|
|
####################################################################################################################################
|
|
sub manifestPathCreate
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strPath = shift;
|
|
my $strSubPath = shift;
|
|
my $strMode = shift;
|
|
|
|
# Determine the manifest key
|
|
my $strManifestKey = $self->manifestKeyGet($oManifestRef, $strPath, $strSubPath);
|
|
|
|
# Create the db path
|
|
my $strDbPath = $self->dbPathCreate($oManifestRef, $strPath, $strSubPath, defined($strMode) ? $strMode : '0700');
|
|
|
|
# Stat the file
|
|
my $oStat = lstat($strDbPath);
|
|
|
|
# Check for errors in stat
|
|
if (!defined($oStat))
|
|
{
|
|
confess 'unable to stat ${strSubPath}';
|
|
}
|
|
|
|
# Load file into manifest
|
|
my $strSection = MANIFEST_SECTION_TARGET_PATH;
|
|
|
|
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
|
|
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
|
|
${$oManifestRef}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_MODE} = sprintf('%04o', S_IMODE($oStat->mode));
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestReference
|
|
#
|
|
# Update all files that do not have a reference with the supplied reference.
|
|
####################################################################################################################################
|
|
sub manifestReference
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strReference = shift;
|
|
my $bClear = shift;
|
|
|
|
# Set prior backup
|
|
if (defined($strReference))
|
|
{
|
|
${$oManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR} = $strReference;
|
|
}
|
|
else
|
|
{
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_BACKUP}{&MANIFEST_KEY_PRIOR});
|
|
}
|
|
|
|
# Find all file sections
|
|
foreach my $strSectionFile (sort(keys(%$oManifestRef)))
|
|
{
|
|
# Skip non-file sections
|
|
if ($strSectionFile !~ /\:file$/)
|
|
{
|
|
next;
|
|
}
|
|
|
|
foreach my $strFile (sort(keys(%{${$oManifestRef}{$strSectionFile}})))
|
|
{
|
|
if (!defined($strReference))
|
|
{
|
|
delete(${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE});
|
|
}
|
|
elsif (defined($bClear) && $bClear)
|
|
{
|
|
if (defined(${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE}) &&
|
|
${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE} ne $strReference)
|
|
{
|
|
delete(${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE});
|
|
}
|
|
}
|
|
elsif (!defined(${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE}))
|
|
{
|
|
${$oManifestRef}{$strSectionFile}{$strFile}{&MANIFEST_SUBKEY_REFERENCE} = $strReference;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestTablespaceCreate
|
|
#
|
|
# Create a tablespace specifying mode and add it to the manifest.
|
|
####################################################################################################################################
|
|
sub manifestTablespaceCreate
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $iOid = shift;
|
|
my $strMode = shift;
|
|
|
|
# Load linked path into manifest
|
|
my $strLinkPath = $self->tablespacePath($iOid);
|
|
my $strTarget = MANIFEST_TARGET_PGTBLSPC . "/${iOid}";
|
|
my $oStat = lstat($strLinkPath);
|
|
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strTarget}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strTarget}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strTarget}{&MANIFEST_SUBKEY_MODE} =
|
|
sprintf('%04o', S_IMODE($oStat->mode));
|
|
|
|
# Create the tablespace path if it does not exist
|
|
my $strTablespacePath = $strLinkPath;
|
|
my $strPathTarget = $strTarget;
|
|
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
|
|
my $strTablespaceId = 'PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
|
|
|
|
$strTablespacePath .= "/${strTablespaceId}";
|
|
$strPathTarget .= "/${strTablespaceId}";
|
|
|
|
if (!-e $strTablespacePath)
|
|
{
|
|
storageTest()->pathCreate($strTablespacePath, {strMode => defined($strMode) ? $strMode : '0700'});
|
|
}
|
|
|
|
# Load tablespace path into manifest
|
|
$oStat = lstat($strTablespacePath);
|
|
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{&MANIFEST_TARGET_PGTBLSPC} =
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{&MANIFEST_TARGET_PGDATA};
|
|
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strPathTarget}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strPathTarget}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strPathTarget}{&MANIFEST_SUBKEY_MODE} =
|
|
sprintf('%04o', S_IMODE($oStat->mode));
|
|
|
|
# Create the link in DB_PATH_PGTBLSPC
|
|
my $strLink = $self->dbBasePath() . '/' . DB_PATH_PGTBLSPC . "/${iOid}";
|
|
|
|
symlink($strLinkPath, $strLink)
|
|
or confess "unable to link ${strLink} to ${strLinkPath}";
|
|
|
|
# Load link into the manifest
|
|
$oStat = lstat($strLink);
|
|
my $strLinkTarget = MANIFEST_TARGET_PGDATA . "/${strTarget}";
|
|
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strLinkTarget}{&MANIFEST_SUBKEY_GROUP} = getgrgid($oStat->gid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strLinkTarget}{&MANIFEST_SUBKEY_USER} = getpwuid($oStat->uid);
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{$strLinkTarget}{&MANIFEST_SUBKEY_DESTINATION} = $strLinkPath;
|
|
|
|
# Load tablespace target into the manifest
|
|
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH} = $strLinkPath;
|
|
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TYPE} = MANIFEST_VALUE_LINK;
|
|
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID} = $iOid;
|
|
${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_NAME} = "ts${iOid}";
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# manifestTablespaceDrop
|
|
#
|
|
# Drop a tablespace add remove it from the manifest.
|
|
####################################################################################################################################
|
|
sub manifestTablespaceDrop
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $iOid = shift;
|
|
my $iIndex = shift;
|
|
|
|
# Remove tablespace path/file/link from manifest
|
|
my $strTarget = DB_PATH_PGTBLSPC . "/${iOid}";
|
|
|
|
# Remove manifest path, link, target
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget});
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_LINK}{&MANIFEST_TARGET_PGDATA . "/${strTarget}"});
|
|
delete(${$oManifestRef}{&MANIFEST_SECTION_TARGET_PATH}{$strTarget});
|
|
|
|
# Remove nested manifest files and paths
|
|
foreach my $strSection (&MANIFEST_SECTION_TARGET_PATH, &MANIFEST_SECTION_TARGET_FILE)
|
|
{
|
|
foreach my $strFile (keys(%{${$oManifestRef}{$strSection}}))
|
|
{
|
|
if (index($strFile, "${strTarget}/") == 0)
|
|
{
|
|
delete($$oManifestRef{$strSection}{$strFile});
|
|
}
|
|
}
|
|
}
|
|
|
|
# Drop the link in DB_PATH_PGTBLSPC
|
|
testFileRemove($self->dbBasePath($iIndex) . "/${strTarget}");
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# dbPathCreate
|
|
#
|
|
# Create a path specifying mode.
|
|
####################################################################################################################################
|
|
sub dbPathCreate
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strSubPath = shift;
|
|
my $strMode = shift;
|
|
|
|
# Create final file location
|
|
my $strFinalPath = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_PATH};
|
|
|
|
# Get tablespace path if this is a tablespace
|
|
if (index($strTarget, DB_PATH_PGTBLSPC . '/') == 0)
|
|
{
|
|
my $iCatalog = ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_CATALOG};
|
|
|
|
$strFinalPath .= '/PG_' . ${$oManifestRef}{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} . "_${iCatalog}";
|
|
}
|
|
|
|
$strFinalPath .= (defined($strSubPath) ? "/${strSubPath}" : '');
|
|
|
|
# Create the path
|
|
if (!(-e $strFinalPath))
|
|
{
|
|
storageTest()->pathCreate($strFinalPath, {strMode => $strMode});
|
|
}
|
|
|
|
return $strFinalPath;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# dbPathMode
|
|
#
|
|
# Change the mode of a path.
|
|
####################################################################################################################################
|
|
sub dbPathMode
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strPath = shift;
|
|
my $strMode = shift;
|
|
|
|
# Get the db path
|
|
my $strDbPath = $self->manifestDbPathGet($oManifestRef, $strTarget, $strPath);
|
|
|
|
testPathMode($strDbPath, $strMode);
|
|
|
|
return $strDbPath;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# dbPathRemove
|
|
#
|
|
# Remove a path.
|
|
####################################################################################################################################
|
|
sub dbPathRemove
|
|
{
|
|
my $self = shift;
|
|
my $oManifestRef = shift;
|
|
my $strTarget = shift;
|
|
my $strPath = shift;
|
|
|
|
# Get the db path
|
|
my $strDbPath = $self->manifestDbPathGet($oManifestRef, $strTarget, $strPath);
|
|
|
|
# Create the path
|
|
testPathRemove($strDbPath);
|
|
|
|
return $strDbPath;
|
|
}
|
|
|
|
1;
|