pgbackrest.git / summary / log / commit / refs

commit    d245f8eb425322f0efcd05ab4c12b3b45cc87138
Author:   David Steele <david@pgmasters.net>
Date:     Mon Jan 21 11:51:45 2019 +0000

    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.


doc/xml/release.xml | 4 + lib/pgBackRest/Info.pm | 748 --------------------- lib/pgBackRest/Protocol/Helper.pm | 4 - lib/pgBackRest/Protocol/Remote/Minion.pm | 5 - src/command/info/info.c | 8 +- src/main.c | 7 + src/perl/embed.auto.c | 679 ------------------- test/define.yaml | 7 - test/expect/mock-all-001.log | 4 +- test/expect/mock-all-003.log | 4 +- .../pgBackRestTest/Module/Info/InfoUnitPerlTest.pm | 502 -------------- 11 files changed, 16 insertions(+), 1956 deletions(-) diff --git a/doc/xml/release.xml b/doc/xml/release.xml index f8d87ce15..762401722 100644 --- a/doc/xml/release.xml +++ b/doc/xml/release.xml @@ -15,6 +15,10 @@ <release date="XXXX-XX-XX" version="2.09dev" title="UNDER DEVELOPMENT"> <release-core-list> <release-improvement-list> + <release-item> + <p>The <cmd>info</cmd> command is implemented entirely in C.</p> + </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> </release-item> diff --git a/lib/pgBackRest/Info.pm b/lib/pgBackRest/Info.pm deleted file mode 100644 index e121197a1..000000000 --- a/lib/pgBackRest/Info.pm +++ /dev/null @@ -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; diff --git a/lib/pgBackRest/Protocol/Helper.pm b/lib/pgBackRest/Protocol/Helper.pm index f71876b41..6ab3660e3 100644 --- a/lib/pgBackRest/Protocol/Helper.pm +++ b/lib/pgBackRest/Protocol/Helper.pm @@ -66,10 +66,6 @@ use constant OP_STORAGE_MOVE => 'storageM use constant OP_STORAGE_PATH_GET => 'storagePathGet'; 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 use constant OP_RESTORE_FILE => 'restoreFile'; push @EXPORT, qw(OP_RESTORE_FILE); diff --git a/lib/pgBackRest/Protocol/Remote/Minion.pm b/lib/pgBackRest/Protocol/Remote/Minion.pm index 8415abfe1..64d48173a 100644 --- a/lib/pgBackRest/Protocol/Remote/Minion.pm +++ b/lib/pgBackRest/Protocol/Remote/Minion.pm @@ -19,7 +19,6 @@ use pgBackRest::Archive::Push::File; use pgBackRest::Check::Check; use pgBackRest::Config::Config; use pgBackRest::Db; -use pgBackRest::Info; use pgBackRest::Protocol::Command::Minion; use pgBackRest::Protocol::Helper; use pgBackRest::Protocol::Storage::Helper; @@ -71,7 +70,6 @@ sub init 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 $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; # Create anonymous subs for each command @@ -122,9 +120,6 @@ sub init &OP_STORAGE_PATH_GET => sub {$oStorage->pathGet(@{shift()})}, &OP_STORAGE_HASH_SIZE => sub {$oStorage->hashSize(@{shift()})}, - # Info commands - &OP_INFO_STANZA_LIST => sub {$oInfo->stanzaList(@{shift()})}, - # Wait command &OP_WAIT => sub {waitRemainder(@{shift()})}, }; diff --git a/src/command/info/info.c b/src/command/info/info.c index dcf462083..8e41b0269 100644 --- a/src/command/info/info.c +++ b/src/command/info/info.c @@ -636,13 +636,7 @@ cmdInfo(void) MEM_CONTEXT_TEMP_BEGIN() { - if (!cfgOptionTest(cfgOptRepoHost)) // {uncovered - Perl code is covered in integration tests} - { - ioHandleWriteOneStr(STDOUT_FILENO, infoRender()); - } - // Else do it in Perl - else - perlExec(); // {+uncovered} + ioHandleWriteOneStr(STDOUT_FILENO, infoRender()); } MEM_CONTEXT_TEMP_END(); diff --git a/src/main.c b/src/main.c index 3fd3c4d36..2e7dcddf7 100644 --- a/src/main.c +++ b/src/main.c @@ -97,6 +97,13 @@ main(int argListSize, const char *argList[]) perlExec(); } + // Info command + // ------------------------------------------------------------------------------------------------------------------------- + else if (cfgCommand() == cfgCmdInfo) + { + cmdInfo(); + } + // Execute Perl for commands not implemented in C // ------------------------------------------------------------------------------------------------------------------------- else diff --git a/src/perl/embed.auto.c b/src/perl/embed.auto.c index 70ea9d4f1..4992e9556 100644 --- a/src/perl/embed.auto.c +++ b/src/perl/embed.auto.c @@ -10320,678 +10320,6 @@ static const EmbeddedModule embeddedModule[] = "\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", .data = @@ -13701,9 +13029,6 @@ static const EmbeddedModule embeddedModule[] = "use constant OP_STORAGE_PATH_GET => 'storagePathGet';\n" "push @EXPORT, qw(OP_STORAGE_PATH_GET);\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" "push @EXPORT, qw(OP_RESTORE_FILE);\n" "\n\n" @@ -14833,7 +14158,6 @@ static const EmbeddedModule embeddedModule[] = "use pgBackRest::Check::Check;\n" "use pgBackRest::Config::Config;\n" "use pgBackRest::Db;\n" - "use pgBackRest::Info;\n" "use pgBackRest::Protocol::Command::Minion;\n" "use pgBackRest::Protocol::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" "\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" "\n\n" "my $hCommandMap =\n" @@ -14919,8 +14242,6 @@ static const EmbeddedModule embeddedModule[] = "&OP_STORAGE_PATH_GET => sub {$oStorage->pathGet(@{shift()})},\n" "&OP_STORAGE_HASH_SIZE => sub {$oStorage->hashSize(@{shift()})},\n" "\n\n" - "&OP_INFO_STANZA_LIST => sub {$oInfo->stanzaList(@{shift()})},\n" - "\n\n" "&OP_WAIT => sub {waitRemainder(@{shift()})},\n" "};\n" "\n\n" diff --git a/test/define.yaml b/test/define.yaml index b9a523f55..3b9603301 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -582,13 +582,6 @@ unit: - name: info test: - # ---------------------------------------------------------------------------------------------------------------------------- - - name: unit-perl - total: 2 - - coverage: - Info: full - # ---------------------------------------------------------------------------------------------------------------------------- - name: info total: 1 diff --git a/test/expect/mock-all-001.log b/test/expect/mock-all-001.log index 96d8a8015..7f0695ebe 100644 --- a/test/expect/mock-all-001.log +++ b/test/expect/mock-all-001.log @@ -4951,7 +4951,7 @@ stanza: db timestamp start/stop: [TIMESTAMP-STR] wal start/stop: n/a 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) > [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] wal start/stop: n/a 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] timestamp start/stop: [TIMESTAMP-STR] diff --git a/test/expect/mock-all-003.log b/test/expect/mock-all-003.log index 72fe7483e..80b49ed77 100644 --- a/test/expect/mock-all-003.log +++ b/test/expect/mock-all-003.log @@ -2589,7 +2589,7 @@ stanza: db timestamp start/stop: [TIMESTAMP-STR] wal start/stop: n/a 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] incr backup: [BACKUP-INCR-3] @@ -3179,7 +3179,7 @@ stanza: db timestamp start/stop: [TIMESTAMP-STR] wal start/stop: n/a 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] info all stanzas - normal output (db-master host) diff --git a/test/lib/pgBackRestTest/Module/Info/InfoUnitPerlTest.pm b/test/lib/pgBackRestTest/Module/Info/InfoUnitPerlTest.pm deleted file mode 100644 index 8a13d7127..000000000 --- a/test/lib/pgBackRestTest/Module/Info/InfoUnitPerlTest.pm +++ /dev/null @@ -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; [parent: f79af47bd4ff]