mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-14 10:13:05 +02:00
ccc255d3e0
The TLS server is an alternative to using SSH for protocol connections to remote hosts. This command is currently experimental and intended only for trial and testing. As such, the new commands and options will not show up in the command-line help unless directly requested.
731 lines
28 KiB
Perl
731 lines
28 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},
|
|
oLogTest => $$oParam{oLogTest},
|
|
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 ($$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90 &&
|
|
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 and pg version >= 9.0
|
|
if (defined(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}) &&
|
|
$$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90)
|
|
{
|
|
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;
|
|
${$oManifestRef}{&MANIFEST_SECTION_TARGET_FILE}{$strManifestKey}{&MANIFEST_SUBKEY_PRIMARY} =
|
|
defined($bPrimary) ? ($bPrimary ? JSON::PP::true : JSON::PP::false) : JSON::PP::false;
|
|
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 and pg version >= 9.0
|
|
if (defined(${$oManifestRef}{&MANIFEST_SECTION_BACKUP_TARGET}{$strTarget}{&MANIFEST_SUBKEY_TABLESPACE_ID}) &&
|
|
$$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90)
|
|
{
|
|
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}{$strSection}{$strManifestKey}{&MANIFEST_SUBKEY_PRIMARY} =
|
|
defined($bPrimary) ? ($bPrimary ? JSON::PP::true : JSON::PP::false) : JSON::PP::false;
|
|
|
|
${$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;
|
|
|
|
if ($$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90)
|
|
{
|
|
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 ($$oManifestRef{&MANIFEST_SECTION_BACKUP_DB}{&MANIFEST_KEY_DB_VERSION} >= PG_VERSION_90 &&
|
|
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;
|