You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-07-03 00:26:59 +02:00
The info command is implemented entirely in C.
The C info code has already been committed but this commit wires it into main. Also remove the info Perl code and tests since they are no longer called.
This commit is contained in:
@ -15,6 +15,10 @@
|
|||||||
<release date="XXXX-XX-XX" version="2.09dev" title="UNDER DEVELOPMENT">
|
<release date="XXXX-XX-XX" version="2.09dev" title="UNDER DEVELOPMENT">
|
||||||
<release-core-list>
|
<release-core-list>
|
||||||
<release-improvement-list>
|
<release-improvement-list>
|
||||||
|
<release-item>
|
||||||
|
<p>The <cmd>info</cmd> command is implemented entirely in C.</p>
|
||||||
|
</release-item>
|
||||||
|
|
||||||
<release-item>
|
<release-item>
|
||||||
<p>Simplify <cmd>info</cmd> command text message when no stanza are present by replacing the repository path with <quote>the repository</quote>.</p>
|
<p>Simplify <cmd>info</cmd> command text message when no stanza are present by replacing the repository path with <quote>the repository</quote>.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
@ -1,748 +0,0 @@
|
|||||||
####################################################################################################################################
|
|
||||||
# INFO MODULE
|
|
||||||
####################################################################################################################################
|
|
||||||
package pgBackRest::Info;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings FATAL => qw(all);
|
|
||||||
use Carp qw(confess);
|
|
||||||
|
|
||||||
use English '-no_match_vars';
|
|
||||||
use Exporter qw(import);
|
|
||||||
our @EXPORT = qw();
|
|
||||||
use File::Basename qw(dirname);
|
|
||||||
|
|
||||||
use pgBackRest::Backup::Common;
|
|
||||||
use pgBackRest::Backup::Info;
|
|
||||||
use pgBackRest::Common::Exception;
|
|
||||||
use pgBackRest::Common::Log;
|
|
||||||
use pgBackRest::Common::Ini;
|
|
||||||
use pgBackRest::Common::String;
|
|
||||||
use pgBackRest::Backup::Common;
|
|
||||||
use pgBackRest::Backup::Info;
|
|
||||||
use pgBackRest::Config::Config;
|
|
||||||
use pgBackRest::InfoCommon;
|
|
||||||
use pgBackRest::Manifest;
|
|
||||||
use pgBackRest::Protocol::Helper;
|
|
||||||
use pgBackRest::Protocol::Storage::Helper;
|
|
||||||
use pgBackRest::Storage::Helper;
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# Info constants
|
|
||||||
####################################################################################################################################
|
|
||||||
use constant INFO_SECTION_BACKREST => 'backrest';
|
|
||||||
use constant INFO_SECTION_ARCHIVE => 'archive';
|
|
||||||
use constant INFO_SECTION_DB => 'database';
|
|
||||||
use constant INFO_SECTION_INFO => 'info';
|
|
||||||
use constant INFO_SECTION_REPO => 'repository';
|
|
||||||
use constant INFO_SECTION_TIMESTAMP => 'timestamp';
|
|
||||||
use constant INFO_SECTION_STATUS => 'status';
|
|
||||||
use constant INFO_SECTION_CIPHER => 'cipher';
|
|
||||||
|
|
||||||
use constant INFO_STANZA_NAME => 'name';
|
|
||||||
|
|
||||||
use constant INFO_STANZA_STATUS_OK => 'ok';
|
|
||||||
use constant INFO_STANZA_STATUS_ERROR => 'error';
|
|
||||||
|
|
||||||
use constant INFO_STANZA_STATUS_OK_CODE => 0;
|
|
||||||
use constant INFO_STANZA_STATUS_OK_MESSAGE => INFO_STANZA_STATUS_OK;
|
|
||||||
use constant INFO_STANZA_STATUS_MISSING_STANZA_CODE => 1;
|
|
||||||
use constant INFO_STANZA_STATUS_MISSING_STANZA_MESSAGE => 'missing stanza path';
|
|
||||||
use constant INFO_STANZA_STATUS_NO_BACKUP_CODE => 2;
|
|
||||||
use constant INFO_STANZA_STATUS_NO_BACKUP_MESSAGE => 'no valid backups';
|
|
||||||
use constant INFO_STANZA_STATUS_MISSING_STANZA_DATA_CODE => 3;
|
|
||||||
use constant INFO_STANZA_STATUS_MISSING_STANZA_DATA_MESSAGE => 'missing stanza data';
|
|
||||||
|
|
||||||
use constant INFO_KEY_CODE => 'code';
|
|
||||||
use constant INFO_KEY_DELTA => 'delta';
|
|
||||||
use constant INFO_KEY_FORMAT => 'format';
|
|
||||||
use constant INFO_KEY_ID => INFO_HISTORY_ID;
|
|
||||||
use constant INFO_KEY_LABEL => 'label';
|
|
||||||
use constant INFO_KEY_MAX => 'max';
|
|
||||||
use constant INFO_KEY_MIN => 'min';
|
|
||||||
use constant INFO_KEY_MESSAGE => 'message';
|
|
||||||
use constant INFO_KEY_PRIOR => 'prior';
|
|
||||||
use constant INFO_KEY_REFERENCE => 'reference';
|
|
||||||
use constant INFO_KEY_SIZE => 'size';
|
|
||||||
use constant INFO_KEY_START => 'start';
|
|
||||||
use constant INFO_KEY_STOP => 'stop';
|
|
||||||
use constant INFO_KEY_SYSTEM_ID => INFO_SYSTEM_ID;
|
|
||||||
use constant INFO_KEY_TYPE => 'type';
|
|
||||||
use constant INFO_KEY_VERSION => INFO_DB_VERSION;
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# CONSTRUCTOR
|
|
||||||
####################################################################################################################################
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift; # Class name
|
|
||||||
|
|
||||||
# Create the class hash
|
|
||||||
my $self = {};
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
# Assign function parameters, defaults, and log debug info
|
|
||||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->new');
|
|
||||||
|
|
||||||
# Return from function and log return values if any
|
|
||||||
return logDebugReturn
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
{name => 'self', value => $self}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# process
|
|
||||||
####################################################################################################################################
|
|
||||||
sub process
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Assign function parameters, defaults, and log debug info
|
|
||||||
my ($strOperation) = logDebugParam(__PACKAGE__ . '->process');
|
|
||||||
|
|
||||||
# Get stanza if specified
|
|
||||||
my $strStanza = cfgOptionTest(CFGOPT_STANZA) ? cfgOption(CFGOPT_STANZA) : undef;
|
|
||||||
|
|
||||||
# Get the stanza list with all info
|
|
||||||
my $oyStanzaList = $self->stanzaList($strStanza);
|
|
||||||
|
|
||||||
if (cfgOptionTest(CFGOPT_OUTPUT, CFGOPTVAL_INFO_OUTPUT_TEXT))
|
|
||||||
{
|
|
||||||
my $strOutput = $self->formatText($oyStanzaList);
|
|
||||||
|
|
||||||
if (defined($strOutput))
|
|
||||||
{
|
|
||||||
syswrite(*STDOUT, $strOutput);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
syswrite(*STDOUT, "No stanzas exist in the repository.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elsif (cfgOptionTest(CFGOPT_OUTPUT, CFGOPTVAL_INFO_OUTPUT_JSON))
|
|
||||||
{
|
|
||||||
my $oJSON = JSON::PP->new()->canonical()->pretty()->indent_length(4);
|
|
||||||
$self->outputJSON($oJSON->encode($oyStanzaList));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
confess &log(ASSERT, "invalid info output option '" . cfgOption(CFGOPT_OUTPUT) . "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return from function and log return values if any
|
|
||||||
return logDebugReturn($strOperation);
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# outputJSON
|
|
||||||
###################################################################################################################################
|
|
||||||
sub outputJSON
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Assign function parameters, defaults, and log debug info
|
|
||||||
my
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
$strJSON,
|
|
||||||
) =
|
|
||||||
logDebugParam
|
|
||||||
(
|
|
||||||
__PACKAGE__ . '->outputJSON', \@_,
|
|
||||||
{name => 'strJSON'},
|
|
||||||
);
|
|
||||||
|
|
||||||
syswrite(*STDOUT, $strJSON);
|
|
||||||
|
|
||||||
# On some systems a linefeed will be appended by encode() but others will not have it. In our case there should always
|
|
||||||
# be a terminating linefeed.
|
|
||||||
if ($strJSON !~ /\n$/)
|
|
||||||
{
|
|
||||||
syswrite(*STDOUT, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# formatText
|
|
||||||
#
|
|
||||||
# Format --output=text info.
|
|
||||||
####################################################################################################################################
|
|
||||||
sub formatText
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Assign function parameters, defaults, and log debug info
|
|
||||||
my
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
$oyStanzaList,
|
|
||||||
) =
|
|
||||||
logDebugParam
|
|
||||||
(
|
|
||||||
__PACKAGE__ . '->formatText', \@_,
|
|
||||||
{name => 'oyStanzaList', trace => true},
|
|
||||||
);
|
|
||||||
|
|
||||||
my $strOutput;
|
|
||||||
|
|
||||||
foreach my $oStanzaInfo (@{$oyStanzaList})
|
|
||||||
{
|
|
||||||
# Output stanza name and status
|
|
||||||
$strOutput .= (defined($strOutput) ? "\n" : '') . $self->formatTextStanza($oStanzaInfo) . "\n";
|
|
||||||
|
|
||||||
# Get the current DB info (always last element in the array)
|
|
||||||
my $hDbCurrent = @{$oStanzaInfo->{&INFO_BACKUP_SECTION_DB}}[-1];
|
|
||||||
|
|
||||||
# Loop through the DB history array for the stanza from oldest to newest
|
|
||||||
foreach my $hDbInfo (@{$oStanzaInfo->{&INFO_BACKUP_SECTION_DB}})
|
|
||||||
{
|
|
||||||
|
|
||||||
if ($hDbInfo->{&INFO_HISTORY_ID} == $hDbCurrent->{&INFO_HISTORY_ID})
|
|
||||||
{
|
|
||||||
$strOutput .= "\n db (current)";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get the archive information for the DB
|
|
||||||
my $strOutputArchive;
|
|
||||||
foreach my $hDbArchive (@{$oStanzaInfo->{&INFO_SECTION_ARCHIVE}})
|
|
||||||
{
|
|
||||||
if ($hDbArchive->{&INFO_SECTION_DB}{&INFO_HISTORY_ID} == $hDbInfo->{&INFO_HISTORY_ID})
|
|
||||||
{
|
|
||||||
# Output archive start / stop values
|
|
||||||
$strOutputArchive .= "\n wal archive min/max (" . $hDbArchive->{&INFO_KEY_ID} . "): ";
|
|
||||||
|
|
||||||
if (defined($hDbArchive->{&INFO_KEY_MIN}))
|
|
||||||
{
|
|
||||||
$strOutputArchive .= $hDbArchive->{&INFO_KEY_MIN} . ' / ' . $hDbArchive->{&INFO_KEY_MAX};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$strOutputArchive .= 'none present';
|
|
||||||
}
|
|
||||||
|
|
||||||
$strOutputArchive .= "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get information for each stanza backup for the DB, from oldest to newest
|
|
||||||
my $strOutputBackup;
|
|
||||||
foreach my $oBackupInfo (@{$$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}})
|
|
||||||
{
|
|
||||||
if ($oBackupInfo->{&INFO_SECTION_DB}{&INFO_KEY_ID} == $hDbInfo->{&INFO_HISTORY_ID})
|
|
||||||
{
|
|
||||||
$strOutputBackup .= "\n" . $self->formatTextBackup($oBackupInfo) . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($strOutputArchive) || defined($strOutputBackup))
|
|
||||||
{
|
|
||||||
if ($hDbInfo->{&INFO_HISTORY_ID} != $hDbCurrent->{&INFO_HISTORY_ID})
|
|
||||||
{
|
|
||||||
$strOutput .= "\n db (prior)";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($strOutputArchive))
|
|
||||||
{
|
|
||||||
$strOutput .= $strOutputArchive;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($strOutputBackup))
|
|
||||||
{
|
|
||||||
$strOutput .= $strOutputBackup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return from function and log return values if any
|
|
||||||
return logDebugReturn
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
{name => 'strOutput', value => $strOutput, trace => true}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# formatTextStanza
|
|
||||||
#
|
|
||||||
# Format --output=text stanza info.
|
|
||||||
####################################################################################################################################
|
|
||||||
sub formatTextStanza
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Assign function parameters, defaults, and log debug info
|
|
||||||
my
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
$oStanzaInfo,
|
|
||||||
) =
|
|
||||||
logDebugParam
|
|
||||||
(
|
|
||||||
__PACKAGE__ . '->formatTextStanza', \@_,
|
|
||||||
{name => 'oStanzaInfo', trace => true},
|
|
||||||
);
|
|
||||||
|
|
||||||
# Output stanza name, status and cipher type
|
|
||||||
my $strOutput =
|
|
||||||
'stanza: ' . $oStanzaInfo->{&INFO_STANZA_NAME} . "\n" .
|
|
||||||
" status: " . ($oStanzaInfo->{&INFO_SECTION_STATUS}{&INFO_KEY_CODE} == 0 ? INFO_STANZA_STATUS_OK :
|
|
||||||
INFO_STANZA_STATUS_ERROR . ' (' . $oStanzaInfo->{&INFO_SECTION_STATUS}{&INFO_KEY_MESSAGE} . ')') .
|
|
||||||
(defined($oStanzaInfo->{&INFO_SECTION_CIPHER}) ? "\n cipher: " . $oStanzaInfo->{&INFO_SECTION_CIPHER} : '');
|
|
||||||
|
|
||||||
# Return from function and log return values if any
|
|
||||||
return logDebugReturn
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
{name => 'strOutput', value => $strOutput, trace => true}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# formatTextBackup
|
|
||||||
#
|
|
||||||
# Format --output=text backup info.
|
|
||||||
####################################################################################################################################
|
|
||||||
sub formatTextBackup
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Assign function parameters, defaults, and log debug info
|
|
||||||
my
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
$oBackupInfo,
|
|
||||||
) =
|
|
||||||
logDebugParam
|
|
||||||
(
|
|
||||||
__PACKAGE__ . '->formatTextBackup', \@_,
|
|
||||||
{name => 'oBackupInfo', trace => true},
|
|
||||||
);
|
|
||||||
|
|
||||||
my $strOutput =
|
|
||||||
' ' . $$oBackupInfo{&INFO_KEY_TYPE} . ' backup: ' . $$oBackupInfo{&INFO_KEY_LABEL} . "\n" .
|
|
||||||
|
|
||||||
' timestamp start/stop: ' .
|
|
||||||
timestampFormat(undef, $$oBackupInfo{&INFO_SECTION_TIMESTAMP}{&INFO_KEY_START}) .
|
|
||||||
' / ' .
|
|
||||||
timestampFormat(undef, $$oBackupInfo{&INFO_SECTION_TIMESTAMP}{&INFO_KEY_STOP}) . "\n" .
|
|
||||||
|
|
||||||
" wal start/stop: ";
|
|
||||||
|
|
||||||
if (defined($oBackupInfo->{&INFO_SECTION_ARCHIVE}{&INFO_KEY_START}) &&
|
|
||||||
defined($oBackupInfo->{&INFO_SECTION_ARCHIVE}{&INFO_KEY_STOP}))
|
|
||||||
{
|
|
||||||
$strOutput .=
|
|
||||||
$oBackupInfo->{&INFO_SECTION_ARCHIVE}{&INFO_KEY_START} . ' / ' . $oBackupInfo->{&INFO_SECTION_ARCHIVE}{&INFO_KEY_STOP};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$strOutput .= 'n/a';
|
|
||||||
}
|
|
||||||
|
|
||||||
$strOutput .=
|
|
||||||
"\n database size: " .
|
|
||||||
(defined($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_KEY_SIZE}) ?
|
|
||||||
fileSizeFormat($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_KEY_SIZE}) : '') .
|
|
||||||
', backup size: ' .
|
|
||||||
(defined($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_KEY_DELTA}) ?
|
|
||||||
fileSizeFormat($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_KEY_DELTA}) : '') . "\n" .
|
|
||||||
|
|
||||||
' repository size: ' .
|
|
||||||
(defined($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_SECTION_REPO}{&INFO_KEY_SIZE}) ?
|
|
||||||
fileSizeFormat($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_SECTION_REPO}{&INFO_KEY_SIZE}) : '') .
|
|
||||||
', repository backup size: ' .
|
|
||||||
(defined($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_SECTION_REPO}{&INFO_KEY_DELTA}) ?
|
|
||||||
fileSizeFormat($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_SECTION_REPO}{&INFO_KEY_DELTA}) : '');
|
|
||||||
|
|
||||||
# List the backup reference chain, if any, for this backup
|
|
||||||
if (defined($oBackupInfo->{&INFO_KEY_REFERENCE}) && @{$oBackupInfo->{&INFO_KEY_REFERENCE}} > 0)
|
|
||||||
{
|
|
||||||
$strOutput .= "\n backup reference list: " . (join(', ', @{$$oBackupInfo{&INFO_KEY_REFERENCE}}));
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return from function and log return values if any
|
|
||||||
return logDebugReturn
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
{name => 'strOutput', value => $strOutput, trace => true}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# stanzaList
|
|
||||||
####################################################################################################################################
|
|
||||||
sub stanzaList
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Assign function parameters, defaults, and log debug info
|
|
||||||
my
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
$strStanza
|
|
||||||
) =
|
|
||||||
logDebugParam
|
|
||||||
(
|
|
||||||
__PACKAGE__ . '->stanzaList', \@_,
|
|
||||||
{name => 'strStanza', required => false}
|
|
||||||
);
|
|
||||||
|
|
||||||
my @oyStanzaList;
|
|
||||||
|
|
||||||
# Run remotely
|
|
||||||
if (!isRepoLocal())
|
|
||||||
{
|
|
||||||
@oyStanzaList = @{protocolGet(CFGOPTVAL_REMOTE_TYPE_BACKUP)->cmdExecute(OP_INFO_STANZA_LIST, [$strStanza], true)};
|
|
||||||
}
|
|
||||||
# Run locally
|
|
||||||
else
|
|
||||||
{
|
|
||||||
my @stryStanza = storageRepo()->list(cfgCommandName(CFGCMD_BACKUP), {bIgnoreMissing => true});
|
|
||||||
|
|
||||||
foreach my $strStanzaFound (@stryStanza)
|
|
||||||
{
|
|
||||||
if (defined($strStanza) && $strStanza ne $strStanzaFound)
|
|
||||||
{
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $oStanzaInfo = {};
|
|
||||||
$$oStanzaInfo{&INFO_STANZA_NAME} = $strStanzaFound;
|
|
||||||
($$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}, $$oStanzaInfo{&INFO_BACKUP_SECTION_DB}) =
|
|
||||||
$self->backupList($strStanzaFound);
|
|
||||||
|
|
||||||
# If there are no backups then set status to no backup
|
|
||||||
if (defined($$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}) && @{$$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}} == 0)
|
|
||||||
{
|
|
||||||
$$oStanzaInfo{&INFO_SECTION_STATUS} =
|
|
||||||
{
|
|
||||||
&INFO_KEY_CODE => INFO_STANZA_STATUS_NO_BACKUP_CODE,
|
|
||||||
&INFO_KEY_MESSAGE => INFO_STANZA_STATUS_NO_BACKUP_MESSAGE
|
|
||||||
};
|
|
||||||
}
|
|
||||||
# Else status is OK
|
|
||||||
elsif (defined($$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}))
|
|
||||||
{
|
|
||||||
$$oStanzaInfo{&INFO_SECTION_STATUS} =
|
|
||||||
{
|
|
||||||
&INFO_KEY_CODE => INFO_STANZA_STATUS_OK_CODE,
|
|
||||||
&INFO_KEY_MESSAGE => INFO_STANZA_STATUS_OK_MESSAGE
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
$$oStanzaInfo{&INFO_SECTION_CIPHER} = defined(storageRepo({strStanza => $strStanzaFound})->cipherType()) ?
|
|
||||||
storageRepo({strStanza => $strStanzaFound})->cipherType() : CFGOPTVAL_REPO_CIPHER_TYPE_NONE;
|
|
||||||
|
|
||||||
# Array to store tne min/max archive for each database for which there are archives
|
|
||||||
my @oyDbArchiveList = ();
|
|
||||||
|
|
||||||
if (!defined($$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}))
|
|
||||||
{
|
|
||||||
$$oStanzaInfo{&INFO_SECTION_STATUS} =
|
|
||||||
{
|
|
||||||
&INFO_KEY_CODE => INFO_STANZA_STATUS_MISSING_STANZA_DATA_CODE,
|
|
||||||
&INFO_KEY_MESSAGE => INFO_STANZA_STATUS_MISSING_STANZA_DATA_MESSAGE
|
|
||||||
};
|
|
||||||
|
|
||||||
$$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP} = [];
|
|
||||||
$$oStanzaInfo{&INFO_BACKUP_SECTION_DB} = [];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
# Get the current DB info (always last element in the array)
|
|
||||||
my $hDbCurrent = @{$oStanzaInfo->{&INFO_BACKUP_SECTION_DB}}[-1];
|
|
||||||
my $strDbCurrentVersion = $hDbCurrent->{&INFO_KEY_VERSION};
|
|
||||||
my $ullDbCurrentSystemId = $hDbCurrent->{&INFO_KEY_SYSTEM_ID};
|
|
||||||
|
|
||||||
# Loop through the DB history from oldest to newest
|
|
||||||
foreach my $hDbInfo (@{$oStanzaInfo->{&INFO_BACKUP_SECTION_DB}})
|
|
||||||
{
|
|
||||||
my $strArchiveStanzaPath = "archive/" . $strStanzaFound;
|
|
||||||
my $strDbVersion = $hDbInfo->{&INFO_KEY_VERSION};
|
|
||||||
my $ullDbSysId = $hDbInfo->{&INFO_KEY_SYSTEM_ID};
|
|
||||||
|
|
||||||
# With multiple DB versions, the backup.info history-id may not be the same as archive.info history-id, so the
|
|
||||||
# archive path must be built by retrieving the archive id given the db version and system id of the backup
|
|
||||||
my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet($strArchiveStanzaPath));
|
|
||||||
my $strArchiveId = $oArchiveInfo->archiveId({strDbVersion => $hDbInfo->{&INFO_KEY_VERSION},
|
|
||||||
ullDbSysId => $hDbInfo->{&INFO_KEY_SYSTEM_ID}});
|
|
||||||
my $strArchivePath = "archive/${strStanzaFound}/${strArchiveId}";
|
|
||||||
|
|
||||||
# Fill in the archive info if available
|
|
||||||
my $hDbArchive = $self->dbArchiveSection($hDbInfo, $strArchiveId, $strArchivePath, $strDbCurrentVersion,
|
|
||||||
$ullDbCurrentSystemId);
|
|
||||||
|
|
||||||
if (defined($hDbArchive))
|
|
||||||
{
|
|
||||||
push(@oyDbArchiveList, $hDbArchive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Store the archive min/max for each database in the archive section
|
|
||||||
$oStanzaInfo->{&INFO_SECTION_ARCHIVE} = \@oyDbArchiveList;
|
|
||||||
|
|
||||||
push @oyStanzaList, $oStanzaInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($strStanza) && @oyStanzaList == 0)
|
|
||||||
{
|
|
||||||
my $oStanzaInfo = {};
|
|
||||||
|
|
||||||
$$oStanzaInfo{&INFO_STANZA_NAME} = $strStanza;
|
|
||||||
|
|
||||||
$$oStanzaInfo{&INFO_SECTION_STATUS} =
|
|
||||||
{
|
|
||||||
&INFO_KEY_CODE => INFO_STANZA_STATUS_MISSING_STANZA_CODE,
|
|
||||||
&INFO_KEY_MESSAGE => INFO_STANZA_STATUS_MISSING_STANZA_MESSAGE
|
|
||||||
};
|
|
||||||
|
|
||||||
$$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP} = [];
|
|
||||||
$$oStanzaInfo{&INFO_BACKUP_SECTION_DB} = [];
|
|
||||||
|
|
||||||
push @oyStanzaList, $oStanzaInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return from function and log return values if any
|
|
||||||
return logDebugReturn
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
{name => 'oyStanzaList', value => \@oyStanzaList, log => false, ref => true}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# backupList
|
|
||||||
###################################################################################################################################
|
|
||||||
sub backupList
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Assign function parameters, defaults, and log debug info
|
|
||||||
my
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
$strStanza
|
|
||||||
) =
|
|
||||||
logDebugParam
|
|
||||||
(
|
|
||||||
__PACKAGE__ . '->backupList', \@_,
|
|
||||||
{name => 'strStanza'}
|
|
||||||
);
|
|
||||||
|
|
||||||
# Load the backup.info but do not attempt to validate it
|
|
||||||
my $oBackupInfo = undef;
|
|
||||||
|
|
||||||
# Turn off console logging to control when to display the error
|
|
||||||
logDisable();
|
|
||||||
|
|
||||||
eval
|
|
||||||
{
|
|
||||||
$oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(cfgCommandName(CFGCMD_BACKUP) . "/${strStanza}"), false);
|
|
||||||
logEnable();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
or do
|
|
||||||
{
|
|
||||||
logEnable();
|
|
||||||
|
|
||||||
if (exceptionCode($EVAL_ERROR) == ERROR_FILE_MISSING)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
elsif (exceptionCode($EVAL_ERROR) == ERROR_CRYPTO)
|
|
||||||
{
|
|
||||||
# Confess the encryption error with additional hint
|
|
||||||
confess &log(ERROR, exceptionMessage($EVAL_ERROR) .
|
|
||||||
"\nHINT: use option --stanza if encryption settings are different for the stanza than the global settings",
|
|
||||||
ERROR_CRYPTO);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
# Confess unhandled errors
|
|
||||||
confess $EVAL_ERROR;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
# Build the db list
|
|
||||||
my @oyDbList;
|
|
||||||
|
|
||||||
foreach my $iHistoryId ($oBackupInfo->keys(INFO_BACKUP_SECTION_DB_HISTORY))
|
|
||||||
{
|
|
||||||
my $oDbHash =
|
|
||||||
{
|
|
||||||
&INFO_HISTORY_ID => $iHistoryId + 0,
|
|
||||||
&INFO_DB_VERSION =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_DB_HISTORY, $iHistoryId, INFO_BACKUP_KEY_DB_VERSION),
|
|
||||||
&INFO_SYSTEM_ID =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_DB_HISTORY, $iHistoryId, INFO_BACKUP_KEY_SYSTEM_ID)
|
|
||||||
};
|
|
||||||
|
|
||||||
push(@oyDbList, $oDbHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build the backup list
|
|
||||||
my @oyBackupList;
|
|
||||||
|
|
||||||
foreach my $strBackup ($oBackupInfo->keys(INFO_BACKUP_SECTION_BACKUP_CURRENT))
|
|
||||||
{
|
|
||||||
my $oBackupHash =
|
|
||||||
{
|
|
||||||
&INFO_SECTION_ARCHIVE =>
|
|
||||||
{
|
|
||||||
&INFO_KEY_START =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_ARCHIVE_START, false),
|
|
||||||
&INFO_KEY_STOP =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_ARCHIVE_STOP, false),
|
|
||||||
},
|
|
||||||
&INFO_SECTION_BACKREST =>
|
|
||||||
{
|
|
||||||
&INFO_KEY_FORMAT =>
|
|
||||||
$oBackupInfo->numericGet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INI_KEY_FORMAT),
|
|
||||||
&INFO_KEY_VERSION =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INI_KEY_VERSION)
|
|
||||||
},
|
|
||||||
&INFO_SECTION_DB =>
|
|
||||||
{
|
|
||||||
&INFO_KEY_ID =>
|
|
||||||
$oBackupInfo->numericGet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_HISTORY_ID)
|
|
||||||
},
|
|
||||||
&INFO_SECTION_INFO =>
|
|
||||||
{
|
|
||||||
&INFO_SECTION_REPO =>
|
|
||||||
{
|
|
||||||
# Size of the backup in the repository, taking compression into account
|
|
||||||
&INFO_KEY_SIZE =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_BACKUP_REPO_SIZE),
|
|
||||||
# Size of this backup only (does not include referenced backups like repo->size)
|
|
||||||
&INFO_KEY_DELTA =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_BACKUP_REPO_SIZE_DELTA),
|
|
||||||
},
|
|
||||||
# Original database size
|
|
||||||
&INFO_KEY_SIZE =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_BACKUP_SIZE),
|
|
||||||
# Amount of database backed up (will be equal for full backups)
|
|
||||||
&INFO_KEY_DELTA =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_BACKUP_SIZE_DELTA),
|
|
||||||
},
|
|
||||||
&INFO_SECTION_TIMESTAMP =>
|
|
||||||
{
|
|
||||||
&INFO_KEY_START =>
|
|
||||||
$oBackupInfo->numericGet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_TIMESTAMP_START),
|
|
||||||
&INFO_KEY_STOP =>
|
|
||||||
$oBackupInfo->numericGet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_TIMESTAMP_STOP),
|
|
||||||
},
|
|
||||||
&INFO_KEY_LABEL => $strBackup,
|
|
||||||
&INFO_KEY_PRIOR =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_PRIOR, false),
|
|
||||||
&INFO_KEY_REFERENCE =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_REFERENCE, false),
|
|
||||||
&INFO_KEY_TYPE =>
|
|
||||||
$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_TYPE)
|
|
||||||
};
|
|
||||||
|
|
||||||
push(@oyBackupList, $oBackupHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return from function and log return values if any
|
|
||||||
return logDebugReturn
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
{name => 'oyBackupList', value => \@oyBackupList, log => false, ref => true},
|
|
||||||
{name => 'oyDbList', value => \@oyDbList, log => false, ref => true}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# dbArchiveSection - fills the archive section for a db. Note this is a function in order to aid unit test coverage.
|
|
||||||
####################################################################################################################################
|
|
||||||
sub dbArchiveSection
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Assign function parameters, defaults, and log debug info
|
|
||||||
my
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
$hDbInfo,
|
|
||||||
$strArchiveId,
|
|
||||||
$strArchivePath,
|
|
||||||
$strDbCurrentVersion,
|
|
||||||
$ullDbCurrentSystemId,
|
|
||||||
) =
|
|
||||||
logDebugParam
|
|
||||||
(
|
|
||||||
__PACKAGE__ . '->dbArchiveSection', \@_,
|
|
||||||
{name => 'hDbInfo'},
|
|
||||||
{name => 'strArchiveId'},
|
|
||||||
{name => 'strArchivePath'},
|
|
||||||
{name => 'strDbCurrentVersion'},
|
|
||||||
{name => 'ullDbCurrentSystemId'},
|
|
||||||
);
|
|
||||||
|
|
||||||
my $hDbArchive = undef;
|
|
||||||
my $strArchiveStart = undef;
|
|
||||||
my $strArchiveStop = undef;
|
|
||||||
|
|
||||||
if (storageRepo()->pathExists($strArchivePath))
|
|
||||||
{
|
|
||||||
my @stryWalMajor = storageRepo()->list($strArchivePath, {strExpression => '^[0-F]{16}$'});
|
|
||||||
|
|
||||||
# Get first WAL segment
|
|
||||||
foreach my $strWalMajor (@stryWalMajor)
|
|
||||||
{
|
|
||||||
my @stryWalFile = storageRepo()->list(
|
|
||||||
"${strArchivePath}/${strWalMajor}",
|
|
||||||
{strExpression => "^[0-F]{24}-[0-f]{40}(\\." . COMPRESS_EXT . "){0,1}\$"});
|
|
||||||
|
|
||||||
if (@stryWalFile > 0)
|
|
||||||
{
|
|
||||||
$strArchiveStart = substr($stryWalFile[0], 0, 24);
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get last WAL segment
|
|
||||||
foreach my $strWalMajor (sort({$b cmp $a} @stryWalMajor))
|
|
||||||
{
|
|
||||||
my @stryWalFile = storageRepo()->list(
|
|
||||||
"${strArchivePath}/${strWalMajor}",
|
|
||||||
{strExpression => "^[0-F]{24}-[0-f]{40}(\\." . COMPRESS_EXT . "){0,1}\$", strSortOrder => 'reverse'});
|
|
||||||
|
|
||||||
if (@stryWalFile > 0)
|
|
||||||
{
|
|
||||||
$strArchiveStop = substr($stryWalFile[0], 0, 24);
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# If there is an archive or the database is the current database then store it
|
|
||||||
if (($strDbCurrentVersion eq $hDbInfo->{&INFO_KEY_VERSION} &&
|
|
||||||
$ullDbCurrentSystemId == $hDbInfo->{&INFO_KEY_SYSTEM_ID}) ||
|
|
||||||
defined($strArchiveStart) )
|
|
||||||
{
|
|
||||||
$hDbArchive =
|
|
||||||
{
|
|
||||||
&INFO_KEY_ID => $strArchiveId,
|
|
||||||
&INFO_KEY_MIN => $strArchiveStart,
|
|
||||||
&INFO_KEY_MAX => $strArchiveStop,
|
|
||||||
&INFO_SECTION_DB =>
|
|
||||||
{
|
|
||||||
&INFO_HISTORY_ID => $hDbInfo->{&INFO_HISTORY_ID} + 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
# Return from function and log return values if any
|
|
||||||
return logDebugReturn
|
|
||||||
(
|
|
||||||
$strOperation,
|
|
||||||
{name => 'hDbArchive', value => $hDbArchive, trace => true},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -66,10 +66,6 @@ use constant OP_STORAGE_MOVE => 'storageM
|
|||||||
use constant OP_STORAGE_PATH_GET => 'storagePathGet';
|
use constant OP_STORAGE_PATH_GET => 'storagePathGet';
|
||||||
push @EXPORT, qw(OP_STORAGE_PATH_GET);
|
push @EXPORT, qw(OP_STORAGE_PATH_GET);
|
||||||
|
|
||||||
# Info module
|
|
||||||
use constant OP_INFO_STANZA_LIST => 'infoStanzList';
|
|
||||||
push @EXPORT, qw(OP_INFO_STANZA_LIST);
|
|
||||||
|
|
||||||
# Restore module
|
# Restore module
|
||||||
use constant OP_RESTORE_FILE => 'restoreFile';
|
use constant OP_RESTORE_FILE => 'restoreFile';
|
||||||
push @EXPORT, qw(OP_RESTORE_FILE);
|
push @EXPORT, qw(OP_RESTORE_FILE);
|
||||||
|
@ -19,7 +19,6 @@ use pgBackRest::Archive::Push::File;
|
|||||||
use pgBackRest::Check::Check;
|
use pgBackRest::Check::Check;
|
||||||
use pgBackRest::Config::Config;
|
use pgBackRest::Config::Config;
|
||||||
use pgBackRest::Db;
|
use pgBackRest::Db;
|
||||||
use pgBackRest::Info;
|
|
||||||
use pgBackRest::Protocol::Command::Minion;
|
use pgBackRest::Protocol::Command::Minion;
|
||||||
use pgBackRest::Protocol::Helper;
|
use pgBackRest::Protocol::Helper;
|
||||||
use pgBackRest::Protocol::Storage::Helper;
|
use pgBackRest::Protocol::Storage::Helper;
|
||||||
@ -71,7 +70,6 @@ sub init
|
|||||||
my $oStorage = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? storageDb() : storageRepo();
|
my $oStorage = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? storageDb() : storageRepo();
|
||||||
|
|
||||||
my $oCheck = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) ? new pgBackRest::Check::Check() : undef;
|
my $oCheck = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) ? new pgBackRest::Check::Check() : undef;
|
||||||
my $oInfo = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) ? new pgBackRest::Info() : undef;
|
|
||||||
my $oDb = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? new pgBackRest::Db() : undef;
|
my $oDb = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? new pgBackRest::Db() : undef;
|
||||||
|
|
||||||
# Create anonymous subs for each command
|
# Create anonymous subs for each command
|
||||||
@ -122,9 +120,6 @@ sub init
|
|||||||
&OP_STORAGE_PATH_GET => sub {$oStorage->pathGet(@{shift()})},
|
&OP_STORAGE_PATH_GET => sub {$oStorage->pathGet(@{shift()})},
|
||||||
&OP_STORAGE_HASH_SIZE => sub {$oStorage->hashSize(@{shift()})},
|
&OP_STORAGE_HASH_SIZE => sub {$oStorage->hashSize(@{shift()})},
|
||||||
|
|
||||||
# Info commands
|
|
||||||
&OP_INFO_STANZA_LIST => sub {$oInfo->stanzaList(@{shift()})},
|
|
||||||
|
|
||||||
# Wait command
|
# Wait command
|
||||||
&OP_WAIT => sub {waitRemainder(@{shift()})},
|
&OP_WAIT => sub {waitRemainder(@{shift()})},
|
||||||
};
|
};
|
||||||
|
@ -635,15 +635,9 @@ cmdInfo(void)
|
|||||||
FUNCTION_DEBUG_VOID(logLevelDebug);
|
FUNCTION_DEBUG_VOID(logLevelDebug);
|
||||||
|
|
||||||
MEM_CONTEXT_TEMP_BEGIN()
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
{
|
|
||||||
if (!cfgOptionTest(cfgOptRepoHost)) // {uncovered - Perl code is covered in integration tests}
|
|
||||||
{
|
{
|
||||||
ioHandleWriteOneStr(STDOUT_FILENO, infoRender());
|
ioHandleWriteOneStr(STDOUT_FILENO, infoRender());
|
||||||
}
|
}
|
||||||
// Else do it in Perl
|
|
||||||
else
|
|
||||||
perlExec(); // {+uncovered}
|
|
||||||
}
|
|
||||||
MEM_CONTEXT_TEMP_END();
|
MEM_CONTEXT_TEMP_END();
|
||||||
|
|
||||||
FUNCTION_DEBUG_RESULT_VOID();
|
FUNCTION_DEBUG_RESULT_VOID();
|
||||||
|
@ -97,6 +97,13 @@ main(int argListSize, const char *argList[])
|
|||||||
perlExec();
|
perlExec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info command
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
else if (cfgCommand() == cfgCmdInfo)
|
||||||
|
{
|
||||||
|
cmdInfo();
|
||||||
|
}
|
||||||
|
|
||||||
// Execute Perl for commands not implemented in C
|
// Execute Perl for commands not implemented in C
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
|
@ -10320,678 +10320,6 @@ static const EmbeddedModule embeddedModule[] =
|
|||||||
"\n"
|
"\n"
|
||||||
"1;\n"
|
"1;\n"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
.name = "pgBackRest/Info.pm",
|
|
||||||
.data =
|
|
||||||
"\n\n\n"
|
|
||||||
"package pgBackRest::Info;\n"
|
|
||||||
"\n"
|
|
||||||
"use strict;\n"
|
|
||||||
"use warnings FATAL => qw(all);\n"
|
|
||||||
"use Carp qw(confess);\n"
|
|
||||||
"\n"
|
|
||||||
"use English '-no_match_vars';\n"
|
|
||||||
"use Exporter qw(import);\n"
|
|
||||||
"our @EXPORT = qw();\n"
|
|
||||||
"use File::Basename qw(dirname);\n"
|
|
||||||
"\n"
|
|
||||||
"use pgBackRest::Backup::Common;\n"
|
|
||||||
"use pgBackRest::Backup::Info;\n"
|
|
||||||
"use pgBackRest::Common::Exception;\n"
|
|
||||||
"use pgBackRest::Common::Log;\n"
|
|
||||||
"use pgBackRest::Common::Ini;\n"
|
|
||||||
"use pgBackRest::Common::String;\n"
|
|
||||||
"use pgBackRest::Backup::Common;\n"
|
|
||||||
"use pgBackRest::Backup::Info;\n"
|
|
||||||
"use pgBackRest::Config::Config;\n"
|
|
||||||
"use pgBackRest::InfoCommon;\n"
|
|
||||||
"use pgBackRest::Manifest;\n"
|
|
||||||
"use pgBackRest::Protocol::Helper;\n"
|
|
||||||
"use pgBackRest::Protocol::Storage::Helper;\n"
|
|
||||||
"use pgBackRest::Storage::Helper;\n"
|
|
||||||
"\n\n\n\n"
|
|
||||||
"use constant INFO_SECTION_BACKREST => 'backrest';\n"
|
|
||||||
"use constant INFO_SECTION_ARCHIVE => 'archive';\n"
|
|
||||||
"use constant INFO_SECTION_DB => 'database';\n"
|
|
||||||
"use constant INFO_SECTION_INFO => 'info';\n"
|
|
||||||
"use constant INFO_SECTION_REPO => 'repository';\n"
|
|
||||||
"use constant INFO_SECTION_TIMESTAMP => 'timestamp';\n"
|
|
||||||
"use constant INFO_SECTION_STATUS => 'status';\n"
|
|
||||||
"use constant INFO_SECTION_CIPHER => 'cipher';\n"
|
|
||||||
"\n"
|
|
||||||
"use constant INFO_STANZA_NAME => 'name';\n"
|
|
||||||
"\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_OK => 'ok';\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_ERROR => 'error';\n"
|
|
||||||
"\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_OK_CODE => 0;\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_OK_MESSAGE => INFO_STANZA_STATUS_OK;\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_MISSING_STANZA_CODE => 1;\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_MISSING_STANZA_MESSAGE => 'missing stanza path';\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_NO_BACKUP_CODE => 2;\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_NO_BACKUP_MESSAGE => 'no valid backups';\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_MISSING_STANZA_DATA_CODE => 3;\n"
|
|
||||||
"use constant INFO_STANZA_STATUS_MISSING_STANZA_DATA_MESSAGE => 'missing stanza data';\n"
|
|
||||||
"\n"
|
|
||||||
"use constant INFO_KEY_CODE => 'code';\n"
|
|
||||||
"use constant INFO_KEY_DELTA => 'delta';\n"
|
|
||||||
"use constant INFO_KEY_FORMAT => 'format';\n"
|
|
||||||
"use constant INFO_KEY_ID => INFO_HISTORY_ID;\n"
|
|
||||||
"use constant INFO_KEY_LABEL => 'label';\n"
|
|
||||||
"use constant INFO_KEY_MAX => 'max';\n"
|
|
||||||
"use constant INFO_KEY_MIN => 'min';\n"
|
|
||||||
"use constant INFO_KEY_MESSAGE => 'message';\n"
|
|
||||||
"use constant INFO_KEY_PRIOR => 'prior';\n"
|
|
||||||
"use constant INFO_KEY_REFERENCE => 'reference';\n"
|
|
||||||
"use constant INFO_KEY_SIZE => 'size';\n"
|
|
||||||
"use constant INFO_KEY_START => 'start';\n"
|
|
||||||
"use constant INFO_KEY_STOP => 'stop';\n"
|
|
||||||
"use constant INFO_KEY_SYSTEM_ID => INFO_SYSTEM_ID;\n"
|
|
||||||
"use constant INFO_KEY_TYPE => 'type';\n"
|
|
||||||
"use constant INFO_KEY_VERSION => INFO_DB_VERSION;\n"
|
|
||||||
"\n\n\n\n"
|
|
||||||
"sub new\n"
|
|
||||||
"{\n"
|
|
||||||
"my $class = shift;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my $self = {};\n"
|
|
||||||
"bless $self, $class;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my ($strOperation) = logDebugParam(__PACKAGE__ . '->new');\n"
|
|
||||||
"\n\n"
|
|
||||||
"return logDebugReturn\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"{name => 'self', value => $self}\n"
|
|
||||||
");\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n\n\n"
|
|
||||||
"sub process\n"
|
|
||||||
"{\n"
|
|
||||||
"my $self = shift;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my ($strOperation) = logDebugParam(__PACKAGE__ . '->process');\n"
|
|
||||||
"\n\n"
|
|
||||||
"my $strStanza = cfgOptionTest(CFGOPT_STANZA) ? cfgOption(CFGOPT_STANZA) : undef;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my $oyStanzaList = $self->stanzaList($strStanza);\n"
|
|
||||||
"\n"
|
|
||||||
"if (cfgOptionTest(CFGOPT_OUTPUT, CFGOPTVAL_INFO_OUTPUT_TEXT))\n"
|
|
||||||
"{\n"
|
|
||||||
"my $strOutput = $self->formatText($oyStanzaList);\n"
|
|
||||||
"\n"
|
|
||||||
"if (defined($strOutput))\n"
|
|
||||||
"{\n"
|
|
||||||
"syswrite(*STDOUT, $strOutput);\n"
|
|
||||||
"}\n"
|
|
||||||
"else\n"
|
|
||||||
"{\n"
|
|
||||||
"syswrite(*STDOUT, \"No stanzas exist in the repository.\\n\");\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"elsif (cfgOptionTest(CFGOPT_OUTPUT, CFGOPTVAL_INFO_OUTPUT_JSON))\n"
|
|
||||||
"{\n"
|
|
||||||
"my $oJSON = JSON::PP->new()->canonical()->pretty()->indent_length(4);\n"
|
|
||||||
"$self->outputJSON($oJSON->encode($oyStanzaList));\n"
|
|
||||||
"}\n"
|
|
||||||
"else\n"
|
|
||||||
"{\n"
|
|
||||||
"confess &log(ASSERT, \"invalid info output option '\" . cfgOption(CFGOPT_OUTPUT) . \"'\");\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"return logDebugReturn($strOperation);\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n\n\n"
|
|
||||||
"sub outputJSON\n"
|
|
||||||
"{\n"
|
|
||||||
"my $self = shift;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"$strJSON,\n"
|
|
||||||
") =\n"
|
|
||||||
"logDebugParam\n"
|
|
||||||
"(\n"
|
|
||||||
"__PACKAGE__ . '->outputJSON', \\@_,\n"
|
|
||||||
"{name => 'strJSON'},\n"
|
|
||||||
");\n"
|
|
||||||
"\n"
|
|
||||||
"syswrite(*STDOUT, $strJSON);\n"
|
|
||||||
"\n\n\n"
|
|
||||||
"if ($strJSON !~ /\\n$/)\n"
|
|
||||||
"{\n"
|
|
||||||
"syswrite(*STDOUT, \"\\n\");\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n\n\n\n\n"
|
|
||||||
"sub formatText\n"
|
|
||||||
"{\n"
|
|
||||||
"my $self = shift;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"$oyStanzaList,\n"
|
|
||||||
") =\n"
|
|
||||||
"logDebugParam\n"
|
|
||||||
"(\n"
|
|
||||||
"__PACKAGE__ . '->formatText', \\@_,\n"
|
|
||||||
"{name => 'oyStanzaList', trace => true},\n"
|
|
||||||
");\n"
|
|
||||||
"\n"
|
|
||||||
"my $strOutput;\n"
|
|
||||||
"\n"
|
|
||||||
"foreach my $oStanzaInfo (@{$oyStanzaList})\n"
|
|
||||||
"{\n"
|
|
||||||
"\n"
|
|
||||||
"$strOutput .= (defined($strOutput) ? \"\\n\" : '') . $self->formatTextStanza($oStanzaInfo) . \"\\n\";\n"
|
|
||||||
"\n\n"
|
|
||||||
"my $hDbCurrent = @{$oStanzaInfo->{&INFO_BACKUP_SECTION_DB}}[-1];\n"
|
|
||||||
"\n\n"
|
|
||||||
"foreach my $hDbInfo (@{$oStanzaInfo->{&INFO_BACKUP_SECTION_DB}})\n"
|
|
||||||
"{\n"
|
|
||||||
"\n"
|
|
||||||
"if ($hDbInfo->{&INFO_HISTORY_ID} == $hDbCurrent->{&INFO_HISTORY_ID})\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutput .= \"\\n db (current)\";\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"my $strOutputArchive;\n"
|
|
||||||
"foreach my $hDbArchive (@{$oStanzaInfo->{&INFO_SECTION_ARCHIVE}})\n"
|
|
||||||
"{\n"
|
|
||||||
"if ($hDbArchive->{&INFO_SECTION_DB}{&INFO_HISTORY_ID} == $hDbInfo->{&INFO_HISTORY_ID})\n"
|
|
||||||
"{\n"
|
|
||||||
"\n"
|
|
||||||
"$strOutputArchive .= \"\\n wal archive min/max (\" . $hDbArchive->{&INFO_KEY_ID} . \"): \";\n"
|
|
||||||
"\n"
|
|
||||||
"if (defined($hDbArchive->{&INFO_KEY_MIN}))\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutputArchive .= $hDbArchive->{&INFO_KEY_MIN} . ' / ' . $hDbArchive->{&INFO_KEY_MAX};\n"
|
|
||||||
"}\n"
|
|
||||||
"else\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutputArchive .= 'none present';\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"$strOutputArchive .= \"\\n\";\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"my $strOutputBackup;\n"
|
|
||||||
"foreach my $oBackupInfo (@{$$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}})\n"
|
|
||||||
"{\n"
|
|
||||||
"if ($oBackupInfo->{&INFO_SECTION_DB}{&INFO_KEY_ID} == $hDbInfo->{&INFO_HISTORY_ID})\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutputBackup .= \"\\n\" . $self->formatTextBackup($oBackupInfo) . \"\\n\";\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"if (defined($strOutputArchive) || defined($strOutputBackup))\n"
|
|
||||||
"{\n"
|
|
||||||
"if ($hDbInfo->{&INFO_HISTORY_ID} != $hDbCurrent->{&INFO_HISTORY_ID})\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutput .= \"\\n db (prior)\";\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"if (defined($strOutputArchive))\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutput .= $strOutputArchive;\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"if (defined($strOutputBackup))\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutput .= $strOutputBackup;\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"return logDebugReturn\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"{name => 'strOutput', value => $strOutput, trace => true}\n"
|
|
||||||
");\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n\n\n\n\n"
|
|
||||||
"sub formatTextStanza\n"
|
|
||||||
"{\n"
|
|
||||||
"my $self = shift;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"$oStanzaInfo,\n"
|
|
||||||
") =\n"
|
|
||||||
"logDebugParam\n"
|
|
||||||
"(\n"
|
|
||||||
"__PACKAGE__ . '->formatTextStanza', \\@_,\n"
|
|
||||||
"{name => 'oStanzaInfo', trace => true},\n"
|
|
||||||
");\n"
|
|
||||||
"\n\n"
|
|
||||||
"my $strOutput =\n"
|
|
||||||
"'stanza: ' . $oStanzaInfo->{&INFO_STANZA_NAME} . \"\\n\" .\n"
|
|
||||||
"\" status: \" . ($oStanzaInfo->{&INFO_SECTION_STATUS}{&INFO_KEY_CODE} == 0 ? INFO_STANZA_STATUS_OK :\n"
|
|
||||||
"INFO_STANZA_STATUS_ERROR . ' (' . $oStanzaInfo->{&INFO_SECTION_STATUS}{&INFO_KEY_MESSAGE} . ')') .\n"
|
|
||||||
"(defined($oStanzaInfo->{&INFO_SECTION_CIPHER}) ? \"\\n cipher: \" . $oStanzaInfo->{&INFO_SECTION_CIPHER} : '');\n"
|
|
||||||
"\n\n"
|
|
||||||
"return logDebugReturn\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"{name => 'strOutput', value => $strOutput, trace => true}\n"
|
|
||||||
");\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n\n\n\n\n"
|
|
||||||
"sub formatTextBackup\n"
|
|
||||||
"{\n"
|
|
||||||
"my $self = shift;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"$oBackupInfo,\n"
|
|
||||||
") =\n"
|
|
||||||
"logDebugParam\n"
|
|
||||||
"(\n"
|
|
||||||
"__PACKAGE__ . '->formatTextBackup', \\@_,\n"
|
|
||||||
"{name => 'oBackupInfo', trace => true},\n"
|
|
||||||
");\n"
|
|
||||||
"\n"
|
|
||||||
"my $strOutput =\n"
|
|
||||||
"' ' . $$oBackupInfo{&INFO_KEY_TYPE} . ' backup: ' . $$oBackupInfo{&INFO_KEY_LABEL} . \"\\n\" .\n"
|
|
||||||
"\n"
|
|
||||||
"' timestamp start/stop: ' .\n"
|
|
||||||
"timestampFormat(undef, $$oBackupInfo{&INFO_SECTION_TIMESTAMP}{&INFO_KEY_START}) .\n"
|
|
||||||
"' / ' .\n"
|
|
||||||
"timestampFormat(undef, $$oBackupInfo{&INFO_SECTION_TIMESTAMP}{&INFO_KEY_STOP}) . \"\\n\" .\n"
|
|
||||||
"\n"
|
|
||||||
"\" wal start/stop: \";\n"
|
|
||||||
"\n"
|
|
||||||
"if (defined($oBackupInfo->{&INFO_SECTION_ARCHIVE}{&INFO_KEY_START}) &&\n"
|
|
||||||
"defined($oBackupInfo->{&INFO_SECTION_ARCHIVE}{&INFO_KEY_STOP}))\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutput .=\n"
|
|
||||||
"$oBackupInfo->{&INFO_SECTION_ARCHIVE}{&INFO_KEY_START} . ' / ' . $oBackupInfo->{&INFO_SECTION_ARCHIVE}{&INFO_KEY_STOP};\n"
|
|
||||||
"}\n"
|
|
||||||
"else\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutput .= 'n/a';\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"$strOutput .=\n"
|
|
||||||
"\"\\n database size: \" .\n"
|
|
||||||
"(defined($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_KEY_SIZE}) ?\n"
|
|
||||||
"fileSizeFormat($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_KEY_SIZE}) : '') .\n"
|
|
||||||
"', backup size: ' .\n"
|
|
||||||
"(defined($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_KEY_DELTA}) ?\n"
|
|
||||||
"fileSizeFormat($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_KEY_DELTA}) : '') . \"\\n\" .\n"
|
|
||||||
"\n"
|
|
||||||
"' repository size: ' .\n"
|
|
||||||
"(defined($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_SECTION_REPO}{&INFO_KEY_SIZE}) ?\n"
|
|
||||||
"fileSizeFormat($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_SECTION_REPO}{&INFO_KEY_SIZE}) : '') .\n"
|
|
||||||
"', repository backup size: ' .\n"
|
|
||||||
"(defined($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_SECTION_REPO}{&INFO_KEY_DELTA}) ?\n"
|
|
||||||
"fileSizeFormat($$oBackupInfo{&INFO_SECTION_INFO}{&INFO_SECTION_REPO}{&INFO_KEY_DELTA}) : '');\n"
|
|
||||||
"\n\n"
|
|
||||||
"if (defined($oBackupInfo->{&INFO_KEY_REFERENCE}) && @{$oBackupInfo->{&INFO_KEY_REFERENCE}} > 0)\n"
|
|
||||||
"{\n"
|
|
||||||
"$strOutput .= \"\\n backup reference list: \" . (join(', ', @{$$oBackupInfo{&INFO_KEY_REFERENCE}}));\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"return logDebugReturn\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"{name => 'strOutput', value => $strOutput, trace => true}\n"
|
|
||||||
");\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n\n\n"
|
|
||||||
"sub stanzaList\n"
|
|
||||||
"{\n"
|
|
||||||
"my $self = shift;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"$strStanza\n"
|
|
||||||
") =\n"
|
|
||||||
"logDebugParam\n"
|
|
||||||
"(\n"
|
|
||||||
"__PACKAGE__ . '->stanzaList', \\@_,\n"
|
|
||||||
"{name => 'strStanza', required => false}\n"
|
|
||||||
");\n"
|
|
||||||
"\n"
|
|
||||||
"my @oyStanzaList;\n"
|
|
||||||
"\n\n"
|
|
||||||
"if (!isRepoLocal())\n"
|
|
||||||
"{\n"
|
|
||||||
"@oyStanzaList = @{protocolGet(CFGOPTVAL_REMOTE_TYPE_BACKUP)->cmdExecute(OP_INFO_STANZA_LIST, [$strStanza], true)};\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"else\n"
|
|
||||||
"{\n"
|
|
||||||
"my @stryStanza = storageRepo()->list(cfgCommandName(CFGCMD_BACKUP), {bIgnoreMissing => true});\n"
|
|
||||||
"\n"
|
|
||||||
"foreach my $strStanzaFound (@stryStanza)\n"
|
|
||||||
"{\n"
|
|
||||||
"if (defined($strStanza) && $strStanza ne $strStanzaFound)\n"
|
|
||||||
"{\n"
|
|
||||||
"next;\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"my $oStanzaInfo = {};\n"
|
|
||||||
"$$oStanzaInfo{&INFO_STANZA_NAME} = $strStanzaFound;\n"
|
|
||||||
"($$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}, $$oStanzaInfo{&INFO_BACKUP_SECTION_DB}) =\n"
|
|
||||||
"$self->backupList($strStanzaFound);\n"
|
|
||||||
"\n\n"
|
|
||||||
"if (defined($$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}) && @{$$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}} == 0)\n"
|
|
||||||
"{\n"
|
|
||||||
"$$oStanzaInfo{&INFO_SECTION_STATUS} =\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_KEY_CODE => INFO_STANZA_STATUS_NO_BACKUP_CODE,\n"
|
|
||||||
"&INFO_KEY_MESSAGE => INFO_STANZA_STATUS_NO_BACKUP_MESSAGE\n"
|
|
||||||
"};\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"elsif (defined($$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}))\n"
|
|
||||||
"{\n"
|
|
||||||
"$$oStanzaInfo{&INFO_SECTION_STATUS} =\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_KEY_CODE => INFO_STANZA_STATUS_OK_CODE,\n"
|
|
||||||
"&INFO_KEY_MESSAGE => INFO_STANZA_STATUS_OK_MESSAGE\n"
|
|
||||||
"};\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"$$oStanzaInfo{&INFO_SECTION_CIPHER} = defined(storageRepo({strStanza => $strStanzaFound})->cipherType()) ?\n"
|
|
||||||
"storageRepo({strStanza => $strStanzaFound})->cipherType() : CFGOPTVAL_REPO_CIPHER_TYPE_NONE;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my @oyDbArchiveList = ();\n"
|
|
||||||
"\n"
|
|
||||||
"if (!defined($$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP}))\n"
|
|
||||||
"{\n"
|
|
||||||
"$$oStanzaInfo{&INFO_SECTION_STATUS} =\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_KEY_CODE => INFO_STANZA_STATUS_MISSING_STANZA_DATA_CODE,\n"
|
|
||||||
"&INFO_KEY_MESSAGE => INFO_STANZA_STATUS_MISSING_STANZA_DATA_MESSAGE\n"
|
|
||||||
"};\n"
|
|
||||||
"\n"
|
|
||||||
"$$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP} = [];\n"
|
|
||||||
"$$oStanzaInfo{&INFO_BACKUP_SECTION_DB} = [];\n"
|
|
||||||
"}\n"
|
|
||||||
"else\n"
|
|
||||||
"{\n"
|
|
||||||
"\n"
|
|
||||||
"my $hDbCurrent = @{$oStanzaInfo->{&INFO_BACKUP_SECTION_DB}}[-1];\n"
|
|
||||||
"my $strDbCurrentVersion = $hDbCurrent->{&INFO_KEY_VERSION};\n"
|
|
||||||
"my $ullDbCurrentSystemId = $hDbCurrent->{&INFO_KEY_SYSTEM_ID};\n"
|
|
||||||
"\n\n"
|
|
||||||
"foreach my $hDbInfo (@{$oStanzaInfo->{&INFO_BACKUP_SECTION_DB}})\n"
|
|
||||||
"{\n"
|
|
||||||
"my $strArchiveStanzaPath = \"archive/\" . $strStanzaFound;\n"
|
|
||||||
"my $strDbVersion = $hDbInfo->{&INFO_KEY_VERSION};\n"
|
|
||||||
"my $ullDbSysId = $hDbInfo->{&INFO_KEY_SYSTEM_ID};\n"
|
|
||||||
"\n\n\n"
|
|
||||||
"my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet($strArchiveStanzaPath));\n"
|
|
||||||
"my $strArchiveId = $oArchiveInfo->archiveId({strDbVersion => $hDbInfo->{&INFO_KEY_VERSION},\n"
|
|
||||||
"ullDbSysId => $hDbInfo->{&INFO_KEY_SYSTEM_ID}});\n"
|
|
||||||
"my $strArchivePath = \"archive/${strStanzaFound}/${strArchiveId}\";\n"
|
|
||||||
"\n\n"
|
|
||||||
"my $hDbArchive = $self->dbArchiveSection($hDbInfo, $strArchiveId, $strArchivePath, $strDbCurrentVersion,\n"
|
|
||||||
"$ullDbCurrentSystemId);\n"
|
|
||||||
"\n"
|
|
||||||
"if (defined($hDbArchive))\n"
|
|
||||||
"{\n"
|
|
||||||
"push(@oyDbArchiveList, $hDbArchive);\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"$oStanzaInfo->{&INFO_SECTION_ARCHIVE} = \\@oyDbArchiveList;\n"
|
|
||||||
"\n"
|
|
||||||
"push @oyStanzaList, $oStanzaInfo;\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"if (defined($strStanza) && @oyStanzaList == 0)\n"
|
|
||||||
"{\n"
|
|
||||||
"my $oStanzaInfo = {};\n"
|
|
||||||
"\n"
|
|
||||||
"$$oStanzaInfo{&INFO_STANZA_NAME} = $strStanza;\n"
|
|
||||||
"\n"
|
|
||||||
"$$oStanzaInfo{&INFO_SECTION_STATUS} =\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_KEY_CODE => INFO_STANZA_STATUS_MISSING_STANZA_CODE,\n"
|
|
||||||
"&INFO_KEY_MESSAGE => INFO_STANZA_STATUS_MISSING_STANZA_MESSAGE\n"
|
|
||||||
"};\n"
|
|
||||||
"\n"
|
|
||||||
"$$oStanzaInfo{&INFO_BACKUP_SECTION_BACKUP} = [];\n"
|
|
||||||
"$$oStanzaInfo{&INFO_BACKUP_SECTION_DB} = [];\n"
|
|
||||||
"\n"
|
|
||||||
"push @oyStanzaList, $oStanzaInfo;\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"return logDebugReturn\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"{name => 'oyStanzaList', value => \\@oyStanzaList, log => false, ref => true}\n"
|
|
||||||
");\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n\n\n"
|
|
||||||
"sub backupList\n"
|
|
||||||
"{\n"
|
|
||||||
"my $self = shift;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"$strStanza\n"
|
|
||||||
") =\n"
|
|
||||||
"logDebugParam\n"
|
|
||||||
"(\n"
|
|
||||||
"__PACKAGE__ . '->backupList', \\@_,\n"
|
|
||||||
"{name => 'strStanza'}\n"
|
|
||||||
");\n"
|
|
||||||
"\n\n"
|
|
||||||
"my $oBackupInfo = undef;\n"
|
|
||||||
"\n\n"
|
|
||||||
"logDisable();\n"
|
|
||||||
"\n"
|
|
||||||
"eval\n"
|
|
||||||
"{\n"
|
|
||||||
"$oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(cfgCommandName(CFGCMD_BACKUP) . \"/${strStanza}\"), false);\n"
|
|
||||||
"logEnable();\n"
|
|
||||||
"return true;\n"
|
|
||||||
"}\n"
|
|
||||||
"or do\n"
|
|
||||||
"{\n"
|
|
||||||
"logEnable();\n"
|
|
||||||
"\n"
|
|
||||||
"if (exceptionCode($EVAL_ERROR) == ERROR_FILE_MISSING)\n"
|
|
||||||
"{\n"
|
|
||||||
"return;\n"
|
|
||||||
"}\n"
|
|
||||||
"elsif (exceptionCode($EVAL_ERROR) == ERROR_CRYPTO)\n"
|
|
||||||
"{\n"
|
|
||||||
"\n"
|
|
||||||
"confess &log(ERROR, exceptionMessage($EVAL_ERROR) .\n"
|
|
||||||
"\"\\nHINT: use option --stanza if encryption settings are different for the stanza than the global settings\",\n"
|
|
||||||
"ERROR_CRYPTO);\n"
|
|
||||||
"}\n"
|
|
||||||
"else\n"
|
|
||||||
"{\n"
|
|
||||||
"\n"
|
|
||||||
"confess $EVAL_ERROR;\n"
|
|
||||||
"}\n"
|
|
||||||
"};\n"
|
|
||||||
"\n\n"
|
|
||||||
"my @oyDbList;\n"
|
|
||||||
"\n"
|
|
||||||
"foreach my $iHistoryId ($oBackupInfo->keys(INFO_BACKUP_SECTION_DB_HISTORY))\n"
|
|
||||||
"{\n"
|
|
||||||
"my $oDbHash =\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_HISTORY_ID => $iHistoryId + 0,\n"
|
|
||||||
"&INFO_DB_VERSION =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_DB_HISTORY, $iHistoryId, INFO_BACKUP_KEY_DB_VERSION),\n"
|
|
||||||
"&INFO_SYSTEM_ID =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_DB_HISTORY, $iHistoryId, INFO_BACKUP_KEY_SYSTEM_ID)\n"
|
|
||||||
"};\n"
|
|
||||||
"\n"
|
|
||||||
"push(@oyDbList, $oDbHash);\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"my @oyBackupList;\n"
|
|
||||||
"\n"
|
|
||||||
"foreach my $strBackup ($oBackupInfo->keys(INFO_BACKUP_SECTION_BACKUP_CURRENT))\n"
|
|
||||||
"{\n"
|
|
||||||
"my $oBackupHash =\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_SECTION_ARCHIVE =>\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_KEY_START =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_ARCHIVE_START, false),\n"
|
|
||||||
"&INFO_KEY_STOP =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_ARCHIVE_STOP, false),\n"
|
|
||||||
"},\n"
|
|
||||||
"&INFO_SECTION_BACKREST =>\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_KEY_FORMAT =>\n"
|
|
||||||
"$oBackupInfo->numericGet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INI_KEY_FORMAT),\n"
|
|
||||||
"&INFO_KEY_VERSION =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INI_KEY_VERSION)\n"
|
|
||||||
"},\n"
|
|
||||||
"&INFO_SECTION_DB =>\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_KEY_ID =>\n"
|
|
||||||
"$oBackupInfo->numericGet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_HISTORY_ID)\n"
|
|
||||||
"},\n"
|
|
||||||
"&INFO_SECTION_INFO =>\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_SECTION_REPO =>\n"
|
|
||||||
"{\n"
|
|
||||||
"\n"
|
|
||||||
"&INFO_KEY_SIZE =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_BACKUP_REPO_SIZE),\n"
|
|
||||||
"\n"
|
|
||||||
"&INFO_KEY_DELTA =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_BACKUP_REPO_SIZE_DELTA),\n"
|
|
||||||
"},\n"
|
|
||||||
"\n"
|
|
||||||
"&INFO_KEY_SIZE =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_BACKUP_SIZE),\n"
|
|
||||||
"\n"
|
|
||||||
"&INFO_KEY_DELTA =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_BACKUP_SIZE_DELTA),\n"
|
|
||||||
"},\n"
|
|
||||||
"&INFO_SECTION_TIMESTAMP =>\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_KEY_START =>\n"
|
|
||||||
"$oBackupInfo->numericGet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_TIMESTAMP_START),\n"
|
|
||||||
"&INFO_KEY_STOP =>\n"
|
|
||||||
"$oBackupInfo->numericGet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_TIMESTAMP_STOP),\n"
|
|
||||||
"},\n"
|
|
||||||
"&INFO_KEY_LABEL => $strBackup,\n"
|
|
||||||
"&INFO_KEY_PRIOR =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_PRIOR, false),\n"
|
|
||||||
"&INFO_KEY_REFERENCE =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_REFERENCE, false),\n"
|
|
||||||
"&INFO_KEY_TYPE =>\n"
|
|
||||||
"$oBackupInfo->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_TYPE)\n"
|
|
||||||
"};\n"
|
|
||||||
"\n"
|
|
||||||
"push(@oyBackupList, $oBackupHash);\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"return logDebugReturn\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"{name => 'oyBackupList', value => \\@oyBackupList, log => false, ref => true},\n"
|
|
||||||
"{name => 'oyDbList', value => \\@oyDbList, log => false, ref => true}\n"
|
|
||||||
");\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n\n\n"
|
|
||||||
"sub dbArchiveSection\n"
|
|
||||||
"{\n"
|
|
||||||
"my $self = shift;\n"
|
|
||||||
"\n\n"
|
|
||||||
"my\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"$hDbInfo,\n"
|
|
||||||
"$strArchiveId,\n"
|
|
||||||
"$strArchivePath,\n"
|
|
||||||
"$strDbCurrentVersion,\n"
|
|
||||||
"$ullDbCurrentSystemId,\n"
|
|
||||||
") =\n"
|
|
||||||
"logDebugParam\n"
|
|
||||||
"(\n"
|
|
||||||
"__PACKAGE__ . '->dbArchiveSection', \\@_,\n"
|
|
||||||
"{name => 'hDbInfo'},\n"
|
|
||||||
"{name => 'strArchiveId'},\n"
|
|
||||||
"{name => 'strArchivePath'},\n"
|
|
||||||
"{name => 'strDbCurrentVersion'},\n"
|
|
||||||
"{name => 'ullDbCurrentSystemId'},\n"
|
|
||||||
");\n"
|
|
||||||
"\n"
|
|
||||||
"my $hDbArchive = undef;\n"
|
|
||||||
"my $strArchiveStart = undef;\n"
|
|
||||||
"my $strArchiveStop = undef;\n"
|
|
||||||
"\n"
|
|
||||||
"if (storageRepo()->pathExists($strArchivePath))\n"
|
|
||||||
"{\n"
|
|
||||||
"my @stryWalMajor = storageRepo()->list($strArchivePath, {strExpression => '^[0-F]{16}$'});\n"
|
|
||||||
"\n\n"
|
|
||||||
"foreach my $strWalMajor (@stryWalMajor)\n"
|
|
||||||
"{\n"
|
|
||||||
"my @stryWalFile = storageRepo()->list(\n"
|
|
||||||
"\"${strArchivePath}/${strWalMajor}\",\n"
|
|
||||||
"{strExpression => \"^[0-F]{24}-[0-f]{40}(\\\\.\" . COMPRESS_EXT . \"){0,1}\\$\"});\n"
|
|
||||||
"\n"
|
|
||||||
"if (@stryWalFile > 0)\n"
|
|
||||||
"{\n"
|
|
||||||
"$strArchiveStart = substr($stryWalFile[0], 0, 24);\n"
|
|
||||||
"last;\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"foreach my $strWalMajor (sort({$b cmp $a} @stryWalMajor))\n"
|
|
||||||
"{\n"
|
|
||||||
"my @stryWalFile = storageRepo()->list(\n"
|
|
||||||
"\"${strArchivePath}/${strWalMajor}\",\n"
|
|
||||||
"{strExpression => \"^[0-F]{24}-[0-f]{40}(\\\\.\" . COMPRESS_EXT . \"){0,1}\\$\", strSortOrder => 'reverse'});\n"
|
|
||||||
"\n"
|
|
||||||
"if (@stryWalFile > 0)\n"
|
|
||||||
"{\n"
|
|
||||||
"$strArchiveStop = substr($stryWalFile[0], 0, 24);\n"
|
|
||||||
"last;\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"}\n"
|
|
||||||
"\n\n"
|
|
||||||
"if (($strDbCurrentVersion eq $hDbInfo->{&INFO_KEY_VERSION} &&\n"
|
|
||||||
"$ullDbCurrentSystemId == $hDbInfo->{&INFO_KEY_SYSTEM_ID}) ||\n"
|
|
||||||
"defined($strArchiveStart) )\n"
|
|
||||||
"{\n"
|
|
||||||
"$hDbArchive =\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_KEY_ID => $strArchiveId,\n"
|
|
||||||
"&INFO_KEY_MIN => $strArchiveStart,\n"
|
|
||||||
"&INFO_KEY_MAX => $strArchiveStop,\n"
|
|
||||||
"&INFO_SECTION_DB =>\n"
|
|
||||||
"{\n"
|
|
||||||
"&INFO_HISTORY_ID => $hDbInfo->{&INFO_HISTORY_ID} + 0,\n"
|
|
||||||
"},\n"
|
|
||||||
"};\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"return logDebugReturn\n"
|
|
||||||
"(\n"
|
|
||||||
"$strOperation,\n"
|
|
||||||
"{name => 'hDbArchive', value => $hDbArchive, trace => true},\n"
|
|
||||||
");\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"1;\n"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
.name = "pgBackRest/InfoCommon.pm",
|
.name = "pgBackRest/InfoCommon.pm",
|
||||||
.data =
|
.data =
|
||||||
@ -13701,9 +13029,6 @@ static const EmbeddedModule embeddedModule[] =
|
|||||||
"use constant OP_STORAGE_PATH_GET => 'storagePathGet';\n"
|
"use constant OP_STORAGE_PATH_GET => 'storagePathGet';\n"
|
||||||
"push @EXPORT, qw(OP_STORAGE_PATH_GET);\n"
|
"push @EXPORT, qw(OP_STORAGE_PATH_GET);\n"
|
||||||
"\n\n"
|
"\n\n"
|
||||||
"use constant OP_INFO_STANZA_LIST => 'infoStanzList';\n"
|
|
||||||
"push @EXPORT, qw(OP_INFO_STANZA_LIST);\n"
|
|
||||||
"\n\n"
|
|
||||||
"use constant OP_RESTORE_FILE => 'restoreFile';\n"
|
"use constant OP_RESTORE_FILE => 'restoreFile';\n"
|
||||||
"push @EXPORT, qw(OP_RESTORE_FILE);\n"
|
"push @EXPORT, qw(OP_RESTORE_FILE);\n"
|
||||||
"\n\n"
|
"\n\n"
|
||||||
@ -14833,7 +14158,6 @@ static const EmbeddedModule embeddedModule[] =
|
|||||||
"use pgBackRest::Check::Check;\n"
|
"use pgBackRest::Check::Check;\n"
|
||||||
"use pgBackRest::Config::Config;\n"
|
"use pgBackRest::Config::Config;\n"
|
||||||
"use pgBackRest::Db;\n"
|
"use pgBackRest::Db;\n"
|
||||||
"use pgBackRest::Info;\n"
|
|
||||||
"use pgBackRest::Protocol::Command::Minion;\n"
|
"use pgBackRest::Protocol::Command::Minion;\n"
|
||||||
"use pgBackRest::Protocol::Helper;\n"
|
"use pgBackRest::Protocol::Helper;\n"
|
||||||
"use pgBackRest::Protocol::Storage::Helper;\n"
|
"use pgBackRest::Protocol::Storage::Helper;\n"
|
||||||
@ -14874,7 +14198,6 @@ static const EmbeddedModule embeddedModule[] =
|
|||||||
"my $oStorage = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? storageDb() : storageRepo();\n"
|
"my $oStorage = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? storageDb() : storageRepo();\n"
|
||||||
"\n"
|
"\n"
|
||||||
"my $oCheck = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) ? new pgBackRest::Check::Check() : undef;\n"
|
"my $oCheck = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) ? new pgBackRest::Check::Check() : undef;\n"
|
||||||
"my $oInfo = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) ? new pgBackRest::Info() : undef;\n"
|
|
||||||
"my $oDb = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? new pgBackRest::Db() : undef;\n"
|
"my $oDb = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? new pgBackRest::Db() : undef;\n"
|
||||||
"\n\n"
|
"\n\n"
|
||||||
"my $hCommandMap =\n"
|
"my $hCommandMap =\n"
|
||||||
@ -14919,8 +14242,6 @@ static const EmbeddedModule embeddedModule[] =
|
|||||||
"&OP_STORAGE_PATH_GET => sub {$oStorage->pathGet(@{shift()})},\n"
|
"&OP_STORAGE_PATH_GET => sub {$oStorage->pathGet(@{shift()})},\n"
|
||||||
"&OP_STORAGE_HASH_SIZE => sub {$oStorage->hashSize(@{shift()})},\n"
|
"&OP_STORAGE_HASH_SIZE => sub {$oStorage->hashSize(@{shift()})},\n"
|
||||||
"\n\n"
|
"\n\n"
|
||||||
"&OP_INFO_STANZA_LIST => sub {$oInfo->stanzaList(@{shift()})},\n"
|
|
||||||
"\n\n"
|
|
||||||
"&OP_WAIT => sub {waitRemainder(@{shift()})},\n"
|
"&OP_WAIT => sub {waitRemainder(@{shift()})},\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n\n"
|
"\n\n"
|
||||||
|
@ -582,13 +582,6 @@ unit:
|
|||||||
- name: info
|
- name: info
|
||||||
|
|
||||||
test:
|
test:
|
||||||
# ----------------------------------------------------------------------------------------------------------------------------
|
|
||||||
- name: unit-perl
|
|
||||||
total: 2
|
|
||||||
|
|
||||||
coverage:
|
|
||||||
Info: full
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------------------------------
|
||||||
- name: info
|
- name: info
|
||||||
total: 1
|
total: 1
|
||||||
|
@ -4951,7 +4951,7 @@ stanza: db
|
|||||||
timestamp start/stop: [TIMESTAMP-STR]
|
timestamp start/stop: [TIMESTAMP-STR]
|
||||||
wal start/stop: n/a
|
wal start/stop: n/a
|
||||||
database size: 176KB, backup size: 176KB
|
database size: 176KB, backup size: 176KB
|
||||||
repository size: 2.3KB, repository backup size: 2.3KB
|
repository size: 2.4KB, repository backup size: 2.4KB
|
||||||
|
|
||||||
info db stanza - normal output (db-master host)
|
info db stanza - normal output (db-master host)
|
||||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --stanza=db --output=json info
|
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --stanza=db --output=json info
|
||||||
@ -5599,7 +5599,7 @@ stanza: db
|
|||||||
timestamp start/stop: [TIMESTAMP-STR]
|
timestamp start/stop: [TIMESTAMP-STR]
|
||||||
wal start/stop: n/a
|
wal start/stop: n/a
|
||||||
database size: 176KB, backup size: 176KB
|
database size: 176KB, backup size: 176KB
|
||||||
repository size: 2.3KB, repository backup size: 2.3KB
|
repository size: 2.4KB, repository backup size: 2.4KB
|
||||||
|
|
||||||
diff backup: [BACKUP-DIFF-5]
|
diff backup: [BACKUP-DIFF-5]
|
||||||
timestamp start/stop: [TIMESTAMP-STR]
|
timestamp start/stop: [TIMESTAMP-STR]
|
||||||
|
@ -2589,7 +2589,7 @@ stanza: db
|
|||||||
timestamp start/stop: [TIMESTAMP-STR]
|
timestamp start/stop: [TIMESTAMP-STR]
|
||||||
wal start/stop: n/a
|
wal start/stop: n/a
|
||||||
database size: 160KB, backup size: 41B
|
database size: 160KB, backup size: 41B
|
||||||
repository size: 160.6KB, repository backup size: 192B
|
repository size: 160.7KB, repository backup size: 192B
|
||||||
backup reference list: [BACKUP-FULL-2]
|
backup reference list: [BACKUP-FULL-2]
|
||||||
|
|
||||||
incr backup: [BACKUP-INCR-3]
|
incr backup: [BACKUP-INCR-3]
|
||||||
@ -3179,7 +3179,7 @@ stanza: db
|
|||||||
timestamp start/stop: [TIMESTAMP-STR]
|
timestamp start/stop: [TIMESTAMP-STR]
|
||||||
wal start/stop: n/a
|
wal start/stop: n/a
|
||||||
database size: 144.1KB, backup size: 9B
|
database size: 144.1KB, backup size: 9B
|
||||||
repository size: 2.5KB, repository backup size: 48B
|
repository size: 2.6KB, repository backup size: 48B
|
||||||
backup reference list: [BACKUP-FULL-3]
|
backup reference list: [BACKUP-FULL-3]
|
||||||
|
|
||||||
info all stanzas - normal output (db-master host)
|
info all stanzas - normal output (db-master host)
|
||||||
|
@ -1,502 +0,0 @@
|
|||||||
####################################################################################################################################
|
|
||||||
# Unit tests for Info module
|
|
||||||
####################################################################################################################################
|
|
||||||
package pgBackRestTest::Module::Info::InfoUnitPerlTest;
|
|
||||||
use parent 'pgBackRestTest::Env::HostEnvTest';
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# Perl includes
|
|
||||||
####################################################################################################################################
|
|
||||||
use strict;
|
|
||||||
use warnings FATAL => qw(all);
|
|
||||||
use Carp qw(confess);
|
|
||||||
use English '-no_match_vars';
|
|
||||||
|
|
||||||
use File::Basename qw(dirname);
|
|
||||||
use Storable qw(dclone);
|
|
||||||
|
|
||||||
use pgBackRest::Backup::Common;
|
|
||||||
use pgBackRest::Backup::Info;
|
|
||||||
use pgBackRest::Common::Exception;
|
|
||||||
use pgBackRest::Common::Lock;
|
|
||||||
use pgBackRest::Common::Log;
|
|
||||||
use pgBackRest::Config::Config;
|
|
||||||
use pgBackRest::DbVersion;
|
|
||||||
use pgBackRest::Info;
|
|
||||||
use pgBackRest::InfoCommon;
|
|
||||||
use pgBackRest::Manifest;
|
|
||||||
use pgBackRest::Protocol::Helper;
|
|
||||||
use pgBackRest::Protocol::Storage::Helper;
|
|
||||||
use pgBackRest::Storage::Local;
|
|
||||||
|
|
||||||
use pgBackRestTest::Common::ExecuteTest;
|
|
||||||
use pgBackRestTest::Common::RunTest;
|
|
||||||
use pgBackRestTest::Env::ExpireEnvTest;
|
|
||||||
use pgBackRestTest::Common::FileTest;
|
|
||||||
use pgBackRestTest::Env::Host::HostBackupTest;
|
|
||||||
use pgBackRestTest::Env::HostEnvTest;
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# initModule
|
|
||||||
####################################################################################################################################
|
|
||||||
use constant STANZA_ENCRYPT => 'encrypt';
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# initModule
|
|
||||||
####################################################################################################################################
|
|
||||||
sub initModule
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
$self->{strRepoPath} = $self->testPath() . '/repo';
|
|
||||||
$self->{strArchivePath} = "$self->{strRepoPath}/archive/" . $self->stanza();
|
|
||||||
$self->{strBackupPath} = "$self->{strRepoPath}/backup/" . $self->stanza();
|
|
||||||
$self->{strDbPath} = $self->testPath() . '/db';
|
|
||||||
$self->{strArchivePathEncrypt} = "$self->{strRepoPath}/archive/" . STANZA_ENCRYPT;
|
|
||||||
$self->{strBackupPathEncrypt} = "$self->{strRepoPath}/backup/" . STANZA_ENCRYPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# initTest
|
|
||||||
####################################################################################################################################
|
|
||||||
sub initTest
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Create parent path for pg_control
|
|
||||||
storageTest()->pathCreate(($self->{strDbPath} . '/' . DB_PATH_GLOBAL), {bCreateParent => true});
|
|
||||||
|
|
||||||
# Create archive info path
|
|
||||||
storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true});
|
|
||||||
|
|
||||||
# Create backup info path
|
|
||||||
storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true});
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# initStanzaCreate - initialize options and create the stanza object
|
|
||||||
####################################################################################################################################
|
|
||||||
sub initStanzaCreate
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my $strStanza = shift;
|
|
||||||
my $bEncrypted = shift;
|
|
||||||
my $strDbVersion = shift;
|
|
||||||
|
|
||||||
# Set options for stanzaCreate
|
|
||||||
my $rhConfig = $self->configTestClear();
|
|
||||||
|
|
||||||
if (!defined($strStanza))
|
|
||||||
{
|
|
||||||
$strStanza = $self->stanza();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined($bEncrypted) && $bEncrypted == true)
|
|
||||||
{
|
|
||||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
|
||||||
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defined($strDbVersion))
|
|
||||||
{
|
|
||||||
$strDbVersion = PG_VERSION_94;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->optionTestSet(CFGOPT_STANZA, $strStanza);
|
|
||||||
$self->optionTestSet(CFGOPT_PG_PATH, $self->{strDbPath});
|
|
||||||
$self->optionTestSet(CFGOPT_REPO_PATH, $self->{strRepoPath});
|
|
||||||
$self->optionTestSet(CFGOPT_LOG_PATH, $self->testPath());
|
|
||||||
$self->optionTestSetBool(CFGOPT_ONLINE, false);
|
|
||||||
$self->optionTestSet(CFGOPT_DB_TIMEOUT, 5);
|
|
||||||
$self->optionTestSet(CFGOPT_PROTOCOL_TIMEOUT, 6);
|
|
||||||
|
|
||||||
$self->configTestLoad(CFGCMD_STANZA_CREATE);
|
|
||||||
$self->configTestSet($rhConfig);
|
|
||||||
|
|
||||||
my $oTestObject = "oExpireTest";
|
|
||||||
|
|
||||||
# Create the test object
|
|
||||||
if (defined($bEncrypted) && $bEncrypted == true)
|
|
||||||
{
|
|
||||||
$oTestObject = "oExpireTestEncrypt";
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->{$oTestObject} = new pgBackRestTest::Env::ExpireEnvTest(undef, $self->backrestExe(), storageRepo(), undef, $self);
|
|
||||||
$self->{$oTestObject}->stanzaCreate($strStanza, $strDbVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# initStanzaUpgrade - initialize options and create the stanza object
|
|
||||||
####################################################################################################################################
|
|
||||||
sub initStanzaUpgrade
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Set options for stanzaCreate
|
|
||||||
my $rhConfig = $self->configTestClear();
|
|
||||||
|
|
||||||
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
|
|
||||||
$self->optionTestSet(CFGOPT_PG_PATH, $self->{strDbPath});
|
|
||||||
$self->optionTestSet(CFGOPT_REPO_PATH, $self->{strRepoPath});
|
|
||||||
$self->optionTestSet(CFGOPT_LOG_PATH, $self->testPath());
|
|
||||||
$self->optionTestSetBool(CFGOPT_ONLINE, false);
|
|
||||||
$self->optionTestSet(CFGOPT_DB_TIMEOUT, 5);
|
|
||||||
$self->optionTestSet(CFGOPT_PROTOCOL_TIMEOUT, 6);
|
|
||||||
|
|
||||||
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
|
|
||||||
$self->configTestSet($rhConfig);
|
|
||||||
|
|
||||||
# Create the test object
|
|
||||||
$self->{oExpireTest} = new pgBackRestTest::Env::ExpireEnvTest(undef, $self->backrestExe(), storageRepo(), undef, $self);
|
|
||||||
|
|
||||||
$self->{oExpireTest}->stanzaUpgrade($self->stanza(), PG_VERSION_95);
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################################################################################################################
|
|
||||||
# run
|
|
||||||
####################################################################################################################################
|
|
||||||
sub run
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# Used to create backups and WAL to test
|
|
||||||
use constant SECONDS_PER_DAY => 86400;
|
|
||||||
my $lBaseTime = 1486137448 - (60 * SECONDS_PER_DAY);
|
|
||||||
|
|
||||||
# Create the initial backup "day" number - backup day is incremented for each backup
|
|
||||||
my $iLastBackup = 5;
|
|
||||||
|
|
||||||
################################################################################################################################
|
|
||||||
if ($self->begin("Info"))
|
|
||||||
{
|
|
||||||
$self->configTestLoad(CFGCMD_INFO);
|
|
||||||
|
|
||||||
my $oInfo = new pgBackRest::Info();
|
|
||||||
|
|
||||||
# Output No stanzas exist in default text option
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$self->testResult(sub {$oInfo->process()}, undef, 'No stanzas exist and default text option');
|
|
||||||
|
|
||||||
# Invalid option
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
cfgOptionSet(CFGOPT_OUTPUT, BOGUS);
|
|
||||||
|
|
||||||
$self->testException(sub {$oInfo->process()}, ERROR_ASSERT, "invalid info output option '" . BOGUS . "'");
|
|
||||||
|
|
||||||
# Output json option with no stanza defined
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$self->optionTestSet(CFGOPT_OUTPUT, CFGOPTVAL_INFO_OUTPUT_JSON);
|
|
||||||
$self->configTestLoad(CFGCMD_INFO);
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->process()}, undef, 'json option');
|
|
||||||
|
|
||||||
# Add linefeed to JSON
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
my $strJson = '[{"archive" : 1}]';
|
|
||||||
$self->testResult(sub {$oInfo->outputJSON($strJson)}, 1, 'add linefeed to json');
|
|
||||||
|
|
||||||
# Missing stanza path
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
my $hyStanza = $oInfo->stanzaList(BOGUS);
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->formatText($hyStanza)},
|
|
||||||
"stanza: bogus\n status: error (missing stanza path)\n",
|
|
||||||
'missing stanza path');
|
|
||||||
|
|
||||||
# formatBackupText - coverage for certain conditions
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
my $oBackupHash =
|
|
||||||
{
|
|
||||||
'archive' =>
|
|
||||||
{
|
|
||||||
'start' => 1,
|
|
||||||
'stop' => undef
|
|
||||||
},
|
|
||||||
'timestamp' =>
|
|
||||||
{
|
|
||||||
'start' => 1481039848,
|
|
||||||
'stop' => 1481039848,
|
|
||||||
},
|
|
||||||
'label' => 'BACKUPLABEL',
|
|
||||||
'reference' => ['BACKUPREFERENCE'],
|
|
||||||
'type' => 'BACKUPTYPE',
|
|
||||||
};
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->formatTextBackup($oBackupHash)},
|
|
||||||
" BACKUPTYPE backup: BACKUPLABEL\n" .
|
|
||||||
" timestamp start/stop: 2016-12-06 15:57:28 / 2016-12-06 15:57:28\n" .
|
|
||||||
" wal start/stop: n/a\n" .
|
|
||||||
" database size: , backup size: \n" .
|
|
||||||
" repository size: , repository backup size: \n" .
|
|
||||||
" backup reference list: BACKUPREFERENCE",
|
|
||||||
'formatTextBackup');
|
|
||||||
|
|
||||||
# Test !isRepoLocal branch
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
cfgOptionSet(CFGOPT_REPO_HOST, false);
|
|
||||||
cfgOptionSet(CFGOPT_REPO_HOST_CONFIG, BOGUS);
|
|
||||||
$self->testException(sub {$oInfo->stanzaList(BOGUS)}, ERROR_ASSERT, "option repo1-host-cmd is required");
|
|
||||||
|
|
||||||
# dbArchiveSection() -- no archive
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
my $hDbInfo =
|
|
||||||
{
|
|
||||||
&INFO_HISTORY_ID => 1,
|
|
||||||
&INFO_DB_VERSION => PG_VERSION_94,
|
|
||||||
&INFO_SYSTEM_ID => $self->dbSysId(PG_VERSION_94),
|
|
||||||
};
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->dbArchiveSection($hDbInfo, PG_VERSION_94 . '-1', $self->{strArchivePath}, PG_VERSION_94,
|
|
||||||
$self->dbSysId(PG_VERSION_94))}, "{database => {id => 1}, id => 9.4-1, max => [undef], min => [undef]}",
|
|
||||||
'no archive, db-ver match, db-sys match');
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->dbArchiveSection($hDbInfo, PG_VERSION_94 . '-1', $self->{strArchivePath}, PG_VERSION_94,
|
|
||||||
$self->dbSysId(PG_VERSION_95))}, undef, 'no archive, db-ver match, db-sys mismatch');
|
|
||||||
|
|
||||||
$hDbInfo->{&INFO_DB_VERSION} = PG_VERSION_95;
|
|
||||||
$self->testResult(sub {$oInfo->dbArchiveSection($hDbInfo, PG_VERSION_94 . '-1', $self->{strArchivePath}, PG_VERSION_94,
|
|
||||||
$self->dbSysId(PG_VERSION_94))}, undef, 'no archive, db-ver mismatch, db-sys match');
|
|
||||||
|
|
||||||
$hDbInfo->{&INFO_SYSTEM_ID} = $self->dbSysId(PG_VERSION_95);
|
|
||||||
$self->testResult(sub {$oInfo->dbArchiveSection($hDbInfo, PG_VERSION_94 . '-1', $self->{strArchivePath}, PG_VERSION_94,
|
|
||||||
$self->dbSysId(PG_VERSION_94))}, undef, 'no archive, db-ver mismatch, db-sys mismatch');
|
|
||||||
|
|
||||||
# Create more than one stanza but no data
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
|
|
||||||
$self->optionTestSet(CFGOPT_REPO_PATH, $self->{strRepoPath});
|
|
||||||
$self->configTestLoad(CFGCMD_INFO);
|
|
||||||
|
|
||||||
# Create archive and backup paths but no info files
|
|
||||||
storageTest()->pathCreate("$self->{strRepoPath}/archive/" . BOGUS, {bIgnoreExists => true, bCreateParent => true});
|
|
||||||
storageTest()->pathCreate("$self->{strRepoPath}/backup/" . BOGUS, {bIgnoreExists => true, bCreateParent => true});
|
|
||||||
|
|
||||||
# Get a list of all stanzas in the repo
|
|
||||||
$hyStanza = $oInfo->stanzaList();
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->formatText($hyStanza)},
|
|
||||||
"stanza: bogus\n status: error (missing stanza data)\n cipher: none\n\n" .
|
|
||||||
"stanza: db\n status: error (missing stanza data)\n cipher: none\n",
|
|
||||||
'fomatText() multiple stanzas missing data');
|
|
||||||
|
|
||||||
# Define the stanza option
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
|
|
||||||
$self->optionTestClear(CFGOPT_OUTPUT);
|
|
||||||
$self->configTestLoad(CFGCMD_INFO);
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->process()}, undef, 'stanza set');
|
|
||||||
|
|
||||||
# Create the stanza - no WAL or backups
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$self->initStanzaCreate();
|
|
||||||
$self->configTestLoad(CFGCMD_INFO);
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->formatText($oInfo->stanzaList())},
|
|
||||||
"stanza: bogus\n status: error (missing stanza data)\n cipher: none\n\n" .
|
|
||||||
"stanza: db\n status: error (no valid backups)\n cipher: none\n\n" .
|
|
||||||
" db (current)\n wal archive min/max (9.4-1): none present\n",
|
|
||||||
"formatText() multiple stanzas, one missing data");
|
|
||||||
|
|
||||||
$hyStanza = $oInfo->stanzaList($self->stanza());
|
|
||||||
$self->testResult(sub {$oInfo->formatText($hyStanza)},
|
|
||||||
"stanza: db\n status: error (no valid backups)\n cipher: none\n\n" .
|
|
||||||
" db (current)\n wal archive min/max (9.4-1): none present\n",
|
|
||||||
"formatText() one stanza");
|
|
||||||
|
|
||||||
# Create a backup and list backup for just one stanza
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$self->{oExpireTest}->backupCreate($self->stanza(), CFGOPTVAL_BACKUP_TYPE_FULL, $lBaseTime += SECONDS_PER_DAY, -1, -1);
|
|
||||||
|
|
||||||
$hyStanza = $oInfo->stanzaList($self->stanza());
|
|
||||||
$self->testResult(sub {$oInfo->formatText($hyStanza)},
|
|
||||||
"stanza: db\n status: ok\n cipher: none\n\n db (current)\n wal archive min/max (9.4-1): none present\n\n" .
|
|
||||||
" full backup: 20161206-155728F\n" .
|
|
||||||
" timestamp start/stop: 2016-12-06 15:57:28 / 2016-12-06 15:57:28\n" .
|
|
||||||
" wal start/stop: n/a\n database size: 0B, backup size: 0B\n" .
|
|
||||||
" repository size: 0B, repository backup size: 0B\n",
|
|
||||||
"formatText() one stanza");
|
|
||||||
|
|
||||||
# Coverage for major WAL paths with no WAL
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
storageTest()->pathCreate($self->{strArchivePath} . "/9.4-1/0000000100000000", {bIgnoreExists => true});
|
|
||||||
storageTest()->pathCreate($self->{strArchivePath} . "/9.4-1/0000000200000000", {bIgnoreExists => true});
|
|
||||||
$hyStanza = $oInfo->stanzaList($self->stanza());
|
|
||||||
$self->testResult(sub {$oInfo->formatText($hyStanza)},
|
|
||||||
"stanza: db\n status: ok\n cipher: none\n\n db (current)\n wal archive min/max (9.4-1): none present\n\n" .
|
|
||||||
" full backup: 20161206-155728F\n" .
|
|
||||||
" timestamp start/stop: 2016-12-06 15:57:28 / 2016-12-06 15:57:28\n" .
|
|
||||||
" wal start/stop: n/a\n database size: 0B, backup size: 0B\n" .
|
|
||||||
" repository size: 0B, repository backup size: 0B\n",
|
|
||||||
"formatText() major WAL paths with no WAL");
|
|
||||||
|
|
||||||
# Upgrade postgres version and backup with WAL
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
undef($self->{oExpireTest});
|
|
||||||
$self->initStanzaUpgrade();
|
|
||||||
|
|
||||||
$self->configTestLoad(CFGCMD_INFO);
|
|
||||||
|
|
||||||
$self->{oExpireTest}->backupCreate($self->stanza(), CFGOPTVAL_BACKUP_TYPE_FULL, $lBaseTime += SECONDS_PER_DAY, 1, 1);
|
|
||||||
$self->{oExpireTest}->backupCreate($self->stanza(), CFGOPTVAL_BACKUP_TYPE_DIFF, $lBaseTime += SECONDS_PER_DAY, 1, 1);
|
|
||||||
|
|
||||||
# Remove the 9.4-1 path for condition test coverage
|
|
||||||
storageTest()->remove($self->{strArchivePath} . "/9.4-1/", {bRecurse => true});
|
|
||||||
|
|
||||||
$hyStanza = $oInfo->stanzaList($self->stanza());
|
|
||||||
$self->testResult(sub {$oInfo->formatText($hyStanza)},
|
|
||||||
"stanza: db\n status: ok\n cipher: none\n" .
|
|
||||||
"\n db (prior)\n" .
|
|
||||||
" full backup: 20161206-155728F\n" .
|
|
||||||
" timestamp start/stop: 2016-12-06 15:57:28 / 2016-12-06 15:57:28\n" .
|
|
||||||
" wal start/stop: n/a\n" .
|
|
||||||
" database size: 0B, backup size: 0B\n" .
|
|
||||||
" repository size: 0B, repository backup size: 0B\n" .
|
|
||||||
"\n db (current)\n" .
|
|
||||||
" wal archive min/max (9.5-2): 000000010000000000000000 / 000000010000000000000003\n\n" .
|
|
||||||
" full backup: 20161207-155728F\n" .
|
|
||||||
" timestamp start/stop: 2016-12-07 15:57:28 / 2016-12-07 15:57:28\n" .
|
|
||||||
" wal start/stop: 000000010000000000000000 / 000000010000000000000000\n" .
|
|
||||||
" database size: 0B, backup size: 0B\n" .
|
|
||||||
" repository size: 0B, repository backup size: 0B\n\n" .
|
|
||||||
" diff backup: 20161207-155728F_20161208-155728D\n" .
|
|
||||||
" timestamp start/stop: 2016-12-08 15:57:28 / 2016-12-08 15:57:28\n" .
|
|
||||||
" wal start/stop: 000000010000000000000002 / 000000010000000000000002\n" .
|
|
||||||
" database size: 0B, backup size: 0B\n" .
|
|
||||||
" repository size: 0B, repository backup size: 0B\n",
|
|
||||||
"formatText() multiple DB versions");
|
|
||||||
|
|
||||||
# Remove backup from db (prior)
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
# Load the backup.info file
|
|
||||||
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
|
|
||||||
my @stryPath = $oBackupInfo->list(backupRegExpGet(true));
|
|
||||||
|
|
||||||
# Remove the db prior full backup from the info file and save it
|
|
||||||
$oBackupInfo->delete($stryPath[0]);
|
|
||||||
$oBackupInfo->save();
|
|
||||||
|
|
||||||
# Remove the backup directory
|
|
||||||
storageTest()->remove($self->{strBackupPath} . "/" . $stryPath[0], {bRecurse => true});
|
|
||||||
|
|
||||||
$hyStanza = $oInfo->stanzaList($self->stanza());
|
|
||||||
$self->testResult(sub {$oInfo->formatText($hyStanza)},
|
|
||||||
"stanza: db\n status: ok\n cipher: none\n" .
|
|
||||||
"\n db (current)\n" .
|
|
||||||
" wal archive min/max (9.5-2): 000000010000000000000000 / 000000010000000000000003\n\n" .
|
|
||||||
" full backup: 20161207-155728F\n" .
|
|
||||||
" timestamp start/stop: 2016-12-07 15:57:28 / 2016-12-07 15:57:28\n" .
|
|
||||||
" wal start/stop: 000000010000000000000000 / 000000010000000000000000\n" .
|
|
||||||
" database size: 0B, backup size: 0B\n" .
|
|
||||||
" repository size: 0B, repository backup size: 0B\n\n" .
|
|
||||||
" diff backup: 20161207-155728F_20161208-155728D\n" .
|
|
||||||
" timestamp start/stop: 2016-12-08 15:57:28 / 2016-12-08 15:57:28\n" .
|
|
||||||
" wal start/stop: 000000010000000000000002 / 000000010000000000000002\n" .
|
|
||||||
" database size: 0B, backup size: 0B\n" .
|
|
||||||
" repository size: 0B, repository backup size: 0B\n",
|
|
||||||
"db (prior) removed");
|
|
||||||
|
|
||||||
# dbArchiveSection() -- with archive
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$hDbInfo->{&INFO_HISTORY_ID} = 2;
|
|
||||||
$hDbInfo->{&INFO_DB_VERSION} = PG_VERSION_95;
|
|
||||||
$hDbInfo->{&INFO_SYSTEM_ID} = $self->dbSysId(PG_VERSION_95);
|
|
||||||
|
|
||||||
my $strArchiveId = PG_VERSION_95 . '-2';
|
|
||||||
$self->testResult(sub {$oInfo->dbArchiveSection($hDbInfo, $strArchiveId, "$self->{strArchivePath}/$strArchiveId",
|
|
||||||
PG_VERSION_95, $self->dbSysId(PG_VERSION_95))},
|
|
||||||
"{database => {id => 2}, id => 9.5-2, max => 000000010000000000000003, min => 000000010000000000000000}",
|
|
||||||
'archive, db-ver match, db-sys-id match');
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->dbArchiveSection($hDbInfo, $strArchiveId, "$self->{strArchivePath}/$strArchiveId",
|
|
||||||
PG_VERSION_95, $self->dbSysId(PG_VERSION_94))},
|
|
||||||
"{database => {id => 2}, id => 9.5-2, max => 000000010000000000000003, min => 000000010000000000000000}",
|
|
||||||
'archive, db-ver match, db-sys-id mismatch');
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->dbArchiveSection($hDbInfo, $strArchiveId, "$self->{strArchivePath}/$strArchiveId",
|
|
||||||
PG_VERSION_94, $self->dbSysId(PG_VERSION_95))},
|
|
||||||
"{database => {id => 2}, id => 9.5-2, max => 000000010000000000000003, min => 000000010000000000000000}",
|
|
||||||
'archive, db-ver mismatch, db-sys-id match');
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->dbArchiveSection($hDbInfo, $strArchiveId, "$self->{strArchivePath}/$strArchiveId",
|
|
||||||
PG_VERSION_94, $self->dbSysId(PG_VERSION_94))},
|
|
||||||
"{database => {id => 2}, id => 9.5-2, max => 000000010000000000000003, min => 000000010000000000000000}",
|
|
||||||
'archive, db-ver mismatch, db-sys-id mismatch');
|
|
||||||
|
|
||||||
# Set last backup run in this test set
|
|
||||||
$iLastBackup = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
################################################################################################################################
|
|
||||||
if ($self->begin("Info - encryption"))
|
|
||||||
{
|
|
||||||
# create an unencrypted and an encrypted repo and run a backup in each
|
|
||||||
#--------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$self->initStanzaCreate();
|
|
||||||
$self->{oExpireTest}->backupCreate($self->stanza(), CFGOPTVAL_BACKUP_TYPE_FULL, $lBaseTime += SECONDS_PER_DAY, -1, -1);
|
|
||||||
$iLastBackup++;
|
|
||||||
my $strUnencryptBackup = ($iLastBackup < 10) ? "0$iLastBackup" : $iLastBackup;
|
|
||||||
|
|
||||||
$self->initStanzaCreate(STANZA_ENCRYPT, true);
|
|
||||||
$self->{oExpireTestEncrypt}->backupCreate(
|
|
||||||
STANZA_ENCRYPT, CFGOPTVAL_BACKUP_TYPE_FULL, $lBaseTime += SECONDS_PER_DAY, -1, -1);
|
|
||||||
$iLastBackup++;
|
|
||||||
my $strEncryptBackup = ($iLastBackup < 10) ? "0$iLastBackup" : $iLastBackup;;
|
|
||||||
|
|
||||||
# Clear the main storage repo settings
|
|
||||||
storageRepoCacheClear(STORAGE_REPO);
|
|
||||||
|
|
||||||
# Clear the stanza setting and set the main storage repo basePath to the testing repo path
|
|
||||||
$self->optionTestClear(CFGOPT_STANZA);
|
|
||||||
$self->optionTestSet(CFGOPT_REPO_PATH, $self->{strRepoPath});
|
|
||||||
|
|
||||||
# Recreate the main storage repo with default unencrypted repo setting and test basePath
|
|
||||||
storageRepo();
|
|
||||||
|
|
||||||
# Test the info command without option --stanza being configured
|
|
||||||
#--------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$self->configTestLoad(CFGCMD_INFO);
|
|
||||||
my $oInfo = new pgBackRest::Info();
|
|
||||||
|
|
||||||
$self->testException(sub {$oInfo->stanzaList()}, ERROR_CRYPTO,
|
|
||||||
"unable to parse '" . $self->{strBackupPathEncrypt} . "/backup.info'" .
|
|
||||||
"\nHINT: Is or was the repo encrypted?" .
|
|
||||||
"\nHINT: use option --stanza if encryption settings are different for the stanza than the global settings");
|
|
||||||
|
|
||||||
# Test the info command with option --stanza configured
|
|
||||||
#--------------------------------------------------------------------------------------------------------------------------
|
|
||||||
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
|
|
||||||
$self->configTestLoad(CFGCMD_INFO);
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->formatText($oInfo->stanzaList($self->stanza()))},
|
|
||||||
"stanza: db\n status: ok\n cipher: none\n\n db (current)\n wal archive min/max (9.4-1): none present\n\n" .
|
|
||||||
" full backup: 201612" . $strUnencryptBackup . "-155728F\n" .
|
|
||||||
" timestamp start/stop: 2016-12-" . $strUnencryptBackup . " 15:57:28 / 2016-12-" . $strUnencryptBackup .
|
|
||||||
" 15:57:28\n" .
|
|
||||||
" wal start/stop: n/a\n database size: 0B, backup size: 0B\n" .
|
|
||||||
" repository size: 0B, repository backup size: 0B\n",
|
|
||||||
"formatText() unencrypted stanza");
|
|
||||||
|
|
||||||
$self->optionTestSet(CFGOPT_STANZA, STANZA_ENCRYPT);
|
|
||||||
$self->configTestLoad(CFGCMD_INFO);
|
|
||||||
|
|
||||||
$self->testResult(sub {$oInfo->formatText($oInfo->stanzaList(STANZA_ENCRYPT))},
|
|
||||||
"stanza: " . STANZA_ENCRYPT ."\n status: ok\n cipher: aes-256-cbc\n\n db (current)" .
|
|
||||||
"\n wal archive min/max (9.4-1): none present\n\n" .
|
|
||||||
" full backup: 201612" . $strEncryptBackup . "-155728F\n" .
|
|
||||||
" timestamp start/stop: 2016-12-" . $strEncryptBackup . " 15:57:28 / 2016-12-" . $strEncryptBackup .
|
|
||||||
" 15:57:28\n" .
|
|
||||||
" wal start/stop: n/a\n database size: 0B, backup size: 0B\n" .
|
|
||||||
" repository size: 0B, repository backup size: 0B\n",
|
|
||||||
"formatText() encrypted stanza");
|
|
||||||
|
|
||||||
# Change the permissions of the backup file so it cannot be read and confirm correct error reported
|
|
||||||
#---------------------------------------------------------------------------------------------------------------------------
|
|
||||||
forceStorageMode(
|
|
||||||
storageRepo({strStanza => STANZA_ENCRYPT}), $self->{strBackupPathEncrypt} . "/backup.inf*", '220');
|
|
||||||
$self->testException(sub {$oInfo->backupList(STANZA_ENCRYPT)}, ERROR_FILE_OPEN,
|
|
||||||
"unable to open '" . $self->{strBackupPathEncrypt} . "/backup.info': Permission denied");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
Reference in New Issue
Block a user