mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-03-03 14:52:21 +02:00
Remove obsolete methods in pgBackRest::Storage::Storage module.
All the methods in this module will need to be implemented via the command-line in order to get rid of LibC, so the first step is to reduce the code in the module as much as possible. First remove storageDb() and use storageTest() instead. Then create storageTest() using pgBackRestTest::Common::Storage which has no dependencies on LibC. Now the only storage using the LibC interface is storageRepo(). Remove all link functions since those operations cannot be performed on a repo unless it is Posix, in which case the LibC interface is not needed. Same for owner(). Remove pathSync() because syncs are not required in the tests. No test data is reused after a crash. Path create/exists functions should never be explicitly performed on a repo so remove those. File exists can be implemented by calling info() instead. Remove encryption detection functions which were only used by Backup/Archive::Info reconstruct() which are now obsolete. Remove all filters except pgBackRest::Storage::Filter::CipherBlock since they are not being used. That also means there are no filters returning results so remove all the result code. Move hashSize() and pathAbsolute() into pgBackRest::Storage::Base where they can be shared between pgBackRest::Storage::Storage and pgBackRestTest::Common::Storage.
This commit is contained in:
parent
00647c7109
commit
02aa03d1a2
@ -334,149 +334,6 @@ sub create
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# reconstruct
|
||||
#
|
||||
# Reconstruct the info file from the existing directory and files
|
||||
####################################################################################################################################
|
||||
sub reconstruct
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strCurrentDbVersion,
|
||||
$ullCurrentDbSysId,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->reconstruct', \@_,
|
||||
{name => 'strCurrentDbVersion'},
|
||||
{name => 'ullCurrentDbSysId'},
|
||||
);
|
||||
|
||||
my $strInvalidFileStructure = undef;
|
||||
|
||||
my @stryArchiveId = storageRepo()->list(
|
||||
$self->{strArchiveClusterPath}, {strExpression => REGEX_ARCHIVE_DIR_DB_VERSION, bIgnoreMissing => true});
|
||||
my %hDbHistoryVersion;
|
||||
|
||||
# Get the db-version and db-id (history id) from the upper level directory names, e.g. 9.4-1
|
||||
foreach my $strArchiveId (@stryArchiveId)
|
||||
{
|
||||
my ($strDbVersion, $iDbHistoryId) = split("-", $strArchiveId);
|
||||
$hDbHistoryVersion{$iDbHistoryId} = $strDbVersion;
|
||||
}
|
||||
|
||||
# Loop through the DBs in the order they were created as indicated by the db-id so that the last one is set in the db section
|
||||
foreach my $iDbHistoryId (sort {$a <=> $b} keys %hDbHistoryVersion)
|
||||
{
|
||||
my $strDbVersion = $hDbHistoryVersion{$iDbHistoryId};
|
||||
my $strVersionDir = $strDbVersion . "-" . $iDbHistoryId;
|
||||
|
||||
# Get the name of the first archive directory
|
||||
my $strArchiveDir = (storageRepo()->list(
|
||||
$self->{strArchiveClusterPath} . "/${strVersionDir}",
|
||||
{strExpression => REGEX_ARCHIVE_DIR_WAL, bIgnoreMissing => true}))[0];
|
||||
|
||||
# Continue if any file structure or missing files info
|
||||
if (!defined($strArchiveDir))
|
||||
{
|
||||
$strInvalidFileStructure = "found empty directory " . $self->{strArchiveClusterPath} . "/${strVersionDir}";
|
||||
next;
|
||||
}
|
||||
|
||||
# ??? Should probably make a function in ArchiveCommon
|
||||
my $strArchiveFile = (storageRepo()->list(
|
||||
$self->{strArchiveClusterPath} . "/${strVersionDir}/${strArchiveDir}",
|
||||
{strExpression => "^[0-F]{24}(\\.partial){0,1}(-[0-f]+){0,1}(\\." . COMPRESS_EXT . "){0,1}\$",
|
||||
bIgnoreMissing => true}))[0];
|
||||
|
||||
# Continue if any file structure or missing files info
|
||||
if (!defined($strArchiveFile))
|
||||
{
|
||||
$strInvalidFileStructure =
|
||||
"found empty directory " . $self->{strArchiveClusterPath} . "/${strVersionDir}/${strArchiveDir}";
|
||||
next;
|
||||
}
|
||||
|
||||
# Get the full path for the file
|
||||
my $strArchiveFilePath = $self->{strArchiveClusterPath}."/${strVersionDir}/${strArchiveDir}/${strArchiveFile}";
|
||||
|
||||
# Get the db-system-id from the WAL file depending on the version of postgres
|
||||
my $iSysIdOffset = $strDbVersion >= PG_VERSION_93 ? PG_WAL_SYSTEM_ID_OFFSET_GTE_93 : PG_WAL_SYSTEM_ID_OFFSET_LT_93;
|
||||
|
||||
# Error if the file encryption setting is not valid for the repo
|
||||
if (!storageRepo()->encryptionValid(storageRepo()->encrypted($strArchiveFilePath)))
|
||||
{
|
||||
confess &log(ERROR, "encryption incompatible for '$strArchiveFilePath'" .
|
||||
"\nHINT: is or was the repo encrypted?", ERROR_CRYPTO);
|
||||
}
|
||||
|
||||
# If the file is encrypted, then the passphrase from the info file is required, else getEncryptionKeySub returns undefined
|
||||
my $oFileIo = storageRepo()->openRead(
|
||||
$strArchiveFilePath,
|
||||
{rhyFilter => $strArchiveFile =~ ('\.' . COMPRESS_EXT . '$') ?
|
||||
[{strClass => STORAGE_FILTER_GZ, rxyParam => [STORAGE_DECOMPRESS, false]}] : undef,
|
||||
strCipherPass => $self->cipherPassSub()});
|
||||
$oFileIo->open();
|
||||
|
||||
my $tBlock;
|
||||
$oFileIo->read(\$tBlock, 512);
|
||||
$oFileIo->close();
|
||||
|
||||
# Get the required data from the file that was pulled into scalar $tBlock
|
||||
my ($iMagic, $iFlag, $junk, $ullDbSysId) = unpack('SSa' . $iSysIdOffset . 'Q', $tBlock);
|
||||
|
||||
if (!defined($ullDbSysId))
|
||||
{
|
||||
confess &log(ERROR, "unable to read database system identifier", ERROR_FILE_READ);
|
||||
}
|
||||
|
||||
# Fill db section and db history section
|
||||
$self->dbSectionSet($strDbVersion, $ullDbSysId, $iDbHistoryId);
|
||||
}
|
||||
|
||||
# If the DB section does not exist, then there were no valid directories to read from so create the DB and History sections.
|
||||
if (!$self->test(INFO_ARCHIVE_SECTION_DB))
|
||||
{
|
||||
$self->create($strCurrentDbVersion, $ullCurrentDbSysId, false);
|
||||
}
|
||||
# Else if it does exist but does not match the current DB, then update the DB section
|
||||
else
|
||||
{
|
||||
# Turn off console logging to control when to display the error
|
||||
logDisable();
|
||||
|
||||
eval
|
||||
{
|
||||
$self->check($strCurrentDbVersion, $ullCurrentDbSysId, false);
|
||||
logEnable();
|
||||
return true;
|
||||
}
|
||||
or do
|
||||
{
|
||||
# Reset the console logging
|
||||
logEnable();
|
||||
|
||||
# Confess unhandled errors
|
||||
confess $EVAL_ERROR if (exceptionCode($EVAL_ERROR) != ERROR_ARCHIVE_MISMATCH);
|
||||
|
||||
# Update the DB section if it does not match the current database
|
||||
$self->dbSectionSet($strCurrentDbVersion, $ullCurrentDbSysId, $self->dbHistoryIdGet(false)+1);
|
||||
};
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strInvalidFileStructure', value => $strInvalidFileStructure}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# dbHistoryIdGet
|
||||
#
|
||||
|
@ -111,7 +111,6 @@ sub new
|
||||
(
|
||||
$strOperation,
|
||||
$strBackupClusterPath,
|
||||
$bValidate,
|
||||
$bRequired,
|
||||
$oStorage,
|
||||
$bLoad, # Should the file attemp to be loaded?
|
||||
@ -122,7 +121,6 @@ sub new
|
||||
(
|
||||
__PACKAGE__ . '->new', \@_,
|
||||
{name => 'strBackupClusterPath'},
|
||||
{name => 'bValidate', default => true},
|
||||
{name => 'bRequired', default => true},
|
||||
{name => 'oStorage', optional => true, default => storageRepo()},
|
||||
{name => 'bLoad', optional => true, default => true},
|
||||
@ -175,12 +173,6 @@ sub new
|
||||
$self->{strBackupClusterPath} = $strBackupClusterPath;
|
||||
$self->{oStorage} = $oStorage;
|
||||
|
||||
# Validate the backup info
|
||||
if ($bValidate)
|
||||
{
|
||||
$self->validate();
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
@ -189,164 +181,6 @@ sub new
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# validate
|
||||
#
|
||||
# Confirm the file exists and reconstruct as necessary.
|
||||
####################################################################################################################################
|
||||
sub validate
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->validate');
|
||||
|
||||
# Confirm the info file exists with the DB section
|
||||
$self->confirmExists();
|
||||
|
||||
$self->reconstruct();
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# reconstruct
|
||||
#
|
||||
# Compare the backup info against the actual backups in the repository. Reconstruct the file based on manifests missing or no
|
||||
# longer valid.
|
||||
####################################################################################################################################
|
||||
sub reconstruct
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$bSave,
|
||||
$bRequired, # If false then must be creating or reconstructing so the DB info must be supplied
|
||||
$strDbVersion,
|
||||
$ullDbSysId,
|
||||
$iControlVersion,
|
||||
$iCatalogVersion,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->reconstruct', \@_,
|
||||
{name => 'bSave', default => true},
|
||||
{name => 'bRequired', default => true},
|
||||
{name => 'strDbVersion', required => false},
|
||||
{name => 'ullDbSysId', required => false},
|
||||
{name => 'iControlVersion', required => false},
|
||||
{name => 'iCatalogVersion', required => false},
|
||||
);
|
||||
|
||||
# Check for backups that are not in FILE_BACKUP_INFO
|
||||
foreach my $strBackup ($self->{oStorage}->list(
|
||||
$self->{strBackupClusterPath}, {strExpression => backupRegExpGet(true, true, true)}))
|
||||
{
|
||||
my $strManifestFile = "$self->{strBackupClusterPath}/${strBackup}/" . FILE_MANIFEST;
|
||||
|
||||
# ??? Check for and move history files that were not moved before and maybe don't consider it to be an error when they
|
||||
# can't be moved. This would also be true for the first move attempt in Backup->process();
|
||||
|
||||
if (!$self->current($strBackup) && $self->{oStorage}->exists($strManifestFile))
|
||||
{
|
||||
my $oManifest = pgBackRest::Manifest->new($strManifestFile,
|
||||
{strCipherPass => ($self->{oStorage}->encrypted($strManifestFile)) ? $self->cipherPassSub() : undef});
|
||||
|
||||
# If we are reconstructing, then we need to be sure this db-id and version is in the history section. Also if it
|
||||
# has a db-id greater than anything in the history section, then add it to the db section.
|
||||
if (!$bRequired)
|
||||
{
|
||||
my $hDbList = $self->dbHistoryList();
|
||||
my $iDbId = $oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID);
|
||||
my $iDbIdMax = 0;
|
||||
my $ullDbSysId = $oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_SYSTEM_ID);
|
||||
my $strDbVersion = $oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION);
|
||||
|
||||
# If this is the max history id then set the db section
|
||||
foreach my $iDbHistoryId (keys %{$hDbList})
|
||||
{
|
||||
# If the current history ID is greater than the running max, then set it to the current id
|
||||
if ($iDbHistoryId > $iDbIdMax)
|
||||
{
|
||||
$iDbIdMax = $iDbHistoryId;
|
||||
}
|
||||
}
|
||||
|
||||
if ($iDbId >= $iDbIdMax)
|
||||
{
|
||||
$self->dbSectionSet($strDbVersion, $oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CONTROL),
|
||||
$oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG), $ullDbSysId, $iDbId);
|
||||
}
|
||||
}
|
||||
|
||||
&log(WARN, "backup ${strBackup} found in repository added to " . FILE_BACKUP_INFO);
|
||||
|
||||
$self->add($oManifest, $bSave, $bRequired);
|
||||
}
|
||||
}
|
||||
|
||||
# If reconstructing, make sure the DB section is correct
|
||||
if (!$bRequired)
|
||||
{
|
||||
# If any database info is missing, then assert
|
||||
if (!defined($strDbVersion) || !defined($ullDbSysId) || !defined($iControlVersion) || !defined($iCatalogVersion))
|
||||
{
|
||||
confess &log(ASSERT, "backup info cannot be reconstructed without database information");
|
||||
}
|
||||
# If the DB section does not exist then create the db and history section
|
||||
elsif (!$self->test(INFO_BACKUP_SECTION_DB))
|
||||
{
|
||||
$self->create($strDbVersion, $ullDbSysId, $iControlVersion, $iCatalogVersion, $bSave);
|
||||
}
|
||||
# Else update the DB section if it does not match the current database
|
||||
else
|
||||
{
|
||||
# Turn off console logging to control when to display the error
|
||||
logDisable();
|
||||
|
||||
eval
|
||||
{
|
||||
$self->check($strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId, $bRequired);
|
||||
logEnable();
|
||||
return true;
|
||||
}
|
||||
or do
|
||||
{
|
||||
# Reset the console logging
|
||||
logEnable();
|
||||
|
||||
# Confess unhandled errors
|
||||
confess $EVAL_ERROR if (exceptionCode($EVAL_ERROR) != ERROR_BACKUP_MISMATCH);
|
||||
|
||||
# Update the DB section if it does not match the current database
|
||||
$self->dbSectionSet($strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId, $self->dbHistoryIdGet(false)+1);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
# Remove backups from FILE_BACKUP_INFO that are no longer in the repository
|
||||
foreach my $strBackup ($self->keys(INFO_BACKUP_SECTION_BACKUP_CURRENT))
|
||||
{
|
||||
my $strManifestFile = "$self->{strBackupClusterPath}/${strBackup}/" . FILE_MANIFEST;
|
||||
my $strBackupPath = "$self->{strBackupClusterPath}/${strBackup}";
|
||||
|
||||
if (!$self->{oStorage}->pathExists($strBackupPath) || !$self->{oStorage}->exists($strManifestFile))
|
||||
{
|
||||
&log(WARN, "backup '${strBackup}' missing manifest removed from " . FILE_BACKUP_INFO);
|
||||
$self->delete($strBackup);
|
||||
}
|
||||
}
|
||||
|
||||
# ??? Add a section to remove backups that are missing references (unless they are hardlinked?)
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# check
|
||||
#
|
||||
|
@ -158,38 +158,28 @@ sub loadVersion
|
||||
my $bCopy = shift;
|
||||
my $bIgnoreError = shift;
|
||||
|
||||
# Make sure the file encryption setting is valid for the repo
|
||||
if ($self->{oStorage}->encryptionValid($self->{oStorage}->encrypted($self->{strFileName} . ($bCopy ? INI_COPY_EXT : ''),
|
||||
{bIgnoreMissing => $bIgnoreError})))
|
||||
# Load main
|
||||
my $rstrContent = $self->{oStorage}->get(
|
||||
$self->{oStorage}->openRead($self->{strFileName} . ($bCopy ? INI_COPY_EXT : ''),
|
||||
{bIgnoreMissing => $bIgnoreError, strCipherPass => $self->{strCipherPass}}));
|
||||
|
||||
# If the file exists then attempt to parse it
|
||||
if (defined($rstrContent))
|
||||
{
|
||||
# Load main
|
||||
my $rstrContent = $self->{oStorage}->get(
|
||||
$self->{oStorage}->openRead($self->{strFileName} . ($bCopy ? INI_COPY_EXT : ''),
|
||||
{bIgnoreMissing => $bIgnoreError, strCipherPass => $self->{strCipherPass}}));
|
||||
my $rhContent = iniParse($$rstrContent, {bIgnoreInvalid => $bIgnoreError});
|
||||
|
||||
# If the file exists then attempt to parse it
|
||||
if (defined($rstrContent))
|
||||
# If the content is valid then check the header
|
||||
if (defined($rhContent))
|
||||
{
|
||||
my $rhContent = iniParse($$rstrContent, {bIgnoreInvalid => $bIgnoreError});
|
||||
$self->{oContent} = $rhContent;
|
||||
|
||||
# If the content is valid then check the header
|
||||
if (defined($rhContent))
|
||||
# If the header is invalid then undef content
|
||||
if (!$self->headerCheck({bIgnoreInvalid => $bIgnoreError}))
|
||||
{
|
||||
$self->{oContent} = $rhContent;
|
||||
|
||||
# If the header is invalid then undef content
|
||||
if (!$self->headerCheck({bIgnoreInvalid => $bIgnoreError}))
|
||||
{
|
||||
delete($self->{oContent});
|
||||
}
|
||||
delete($self->{oContent});
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
confess &log(ERROR, "unable to parse '$self->{strFileName}" . ($bCopy ? INI_COPY_EXT : '') . "'" .
|
||||
"\nHINT: is or was the repo encrypted?", ERROR_CRYPTO);
|
||||
}
|
||||
|
||||
return defined($self->{oContent});
|
||||
}
|
||||
@ -423,10 +413,20 @@ sub save
|
||||
|
||||
# Save the file
|
||||
$self->{oStorage}->put($self->{strFileName}, iniRender($self->{oContent}), {strCipherPass => $self->{strCipherPass}});
|
||||
$self->{oStorage}->pathSync(dirname($self->{strFileName}));
|
||||
|
||||
if ($self->{oStorage}->can('pathSync'))
|
||||
{
|
||||
$self->{oStorage}->pathSync(dirname($self->{strFileName}));
|
||||
}
|
||||
|
||||
$self->{oStorage}->put($self->{strFileName} . INI_COPY_EXT, iniRender($self->{oContent}),
|
||||
{strCipherPass => $self->{strCipherPass}});
|
||||
$self->{oStorage}->pathSync(dirname($self->{strFileName}));
|
||||
|
||||
if ($self->{oStorage}->can('pathSync'))
|
||||
{
|
||||
$self->{oStorage}->pathSync(dirname($self->{strFileName}));
|
||||
}
|
||||
|
||||
$self->{bModified} = false;
|
||||
|
||||
# Indicate the file now exists
|
||||
|
@ -61,9 +61,6 @@ sub handleWriteSet {shift->{oParent}->handleWriteSet(@_)};
|
||||
sub name {shift->{oParent}->name()};
|
||||
sub read {shift->{oParent}->read(@_)};
|
||||
sub readLine {shift->{oParent}->readLine(@_)};
|
||||
sub result {shift->{oParent}->result(@_)};
|
||||
sub resultAll {shift->{oParent}->resultAll()};
|
||||
sub resultSet {shift->{oParent}->resultSet(@_)};
|
||||
sub size {shift->{oParent}->size()};
|
||||
sub timeout {shift->{oParent}->timeout()};
|
||||
sub write {shift->{oParent}->write(@_)};
|
||||
|
@ -34,38 +34,6 @@ use constant STORAGE_REPO_BACKUP => '<REPO:BA
|
||||
####################################################################################################################################
|
||||
my $hStorage;
|
||||
|
||||
####################################################################################################################################
|
||||
# storageDb - get db storage
|
||||
####################################################################################################################################
|
||||
sub storageDb
|
||||
{
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '::storageDb', \@_,
|
||||
);
|
||||
|
||||
# Create storage if not defined
|
||||
if (!defined($hStorage->{&STORAGE_DB}))
|
||||
{
|
||||
$hStorage->{&STORAGE_DB} = new pgBackRest::Storage::Storage(
|
||||
STORAGE_DB, {lBufferMax => cfgOption(CFGOPT_BUFFER_SIZE)});
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'oStorageDb', value => $hStorage->{&STORAGE_DB}, trace => true},
|
||||
);
|
||||
}
|
||||
|
||||
push @EXPORT, qw(storageDb);
|
||||
|
||||
####################################################################################################################################
|
||||
# storageRepo - get repository storage
|
||||
####################################################################################################################################
|
||||
|
@ -8,6 +8,7 @@ use warnings FATAL => qw(all);
|
||||
use Carp qw(confess);
|
||||
use English '-no_match_vars';
|
||||
|
||||
use Digest::SHA qw(sha1_hex);
|
||||
use Exporter qw(import);
|
||||
our @EXPORT = qw();
|
||||
use File::Basename qw(dirname);
|
||||
@ -27,45 +28,18 @@ use constant STORAGE_S3 => 's3';
|
||||
use constant STORAGE_POSIX => 'posix';
|
||||
push @EXPORT, qw(STORAGE_POSIX);
|
||||
|
||||
####################################################################################################################################
|
||||
# Compress constants
|
||||
####################################################################################################################################
|
||||
use constant STORAGE_COMPRESS => 'compress';
|
||||
push @EXPORT, qw(STORAGE_COMPRESS);
|
||||
use constant STORAGE_DECOMPRESS => 'decompress';
|
||||
push @EXPORT, qw(STORAGE_DECOMPRESS);
|
||||
|
||||
####################################################################################################################################
|
||||
# Cipher constants
|
||||
####################################################################################################################################
|
||||
use constant STORAGE_ENCRYPT => 'encrypt';
|
||||
push @EXPORT, qw(STORAGE_ENCRYPT);
|
||||
use constant STORAGE_DECRYPT => 'decrypt';
|
||||
push @EXPORT, qw(STORAGE_DECRYPT);
|
||||
use constant CIPHER_MAGIC => 'Salted__';
|
||||
push @EXPORT, qw(CIPHER_MAGIC);
|
||||
|
||||
####################################################################################################################################
|
||||
# Filter constants
|
||||
####################################################################################################################################
|
||||
use constant STORAGE_FILTER_CIPHER_BLOCK => 'pgBackRest::Storage::Filter::CipherBlock';
|
||||
push @EXPORT, qw(STORAGE_FILTER_CIPHER_BLOCK);
|
||||
use constant STORAGE_FILTER_GZ => 'pgBackRest::Storage::Filter::Gz';
|
||||
push @EXPORT, qw(STORAGE_FILTER_GZ);
|
||||
|
||||
####################################################################################################################################
|
||||
# Capability constants
|
||||
####################################################################################################################################
|
||||
# Can the size in the storage be different than what was written? For example, a ZFS filesystem could be doing compression of a
|
||||
# backup where compression was not enabled. This affects how repo-size is calculated. If the file system only stores what was
|
||||
# written or won't report differently then we can save some time by just setting repo-size to size.
|
||||
use constant STORAGE_CAPABILITY_SIZE_DIFF => 'size-diff';
|
||||
push @EXPORT, qw(STORAGE_CAPABILITY_SIZE_DIFF);
|
||||
|
||||
# Does the storage support symlinks and hardlinks?
|
||||
use constant STORAGE_CAPABILITY_LINK => 'link';
|
||||
push @EXPORT, qw(STORAGE_CAPABILITY_LINK);
|
||||
use constant STORAGE_CAPABILITY_PATH_SYNC => 'path-sync';
|
||||
push @EXPORT, qw(STORAGE_CAPABILITY_PATH_SYNC);
|
||||
|
||||
####################################################################################################################################
|
||||
# new
|
||||
@ -236,6 +210,58 @@ sub get
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Calculate sha1 hash and size of file. If special encryption settings are required, then the file objects from openRead/openWrite
|
||||
# must be passed instead of file names.
|
||||
####################################################################################################################################
|
||||
sub hashSize
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$xFileExp,
|
||||
$bIgnoreMissing,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->hashSize', \@_,
|
||||
{name => 'xFileExp'},
|
||||
{name => 'bIgnoreMissing', optional => true, default => false},
|
||||
);
|
||||
|
||||
# Set operation variables
|
||||
my $strHash;
|
||||
my $lSize;
|
||||
|
||||
# Is this an IO object or a file expression?
|
||||
my $rtContent = $self->get($xFileExp, {bIgnoreMissing => $bIgnoreMissing});
|
||||
|
||||
if (defined($rtContent))
|
||||
{
|
||||
if (defined($$rtContent))
|
||||
{
|
||||
$strHash = sha1_hex($$rtContent);
|
||||
$lSize = length($$rtContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
$strHash = sha1_hex('');
|
||||
$lSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strHash', value => $strHash},
|
||||
{name => 'lSize', value => $lSize}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# pathAbsolute - generate an absolute path from an absolute base path and a relative path
|
||||
####################################################################################################################################
|
||||
|
@ -92,14 +92,11 @@ sub exists
|
||||
{name => 'strFileExp'},
|
||||
);
|
||||
|
||||
# Check exists
|
||||
my $bExists = $self->{oStorageC}->exists($strFileExp);
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'bExists', value => $bExists ? true : false}
|
||||
{name => 'bExists', value => defined($self->info($strFileExp, {bIgnoreMissing => true}))}
|
||||
);
|
||||
}
|
||||
|
||||
@ -146,58 +143,6 @@ sub get
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Calculate sha1 hash and size of file. If special encryption settings are required, then the file objects from openRead/openWrite
|
||||
# must be passed instead of file names.
|
||||
####################################################################################################################################
|
||||
sub hashSize
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$xFileExp,
|
||||
$bIgnoreMissing,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->hashSize', \@_,
|
||||
{name => 'xFileExp'},
|
||||
{name => 'bIgnoreMissing', optional => true, default => false},
|
||||
);
|
||||
|
||||
# Set operation variables
|
||||
my $strHash;
|
||||
my $lSize;
|
||||
|
||||
# Is this an IO object or a file expression?
|
||||
my $rtContent = $self->get($xFileExp, {bIgnoreMissing => $bIgnoreMissing});
|
||||
|
||||
if (defined($rtContent))
|
||||
{
|
||||
if (defined($$rtContent))
|
||||
{
|
||||
$strHash = sha1_hex($$rtContent);
|
||||
$lSize = length($$rtContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
$strHash = sha1_hex('');
|
||||
$lSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strHash', value => $strHash},
|
||||
{name => 'lSize', value => $lSize}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Get information for path/file
|
||||
####################################################################################################################################
|
||||
@ -235,112 +180,6 @@ sub info
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# linkCreate - create a link
|
||||
####################################################################################################################################
|
||||
sub linkCreate
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strSourcePathFileExp,
|
||||
$strDestinationLinkExp,
|
||||
$bHard,
|
||||
$bRelative,
|
||||
$bPathCreate,
|
||||
$bIgnoreExists,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->linkCreate', \@_,
|
||||
{name => 'strSourcePathFileExp'},
|
||||
{name => 'strDestinationLinkExp'},
|
||||
{name => 'bHard', optional=> true, default => false},
|
||||
{name => 'bRelative', optional=> true, default => false},
|
||||
{name => 'bPathCreate', optional=> true, default => true},
|
||||
{name => 'bIgnoreExists', optional => true, default => false},
|
||||
);
|
||||
|
||||
# Get source and destination paths
|
||||
my $strSourcePathFile = $self->pathGet($strSourcePathFileExp);
|
||||
my $strDestinationLink = $self->pathGet($strDestinationLinkExp);
|
||||
|
||||
# Generate relative path if requested
|
||||
if ($bRelative)
|
||||
{
|
||||
# Determine how much of the paths are common
|
||||
my @strySource = split('/', $strSourcePathFile);
|
||||
my @stryDestination = split('/', $strDestinationLink);
|
||||
|
||||
while (defined($strySource[0]) && defined($stryDestination[0]) && $strySource[0] eq $stryDestination[0])
|
||||
{
|
||||
shift(@strySource);
|
||||
shift(@stryDestination);
|
||||
}
|
||||
|
||||
# Add relative path sections
|
||||
$strSourcePathFile = '';
|
||||
|
||||
for (my $iIndex = 0; $iIndex < @stryDestination - 1; $iIndex++)
|
||||
{
|
||||
$strSourcePathFile .= '../';
|
||||
}
|
||||
|
||||
# Add path to source
|
||||
$strSourcePathFile .= join('/', @strySource);
|
||||
|
||||
logDebugMisc
|
||||
(
|
||||
$strOperation, 'apply relative path',
|
||||
{name => 'strSourcePathFile', value => $strSourcePathFile, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
if (!($bHard ? link($strSourcePathFile, $strDestinationLink) : symlink($strSourcePathFile, $strDestinationLink)))
|
||||
{
|
||||
my $strMessage = "unable to create link '${strDestinationLink}'";
|
||||
|
||||
# If parent path or source is missing
|
||||
if ($OS_ERROR{ENOENT})
|
||||
{
|
||||
# Check if source is missing
|
||||
if (!$self->exists($strSourcePathFile))
|
||||
{
|
||||
confess &log(ERROR, "${strMessage} because source '${strSourcePathFile}' does not exist", ERROR_FILE_MISSING);
|
||||
}
|
||||
|
||||
if (!$bPathCreate)
|
||||
{
|
||||
confess &log(ERROR, "${strMessage} because parent does not exist", ERROR_PATH_MISSING);
|
||||
}
|
||||
|
||||
# Create parent path
|
||||
$self->pathCreate(dirname($strDestinationLink), {bIgnoreExists => true, bCreateParent => true});
|
||||
|
||||
# Create link
|
||||
$self->linkCreate($strSourcePathFile, $strDestinationLink, {bHard => $bHard});
|
||||
}
|
||||
# Else if link already exists
|
||||
elsif ($OS_ERROR{EEXIST})
|
||||
{
|
||||
if (!$bIgnoreExists)
|
||||
{
|
||||
confess &log(ERROR, "${strMessage} because it already exists", ERROR_PATH_EXISTS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logErrorResult(ERROR_PATH_CREATE, ${strMessage}, $OS_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# List all files/paths in path
|
||||
####################################################################################################################################
|
||||
@ -442,42 +281,6 @@ sub manifestJson
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# move - move path/file
|
||||
####################################################################################################################################
|
||||
sub move
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strSourceFileExp,
|
||||
$strDestinationFileExp,
|
||||
$bPathCreate,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->move', \@_,
|
||||
{name => 'strSourceFileExp'},
|
||||
{name => 'strDestinationFileExp'},
|
||||
);
|
||||
|
||||
# Get source and destination paths
|
||||
my $strSourceFile = $self->pathGet($strSourceFileExp);
|
||||
my $strDestinationFile = $self->pathGet($strDestinationFileExp);
|
||||
|
||||
# Move the file
|
||||
if (!rename($strSourceFile, $strDestinationFile))
|
||||
{
|
||||
logErrorResult(ERROR_FILE_MOVE, "unable to move '${strSourceFile}' to '${strDestinationFile}'", $OS_ERROR);
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Open file for reading
|
||||
####################################################################################################################################
|
||||
@ -560,7 +363,7 @@ sub openWrite
|
||||
{name => 'strGroup', optional => true},
|
||||
{name => 'lTimestamp', optional => true, default => '0'},
|
||||
{name => 'bAtomic', optional => true, default => false},
|
||||
{name => 'bPathCreate', optional => true, default => false},
|
||||
{name => 'bPathCreate', optional => true, default => true},
|
||||
{name => 'rhyFilter', optional => true},
|
||||
{name => 'strCipherPass', optional => true, default => $self->cipherPassUser(), redact => true},
|
||||
);
|
||||
@ -593,226 +396,6 @@ sub openWrite
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Change ownership of path/file
|
||||
####################################################################################################################################
|
||||
sub owner
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strPathFileExp,
|
||||
$strUser,
|
||||
$strGroup
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->owner', \@_,
|
||||
{name => 'strPathFileExp'},
|
||||
{name => 'strUser', required => false},
|
||||
{name => 'strGroup', required => false}
|
||||
);
|
||||
|
||||
# Only proceed if user or group was specified
|
||||
if (defined($strUser) || defined($strGroup))
|
||||
{
|
||||
my $strPathFile = $self->pathGet($strPathFileExp);
|
||||
my $strMessage = "unable to set ownership for '${strPathFile}'";
|
||||
my $iUserId;
|
||||
my $iGroupId;
|
||||
|
||||
# If the user or group is not defined then get it by stat'ing the file. This is because the chown function requires that
|
||||
# both user and group be set.
|
||||
my $oStat = lstat($strPathFile);
|
||||
|
||||
if (!defined($oStat))
|
||||
{
|
||||
confess &log(ERROR, "unable to stat '${strPathFile}': No such file or directory", ERROR_FILE_MISSING);
|
||||
}
|
||||
|
||||
if (!defined($strUser))
|
||||
{
|
||||
$iUserId = $oStat->uid;
|
||||
}
|
||||
|
||||
if (!defined($strGroup))
|
||||
{
|
||||
$iGroupId = $oStat->gid;
|
||||
}
|
||||
|
||||
# Lookup user if specified
|
||||
if (defined($strUser))
|
||||
{
|
||||
$iUserId = getpwnam($strUser);
|
||||
|
||||
if (!defined($iUserId))
|
||||
{
|
||||
logErrorResult(ERROR_FILE_OWNER, "${strMessage} because user '${strUser}' does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
# Lookup group if specified
|
||||
if (defined($strGroup))
|
||||
{
|
||||
$iGroupId = getgrnam($strGroup);
|
||||
|
||||
if (!defined($iGroupId))
|
||||
{
|
||||
logErrorResult(ERROR_FILE_OWNER, "${strMessage} because group '${strGroup}' does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
# Set ownership on the file if the user or group would be changed
|
||||
if ($iUserId != $oStat->uid || $iGroupId != $oStat->gid)
|
||||
{
|
||||
if (!chown($iUserId, $iGroupId, $strPathFile))
|
||||
{
|
||||
logErrorResult(ERROR_FILE_OWNER, "${strMessage}", $OS_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Generate an absolute path from an absolute base path and a relative path
|
||||
####################################################################################################################################
|
||||
sub pathAbsolute
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strBasePath,
|
||||
$strPath
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->pathAbsolute', \@_,
|
||||
{name => 'strBasePath', trace => true},
|
||||
{name => 'strPath', trace => true}
|
||||
);
|
||||
|
||||
# Working variables
|
||||
my $strAbsolutePath;
|
||||
|
||||
# If the path is already absolute
|
||||
if (index($strPath, '/') == 0)
|
||||
{
|
||||
$strAbsolutePath = $strPath;
|
||||
}
|
||||
# Else make it absolute using the base path
|
||||
else
|
||||
{
|
||||
# Make sure the absolute path is really absolute
|
||||
if (index($strBasePath, '/') != 0 || index($strBasePath, '/..') != -1)
|
||||
{
|
||||
confess &log(ERROR, "${strBasePath} is not an absolute path", ERROR_PATH_TYPE);
|
||||
}
|
||||
|
||||
while (index($strPath, '..') == 0)
|
||||
{
|
||||
$strBasePath = dirname($strBasePath);
|
||||
$strPath = substr($strPath, 2);
|
||||
|
||||
if (index($strPath, '/') == 0)
|
||||
{
|
||||
$strPath = substr($strPath, 1);
|
||||
}
|
||||
}
|
||||
|
||||
$strAbsolutePath = "${strBasePath}/${strPath}";
|
||||
}
|
||||
|
||||
# Make sure the result is really an absolute path
|
||||
if (index($strAbsolutePath, '/') != 0 || index($strAbsolutePath, '/..') != -1)
|
||||
{
|
||||
confess &log(ERROR, "result ${strAbsolutePath} was not an absolute path", ERROR_PATH_TYPE);
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'strAbsolutePath', value => $strAbsolutePath, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Create a path
|
||||
####################################################################################################################################
|
||||
sub pathCreate
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strPathExp,
|
||||
$strMode,
|
||||
$bIgnoreExists,
|
||||
$bCreateParent,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->pathCreate', \@_,
|
||||
{name => 'strPathExp'},
|
||||
{name => 'strMode', optional => true},
|
||||
{name => 'bIgnoreExists', optional => true, default => false},
|
||||
{name => 'bCreateParent', optional => true, default => false},
|
||||
);
|
||||
|
||||
# Create path
|
||||
$self->{oStorageC}->pathCreate($strPathExp, $strMode, $bIgnoreExists, $bCreateParent);
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Check if path exists
|
||||
####################################################################################################################################
|
||||
sub pathExists
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strPathExp,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->pathExists', \@_,
|
||||
{name => 'strPathExp'},
|
||||
);
|
||||
|
||||
# Check exists
|
||||
my $bExists = $self->{oStorageC}->pathExists($strPathExp);
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'bExists', value => $bExists ? true : false}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Resolve a path expression into an absolute path
|
||||
####################################################################################################################################
|
||||
@ -872,31 +455,6 @@ sub pathRemove
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Sync path so newly added file entries are not lost
|
||||
####################################################################################################################################
|
||||
sub pathSync
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strPathExp,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->pathSync', \@_,
|
||||
{name => 'strPathExp'},
|
||||
);
|
||||
|
||||
$self->{oStorageC}->pathSync($strPathExp);
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# put - writes a buffer out to storage all at once
|
||||
####################################################################################################################################
|
||||
@ -965,92 +523,6 @@ sub remove
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# encrypted - determine if the file is encrypted or not
|
||||
####################################################################################################################################
|
||||
sub encrypted
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strFileExp,
|
||||
$bIgnoreMissing,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->encrypted', \@_,
|
||||
{name => 'strFileExp'},
|
||||
{name => 'bIgnoreMissing', optional => true, default => false},
|
||||
);
|
||||
|
||||
my $bEncrypted = false;
|
||||
|
||||
# Open the file via the driver
|
||||
my $oFileIo = new pgBackRest::Storage::StorageRead(
|
||||
$self, pgBackRest::LibC::StorageRead->new($self->{oStorageC}, $strFileExp, $bIgnoreMissing));
|
||||
|
||||
# If the file does not exist because we're ignoring missing (else it would error before this is executed) then determine if it
|
||||
# should be encrypted based on the repo
|
||||
if (!$oFileIo->open())
|
||||
{
|
||||
if (defined($self->cipherType()))
|
||||
{
|
||||
$bEncrypted = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# If the file does exist, then read the magic signature
|
||||
my $tMagicSignature = '';
|
||||
my $lSizeRead = $oFileIo->read(\$tMagicSignature, length(CIPHER_MAGIC));
|
||||
$oFileIo->close();
|
||||
|
||||
if (substr($tMagicSignature, 0, length(CIPHER_MAGIC)) eq CIPHER_MAGIC)
|
||||
{
|
||||
$bEncrypted = true;
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'bEncrypted', value => $bEncrypted}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# encryptionValid - determine if encryption set properly based on the value passed
|
||||
####################################################################################################################################
|
||||
sub encryptionValid
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$bEncrypted,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->encryptionValid', \@_,
|
||||
{name => 'bEncrypted'},
|
||||
);
|
||||
|
||||
my $bValid = ($bEncrypted && defined($self->cipherType())) || (!$bEncrypted && !defined($self->cipherType()));
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'bValid', value => $bValid ? true : false}
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Getters
|
||||
####################################################################################################################################
|
||||
|
@ -140,51 +140,4 @@ sub close
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Get a filter result
|
||||
####################################################################################################################################
|
||||
sub result
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strClass,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->result', \@_,
|
||||
{name => 'strClass'},
|
||||
);
|
||||
|
||||
my $xResult = $self->{oStorage}->{oJSON}->decode($self->{oStorageCRead}->result($strClass));
|
||||
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'xResult', value => $xResult, trace => true},
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Get all filter results
|
||||
####################################################################################################################################
|
||||
sub resultAll
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->resultAll');
|
||||
|
||||
my $xResult = $self->{oStorage}->{oJSON}->decode($self->{oStorageCRead}->resultAll());
|
||||
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'xResultAll', value => $xResult, trace => true},
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -113,51 +113,4 @@ sub close
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Get a filter result
|
||||
####################################################################################################################################
|
||||
sub result
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strClass,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '->result', \@_,
|
||||
{name => 'strClass'},
|
||||
);
|
||||
|
||||
my $xResult = $self->{oStorage}->{oJSON}->decode($self->{oStorageCWrite}->result($strClass));
|
||||
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'xResult', value => $xResult, trace => true},
|
||||
);
|
||||
}
|
||||
|
||||
####################################################################################################################################
|
||||
# Get all filter results
|
||||
####################################################################################################################################
|
||||
sub resultAll
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->resultAll');
|
||||
|
||||
my $xResult = $self->{oStorage}->{oJSON}->decode($self->{oStorageCWrite}->resultAll());
|
||||
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'xResultAll', value => $xResult, trace => true},
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -83,23 +83,6 @@ CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
bool
|
||||
exists(self, fileExp)
|
||||
PREINIT:
|
||||
MEM_CONTEXT_XS_TEMP_BEGIN()
|
||||
{
|
||||
INPUT:
|
||||
pgBackRest::LibC::Storage self
|
||||
const String *fileExp = STR_NEW_SV($arg);
|
||||
CODE:
|
||||
RETVAL = storageExistsP(self, fileExp);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
SV *
|
||||
get(self, read)
|
||||
@ -215,47 +198,6 @@ CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
void
|
||||
pathCreate(self, pathExp, mode, ignoreExists, createParent)
|
||||
PREINIT:
|
||||
MEM_CONTEXT_XS_TEMP_BEGIN()
|
||||
{
|
||||
INPUT:
|
||||
pgBackRest::LibC::Storage self
|
||||
const String *pathExp = STR_NEW_SV($arg);
|
||||
const String *mode = STR_NEW_SV($arg);
|
||||
bool ignoreExists
|
||||
bool createParent
|
||||
CODE:
|
||||
if (storageFeature(self, storageFeaturePath))
|
||||
storagePathCreateP(
|
||||
self, pathExp, .mode = mode ? cvtZToMode(strPtr(mode)) : 0, .errorOnExists = !ignoreExists,
|
||||
.noParentCreate = !createParent);
|
||||
CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
bool
|
||||
pathExists(self, pathExp)
|
||||
PREINIT:
|
||||
MEM_CONTEXT_XS_TEMP_BEGIN()
|
||||
{
|
||||
INPUT:
|
||||
pgBackRest::LibC::Storage self
|
||||
const String *pathExp = STR_NEW_SV($arg);
|
||||
CODE:
|
||||
RETVAL = true;
|
||||
|
||||
if (storageFeature(self, storageFeaturePath))
|
||||
RETVAL = storagePathExistsP(self, pathExp);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
SV *
|
||||
pathGet(self, pathExp)
|
||||
@ -292,21 +234,6 @@ CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
void
|
||||
pathSync(self, pathExp)
|
||||
PREINIT:
|
||||
MEM_CONTEXT_XS_TEMP_BEGIN()
|
||||
{
|
||||
INPUT:
|
||||
pgBackRest::LibC::Storage self
|
||||
const String *pathExp = STR_NEW_SV($arg);
|
||||
CODE:
|
||||
storagePathSyncP(self, pathExp);
|
||||
CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
UV
|
||||
put(self, write, buffer)
|
||||
|
@ -124,72 +124,6 @@ storageFilterXsAdd(IoFilterGroup *filterGroup, const String *filter, const Strin
|
||||
varUInt64Force(varLstGet(paramList, 0)) ? cipherModeEncrypt : cipherModeDecrypt,
|
||||
cipherType(varStr(varLstGet(paramList, 1))), BUFSTR(varStr(varLstGet(paramList, 2))), NULL));
|
||||
}
|
||||
else if (strEqZ(filter, "pgBackRest::Common::Io::Handle"))
|
||||
{
|
||||
ioFilterGroupAdd(filterGroup, ioSizeNew());
|
||||
}
|
||||
else if (strEqZ(filter, "pgBackRest::Storage::Filter::Gz"))
|
||||
{
|
||||
if (strEqZ(varStr(varLstGet(paramList, 0)), "compress"))
|
||||
ioFilterGroupAdd(filterGroup, gzCompressNew(varUIntForce(varLstGet(paramList, 1))));
|
||||
else
|
||||
ioFilterGroupAdd(filterGroup, gzDecompressNew());
|
||||
}
|
||||
else
|
||||
THROW_FMT(AssertError, "unable to add invalid filter '%s'", strPtr(filter));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get result from IO filter
|
||||
***********************************************************************************************************************************/
|
||||
String *
|
||||
storageFilterXsResult(const IoFilterGroup *filterGroup, const String *filter)
|
||||
{
|
||||
const Variant *result;
|
||||
|
||||
if (strEqZ(filter, "pgBackRest::Common::Io::Handle"))
|
||||
{
|
||||
result = ioFilterGroupResult(filterGroup, SIZE_FILTER_TYPE_STR);
|
||||
}
|
||||
else
|
||||
THROW_FMT(AssertError, "unable to get result for invalid filter '%s'", strPtr(filter));
|
||||
|
||||
if (result == NULL)
|
||||
THROW_FMT(AssertError, "unable to find result for filter '%s'", strPtr(filter));
|
||||
|
||||
return jsonFromVar(result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get results from all IO filters
|
||||
***********************************************************************************************************************************/
|
||||
String *
|
||||
storageFilterXsResultAll(const IoFilterGroup *filterGroup)
|
||||
{
|
||||
const VariantList *filterList = kvKeyList(varKv(ioFilterGroupResultAll(filterGroup)));
|
||||
String *result = strNew("{");
|
||||
|
||||
for (unsigned int filterIdx = 0; filterIdx < varLstSize(filterList); filterIdx++)
|
||||
{
|
||||
const String *filter = varStr(varLstGet(filterList, filterIdx));
|
||||
const String *filterPerl = NULL;
|
||||
|
||||
if (strEq(filter, SIZE_FILTER_TYPE_STR))
|
||||
{
|
||||
filterPerl = strNew("pgBackRest::Common::Io::Handle");
|
||||
}
|
||||
|
||||
if (filterPerl != NULL)
|
||||
{
|
||||
if (strSize(result) > 1)
|
||||
strCat(result, ",");
|
||||
|
||||
strCatFmt(
|
||||
result, "%s:%s", strPtr(jsonFromStr(filterPerl)), strPtr(storageFilterXsResult(filterGroup, filterPerl)));
|
||||
}
|
||||
}
|
||||
|
||||
strCat(result, "}");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -111,39 +111,6 @@ CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
const char *
|
||||
result(self, filter)
|
||||
PREINIT:
|
||||
MEM_CONTEXT_XS_TEMP_BEGIN()
|
||||
{
|
||||
INPUT:
|
||||
pgBackRest::LibC::StorageRead self
|
||||
const String *filter = STR_NEW_SV($arg);
|
||||
CODE:
|
||||
RETVAL = strPtr(storageFilterXsResult(ioReadFilterGroup(storageReadIo(self)), filter));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
const char *
|
||||
resultAll(self)
|
||||
PREINIT:
|
||||
MEM_CONTEXT_XS_TEMP_BEGIN()
|
||||
{
|
||||
INPUT:
|
||||
pgBackRest::LibC::StorageRead self
|
||||
CODE:
|
||||
RETVAL = strPtr(storageFilterXsResultAll(ioReadFilterGroup(storageReadIo(self))));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
void
|
||||
DESTROY(self)
|
||||
|
@ -98,39 +98,6 @@ CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
const char *
|
||||
result(self, filter)
|
||||
PREINIT:
|
||||
MEM_CONTEXT_XS_TEMP_BEGIN()
|
||||
{
|
||||
INPUT:
|
||||
pgBackRest::LibC::StorageWrite self
|
||||
const String *filter = STR_NEW_SV($arg);
|
||||
CODE:
|
||||
RETVAL = strPtr(storageFilterXsResult(ioWriteFilterGroup(storageWriteIo(self)), filter));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
const char *
|
||||
resultAll(self)
|
||||
PREINIT:
|
||||
MEM_CONTEXT_XS_TEMP_BEGIN()
|
||||
{
|
||||
INPUT:
|
||||
pgBackRest::LibC::StorageWrite self
|
||||
CODE:
|
||||
RETVAL = strPtr(storageFilterXsResultAll(ioWriteFilterGroup(storageWriteIo(self))));
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
CLEANUP:
|
||||
}
|
||||
MEM_CONTEXT_XS_TEMP_END();
|
||||
|
||||
####################################################################################################################################
|
||||
void
|
||||
DESTROY(self)
|
||||
|
@ -168,7 +168,7 @@ sub forceStorageMode
|
||||
);
|
||||
|
||||
# Mode commands are ignored on S3
|
||||
if ($oStorage->type() ne STORAGE_S3)
|
||||
if (!$oStorage->can('type') || $oStorage->type() ne STORAGE_S3)
|
||||
{
|
||||
executeTest('chmod ' . ($bRecurse ? '-R ' : '') . "${strMode} " . $oStorage->pathGet($strPathExp));
|
||||
}
|
||||
|
@ -19,14 +19,14 @@ use pgBackRest::Common::Exception;
|
||||
use pgBackRest::Common::Log;
|
||||
use pgBackRest::Common::String;
|
||||
use pgBackRest::Common::Wait;
|
||||
use pgBackRest::Storage::Base;
|
||||
use pgBackRest::Storage::Storage;
|
||||
use pgBackRest::Version;
|
||||
|
||||
use pgBackRestTest::Common::BuildTest;
|
||||
use pgBackRestTest::Common::DefineTest;
|
||||
use pgBackRestTest::Common::ExecuteTest;
|
||||
use pgBackRestTest::Common::LogTest;
|
||||
use pgBackRestTest::Common::Storage;
|
||||
use pgBackRestTest::Common::StoragePosix;
|
||||
use pgBackRestTest::Common::VmTest;
|
||||
|
||||
####################################################################################################################################
|
||||
@ -156,7 +156,8 @@ sub process
|
||||
$self->{bFirstTest} = true;
|
||||
|
||||
# Initialize test storage
|
||||
$oStorage = new pgBackRest::Storage::Storage(STORAGE_LOCAL, {strPath => $self->testPath()});
|
||||
$oStorage = new pgBackRestTest::Common::Storage(
|
||||
$self->testPath(), new pgBackRestTest::Common::StoragePosix({bFileSync => false, bPathSync => false}));
|
||||
|
||||
# Generate backrest exe
|
||||
$self->{strBackRestExe} = defined($self->{strBackRestExeC}) ? $self->{strBackRestExeC} : $self->{strBackRestExeHelper};
|
||||
|
@ -221,7 +221,7 @@ sub stanzaSet
|
||||
new pgBackRest::Archive::Info($self->{oStorageRepo}->pathGet(STORAGE_REPO_ARCHIVE), false,
|
||||
{bIgnoreMissing => true, strCipherPassSub => $bEncrypted ? ENCRYPTION_KEY_ARCHIVE : undef});
|
||||
$oBackupInfo =
|
||||
new pgBackRest::Backup::Info($self->{oStorageRepo}->pathGet(STORAGE_REPO_BACKUP), false, false,
|
||||
new pgBackRest::Backup::Info($self->{oStorageRepo}->pathGet(STORAGE_REPO_BACKUP), false,
|
||||
{bIgnoreMissing => true, strCipherPassSub => $bEncrypted ? ENCRYPTION_KEY_MANIFEST : undef});
|
||||
}
|
||||
# Else get the info data from disk
|
||||
@ -260,7 +260,6 @@ sub stanzaSet
|
||||
# Get the archive and directory paths for the stanza
|
||||
$$oStanza{strArchiveClusterPath} = $self->{oStorageRepo}->pathGet(STORAGE_REPO_ARCHIVE) . '/' . ($oArchiveInfo->archiveId());
|
||||
$$oStanza{strBackupClusterPath} = $self->{oStorageRepo}->pathGet(STORAGE_REPO_BACKUP);
|
||||
storageRepo()->pathCreate($$oStanza{strArchiveClusterPath}, {bCreateParent => true});
|
||||
|
||||
$self->{oStanzaHash}{$strStanza} = $oStanza;
|
||||
|
||||
@ -301,15 +300,6 @@ sub stanzaCreate
|
||||
$self->controlGenerate($strDbPath, $strDbVersion);
|
||||
executeTest('chmod 600 ' . $strDbPath . '/' . DB_FILE_PGCONTROL);
|
||||
|
||||
# Create the stanza repo paths if they don't exist
|
||||
if (!cfgOptionTest(CFGOPT_REPO_TYPE, CFGOPTVAL_REPO_TYPE_S3))
|
||||
{
|
||||
storageTest()->pathCreate(
|
||||
cfgOption(CFGOPT_REPO_PATH) . "/archive/$strStanza", {bIgnoreExists => true, bCreateParent => true});
|
||||
storageTest()->pathCreate(
|
||||
cfgOption(CFGOPT_REPO_PATH) . "/backup/$strStanza", {bIgnoreExists => true, bCreateParent => true});
|
||||
}
|
||||
|
||||
# Create the stanza and set the local stanza object
|
||||
$self->stanzaSet($strStanza, $strDbVersion, false);
|
||||
|
||||
@ -398,7 +388,6 @@ sub backupCreate
|
||||
$lTimestamp);
|
||||
|
||||
my $strBackupClusterSetPath = "$$oStanza{strBackupClusterPath}/${strBackupLabel}";
|
||||
storageRepo()->pathCreate($strBackupClusterSetPath);
|
||||
|
||||
&log(INFO, "create backup ${strBackupLabel}");
|
||||
|
||||
@ -558,8 +547,6 @@ sub archiveCreate
|
||||
do
|
||||
{
|
||||
my $strPath = "$$oStanza{strArchiveClusterPath}/" . substr($strArchive, 0, 16);
|
||||
storageRepo()->pathCreate($strPath, {bIgnoreExists => true});
|
||||
|
||||
my $strFile = "${strPath}/${strArchive}-0000000000000000000000000000000000000000" . ($iArchiveIdx % 2 == 0 ? '.gz' : '');
|
||||
|
||||
storageRepo()->put($strFile, 'ARCHIVE', {strCipherPass => $strCipherPass});
|
||||
|
@ -102,12 +102,6 @@ sub new
|
||||
$self->{strRepoPath} = '/';
|
||||
}
|
||||
|
||||
# Create the repo-path if on a local filesystem
|
||||
if ($$oParam{strBackupDestination} eq $self->nameGet() && $oParam->{bRepoLocal})
|
||||
{
|
||||
storageTest()->pathCreate($self->repoPath(), {strMode => '0770'});
|
||||
}
|
||||
|
||||
# Set log/lock paths
|
||||
$self->{strLogPath} = $self->testPath() . '/' . HOST_PATH_LOG;
|
||||
storageTest()->pathCreate($self->{strLogPath}, {strMode => '0770'});
|
||||
@ -309,8 +303,11 @@ sub backupEnd
|
||||
}
|
||||
}
|
||||
}
|
||||
# Else there should not be a tablespace directory at all
|
||||
elsif (storageRepo()->pathExists(STORAGE_REPO_BACKUP . "/${strBackup}/" . MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGTBLSPC))
|
||||
# Else there should not be a tablespace directory at all. This is only valid for storage that supports links.
|
||||
elsif (storageRepo()->capability(STORAGE_CAPABILITY_LINK) &&
|
||||
storageTest()->pathExists(
|
||||
storageRepo()->pathGet(
|
||||
STORAGE_REPO_BACKUP . "/${strBackup}/" . MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGTBLSPC)))
|
||||
{
|
||||
confess &log(ERROR, 'backup must be full or hard-linked to have ' . DB_PATH_PGTBLSPC . ' directory');
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ sub run
|
||||
'184473f470864e067ee3a22e64b47b0a1c356f29', $lTime, undef, true);
|
||||
|
||||
# Load sample page
|
||||
my $tBasePage = ${storageLocal()->get($self->dataPath() . '/page.bin')};
|
||||
my $tBasePage = ${storageTest()->get($self->dataPath() . '/page.bin')};
|
||||
my $iBasePageChecksum = 0x1B99;
|
||||
|
||||
# Create base path
|
||||
@ -477,7 +477,7 @@ sub run
|
||||
strOptionalParam => '--force --' . cfgOptionName(CFGOPT_CHECKSUM_PAGE) . ($bDeltaBackup ? ' --delta' : '')});
|
||||
|
||||
# Remove postmaster.pid so restore will succeed (the rest will be cleaned up by the delta)
|
||||
storageDb->remove($oHostDbMaster->dbBasePath() . '/' . DB_FILE_POSTMASTERPID);
|
||||
storageTest->remove($oHostDbMaster->dbBasePath() . '/' . DB_FILE_POSTMASTERPID);
|
||||
|
||||
# Restore - tests various mode, extra files/paths, missing files/paths
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
@ -680,7 +680,7 @@ sub run
|
||||
$oManifest{&MANIFEST_SECTION_TARGET_FILE}{'pg_data/changetime.txt'}{&MANIFEST_SUBKEY_TIMESTAMP} = $lTime - 100;
|
||||
|
||||
# Change the content of the changecontent file to be the same size but leave the timestamp the same on the file
|
||||
storageDb()->put($oHostDbMaster->dbBasePath() . '/changecontent.txt', 'CHGCONT');
|
||||
storageTest()->put($oHostDbMaster->dbBasePath() . '/changecontent.txt', 'CHGCONT');
|
||||
utime($lTime, $lTime, $oHostDbMaster->dbBasePath() . '/changecontent.txt')
|
||||
or confess &log(ERROR, "unable to set time for file ".$oHostDbMaster->dbBasePath() . '/changecontent.txt');
|
||||
|
||||
|
@ -180,9 +180,9 @@ sub run
|
||||
$strCommandGet . " ${strSourceFile} ${strWalPath}/RECOVERYXLOG", {oLogTest => $self->expect()});
|
||||
|
||||
# Check that the destination file exists
|
||||
if (storageDb()->exists("${strWalPath}/RECOVERYXLOG"))
|
||||
if (storageTest()->exists("${strWalPath}/RECOVERYXLOG"))
|
||||
{
|
||||
my ($strActualChecksum) = storageDb()->hashSize("${strWalPath}/RECOVERYXLOG");
|
||||
my ($strActualChecksum) = storageTest()->hashSize("${strWalPath}/RECOVERYXLOG");
|
||||
|
||||
if ($strActualChecksum ne $strArchiveChecksum)
|
||||
{
|
||||
@ -344,9 +344,9 @@ sub run
|
||||
{oLogTest => $self->expect()});
|
||||
|
||||
# Check that the destination file exists
|
||||
if (storageDb()->exists("${strWalPath}/RECOVERYXLOG"))
|
||||
if (storageTest()->exists("${strWalPath}/RECOVERYXLOG"))
|
||||
{
|
||||
my ($strActualChecksum) = storageDb()->hashSize("${strWalPath}/RECOVERYXLOG");
|
||||
my ($strActualChecksum) = storageTest()->hashSize("${strWalPath}/RECOVERYXLOG");
|
||||
|
||||
if ($strActualChecksum ne $strArchiveChecksum)
|
||||
{
|
||||
@ -369,7 +369,7 @@ sub run
|
||||
$strCommandGet . " --archive-async 00000002.history ${strWalPath}/00000002.history",
|
||||
{oLogTest => $self->expect()});
|
||||
|
||||
if (${storageDb()->get("${strWalPath}/00000002.history")} ne 'HISTORYDATA')
|
||||
if (${storageTest()->get("${strWalPath}/00000002.history")} ne 'HISTORYDATA')
|
||||
{
|
||||
confess 'history contents do not match original';
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ sub run
|
||||
strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE) . ' --' . cfgOptionName(CFGOPT_LOG_LEVEL_FILE) . '=info'});
|
||||
|
||||
# Generate pg_control for stanza-create
|
||||
storageDb()->pathCreate(($oHostDbMaster->dbBasePath() . '/' . DB_PATH_GLOBAL), {bCreateParent => true});
|
||||
storageTest()->pathCreate(($oHostDbMaster->dbBasePath() . '/' . DB_PATH_GLOBAL), {bCreateParent => true});
|
||||
$self->controlGenerate($oHostDbMaster->dbBasePath(), PG_VERSION_93);
|
||||
|
||||
# Fail stanza upgrade before stanza-create has been performed
|
||||
@ -119,7 +119,7 @@ sub run
|
||||
|
||||
# Create the wal path
|
||||
my $strWalPath = $oHostDbMaster->dbBasePath() . '/pg_xlog';
|
||||
storageDb()->pathCreate("${strWalPath}/archive_status", {bCreateParent => true});
|
||||
storageTest()->pathCreate("${strWalPath}/archive_status", {bCreateParent => true});
|
||||
|
||||
# Stanza Create fails - missing archive.info from non-empty archive dir
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
@ -158,7 +158,7 @@ sub run
|
||||
|
||||
# Upgrade the DB by copying new pg_control
|
||||
$self->controlGenerate($oHostDbMaster->dbBasePath(), PG_VERSION_94);
|
||||
forceStorageMode(storageDb(), $oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL, '600');
|
||||
forceStorageMode(storageTest(), $oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL, '600');
|
||||
|
||||
# Fail on attempt to push an archive
|
||||
$oHostDbMaster->archivePush($strWalPath, $strArchiveTestFile, 1, ERROR_ARCHIVE_MISMATCH);
|
||||
@ -184,7 +184,7 @@ sub run
|
||||
|
||||
# Copy the new pg_control back so the tests can continue with the upgraded stanza
|
||||
$self->controlGenerate($oHostDbMaster->dbBasePath(), PG_VERSION_94);
|
||||
forceStorageMode(storageDb(), $oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL, '600');
|
||||
forceStorageMode(storageTest(), $oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL, '600');
|
||||
|
||||
# After stanza upgrade, make sure archives are pushed to the new db verion-id directory (9.4-2)
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
@ -206,7 +206,7 @@ sub run
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
# Copy pg_control for 9.5
|
||||
$self->controlGenerate($oHostDbMaster->dbBasePath(), PG_VERSION_95);
|
||||
forceStorageMode(storageDb(), $oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL, '600');
|
||||
forceStorageMode(storageTest(), $oHostDbMaster->dbBasePath() . '/' . DB_FILE_PGCONTROL, '600');
|
||||
|
||||
|
||||
$oHostBackup->stanzaUpgrade('successfully upgrade', {strOptionalParam => '--no-' . cfgOptionName(CFGOPT_ONLINE)});
|
||||
|
@ -324,7 +324,7 @@ sub run
|
||||
'fail on backup info file missing from non-empty dir', {iExpectedExitStatus => ERROR_PATH_NOT_EMPTY});
|
||||
|
||||
# Change the database version by copying a new pg_control file to a new pg-path to use for db mismatch test
|
||||
storageLocal()->pathCreate(
|
||||
storageTest()->pathCreate(
|
||||
$oHostDbMaster->dbPath() . '/testbase/' . DB_PATH_GLOBAL,
|
||||
{strMode => '0700', bIgnoreExists => true, bCreateParent => true});
|
||||
$self->controlGenerate(
|
||||
@ -774,7 +774,7 @@ sub run
|
||||
# Version <= 8.4 always places a PG_VERSION file in the tablespace
|
||||
if ($oHostDbMaster->pgVersion() <= PG_VERSION_84)
|
||||
{
|
||||
if (!storageLocal()->exists("${strTablespacePath}/" . DB_FILE_PGVERSION))
|
||||
if (!storageTest()->exists("${strTablespacePath}/" . DB_FILE_PGVERSION))
|
||||
{
|
||||
confess &log(ASSERT, "unable to find '" . DB_FILE_PGVERSION . "' in tablespace path '${strTablespacePath}'");
|
||||
}
|
||||
@ -792,14 +792,14 @@ sub run
|
||||
'/PG_' . $oHostDbMaster->pgVersion() . qw{_} . $oBackupInfo->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_CATALOG);
|
||||
|
||||
# Check that path exists
|
||||
if (!storageLocal()->pathExists($strTablespacePath))
|
||||
if (!storageTest()->pathExists($strTablespacePath))
|
||||
{
|
||||
confess &log(ASSERT, "unable to find tablespace path '${strTablespacePath}'");
|
||||
}
|
||||
}
|
||||
|
||||
# Make sure there are some files in the tablespace path (exclude PG_VERSION if <= 8.4 since that was tested above)
|
||||
if (grep(!/^PG\_VERSION$/i, storageLocal()->list($strTablespacePath)) == 0)
|
||||
if (grep(!/^PG\_VERSION$/i, storageTest()->list($strTablespacePath)) == 0)
|
||||
{
|
||||
confess &log(ASSERT, "no files found in tablespace path '${strTablespacePath}'");
|
||||
}
|
||||
@ -869,7 +869,7 @@ sub run
|
||||
# Save recovery file to test so we can use it in the next test
|
||||
$strRecoveryFile = $oHostDbMaster->pgVersion() >= PG_VERSION_12 ? 'postgresql.auto.conf' : DB_FILE_RECOVERYCONF;
|
||||
|
||||
storageLocal()->copy(
|
||||
storageTest()->copy(
|
||||
$oHostDbMaster->dbBasePath() . qw{/} . $strRecoveryFile, $self->testPath() . qw{/} . $strRecoveryFile);
|
||||
|
||||
$oHostDbMaster->clusterStart();
|
||||
@ -891,12 +891,12 @@ sub run
|
||||
executeTest('rm -rf ' . $oHostDbMaster->tablespacePath(1) . "/*");
|
||||
|
||||
# Restore recovery file that was saved in last test
|
||||
storageLocal()->move($self->testPath . "/${strRecoveryFile}", $oHostDbMaster->dbBasePath() . "/${strRecoveryFile}");
|
||||
storageTest()->move($self->testPath . "/${strRecoveryFile}", $oHostDbMaster->dbBasePath() . "/${strRecoveryFile}");
|
||||
|
||||
# Also touch recovery.signal when required
|
||||
if ($oHostDbMaster->pgVersion() >= PG_VERSION_12)
|
||||
{
|
||||
storageDb()->put($oHostDbMaster->dbBasePath() . "/" . DB_FILE_RECOVERYSIGNAL);
|
||||
storageTest()->put($oHostDbMaster->dbBasePath() . "/" . DB_FILE_RECOVERYSIGNAL);
|
||||
}
|
||||
|
||||
$oHostDbMaster->restore(
|
||||
|
Loading…
x
Reference in New Issue
Block a user