From f0ef73db7009cd6e08740d270a6ee7565efc9f8c Mon Sep 17 00:00:00 2001 From: David Steele Date: Fri, 13 Dec 2019 17:55:41 -0500 Subject: [PATCH] pgBackRest is now pure C. Remove embedded Perl from the distributed binary. This includes code, configure, Makefile, and packages. The distributed binary is now pure C. Remove storagePathEnforceSet() from the C Storage object which allowed Perl to write outside of the storage base directory. Update mock/all and real/all integration tests to use storageLocal() where they were violating this rule. Remove "c" option that allowed the remote to tell if it was being called from C or Perl. Code to convert options to JSON for passing to Perl (perl/config.c) has been moved to LibC since it is still required for Perl integration tests. Update build and installation instructions in the user guide. Remove all Perl unit tests. Remove obsolete Perl code. In particular this included all the Perl protocol code which required modifications to the Perl storage, manifest, and db objects that are still required for integration testing but only run locally. Any remaining Perl code is required for testing, documentation, or code generation. Rename perlReq to binReq in define.yaml to indicate that the binary is required for a test. This had been the actual meaning for quite some time but the key was never renamed. --- .../lib/pgBackRestBuild/Config/BuildDefine.pm | 2 +- build/lib/pgBackRestBuild/Config/Data.pm | 13 - build/lib/pgBackRestBuild/Embed/Build.pm | 128 - doc/xml/release.xml | 6 + doc/xml/user-guide.xml | 79 +- lib/pgBackRest/Backup/Info.pm | 1 - lib/pgBackRest/Common/Cipher.pm | 48 - lib/pgBackRest/Common/Io/Process.pm | 187 - lib/pgBackRest/Db.pm | 198 +- lib/pgBackRest/LibCAuto.pm | 1 - lib/pgBackRest/Main.pm | 196 - lib/pgBackRest/Manifest.pm | 5 +- lib/pgBackRest/Protocol/Base/Master.pm | 293 - lib/pgBackRest/Protocol/Base/Minion.pm | 247 - lib/pgBackRest/Protocol/Command/Master.pm | 148 - lib/pgBackRest/Protocol/Command/Minion.pm | 62 - lib/pgBackRest/Protocol/Helper.pm | 489 - lib/pgBackRest/Protocol/Local/Master.pm | 51 - lib/pgBackRest/Protocol/Local/Process.pm | 667 - lib/pgBackRest/Protocol/Remote/Master.pm | 76 - lib/pgBackRest/Protocol/Remote/Minion.pm | 122 - lib/pgBackRest/Protocol/Storage/File.pm | 180 - lib/pgBackRest/Protocol/Storage/Helper.pm | 34 +- lib/pgBackRest/Protocol/Storage/Remote.pm | 342 - libc/LibC.xs | 2 +- libc/Makefile.PL | 1 - .../config.c => libc/xs/config/configTest.xsh | 9 +- libc/xs/storage/storage.xs | 2 - src/Makefile.in | 18 +- src/build.auto.h.in | 3 - src/command/archive/get/get.c | 1 - src/command/backup/pageChecksum.c | 4 +- src/command/info/info.c | 1 - src/common/exit.c | 47 +- src/config/config.auto.c | 9 - src/config/config.auto.h | 5 +- src/config/config.h | 2 +- src/config/define.auto.c | 23 - src/config/define.auto.h | 1 - src/config/load.c | 3 +- src/config/parse.auto.c | 8 - src/configure | 55 +- src/configure.ac | 6 - src/info/infoPg.c | 4 +- src/main.c | 9 +- src/perl/config.h | 14 - src/perl/embed.auto.c | 11537 ---------------- src/perl/exec.c | 276 - src/perl/exec.h | 18 - src/perl/libc.auto.c | 2337 ---- src/protocol/helper.c | 3 - src/storage/storage.c | 20 +- src/storage/storage.intern.h | 4 - test/define.yaml | 97 +- test/lib/pgBackRestTest/Common/DefineTest.pm | 6 +- test/lib/pgBackRestTest/Common/JobTest.pm | 14 +- test/lib/pgBackRestTest/Common/ListTest.pm | 6 +- .../Module/Common/CommonEncodePerlTest.pm | 62 - .../Module/Common/CommonIniPerlTest.pm | 533 - .../Module/Common/CommonIoBufferedPerlTest.pm | 259 - .../Module/Common/CommonIoHandlePerlTest.pm | 209 - .../Module/Common/CommonIoProcessPerlTest.pm | 72 - .../Module/Common/CommonLogPerlTest.pm | 46 - .../Module/Info/InfoInfoArchivePerlTest.pm | 249 - .../Module/Info/InfoInfoBackupPerlTest.pm | 262 - .../Module/Manifest/ManifestAllPerlTest.pm | 1733 --- .../pgBackRestTest/Module/Mock/MockAllTest.pm | 3 +- .../Protocol/ProtocolCommonMinionPerlTest.pm | 135 - .../Module/Protocol/ProtocolHelperPerlTest.pm | 155 - .../pgBackRestTest/Module/Real/RealAllTest.pm | 13 +- .../Module/Storage/StorageHelperPerlTest.pm | 116 - .../Module/Storage/StoragePerlTest.pm | 351 - test/patch/debian-package.patch | 36 + test/patch/rhel-package.patch | 20 + test/src/module/common/exitTest.c | 13 - test/src/module/perl/configTest.c | 112 - test/src/module/perl/execTest.c | 82 - test/src/module/protocol/protocolTest.c | 12 +- test/src/module/storage/posixTest.c | 5 - test/test.pl | 56 +- 80 files changed, 239 insertions(+), 22415 deletions(-) delete mode 100644 build/lib/pgBackRestBuild/Embed/Build.pm delete mode 100644 lib/pgBackRest/Common/Cipher.pm delete mode 100644 lib/pgBackRest/Common/Io/Process.pm delete mode 100644 lib/pgBackRest/Main.pm delete mode 100644 lib/pgBackRest/Protocol/Base/Master.pm delete mode 100644 lib/pgBackRest/Protocol/Base/Minion.pm delete mode 100644 lib/pgBackRest/Protocol/Command/Master.pm delete mode 100644 lib/pgBackRest/Protocol/Command/Minion.pm delete mode 100644 lib/pgBackRest/Protocol/Helper.pm delete mode 100644 lib/pgBackRest/Protocol/Local/Master.pm delete mode 100644 lib/pgBackRest/Protocol/Local/Process.pm delete mode 100644 lib/pgBackRest/Protocol/Remote/Master.pm delete mode 100644 lib/pgBackRest/Protocol/Remote/Minion.pm delete mode 100644 lib/pgBackRest/Protocol/Storage/File.pm delete mode 100644 lib/pgBackRest/Protocol/Storage/Remote.pm rename src/perl/config.c => libc/xs/config/configTest.xsh (96%) delete mode 100644 src/perl/config.h delete mode 100644 src/perl/embed.auto.c delete mode 100644 src/perl/exec.c delete mode 100644 src/perl/exec.h delete mode 100644 src/perl/libc.auto.c delete mode 100644 test/lib/pgBackRestTest/Module/Common/CommonEncodePerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Common/CommonIniPerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Common/CommonIoBufferedPerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Common/CommonIoHandlePerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Common/CommonIoProcessPerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Common/CommonLogPerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Info/InfoInfoArchivePerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Info/InfoInfoBackupPerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Manifest/ManifestAllPerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Protocol/ProtocolCommonMinionPerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Protocol/ProtocolHelperPerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Storage/StorageHelperPerlTest.pm delete mode 100644 test/lib/pgBackRestTest/Module/Storage/StoragePerlTest.pm create mode 100644 test/patch/debian-package.patch create mode 100644 test/patch/rhel-package.patch delete mode 100644 test/src/module/perl/configTest.c delete mode 100644 test/src/module/perl/execTest.c diff --git a/build/lib/pgBackRestBuild/Config/BuildDefine.pm b/build/lib/pgBackRestBuild/Config/BuildDefine.pm index e3ae04420..78c6b225d 100644 --- a/build/lib/pgBackRestBuild/Config/BuildDefine.pm +++ b/build/lib/pgBackRestBuild/Config/BuildDefine.pm @@ -134,7 +134,7 @@ sub helpFormatText $strText .= "\n"; } - # Escape perl special characters + # Escape special characters $strLine =~ s/\"/\\"/g; my $strPart; diff --git a/build/lib/pgBackRestBuild/Config/Data.pm b/build/lib/pgBackRestBuild/Config/Data.pm index 8c023f18b..07b7923b9 100644 --- a/build/lib/pgBackRestBuild/Config/Data.pm +++ b/build/lib/pgBackRestBuild/Config/Data.pm @@ -151,8 +151,6 @@ use constant CFGOPT_OUTPUT => 'output'; # Command-line only local/remote options #----------------------------------------------------------------------------------------------------------------------------------- -use constant CFGOPT_C => 'c'; - push @EXPORT, qw(CFGOPT_C); use constant CFGOPT_COMMAND => 'command'; push @EXPORT, qw(CFGOPT_COMMAND); use constant CFGOPT_PROCESS => 'process'; @@ -1038,17 +1036,6 @@ my %hConfigDefine = # Command-line only local/remote options #------------------------------------------------------------------------------------------------------------------------------- - &CFGOPT_C => - { - &CFGDEF_TYPE => CFGDEF_TYPE_BOOLEAN, - &CFGDEF_INTERNAL => true, - &CFGDEF_DEFAULT => false, - &CFGDEF_COMMAND => - { - &CFGCMD_REMOTE => {}, - } - }, - &CFGOPT_COMMAND => { &CFGDEF_TYPE => CFGDEF_TYPE_STRING, diff --git a/build/lib/pgBackRestBuild/Embed/Build.pm b/build/lib/pgBackRestBuild/Embed/Build.pm deleted file mode 100644 index 450115a25..000000000 --- a/build/lib/pgBackRestBuild/Embed/Build.pm +++ /dev/null @@ -1,128 +0,0 @@ -#################################################################################################################################### -# Auto-Generate Embedded Perl Modules -#################################################################################################################################### -package pgBackRestBuild::Embed::Build; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use Exporter qw(import); - our @EXPORT = qw(); - -use pgBackRestBuild::Build::Common; - -use pgBackRest::Common::Log; -use pgBackRest::Common::String; - -#################################################################################################################################### -# Constants -#################################################################################################################################### -use constant BLDLCL_FILE_DEFINE => 'embed'; - -use constant BLDLCL_DATA_EMBED => '01-dataEmbed'; - -#################################################################################################################################### -# Definitions for constants and data to build -#################################################################################################################################### -my $strSummary = 'Embed Perl modules'; - -my $rhBuild = -{ - &BLD_FILE => - { - &BLDLCL_FILE_DEFINE => - { - &BLD_SUMMARY => $strSummary, - - &BLD_DATA => - { - &BLDLCL_DATA_EMBED => - { - &BLD_SUMMARY => 'Embedded Perl modules', - }, - }, - }, - }, -}; - -#################################################################################################################################### -# Embed Perl modules -#################################################################################################################################### -sub buildEmbed -{ - my $oStorage = shift; - - # Output embedded modules array - my $strBuildSource = - "static const EmbeddedModule embeddedModule[] =\n" . - "{\n"; - - foreach my $strModule (sort(keys(%{$oStorage->manifest('lib')}))) - { - # Ignore non-Perl modules - if ($strModule =~ /\.pm$/) - { - # Load data - my $strData = trim(${$oStorage->get("lib/${strModule}")}); - - # Escape \ and quotes - $strData =~ s/\\/\\\\/g; - $strData =~ s/\"/\\\"/g; - - $strBuildSource .= - " {\n" . - " .name = \"${strModule}\",\n" . - " .data =\n"; - - my $strLfLine = undef; - - # Process each line - foreach my $strLine (split("\n", $strData)) - { - # Remove comments - $strLine =~ s/^\s*\#.*$//; - $strLine =~ s/\#[^\'\"]*$//; - - # Remove spacing in constant declarations - if ($strLine =~ /use constant [A-Z0-9_]+/) - { - $strLine =~ s/\s{2,}\=\> / \=\> /g; - } - - # Remove leading/trailing spaces - $strLine = trim($strLine); - - # If empty line then add it to the total empty lines - if ($strLine eq "") - { - $strLfLine .= "\\n"; - } - # Output line (and empty lines if any) - else - { - $strBuildSource .= - (defined($strLfLine) ? " \"$strLfLine\"\n" : '') . - " \"$strLine\\n\"\n"; - - $strLfLine = undef; - } - } - - $strBuildSource .= - " },\n"; - } - } - - $strBuildSource .= - "};"; - - $rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_DATA}{&BLDLCL_DATA_EMBED}{&BLD_SOURCE} = $strBuildSource; - - return $rhBuild; -} - -push @EXPORT, qw(buildEmbed); - -1; diff --git a/doc/xml/release.xml b/doc/xml/release.xml index 39cd9f0e5..64b9d7d43 100644 --- a/doc/xml/release.xml +++ b/doc/xml/release.xml @@ -14,6 +14,12 @@ + + +

is now pure C.

+
+
+ diff --git a/doc/xml/user-guide.xml b/doc/xml/user-guide.xml index b0e37ff01..b6273edc3 100644 --- a/doc/xml/user-guide.xml +++ b/doc/xml/user-guide.xml @@ -83,13 +83,10 @@ postgres - /usr/share/perl5 - /usr/bin - /var/lib/pgbackrest aes-256-cbc zWaf6XtpjIVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO - {[perl-bin-path]}/pgbackrest + /usr/bin/pgbackrest pgbackrest {[br-user]} /home/{[br-user]} @@ -448,6 +445,23 @@

needs to be installed from a package or installed manually as shown here.

+ + Install dependencies + + + + apt-get install postgresql-client libxml2 + -y 2>&1 + + + + + yum install postgresql-libs + + -y 2>&1 + + + Copy <backrest/> binary from build host @@ -461,30 +475,7 @@ - -

contains embedded Perl which requires some additional packages.

- - - Install required Perl packages - - - apt-get install perl - -y 2>&1 - - - - yum install perl perl-Time-HiRes perl-parent perl-JSON - perl-Digest-SHA - -y 2>&1 - - - - yum install perl perl-Time-HiRes perl-Digest-SHA perl-JSON-PP - -y 2>&1 - - - -

Finally, requires log and configuration directories and a configuration file.

+

requires log and configuration directories and a configuration file.

Create <backrest/> configuration file and directories @@ -638,7 +629,7 @@

This user guide is intended to be followed sequentially from beginning to end &mdash; each section depends on the last. For example, the Backup section relies on setup that is performed in the Quick Start section. Once is up and running then skipping around is possible but following the user guide in order is recommended the first time through.

-

Although the examples are targeted at {[user-guide-os]} and {[pg-version]}, it should be fairly easy to apply this guide to any Unix distribution and version. The only OS-specific commands are those to create, start, stop, and drop clusters. The commands will be the same on any Unix system though the locations to install Perl libraries and executables may vary. +

Although the examples are targeted at {[user-guide-os]} and {[pg-version]}, it should be fairly easy to apply this guide to any Unix distribution and version. The only OS-specific commands are those to create, start, stop, and drop clusters. The commands will be the same on any Unix system though the location to install the executable may vary. Configuration information and documentation for PostgreSQL can be found in the Manual.

@@ -766,42 +757,20 @@ - apt-get install build-essential libssl-dev libxml2-dev libperl-dev zlib1g-dev - libpq-dev + apt-get install make gcc libpq-dev libssl-dev libxml2-dev -y 2>&1 - + - yum install build-essential gcc openssl-devel libxml2-devel - postgresql-devel perl-ExtUtils-Embed - - -y 2>&1 - - - - - yum install build-essential gcc make openssl-devel libxml2-devel - postgresql-devel perl-ExtUtils-Embed + yum install make gcc postgresql-devel openssl-devel libxml2-devel -y 2>&1
-

supports 32-bit distributions that build Perl with 64-bit integer support.

- - Check for 64-bit integers - - - perl -V | grep USE_64_BIT_INT - - - -

The executable is written in C. This allows certain time-critical commands (like async archive-push/archive-get) to run more quickly.

- - - Build <backrest/> package + Compile <backrest/> cd /build/pgbackrest-release-{[version]}/src && ./configure diff --git a/lib/pgBackRest/Backup/Info.pm b/lib/pgBackRest/Backup/Info.pm index 8c209e786..615fec016 100644 --- a/lib/pgBackRest/Backup/Info.pm +++ b/lib/pgBackRest/Backup/Info.pm @@ -22,7 +22,6 @@ use pgBackRest::Common::Log; use pgBackRest::Config::Config; use pgBackRest::InfoCommon; use pgBackRest::Manifest; -use pgBackRest::Protocol::Helper; use pgBackRest::Protocol::Storage::Helper; use pgBackRest::Storage::Helper; diff --git a/lib/pgBackRest/Common/Cipher.pm b/lib/pgBackRest/Common/Cipher.pm deleted file mode 100644 index d13fdc0a6..000000000 --- a/lib/pgBackRest/Common/Cipher.pm +++ /dev/null @@ -1,48 +0,0 @@ -#################################################################################################################################### -# Cipher Miscellaneous -#################################################################################################################################### -package pgBackRest::Common::Cipher; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use Exporter qw(import); - our @EXPORT = qw(); - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Log; -use pgBackRest::LibC qw(:random :encode); - -#################################################################################################################################### -# cipherPassGen - generate a passphrase of the specified size (in bytes) -#################################################################################################################################### -sub cipherPassGen -{ - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $iKeySizeInBytes, - ) = - logDebugParam - ( - __PACKAGE__ . '::cipherPassGen', \@_, - {name => 'iKeySizeInBytes', default => 48}, - ); - - # Create and base64 encode the key - my $strCipherPass = encodeToStr(ENCODE_TYPE_BASE64, cryptoRandomBytes($iKeySizeInBytes)); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'strCipherPass', value => $strCipherPass, redact => true} - ); -} - -push @EXPORT, qw(cipherPassGen); - -1; diff --git a/lib/pgBackRest/Common/Io/Process.pm b/lib/pgBackRest/Common/Io/Process.pm deleted file mode 100644 index 10d32aab8..000000000 --- a/lib/pgBackRest/Common/Io/Process.pm +++ /dev/null @@ -1,187 +0,0 @@ -#################################################################################################################################### -# Process Execution, Management, and IO -#################################################################################################################################### -package pgBackRest::Common::Io::Process; -use parent 'pgBackRest::Common::Io::Filter'; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use Exporter qw(import); - our @EXPORT = qw(); -use IPC::Open3 qw(open3); -use POSIX qw(:sys_wait_h); -use Symbol 'gensym'; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Io::Buffered; -use pgBackRest::Common::Log; -use pgBackRest::Common::Wait; - -#################################################################################################################################### -# Package name constant -#################################################################################################################################### -use constant COMMON_IO_PROCESS => __PACKAGE__; - push @EXPORT, qw(COMMON_IO_PROCESS); - -#################################################################################################################################### -# Amount of time to attempt to retrieve errors when a process terminates unexpectedly -#################################################################################################################################### -use constant IO_ERROR_TIMEOUT => 5; - -#################################################################################################################################### -# new - use open3 to run the command and get the io handles -#################################################################################################################################### -sub new -{ - my $class = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $oParent, - $strCommand, - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'oParent', trace => true}, - {name => 'strCommand', trace => true}, - ); - - # Bless with new class - my $self = $class->SUPER::new($oParent); - bless $self, $class; - - # Use open3 to run the command - my ($iProcessId, $fhRead, $fhWrite, $fhReadError); - $fhReadError = gensym; - - $iProcessId = IPC::Open3::open3($fhWrite, $fhRead, $fhReadError, $strCommand); - - # Set handles - $self->handleReadSet($fhRead); - $self->handleWriteSet($fhWrite); - - # Set variables - $self->{iProcessId} = $iProcessId; - $self->{fhReadError} = $fhReadError; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self} - ); -} - -#################################################################################################################################### -# error - handle errors -#################################################################################################################################### -sub error -{ - my $self = shift; - my $iCode = shift; - my $strMessage = shift; - my $strDetail = shift; - my $bClose = shift; - - if (defined($self->{iProcessId})) - { - my $oWait = waitInit(defined($iCode) ? IO_ERROR_TIMEOUT : 0); - - do - { - # Check the result - my $iResult = waitpid($self->{iProcessId}, $bClose ? 0 : WNOHANG); - - # Error if the process exited unexpectedly - if ($iResult != 0) - { - # Get the exit status - my $iExitStatus = $iResult == -1 ? 255 : ${^CHILD_ERROR_NATIVE} >> 8; - - # Drain the stderr stream - my $strError; - my $oIoError = new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle($self->id(), $self->{fhReadError}), 5, $self->bufferMax()); - - while (defined(my $strLine = $oIoError->readLine(true, false))) - { - $strError .= (defined($strError) ? "\n" : '') . $strLine; - } - - delete($self->{iProcessId}); - - if (!$bClose || $iExitStatus != 0 || defined($strError)) - { - my $iErrorCode = - $iExitStatus >= ERROR_MINIMUM && $iExitStatus <= ERROR_MAXIMUM ? $iExitStatus : ERROR_FILE_READ; - - logErrorResult( - $iErrorCode, $self->id() . ' terminated unexpectedly' . - ($iExitStatus != 255 ? sprintf(' [%03d]', $iExitStatus) : ''), - $strError); - } - } - } - while (waitMore($oWait)); - - if (defined($iCode)) - { - $self->parent()->error($iCode, $strMessage, $strDetail); - } - } - else - { - confess &log(ASSERT, 'cannot call error() after process has been closed'); - } -} - -#################################################################################################################################### -# Get process id -#################################################################################################################################### -sub processId -{ - my $self = shift; - - return $self->{iProcessId}; -} - -#################################################################################################################################### -# writeLine - check for error before writing line -#################################################################################################################################### -sub writeLine -{ - my $self = shift; - my $strBuffer = shift; - - # Check if the process has exited abnormally (doesn't seem like we should need this, but the next syswrite does a hard - # abort if the remote process has already closed) - $self->error(); - - return $self->parent()->writeLine($strBuffer); -} - -#################################################################################################################################### -# close - check if the process terminated on error -#################################################################################################################################### -sub close -{ - my $self = shift; - - if (defined($self->{iProcessId})) - { - $self->error(undef, undef, undef, true); - - # Class parent close - $self->parent()->close(); - } - - return true; -} - -1; diff --git a/lib/pgBackRest/Db.pm b/lib/pgBackRest/Db.pm index 368896fd2..49700bdf5 100644 --- a/lib/pgBackRest/Db.pm +++ b/lib/pgBackRest/Db.pm @@ -21,7 +21,6 @@ use pgBackRest::Common::String; use pgBackRest::Common::Wait; use pgBackRest::Config::Config; use pgBackRest::Manifest; -use pgBackRest::Protocol::Helper; use pgBackRest::Protocol::Storage::Helper; use pgBackRest::Version; @@ -98,11 +97,6 @@ sub new if (defined($self->{iRemoteIdx})) { $self->{strDbPath} = cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $self->{iRemoteIdx})); - - if (!isDbLocal({iRemoteIdx => $self->{iRemoteIdx}})) - { - $self->{oProtocol} = protocolGet(CFGOPTVAL_REMOTE_TYPE_DB, $self->{iRemoteIdx}); - } } # Return from function and log return values if any @@ -155,56 +149,46 @@ sub connect # Only connect if not already connected my $bResult = true; - # Run remotely - if (defined($self->{oProtocol})) + if (!defined($self->{oDb})) { - # Set bResult to false if undef is returned - $bResult = $self->{oProtocol}->cmdExecute(OP_DB_CONNECT, undef, false, $bWarnOnError) ? true : false; - } - # Else run locally - else - { - if (!defined($self->{oDb})) + $self->{oDb} = new pgBackRest::LibC::PgClient( + cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $self->{iRemoteIdx}), false), + cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $self->{iRemoteIdx})), 'postgres', + cfgOption(CFGOPT_DB_TIMEOUT) * 1000); + + if ($bWarnOnError) { - $self->{oDb} = new pgBackRest::LibC::PgClient( - cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $self->{iRemoteIdx}), false), - cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $self->{iRemoteIdx})), 'postgres', - cfgOption(CFGOPT_DB_TIMEOUT) * 1000); - - if ($bWarnOnError) - { - eval - { - $self->{oDb}->open(); - return true; - } - or do - { - &log(WARN, exceptionMessage($EVAL_ERROR)); - $bResult = false; - - undef($self->{oDb}); - } - } - else + eval { $self->{oDb}->open(); + return true; } - - if (defined($self->{oDb})) + or do { - my ($fDbVersion) = $self->versionGet(); + &log(WARN, exceptionMessage($EVAL_ERROR)); + $bResult = false; - if ($fDbVersion >= PG_VERSION_APPLICATION_NAME) - { - # Set application name for monitoring and debugging - $self->{oDb}->query( - "set application_name = '" . PROJECT_NAME . ' [' . - (cfgOptionValid(CFGOPT_COMMAND) ? cfgOption(CFGOPT_COMMAND) : cfgCommandName(cfgCommandGet())) . "]'"); + undef($self->{oDb}); + } + } + else + { + $self->{oDb}->open(); + } - # Clear search path to prevent possible function overrides - $self->{oDb}->query("set search_path = 'pg_catalog'"); - } + if (defined($self->{oDb})) + { + my ($fDbVersion) = $self->versionGet(); + + if ($fDbVersion >= PG_VERSION_APPLICATION_NAME) + { + # Set application name for monitoring and debugging + $self->{oDb}->query( + "set application_name = '" . PROJECT_NAME . ' [' . + (cfgOptionValid(CFGOPT_COMMAND) ? cfgOption(CFGOPT_COMMAND) : cfgCommandName(cfgCommandGet())) . "]'"); + + # Clear search path to prevent possible function overrides + $self->{oDb}->query("set search_path = 'pg_catalog'"); } } } @@ -243,22 +227,12 @@ sub executeSql # Get the user-defined command for psql my @stryResult; - # Run remotely - if (defined($self->{oProtocol})) - { - # Execute the command - @stryResult = @{$self->{oProtocol}->cmdExecute(OP_DB_EXECUTE_SQL, [$strSql, $bIgnoreError, $bResult], $bResult)}; - } - # Else run locally - else - { - $self->connect(); - my $strResult = $self->{oDb}->query($strSql); + $self->connect(); + my $strResult = $self->{oDb}->query($strSql); - if (defined($strResult)) - { - @stryResult = @{JSON::PP->new()->allow_nonref()->decode($strResult)}; - } + if (defined($strResult)) + { + @stryResult = @{JSON::PP->new()->allow_nonref()->decode($strResult)}; } # Return from function and log return values if any @@ -346,63 +320,49 @@ sub info #------------------------------------------------------------------------------------------------------------------------------- if (!defined($self->{info}{$strDbPath})) { - # Get info from remote - #--------------------------------------------------------------------------------------------------------------------------- - if (defined($self->{oProtocol})) + # Open the control file and read system id and versions + #----------------------------------------------------------------------------------------------------------------------- + my $strControlFile = "${strDbPath}/" . DB_FILE_PGCONTROL; + my $hFile; + my $tBlock; + + sysopen($hFile, $strControlFile, O_RDONLY) + or confess &log(ERROR, "unable to open ${strControlFile}", ERROR_FILE_OPEN); + + # Read system identifier + sysread($hFile, $tBlock, 8) == 8 + or confess &log(ERROR, "unable to read database system identifier"); + + $self->{info}{$strDbPath}{ullDbSysId} = unpack('Q', $tBlock); + + # Read control version + sysread($hFile, $tBlock, 4) == 4 + or confess &log(ERROR, "unable to read control version"); + + $self->{info}{$strDbPath}{iDbControlVersion} = unpack('L', $tBlock); + + # Read catalog version + sysread($hFile, $tBlock, 4) == 4 + or confess &log(ERROR, "unable to read catalog version"); + + $self->{info}{$strDbPath}{iDbCatalogVersion} = unpack('L', $tBlock); + + # Close the control file + close($hFile); + + # Get PostgreSQL version + $self->{info}{$strDbPath}{strDbVersion} = + $oPgControlVersionHash->{$self->{info}{$strDbPath}{iDbControlVersion}} + {$self->{info}{$strDbPath}{iDbCatalogVersion}}; + + if (!defined($self->{info}{$strDbPath}{strDbVersion})) { - # Execute the command - ($self->{info}{$strDbPath}{strDbVersion}, $self->{info}{$strDbPath}{iDbControlVersion}, - $self->{info}{$strDbPath}{iDbCatalogVersion}, $self->{info}{$strDbPath}{ullDbSysId}) = - $self->{oProtocol}->cmdExecute(OP_DB_INFO, [$strDbPath], true); - } - # Get info locally - #--------------------------------------------------------------------------------------------------------------------------- - else - { - # Open the control file and read system id and versions - #----------------------------------------------------------------------------------------------------------------------- - my $strControlFile = "${strDbPath}/" . DB_FILE_PGCONTROL; - my $hFile; - my $tBlock; - - sysopen($hFile, $strControlFile, O_RDONLY) - or confess &log(ERROR, "unable to open ${strControlFile}", ERROR_FILE_OPEN); - - # Read system identifier - sysread($hFile, $tBlock, 8) == 8 - or confess &log(ERROR, "unable to read database system identifier"); - - $self->{info}{$strDbPath}{ullDbSysId} = unpack('Q', $tBlock); - - # Read control version - sysread($hFile, $tBlock, 4) == 4 - or confess &log(ERROR, "unable to read control version"); - - $self->{info}{$strDbPath}{iDbControlVersion} = unpack('L', $tBlock); - - # Read catalog version - sysread($hFile, $tBlock, 4) == 4 - or confess &log(ERROR, "unable to read catalog version"); - - $self->{info}{$strDbPath}{iDbCatalogVersion} = unpack('L', $tBlock); - - # Close the control file - close($hFile); - - # Get PostgreSQL version - $self->{info}{$strDbPath}{strDbVersion} = - $oPgControlVersionHash->{$self->{info}{$strDbPath}{iDbControlVersion}} - {$self->{info}{$strDbPath}{iDbCatalogVersion}}; - - if (!defined($self->{info}{$strDbPath}{strDbVersion})) - { - confess &log( - ERROR, - 'unexpected control version = ' . $self->{info}{$strDbPath}{iDbControlVersion} . - ' and catalog version = ' . $self->{info}{$strDbPath}{iDbCatalogVersion} . "\n" . - 'HINT: is this version of PostgreSQL supported?', - ERROR_VERSION_NOT_SUPPORTED); - } + confess &log( + ERROR, + 'unexpected control version = ' . $self->{info}{$strDbPath}{iDbControlVersion} . + ' and catalog version = ' . $self->{info}{$strDbPath}{iDbCatalogVersion} . "\n" . + 'HINT: is this version of PostgreSQL supported?', + ERROR_VERSION_NOT_SUPPORTED); } } diff --git a/lib/pgBackRest/LibCAuto.pm b/lib/pgBackRest/LibCAuto.pm index 75c4df9fa..100e4c98a 100644 --- a/lib/pgBackRest/LibCAuto.pm +++ b/lib/pgBackRest/LibCAuto.pm @@ -143,7 +143,6 @@ sub libcAutoExportTag 'CFGOPT_ARCHIVE_TIMEOUT', 'CFGOPT_BACKUP_STANDBY', 'CFGOPT_BUFFER_SIZE', - 'CFGOPT_C', 'CFGOPT_CHECKSUM_PAGE', 'CFGOPT_CMD_SSH', 'CFGOPT_COMMAND', diff --git a/lib/pgBackRest/Main.pm b/lib/pgBackRest/Main.pm deleted file mode 100644 index 80cee4aa5..000000000 --- a/lib/pgBackRest/Main.pm +++ /dev/null @@ -1,196 +0,0 @@ -#################################################################################################################################### -# pgBackRest - Reliable PostgreSQL Backup & Restore -#################################################################################################################################### -package pgBackRest::Main; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -# Convert die to confess to capture the stack trace -$SIG{__DIE__} = sub {Carp::confess @_}; - -use File::Basename qw(dirname); - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Lock; -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::Protocol::Helper; -use pgBackRest::Protocol::Storage::Helper; -use pgBackRest::Storage::Helper; -use pgBackRest::Version; - -#################################################################################################################################### -# Set config JSON separately to avoid exposing secrets in the stack trace -#################################################################################################################################### -my $strConfigJson; -my $strConfigBin; -my $bConfigLoaded = false; - -sub mainConfigSet -{ - $strConfigBin = shift; - $strConfigJson = shift; -} - -#################################################################################################################################### -# Main entry point for the library -#################################################################################################################################### -sub main -{ - my $strCommand = shift; - my @stryCommandArg = @_; - - # Run in eval block to catch errors - # ------------------------------------------------------------------------------------------------------------------------------ - my $iResult = 0; - my $bErrorC = false; - my $strMessage = ''; - - eval - { - # Load command line parameters and config -- pass config by reference to hide secrets more than for efficiency - # -------------------------------------------------------------------------------------------------------------------------- - if (!$bConfigLoaded) - { - configLoad(undef, $strConfigBin, $strCommand, \$strConfigJson); - $bConfigLoaded = true; - } - else - { - cfgCommandSet(cfgCommandId($strCommand)); - } - - # Process remote command - # -------------------------------------------------------------------------------------------------------------------------- - if (cfgCommandTest(CFGCMD_REMOTE)) - { - # Set log levels - cfgOptionSet(CFGOPT_LOG_LEVEL_STDERR, PROTOCOL, true); - logLevelSet(cfgOption(CFGOPT_LOG_LEVEL_FILE), OFF, cfgOption(CFGOPT_LOG_LEVEL_STDERR)); - - logFileSet( - storageLocal(), - cfgOption(CFGOPT_LOG_PATH) . '/' . (cfgOptionTest(CFGOPT_STANZA) ? cfgOption(CFGOPT_STANZA) : 'all') . '-' . - lc(cfgOption(CFGOPT_COMMAND)) . '-' . lc(cfgCommandName(cfgCommandGet())) . '-' . - sprintf("%03d", cfgOption(CFGOPT_PROCESS))); - - if (cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) && - !cfgOptionTest(CFGOPT_REPO_TYPE, CFGOPTVAL_REPO_TYPE_S3) && - !-e cfgOption(CFGOPT_REPO_PATH)) - { - confess &log(ERROR, - cfgOptionName(CFGOPT_REPO_PATH) . ' \'' . cfgOption(CFGOPT_REPO_PATH) . '\' does not exist', - ERROR_PATH_MISSING); - } - - # Load module dynamically - require pgBackRest::Protocol::Remote::Minion; - pgBackRest::Protocol::Remote::Minion->import(); - - # Create the remote object - my $oRemote = new pgBackRest::Protocol::Remote::Minion( - cfgOption(CFGOPT_BUFFER_SIZE), cfgOption(CFGOPT_PROTOCOL_TIMEOUT)); - - # Process remote requests - $oRemote->process( - cfgOption(CFGOPT_LOCK_PATH), cfgOption(CFGOPT_COMMAND), cfgOption(CFGOPT_STANZA, false), cfgOption(CFGOPT_PROCESS)); - } - else - { - # Check that the repo path exists - require pgBackRest::Protocol::Storage::Helper; - pgBackRest::Protocol::Storage::Helper->import(); - - if (isRepoLocal() && !cfgOptionTest(CFGOPT_REPO_TYPE, CFGOPTVAL_REPO_TYPE_S3) && !storageRepo()->pathExists('')) - { - confess &log(ERROR, - cfgOptionName(CFGOPT_REPO_PATH) . ' \'' . cfgOption(CFGOPT_REPO_PATH) . '\' does not exist', - ERROR_PATH_MISSING); - } - - logFileSet( - storageLocal(), - cfgOption(CFGOPT_LOG_PATH) . '/' . cfgOption(CFGOPT_STANZA) . '-' . lc(cfgCommandName(cfgCommandGet()))); - } - - return 1; - } - - # Check for errors - # ------------------------------------------------------------------------------------------------------------------------------ - or do - { - # Perl 5.10 seems to have a problem propagating errors up through a large call stack, so in the case that the error arrives - # blank just use the last logged error instead. Don't do this in all cases because newer Perls seem to work fine and there - # are other errors that could be arriving in $EVAL_ERROR. - my $oException = defined($EVAL_ERROR) && length($EVAL_ERROR) > 0 ? $EVAL_ERROR : logErrorLast(); - - # If a backrest exception - if (isException(\$oException)) - { - $iResult = $oException->code(); - $bErrorC = $oException->errorC(); - - # Only return message if we are in an async process since this will not be logged to the console - if (!$bConfigLoaded && cfgOption(CFGOPT_ARCHIVE_ASYNC)) - { - $strMessage = $oException->message(); - } - } - # Else a regular Perl exception - else - { - $iResult = ERROR_UNHANDLED; - $strMessage = - 'process terminated due to an unhandled exception' . - (defined($oException) ? ":\n${oException}" : ': [exception not defined]'); - } - }; - - # Return result and error message if the result is an error - return $iResult, $bErrorC, $strMessage; -} - -#################################################################################################################################### -# Do any cleanup required when the perl process is about to be shut down -#################################################################################################################################### -sub mainCleanup -{ - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $iExitCode, - ) = - logDebugParam - ( - __PACKAGE__ . '::mainCleanup', \@_, - {name => 'iExitCode', required => false}, - ); - - # Don't fail if the remote can't be closed - eval - { - protocolDestroy(undef, undef, defined($iExitCode) && ($iExitCode == 0 || $iExitCode == 1)); - return true; - } - # this eval exists only to suppress protocol shutdown errors so original error will not be lost - or do {}; - - # Don't fail if the lock can't be released (it will be freed by the system though the file will remain) - eval - { - lockRelease(false); - return true; - } - # this eval exists only to suppress lock errors so original error will not be lost - or do {}; - - # Log return values if any - return logDebugReturn($strOperation); -} - -1; diff --git a/lib/pgBackRest/Manifest.pm b/lib/pgBackRest/Manifest.pm index b9b6f5c54..7bbd97400 100644 --- a/lib/pgBackRest/Manifest.pm +++ b/lib/pgBackRest/Manifest.pm @@ -19,7 +19,6 @@ use pgBackRest::Common::Ini; use pgBackRest::Common::Log; use pgBackRest::Common::Wait; use pgBackRest::Config::Config; -use pgBackRest::Protocol::Helper; use pgBackRest::Protocol::Storage::Helper; use pgBackRest::Storage::Helper; @@ -1108,9 +1107,7 @@ sub build # lead to an invalid diff/incr backup later when using timestamps to determine which files have changed. Offline backups do # not wait because it makes testing much faster and Postgres should not be running (if it is the backup will not be # consistent anyway and the one-second resolution problem is the least of our worries). - my $lTimeBegin = - $oStorageDbMaster->can('protocol') ? - $oStorageDbMaster->protocol()->cmdExecute(OP_WAIT, [$bOnline]) : waitRemainder($bOnline); + my $lTimeBegin = waitRemainder($bOnline); # Check that links are valid $self->linkCheck(); diff --git a/lib/pgBackRest/Protocol/Base/Master.pm b/lib/pgBackRest/Protocol/Base/Master.pm deleted file mode 100644 index a1b2818e3..000000000 --- a/lib/pgBackRest/Protocol/Base/Master.pm +++ /dev/null @@ -1,293 +0,0 @@ -#################################################################################################################################### -# Protocol Master Base -#################################################################################################################################### -package pgBackRest::Protocol::Base::Master; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use Exporter qw(import); - our @EXPORT = qw(); -use Time::HiRes qw(gettimeofday); -use JSON::PP; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Ini; -use pgBackRest::Common::Log; -use pgBackRest::Version; - -#################################################################################################################################### -# Operation constants -#################################################################################################################################### -use constant OP_NOOP => 'noop'; - push @EXPORT, qw(OP_NOOP); -use constant OP_EXIT => 'exit'; - push @EXPORT, qw(OP_EXIT); - -#################################################################################################################################### -# 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, - $self->{strName}, - $self->{strId}, - $self->{oIo}, - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'strName', trace => true}, - {name => 'strId', trace => true}, - {name => 'oIo', trace => true}, - ); - - # Create JSON object - $self->{oJSON} = JSON::PP->new()->allow_nonref(); - - # Setup the keepalive timer - $self->{fKeepAliveTimeout} = $self->io()->timeout() / 2 > 120 ? 120 : $self->io()->timeout() / 2; - $self->{fKeepAliveTime} = gettimeofday(); - - # Set the error prefix used when raising error messages - $self->{strErrorPrefix} = 'raised from ' . $self->{strId}; - - # Check greeting to be sure the protocol matches - $self->greetingRead(); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self, trace => true} - ); -} - -#################################################################################################################################### -# DESTROY -#################################################################################################################################### -sub DESTROY -{ - my $self = shift; - - $self->close(); -} - -#################################################################################################################################### -# greetingRead -# -# Read the greeting and make sure it is as expected. -#################################################################################################################################### -sub greetingRead -{ - my $self = shift; - - # Get the first line of output from the remote if possible - my $strGreeting = $self->io()->readLine(true); - - # Parse the greeting and make sure it is valid - my $hGreeting; - - eval - { - $hGreeting = $self->{oJSON}->decode($strGreeting); - - return true; - } - # Report any error that stopped parsing - or do - { - $self->io()->error(ERROR_PROTOCOL, 'invalid protocol greeting', $strGreeting); - }; - - # Error if greeting parameters do not match - for my $hParam ({strName => 'name', strExpected => PROJECT_NAME}, - {strName => 'version', strExpected => PROJECT_VERSION}, - {strName => 'service', strExpected => $self->{strName}}) - { - if (!defined($hGreeting->{$hParam->{strName}}) || $hGreeting->{$hParam->{strName}} ne $hParam->{strExpected}) - { - confess &log(ERROR, - 'found name \'' . (defined($hGreeting->{$hParam->{strName}}) ? $hGreeting->{$hParam->{strName}} : '[undef]') . - "' in protocol greeting instead of expected '$hParam->{strExpected}'", ERROR_HOST_CONNECT); - } - } - - # Perform noop to catch errors early - $self->noOp(); -} - -#################################################################################################################################### -# outputRead -# -# Read output from the remote process. -#################################################################################################################################### -sub outputRead -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $bOutputRequired, - $bSuppressLog, - $bWarnOnError, - $bRef, - ) = - logDebugParam - ( - __PACKAGE__ . '->outputRead', \@_, - {name => 'bOutputRequired', default => false, trace => true}, - {name => 'bSuppressLog', required => false, trace => true}, - {name => 'bWarnOnError', default => false, trace => true}, - {name => 'bRef', default => false, trace => true}, - ); - - my $strProtocolResult = $self->io()->readLine(); - - logDebugMisc - ( - $strOperation, undef, - {name => 'strProtocolResult', value => $strProtocolResult, trace => true} - ); - - my $hResult = $self->{oJSON}->decode($strProtocolResult); - - # Raise any errors - if (defined($hResult->{err})) - { - my $strError = $self->{strErrorPrefix} . (defined($hResult->{out}) ? ": $hResult->{out}" : ''); - - # Raise the error if a warning is not requested - if (!$bWarnOnError) - { - confess &log( - ERROR, $strError . (defined($hResult->{errStack}) ? "\n$hResult->{errStack}" : ''), $hResult->{err}, $bSuppressLog); - } - - &log(WARN, $strError, $hResult->{err}); - undef($hResult->{out}); - } - - # Reset the keep alive time - $self->{fKeepAliveTime} = gettimeofday(); - - # If output is required and there is no output, raise exception - if ($bOutputRequired && !defined($hResult->{out})) - { - confess &log(ERROR, "$self->{strErrorPrefix}: output is not defined", ERROR_PROTOCOL_OUTPUT_REQUIRED); - } - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'hOutput', value => $hResult->{out}, ref => $bRef, trace => true} - ); -} - -#################################################################################################################################### -# cmdWrite -# -# Send command to remote process. -#################################################################################################################################### -sub cmdWrite -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strCommand, - $hParam, - ) = - logDebugParam - ( - __PACKAGE__ . '->cmdWrite', \@_, - {name => 'strCommand', trace => true}, - {name => 'hParam', required => false, trace => true}, - ); - - my $strProtocolCommand = $self->{oJSON}->encode({cmd => $strCommand, param => $hParam}); - - logDebugMisc - ( - $strOperation, undef, - {name => 'strProtocolCommand', value => $strProtocolCommand, trace => true} - ); - - # Write out the command - $self->io()->writeLine($strProtocolCommand); - - # Reset the keep alive time - $self->{fKeepAliveTime} = gettimeofday(); - - # Return from function and log return values if any - logDebugReturn($strOperation); -} - -#################################################################################################################################### -# cmdExecute -# -# Send command to remote process and wait for output. -#################################################################################################################################### -sub cmdExecute -{ - my $self = shift; - my $strCommand = shift; - my $oParamRef = shift; - my $bOutputRequired = shift; - my $bWarnOnError = shift; - - $self->cmdWrite($strCommand, $oParamRef); - - return $self->outputRead($bOutputRequired, undef, $bWarnOnError); -} - -#################################################################################################################################### -# keepAlive -# -# Send periodic noops so the remote does not time out. -#################################################################################################################################### -sub keepAlive -{ - my $self = shift; - - if (gettimeofday() - $self->{fKeepAliveTimeout} > $self->{fKeepAliveTime}) - { - $self->noOp(); - } -} - -#################################################################################################################################### -# noOp -# -# Send noop to test connection or keep it alive. -#################################################################################################################################### -sub noOp -{ - my $self = shift; - - $self->cmdExecute(OP_NOOP, undef, false); - $self->{fKeepAliveTime} = gettimeofday(); -} - -#################################################################################################################################### -# Getters -#################################################################################################################################### -sub io {shift->{oIo}} -sub master {true} - -1; diff --git a/lib/pgBackRest/Protocol/Base/Minion.pm b/lib/pgBackRest/Protocol/Base/Minion.pm deleted file mode 100644 index 2ad254574..000000000 --- a/lib/pgBackRest/Protocol/Base/Minion.pm +++ /dev/null @@ -1,247 +0,0 @@ -#################################################################################################################################### -# Protocol Minion Base -#################################################################################################################################### -package pgBackRest::Protocol::Base::Minion; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use Exporter qw(import); - our @EXPORT = qw(); -use JSON::PP; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Ini; -use pgBackRest::Common::Lock; -use pgBackRest::Common::Log; -use pgBackRest::Common::String; -use pgBackRest::LibC qw(:lock); -use pgBackRest::Protocol::Base::Master; -use pgBackRest::Protocol::Helper; -use pgBackRest::Version; - -#################################################################################################################################### -# Constant used to define code to run after each operation -#################################################################################################################################### -use constant OP_POST => 'post'; - push @EXPORT, qw(OP_POST); - -#################################################################################################################################### -# 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, - $self->{strName}, - $self->{oIo}, - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'strName', trace => true}, - {name => 'oIo', trace => true}, - ); - - # Create JSON object - $self->{oJSON} = JSON::PP->new()->allow_nonref(); - - # Write the greeting so master process knows who we are - $self->greetingWrite(); - - # Initialize module variables - $self->{hCommandMap} = $self->can('init') ? $self->init() : undef; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self, trace => true} - ); -} - -#################################################################################################################################### -# greetingWrite -# -# Send a greeting to the master process. -#################################################################################################################################### -sub greetingWrite -{ - my $self = shift; - - # Write the greeting - $self->io()->writeLine((JSON::PP->new()->canonical()->allow_nonref())->encode( - {name => PROJECT_NAME, service => $self->{strName}, version => PROJECT_VERSION})); -} - -#################################################################################################################################### -# errorWrite -# -# Write errors with error codes in protocol format, otherwise write to stderr and exit with error. -#################################################################################################################################### -sub errorWrite -{ - my $self = shift; - my $oException = shift; - - # Throw hard error if this is not a standard exception - if (!isException(\$oException)) - { - confess &log(ERROR, 'unknown error: ' . $oException, ERROR_UNKNOWN); - } - - # Write error code and message - $self->io()->writeLine($self->{oJSON}->encode({err => $oException->code(), out => $oException->message()})); -} - -#################################################################################################################################### -# outputWrite -# -# Write output for the master process. -#################################################################################################################################### -sub outputWrite -{ - my $self = shift; - - $self->io()->writeLine($self->{oJSON}->encode({out => \@_})); -} - -#################################################################################################################################### -# cmdRead -# -# Read command sent by the master process. -#################################################################################################################################### -sub cmdRead -{ - my $self = shift; - - my $hCommand = $self->{oJSON}->decode($self->io()->readLine()); - - return $hCommand->{cmd}, $hCommand->{param}; -} - -#################################################################################################################################### -# process -#################################################################################################################################### -sub process -{ - my $self = shift; - my $strLockPath = shift; - my $strLockCommand = shift; - my $strLockStanza = shift; - my $iProcessId = shift; - - # Reset stderr log level so random errors do not get output - logLevelSet(undef, undef, OFF); - - # A permanent error will be returned from every command once it has been set. In some cases this is a more graceful way to - # exit than a hard error. - my $oPermanentError; - - # Loop until the exit command is received - eval - { - # Acquire a lock if required (this will be determined by lockAcquire()). This is done here so any errors will be - # transmitted through the protocol layer and cause a graceful shutdown rather than a remote abort. - if (defined($strLockPath) && defined($strLockStanza) && $iProcessId == 0) - { - eval - { - if (lockAcquire($strLockPath, $strLockCommand, $strLockStanza, 30, true)) - { - # Check if processes have been stopped - lockStopTest(); - } - - return true; - } - or do - { - $oPermanentError = $EVAL_ERROR; - }; - } - - while (true) - { - my ($strCommand, $rParam) = $self->cmdRead(); - - last if ($strCommand eq OP_EXIT); - - # If permanent error is set then always return it - if (defined($oPermanentError)) - { - $self->errorWrite($oPermanentError); - } - # Else process as usual - else - { - eval - { - # Check for the command in the map and run it if found - if (defined($self->{hCommandMap}{$strCommand})) - { - $self->outputWrite($self->{hCommandMap}{$strCommand}->($rParam)); - } - # Run the standard NOOP command. This this can be overridden in hCommandMap to implement a custom NOOP. - elsif ($strCommand eq OP_NOOP) - { - protocolKeepAlive(); - $self->outputWrite(); - } - else - { - confess "invalid command: ${strCommand}"; - } - - # Run the post command if defined - if (defined($self->{hCommandMap}{&OP_POST})) - { - $self->{hCommandMap}{&OP_POST}->(); - } - - return true; - } - # Process errors - or do - { - $self->errorWrite($EVAL_ERROR); - }; - } - } - - return true; - } - or do - { - my $oException = $EVAL_ERROR; - - # Change log level so error will go to stderr - logLevelSet(undef, undef, PROTOCOL); - - # If standard exception - if (isException(\$oException)) - { - confess &log($oException->level(), $oException->message(), $oException->code()); - } - - # Else unexpected Perl exception - confess &log(ERROR, 'unknown error: ' . $oException, ERROR_UNKNOWN); - }; -} - -#################################################################################################################################### -# Getters -#################################################################################################################################### -sub io {shift->{oIo}} -sub master {false} - -1; diff --git a/lib/pgBackRest/Protocol/Command/Master.pm b/lib/pgBackRest/Protocol/Command/Master.pm deleted file mode 100644 index ab0ba61b1..000000000 --- a/lib/pgBackRest/Protocol/Command/Master.pm +++ /dev/null @@ -1,148 +0,0 @@ -#################################################################################################################################### -# PROTOCOL COMMAND MASTER MODULE -#################################################################################################################################### -package pgBackRest::Protocol::Command::Master; -use parent 'pgBackRest::Protocol::Base::Master'; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use File::Basename qw(dirname); -use Time::HiRes qw(gettimeofday); - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Ini; -use pgBackRest::Common::Log; -use pgBackRest::Common::Io::Process; -use pgBackRest::Protocol::Base::Master; -use pgBackRest::Version; - -#################################################################################################################################### -# CONSTRUCTOR -#################################################################################################################################### -sub new -{ - my $class = shift; # Class name - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strName, # Name of the protocol - $strId, # Id of this process for error messages - $strCommand, # Command to execute on local/remote - $iBufferMax, # Maximum buffer size - $iCompressLevel, # Set compression level - $iCompressLevelNetwork, # Set compression level for network only compression - $iProtocolTimeout, # Protocol timeout - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'strName'}, - {name => 'strId'}, - {name => 'strCommand'}, - {name => 'iBufferMax'}, - {name => 'iCompressLevel'}, - {name => 'iCompressLevelNetwork'}, - {name => 'iProtocolTimeout'}, - ); - - # Set command - if (!defined($strCommand)) - { - confess &log(ASSERT, 'strCommand must be set'); - } - - # Execute the command - my $oIo = new pgBackRest::Common::Io::Process( - new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle($strId), $iProtocolTimeout, $iBufferMax), $strCommand); - - # Create the class hash - my $self = $class->SUPER::new($strName, $strId, $oIo); - bless $self, $class; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self} - ); -} - -#################################################################################################################################### -# close -#################################################################################################################################### -sub close -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $bComplete, - ) = - logDebugParam - ( - __PACKAGE__ . '->close', \@_, - {name => 'bComplete', default => false, trace => true}, - ); - - # Exit status defaults to success - my $iExitStatus = 0; - my $bClosed = false; - - # Only send the exit command if the process is running - if (defined($self->io()) && defined($self->io()->processId())) - { - &log(TRACE, "sending exit command to process"); - - eval - { - $self->cmdWrite(OP_EXIT); - return true; - } - or do - { - my $oException = $EVAL_ERROR; - my $strError = 'unable to shutdown protocol'; - my $strHint = 'HINT: the process completed all operations successfully but protocol-timeout may need to be increased.'; - - if (isException(\$oException)) - { - $iExitStatus = $oException->code(); - } - else - { - if (!defined($oException)) - { - $oException = 'unknown error'; - } - - $iExitStatus = ERROR_UNKNOWN; - } - - &log(WARN, - $strError . ($iExitStatus == ERROR_UNKNOWN ? '' : sprintf(' [%03d]', $oException->code())) . ': ' . - ($iExitStatus == ERROR_UNKNOWN ? $oException : $oException->message()) . - ($bComplete ? "\n${strHint}" : '')); - }; - - $self->{oIo}->close(); - undef($self->{oIo}); - $bClosed = true; - } - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'iExitStatus', value => $iExitStatus, trace => !$bClosed} - ); -} - -1; diff --git a/lib/pgBackRest/Protocol/Command/Minion.pm b/lib/pgBackRest/Protocol/Command/Minion.pm deleted file mode 100644 index 8618a0ad2..000000000 --- a/lib/pgBackRest/Protocol/Command/Minion.pm +++ /dev/null @@ -1,62 +0,0 @@ -#################################################################################################################################### -# PROTOCOL COMMAND MINION MODULE -#################################################################################################################################### -package pgBackRest::Protocol::Command::Minion; -use parent 'pgBackRest::Protocol::Base::Minion'; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use JSON::PP; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Ini; -use pgBackRest::Common::Log; -use pgBackRest::Common::String; -use pgBackRest::Protocol::Base::Minion; -use pgBackRest::Common::Io::Buffered; -use pgBackRest::Version; - -#################################################################################################################################### -# CONSTRUCTOR -#################################################################################################################################### -sub new -{ - my $class = shift; # Class name - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strName, # Name of the protocol - $iBufferMax, # Maximum buffer size - $iProtocolTimeout, # Protocol timeout - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'strName'}, - {name => 'iBufferMax'}, - {name => 'iProtocolTimeout'}, - ); - - # Open buffered protocol io - my $oIo = - new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle('stdio', *STDIN, *STDOUT), $iProtocolTimeout, $iBufferMax); - - # Create the class hash - my $self = $class->SUPER::new($strName, $oIo); - bless $self, $class; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self} - ); -} - -1; diff --git a/lib/pgBackRest/Protocol/Helper.pm b/lib/pgBackRest/Protocol/Helper.pm deleted file mode 100644 index d8be1d459..000000000 --- a/lib/pgBackRest/Protocol/Helper.pm +++ /dev/null @@ -1,489 +0,0 @@ -#################################################################################################################################### -# Create and manage protocol objects. -#################################################################################################################################### -package pgBackRest::Protocol::Helper; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); - -use Exporter qw(import); - our @EXPORT = qw(); - -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::Protocol::Remote::Master; -use pgBackRest::Version; - -#################################################################################################################################### -# Operation constants -#################################################################################################################################### -# Backup module -use constant OP_BACKUP_FILE => 'backupFile'; - push @EXPORT, qw(OP_BACKUP_FILE); - -# Archive Module -use constant OP_ARCHIVE_GET_CHECK => 'archiveCheck'; - push @EXPORT, qw(OP_ARCHIVE_GET_CHECK); - -# Db Module -use constant OP_DB_CONNECT => 'dbConnect'; - push @EXPORT, qw(OP_DB_CONNECT); -use constant OP_DB_EXECUTE_SQL => 'dbExecSql'; - push @EXPORT, qw(OP_DB_EXECUTE_SQL); -use constant OP_DB_INFO => 'dbInfo'; - push @EXPORT, qw(OP_DB_INFO); - -# Storage Module -use constant OP_STORAGE_OPEN_READ => 'storageOpenRead'; - push @EXPORT, qw(OP_STORAGE_OPEN_READ); -use constant OP_STORAGE_OPEN_WRITE => 'storageOpenWrite'; - push @EXPORT, qw(OP_STORAGE_OPEN_WRITE); -use constant OP_STORAGE_CIPHER_PASS_USER => 'storageCipherPassUser'; - push @EXPORT, qw(OP_STORAGE_CIPHER_PASS_USER); -use constant OP_STORAGE_EXISTS => 'storageExists'; - push @EXPORT, qw(OP_STORAGE_EXISTS); -use constant OP_STORAGE_HASH_SIZE => 'storageHashSize'; - push @EXPORT, qw(OP_STORAGE_HASH_SIZE); -use constant OP_STORAGE_LIST => 'storageList'; - push @EXPORT, qw(OP_STORAGE_LIST); -use constant OP_STORAGE_MANIFEST => 'storageManifest'; - push @EXPORT, qw(OP_STORAGE_MANIFEST); -use constant OP_STORAGE_MOVE => 'storageMove'; - push @EXPORT, qw(OP_STORAGE_MOVE); -use constant OP_STORAGE_PATH_GET => 'storagePathGet'; - push @EXPORT, qw(OP_STORAGE_PATH_GET); - -# Restore module -use constant OP_RESTORE_FILE => 'restoreFile'; - push @EXPORT, qw(OP_RESTORE_FILE); - -# Wait -use constant OP_WAIT => 'wait'; - push @EXPORT, qw(OP_WAIT); - -#################################################################################################################################### -# Module variables -#################################################################################################################################### -my $hProtocol = {}; # Global remote hash that is created on first request - -#################################################################################################################################### -# isRepoLocal -# -# Is the backup/archive repository local? -#################################################################################################################################### -sub isRepoLocal -{ - # Not valid for remote - if (cfgCommandTest(CFGCMD_REMOTE) && !cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP)) - { - confess &log(ASSERT, 'isRepoLocal() not valid on ' . cfgOption(CFGOPT_TYPE) . ' remote'); - } - - return cfgOptionTest(CFGOPT_REPO_HOST) ? false : true; -} - -push @EXPORT, qw(isRepoLocal); - -#################################################################################################################################### -# isDbLocal - is the database local? -#################################################################################################################################### -sub isDbLocal -{ - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $iRemoteIdx, - ) = - logDebugParam - ( - __PACKAGE__ . '::isDbLocal', \@_, - {name => 'iRemoteIdx', optional => true, default => cfgOptionValid(CFGOPT_HOST_ID) ? cfgOption(CFGOPT_HOST_ID) : 1, - trace => true}, - ); - - # Not valid for remote - if (cfgCommandTest(CFGCMD_REMOTE) && !cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB)) - { - confess &log(ASSERT, 'isDbLocal() not valid on ' . cfgOption(CFGOPT_TYPE) . ' remote'); - } - - my $bLocal = cfgOptionTest(cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iRemoteIdx)) ? false : true; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'bLocal', value => $bLocal, trace => true} - ); -} - -push @EXPORT, qw(isDbLocal); - -#################################################################################################################################### -# Gets the parameters required to setup the protocol -#################################################################################################################################### -sub protocolParam -{ - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strCommand, - $strRemoteType, - $iRemoteIdx, - $strBackRestBin, - $iProcessIdx, - ) = - logDebugParam - ( - __PACKAGE__ . '::protocolParam', \@_, - {name => 'strCommand'}, - {name => 'strRemoteType'}, - {name => 'iRemoteIdx', default => cfgOptionValid(CFGOPT_HOST_ID) ? cfgOption(CFGOPT_HOST_ID) : 1}, - {name => 'strBackRestBin', optional => true}, - {name => 'iProcessIdx', optional => true, - default => cfgOptionValid(CFGOPT_PROCESS) ? cfgOption(CFGOPT_PROCESS, false) : undef}, - ); - - # Return the remote when required - my $iOptionIdCmd = CFGOPT_REPO_HOST_CMD; - my $iOptionIdConfig = CFGOPT_REPO_HOST_CONFIG; - my $iOptionIdConfigIncludePath = CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH; - my $iOptionIdConfigPath = CFGOPT_REPO_HOST_CONFIG_PATH; - my $iOptionIdHost = CFGOPT_REPO_HOST; - my $iOptionIdUser = CFGOPT_REPO_HOST_USER; - my $strOptionDbPath = undef; - my $strOptionDbPort = undef; - my $strOptionDbSocketPath = undef; - my $strOptionSshPort = CFGOPT_REPO_HOST_PORT; - - if ($strRemoteType eq CFGOPTVAL_REMOTE_TYPE_DB) - { - $iOptionIdCmd = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CMD, $iRemoteIdx); - $iOptionIdConfig = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG, $iRemoteIdx); - $iOptionIdConfigIncludePath = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH, $iRemoteIdx); - $iOptionIdConfigPath = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_PATH, $iRemoteIdx); - $iOptionIdHost = cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iRemoteIdx); - $iOptionIdUser = cfgOptionIdFromIndex(CFGOPT_PG_HOST_USER, $iRemoteIdx); - $strOptionSshPort = cfgOptionIdFromIndex(CFGOPT_PG_HOST_PORT, $iRemoteIdx); - } - - # Db path is not valid in all contexts (restore, for instance) - if (cfgOptionValid(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx))) - { - $strOptionDbPath = - cfgOptionSource(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)) eq CFGDEF_SOURCE_DEFAULT ? - undef : cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)); - } - - # Db port is not valid in all contexts (restore, for instance) - if (cfgOptionValid(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $iRemoteIdx))) - { - $strOptionDbPort = - cfgOptionSource(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $iRemoteIdx)) eq CFGDEF_SOURCE_DEFAULT ? - undef : cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $iRemoteIdx)); - } - - # Db socket is not valid in all contexts (restore, for instance) - if (cfgOptionValid(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $iRemoteIdx))) - { - $strOptionDbSocketPath = - cfgOptionSource(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $iRemoteIdx)) eq CFGDEF_SOURCE_DEFAULT ? - undef : cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $iRemoteIdx)); - } - - # Build hash to set and override command options - my $rhCommandOption = - { - &CFGOPT_COMMAND => {value => $strCommand}, - &CFGOPT_PROCESS => {value => defined($iProcessIdx) ? $iProcessIdx : 0}, - &CFGOPT_CONFIG => - {value => cfgOptionValid($iOptionIdConfig) && cfgOptionSource($iOptionIdConfig) eq CFGDEF_SOURCE_DEFAULT ? - undef : cfgOption($iOptionIdConfig)}, - &CFGOPT_CONFIG_INCLUDE_PATH => - {value => cfgOptionValid($iOptionIdConfigIncludePath) && - cfgOptionSource($iOptionIdConfigIncludePath) eq CFGDEF_SOURCE_DEFAULT ? - undef : cfgOption($iOptionIdConfigIncludePath)}, - &CFGOPT_CONFIG_PATH => - {value => cfgOptionValid($iOptionIdConfigPath) && cfgOptionSource($iOptionIdConfigPath) eq CFGDEF_SOURCE_DEFAULT ? - undef : cfgOption($iOptionIdConfigPath)}, - &CFGOPT_TYPE => {value => $strRemoteType}, - &CFGOPT_LOG_PATH => {}, - &CFGOPT_LOCK_PATH => {}, - - # Only enable file logging on the remote when requested - &CFGOPT_LOG_LEVEL_FILE => {value => cfgOption(CFGOPT_LOG_SUBPROCESS) ? cfgOption(CFGOPT_LOG_LEVEL_FILE) : lc(OFF)}, - - # Don't pass CFGOPT_LOG_LEVEL_STDERR because in the case of the local process calling the remote process the - # option will be set to 'protocol' which is not a valid value from the command line. - &CFGOPT_LOG_LEVEL_STDERR => {}, - - cfgOptionIdFromIndex(CFGOPT_PG_PATH, 1) => {value => $strOptionDbPath}, - cfgOptionIdFromIndex(CFGOPT_PG_PORT, 1) => {value => $strOptionDbPort}, - cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, 1) => {value => $strOptionDbSocketPath}, - - # Set protocol options explicitly so values are not picked up from remote config files - &CFGOPT_BUFFER_SIZE => {value => cfgOption(CFGOPT_BUFFER_SIZE)}, - &CFGOPT_COMPRESS_LEVEL => {value => cfgOption(CFGOPT_COMPRESS_LEVEL)}, - &CFGOPT_COMPRESS_LEVEL_NETWORK => {value => cfgOption(CFGOPT_COMPRESS_LEVEL_NETWORK)}, - &CFGOPT_PROTOCOL_TIMEOUT => {value => cfgOption(CFGOPT_PROTOCOL_TIMEOUT)} - }; - - # Override some per-db options that shouldn't be passed to the command. ??? This could be done better as a new define - # for these options which would then be implemented in cfgCommandWrite(). - for (my $iOptionIdx = 1; $iOptionIdx <= cfgOptionIndexTotal(CFGOPT_PG_HOST); $iOptionIdx++) - { - if ($iOptionIdx != 1) - { - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG, $iOptionIdx)} = {}; - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH, $iOptionIdx)} = {}; - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_PATH, $iOptionIdx)} = {}; - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iOptionIdx)} = {}; - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iOptionIdx)} = {}; - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_PORT, $iOptionIdx)} = {}; - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $iOptionIdx)} = {}; - } - - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CMD, $iOptionIdx)} = {}; - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_USER, $iOptionIdx)} = {}; - $rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_PORT, $iOptionIdx)} = {}; - } - - # Generate the remote command - my $strRemoteCommand = cfgCommandWrite( - CFGCMD_REMOTE, true, defined($strBackRestBin) ? $strBackRestBin : cfgOption($iOptionIdCmd), undef, $rhCommandOption); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'strRemoteHost', value => cfgOption($iOptionIdHost)}, - {name => 'strRemoteHostUser', value => cfgOption($iOptionIdUser)}, - {name => 'strRemoteHostSshPort', value => cfgOption($strOptionSshPort, false)}, - {name => 'strRemoteCommand', value => $strRemoteCommand}, - ); -} - -#################################################################################################################################### -# protocolGet -# -# Get the protocol object or create it if does not exist. Shared protocol objects are used because they create an SSH connection -# to the remote host and the number of these connections should be minimized. -#################################################################################################################################### -sub protocolGet -{ - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strRemoteType, - $iRemoteIdx, - $bCache, - $strBackRestBin, - $iProcessIdx, - $strCommand, - ) = - logDebugParam - ( - __PACKAGE__ . '::protocolGet', \@_, - {name => 'strRemoteType'}, - {name => 'iRemoteIdx', default => cfgOptionValid(CFGOPT_HOST_ID) ? cfgOption(CFGOPT_HOST_ID) : 1}, - {name => 'bCache', optional => true, default => true}, - {name => 'strBackRestBin', optional => true}, - {name => 'iProcessIdx', optional => true}, - {name => 'strCommand', optional => true, - default => cfgOptionValid(CFGOPT_COMMAND) ? cfgOption(CFGOPT_COMMAND) : cfgCommandName(cfgCommandGet())}, - ); - - # Protocol object - my $oProtocol; - - # If no remote requested or if the requested remote type is local then return a local protocol object - if (!cfgOptionTest( - cfgOptionIdFromIndex($strRemoteType eq CFGOPTVAL_REMOTE_TYPE_DB ? CFGOPT_PG_HOST : CFGOPT_REPO_HOST, $iRemoteIdx))) - { - confess &log(ASSERT, 'protocol cannot be created when remote host is not specified'); - } - # Else create the remote protocol - else - { - # Set protocol to cached value - $oProtocol = - $bCache && defined($$hProtocol{$strRemoteType}{$iRemoteIdx}) ? $$hProtocol{$strRemoteType}{$iRemoteIdx} : undef; - - if ($bCache && $$hProtocol{$strRemoteType}{$iRemoteIdx}) - { - $oProtocol = $$hProtocol{$strRemoteType}{$iRemoteIdx}; - logDebugMisc($strOperation, 'found cached protocol'); - - # Issue a noop on protocol pulled from the cache to be sure it is still functioning. It's better to get an error at - # request time than somewhere randomly later. - $oProtocol->noOp(); - } - - # If protocol was not returned from cache then create it - if (!defined($oProtocol)) - { - logDebugMisc($strOperation, 'create (' . ($bCache ? '' : 'un') . 'cached) remote protocol'); - - my ($strRemoteHost, $strRemoteHostUser, $strRemoteHostSshPort, $strRemoteCommand) = protocolParam( - $strCommand, $strRemoteType, $iRemoteIdx, {strBackRestBin => $strBackRestBin, iProcessIdx => $iProcessIdx}); - - $oProtocol = new pgBackRest::Protocol::Remote::Master - ( - cfgOption(CFGOPT_CMD_SSH), - $strRemoteCommand, - cfgOption(CFGOPT_BUFFER_SIZE), - cfgOption(CFGOPT_COMPRESS_LEVEL), - cfgOption(CFGOPT_COMPRESS_LEVEL_NETWORK), - $strRemoteHost, - $strRemoteHostUser, - $strRemoteHostSshPort, - cfgOption(CFGOPT_PROTOCOL_TIMEOUT) - ); - - # Cache the protocol - if ($bCache) - { - $$hProtocol{$strRemoteType}{$iRemoteIdx} = $oProtocol; - } - } - } - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'oProtocol', value => $oProtocol, trace => true} - ); -} - -push @EXPORT, qw(protocolGet); - -#################################################################################################################################### -# protocolList - list all active protocols -#################################################################################################################################### -sub protocolList -{ - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strRemoteType, - $iRemoteIdx, - ) = - logDebugParam - ( - __PACKAGE__ . '::protocolList', \@_, - {name => 'strRemoteType', required => false, trace => true}, - {name => 'iRemoteIdx', required => false, trace => true}, - ); - - my @oyProtocol; - - if (!defined($strRemoteType)) - { - foreach my $strRemoteType (sort(keys(%{$hProtocol}))) - { - push(@oyProtocol, protocolList($strRemoteType)); - } - } - elsif (!defined($iRemoteIdx)) - { - foreach my $iRemoteIdx (sort(keys(%{$hProtocol->{$strRemoteType}}))) - { - push(@oyProtocol, protocolList($strRemoteType, $iRemoteIdx)); - } - } - elsif (defined($hProtocol->{$strRemoteType}{$iRemoteIdx})) - { - push(@oyProtocol, {strRemoteType => $strRemoteType, iRemoteIdx => $iRemoteIdx}); - } - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'oyProtocol', value => \@oyProtocol, trace => true} - ); -} - -#################################################################################################################################### -# protocolDestroy -# -# Undefine the protocol if it is stored locally. -#################################################################################################################################### -sub protocolDestroy -{ - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strRemoteType, - $iRemoteIdx, - $bComplete, - ) = - logDebugParam - ( - __PACKAGE__ . '::protocolDestroy', \@_, - {name => 'strRemoteType', required => false}, - {name => 'iRemoteIdx', required => false}, - {name => 'bComplete', default => false}, - ); - - my $iExitStatus = 0; - - foreach my $rhProtocol (protocolList($strRemoteType, $iRemoteIdx)) - { - logDebugMisc( - $strOperation, 'found cached protocol', - {name => 'strRemoteType', value => $rhProtocol->{strRemoteType}}, - {name => 'iRemoteIdx', value => $rhProtocol->{iRemoteIdx}}); - - $iExitStatus = $hProtocol->{$rhProtocol->{strRemoteType}}{$rhProtocol->{iRemoteIdx}}->close($bComplete); - delete($hProtocol->{$rhProtocol->{strRemoteType}}{$rhProtocol->{iRemoteIdx}}); - } - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'iExitStatus', value => $iExitStatus} - ); -} - -push @EXPORT, qw(protocolDestroy); - -#################################################################################################################################### -# protocolKeepAlive - call keepAlive() on all protocols -#################################################################################################################################### -sub protocolKeepAlive -{ - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strRemoteType, - $iRemoteIdx, - ) = - logDebugParam - ( - __PACKAGE__ . '::protocolDestroy', \@_, - {name => 'strRemoteType', required => false, trace => true}, - {name => 'iRemoteIdx', required => false, trace => true}, - ); - - foreach my $rhProtocol (protocolList($strRemoteType, $iRemoteIdx)) - { - $hProtocol->{$rhProtocol->{strRemoteType}}{$rhProtocol->{iRemoteIdx}}->keepAlive(); - } - - # Return from function and log return values if any - return logDebugReturn($strOperation); -} - -push @EXPORT, qw(protocolKeepAlive); - -1; diff --git a/lib/pgBackRest/Protocol/Local/Master.pm b/lib/pgBackRest/Protocol/Local/Master.pm deleted file mode 100644 index 81c25a386..000000000 --- a/lib/pgBackRest/Protocol/Local/Master.pm +++ /dev/null @@ -1,51 +0,0 @@ -#################################################################################################################################### -# PROTOCOL LOCAL MASTER MODULE -#################################################################################################################################### -package pgBackRest::Protocol::Local::Master; -use parent 'pgBackRest::Protocol::Command::Master'; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); - -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::Protocol::Command::Master; - -#################################################################################################################################### -# CONSTRUCTOR -#################################################################################################################################### -sub new -{ - my $class = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strCommand, - $iProcessIdx, - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'strCommand'}, - {name => 'iProcessIdx', default => 1}, - ); - - # Init object and store variables - my $self = $class->SUPER::new( - 'local', "local-${iProcessIdx} process", $strCommand, cfgOption(CFGOPT_BUFFER_SIZE), - cfgOption(CFGOPT_COMPRESS_LEVEL), cfgOption(CFGOPT_COMPRESS_LEVEL_NETWORK), cfgOption(CFGOPT_PROTOCOL_TIMEOUT)); - - bless $self, $class; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self} - ); -} - -1; diff --git a/lib/pgBackRest/Protocol/Local/Process.pm b/lib/pgBackRest/Protocol/Local/Process.pm deleted file mode 100644 index 8e197e022..000000000 --- a/lib/pgBackRest/Protocol/Local/Process.pm +++ /dev/null @@ -1,667 +0,0 @@ -#################################################################################################################################### -# PROTOCOL LOCAL PROCESS MODULE -# -# This module can be extended by commands that want to perform jobs in parallel. -#################################################################################################################################### -package pgBackRest::Protocol::Local::Process; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use IO::Select; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::Protocol::Local::Master; -use pgBackRest::Version; - -#################################################################################################################################### -# CONSTRUCTOR -#################################################################################################################################### -sub new -{ - my $class = shift; - - my $self = {}; - bless $self, $class; - - # Assign function parameters, defaults, and log debug info - ( - my $strOperation, - $self->{strHostType}, - $self->{iSelectTimeout}, - $self->{strBackRestBin}, - $self->{bConfessError}, - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'strHostType'}, - {name => 'iSelectTimeout', default => int(cfgOption(CFGOPT_PROTOCOL_TIMEOUT) / 2)}, - {name => 'strBackRestBin', default => projectBin()}, - {name => 'bConfessError', default => true}, - ); - - # Declare host map and array - $self->{hHostMap} = {}; - $self->{hyHost} = undef; - - # Reset module variables to get ready for queueing - $self->reset(); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self} - ); -} - -#################################################################################################################################### -# reset -# -# Reset to initial state. -#################################################################################################################################### -sub reset -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my ($strOperation) = logDebugParam(__PACKAGE__ . '->reset'); - - # Select object is used to check for new results - $self->{oSelect} = undef; - - # Declare local process map and array - $self->{hyLocalMap} = undef; - $self->{hyLocal} = undef; - - # Set the processing flag to false - $self->{bProcessing} = false; - - # Initialize job total to 0 - $self->{iQueued} = 0; - - # Initialize running job total to 0 - $self->{iRunning} = 0; - - # Return from function and log return values if any - return logDebugReturn($strOperation); -} - -#################################################################################################################################### -# hostAdd -# -# Add a host where jobs can be executed. -#################################################################################################################################### -sub hostAdd -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $iHostConfigIdx, - $iProcessMax, - ) = - logDebugParam - ( - __PACKAGE__ . '->hostAdd', \@_, - {name => 'iHostConfigIdx'}, - {name => 'iProcessMax'}, - ); - - my $iHostIdx = $self->{hHostMap}{$iHostConfigIdx}; - - if (!defined($iHostIdx)) - { - $iHostIdx = defined($self->{hyHost}) ? @{$self->{hyHost}} : 0; - $self->{hHostMap}{$iHostConfigIdx} = $iHostIdx; - } - - my $hHost = - { - iHostConfigIdx => $iHostConfigIdx, - iProcessMax => $iProcessMax, - }; - - push(@{$self->{hyHost}}, $hHost); - - # Return from function and log return values if any - return logDebugReturn($strOperation); -} - -#################################################################################################################################### -# hostConnect -# -# Connect local processes to the hosts. -#################################################################################################################################### -sub hostConnect -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my ($strOperation) = logDebugParam(__PACKAGE__ . '->hostConnect'); - - # Create a select object used to monitor output from minions - $self->{oSelect} = IO::Select->new(); - - # Iterate hosts - my $iHostIdx = 0; - - foreach my $hHost (@{$self->{hyHost}}) - { - # If there are no jobs in the queue for this host then no need to connect - if (!defined($hHost->{hyQueue})) - { - logDebugMisc( - $strOperation, "no jobs for host", - {name => 'strHostType', value => $self->{strHostType}}, - {name => 'iHostConfigIdx', value => $hHost->{iHostConfigIdx}}); - next; - } - - for (my $iHostProcessIdx = 0; $iHostProcessIdx < $hHost->{iProcessMax}; $iHostProcessIdx++) - { - my $iLocalIdx = defined($self->{hyLocal}) ? @{$self->{hyLocal}} : 0; - my $iProcessId = $iLocalIdx + 1; - - logDebugMisc( - $strOperation, 'start local process', - {name => 'strHostType', value => $self->{strHostType}}, - {name => 'iHostProcessIdx', value => $iHostProcessIdx}, - {name => 'iHostConfigIdx', value => $hHost->{iHostConfigIdx}}, - {name => 'iHostIdx', value => $iHostIdx}, - {name => 'iProcessId', value => $iProcessId}); - - my $oLocal = new pgBackRest::Protocol::Local::Master - ( - cfgCommandWrite( - CFGCMD_LOCAL, true, $self->{strBackRestBin}, undef, - { - &CFGOPT_COMMAND => {value => cfgCommandName(cfgCommandGet())}, - &CFGOPT_PROCESS => {value => $iProcessId}, - &CFGOPT_TYPE => {value => $self->{strHostType}}, - &CFGOPT_HOST_ID => {value => $hHost->{iHostConfigIdx}}, - - # Only enable file logging on the local when requested - &CFGOPT_LOG_LEVEL_FILE => - {value => cfgOption(CFGOPT_LOG_SUBPROCESS) ? cfgOption(CFGOPT_LOG_LEVEL_FILE) : lc(OFF)}, - &CFGOPT_LOG_LEVEL_STDERR => {}, - }), - $iLocalIdx + 1 - ); - - my $hLocal = - { - iHostIdx => $iHostIdx, - iProcessId => $iProcessId, - iHostProcessIdx => $iHostProcessIdx, - oLocal => $oLocal, - hndIn => fileno($oLocal->io()->handleRead()), - }; - - push(@{$self->{hyLocal}}, $hLocal); - - $self->{hLocalMap}{$hLocal->{hndIn}} = $hLocal; - $self->{oSelect}->add($hLocal->{hndIn}); - } - - $iHostIdx++; - } - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'bResult', value => $iHostIdx > 0 ? true : false} - ); -} - -#################################################################################################################################### -# init -# -# Initialize data structures required for processing. -#################################################################################################################################### -sub init -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my ($strOperation) = logDebugParam(__PACKAGE__ . '->init'); - - if ($self->hostConnect()) - { - foreach my $hLocal (@{$self->{hyLocal}}) - { - my $hHost = $self->{hyHost}[$hLocal->{iHostIdx}]; - my $hyQueue = $hHost->{hyQueue}; - - # Initialize variables to keep track of what job the local is working on - $hLocal->{iDirection} = $hLocal->{iHostProcessIdx} % 2 == 0 ? 1 : -1; - $hLocal->{iQueueIdx} = int((@{$hyQueue} / $hHost->{iProcessMax}) * $hLocal->{iHostProcessIdx}); - - # Calculate the last queue that this process should pull from - $hLocal->{iQueueLastIdx} = $hLocal->{iQueueIdx} + ($hLocal->{iDirection} * -1); - - if ($hLocal->{iQueueLastIdx} < 0) - { - $hLocal->{iQueueLastIdx} = @{$hyQueue} - 1; - } - elsif ($hLocal->{iQueueLastIdx} >= @{$hyQueue}) - { - $hLocal->{iQueueLastIdx} = 0; - } - - logDebugMisc( - $strOperation, 'init local process', - {name => 'iHostIdx', value => $hLocal->{iHostIdx}}, - {name => 'iProcessId', value => $hLocal->{iProcessId}}, - {name => 'iDirection', value => $hLocal->{iDirection}}, - {name => 'iQueueIdx', value => $hLocal->{iQueueIdx}}, - {name => 'iQueueLastIdx', value => $hLocal->{iQueueLastIdx}}); - } - - $self->{bProcessing} = true; - } - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'bResult', value => $self->processing()} - ); -} - -#################################################################################################################################### -# process -# -# Run all jobs and return results in batches. -#################################################################################################################################### -sub process -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my ($strOperation) = logDebugParam(__PACKAGE__ . '->process'); - - # Initialize processing - if (!$self->processing()) - { - if (!$self->init()) - { - logDebugMisc($strOperation, 'no jobs to run'); - $self->reset(); - return; - } - } - - # If jobs are running then wait for any of them to complete - my @hyResult = (); - my $iCompleted = 0; - - if ($self->{iRunning} > 0) - { - &logDebugMisc( - $strOperation, 'check running jobs', - {name => 'iRunning', value => $self->{iRunning}, trace => true}); - - # Wait for results to be available on any of the local process inputs - my @hndyIn = $self->{oSelect}->can_read($self->{iSelectTimeout}); - - # Fetch results from the completed jobs - foreach my $hndIn (@hndyIn) - { - # Get the local data - my $hLocal = $self->{hLocalMap}{$hndIn}; - - if (!defined($hLocal)) - { - confess &log(ASSERT, "unable to map from fileno ${hndIn} to local"); - } - - # Get the job result - my $hJob = $hLocal->{hJob}; - - eval - { - $hJob->{rResult} = $hLocal->{oLocal}->outputRead(true, undef, undef, true); - - # Create a result array when the result is not already an array. The Perl locals always return an array but the C - # locals only do so when needed. - if (ref($hJob->{rResult}) ne 'ARRAY') - { - my @resultArray = (${$hJob->{rResult}}); - $hJob->{rResult} = \@resultArray; - } - - return true; - } - or do - { - my $oException = $EVAL_ERROR; - - # If not a backrest exception then always confess it - something has gone very wrong - confess $oException if (!isException(\$oException)); - - # If the process is has terminated throw the exception - if (!defined($hLocal->{oLocal}->io()->processId())) - { - confess logException($oException); - } - - # If errors should be confessed then do so - if ($self->{bConfessError}) - { - confess logException($oException); - } - # Else store exception so caller can process it - else - { - $hJob->{oException} = $oException; - } - }; - - $hJob->{iProcessId} = $hLocal->{iProcessId}; - push(@hyResult, $hJob); - - logDebugMisc( - $strOperation, 'job complete', - {name => 'iProcessId', value => $hJob->{iProcessId}}, - {name => 'strKey', value => $hJob->{strKey}}, - {name => 'rResult', value => $hJob->{rResult}}); - - # Free the local process to receive another job - $hLocal->{hJob} = undef; - $self->{iRunning}--; - $iCompleted++; - } - } - - # If any jobs are not running/completed then assign new jobs - if ($self->{iRunning} == 0 || $iCompleted > 0) - { - &logDebugMisc( - $strOperation, 'get new jobs', - {name => 'iRunning', value => $self->{iRunning}, trace => true}, - {name => 'iCompleted', value => $iCompleted, trace => true}); - - my $bFound = false; - my $iLocalIdx = -1; - - # Iterate all local processes - foreach my $hLocal (@{$self->{hyLocal}}) - { - # Skip this local process if it has already completed - $iLocalIdx++; - next if (!defined($hLocal)); - - my $hHost = $self->{hyHost}[$hLocal->{iHostIdx}]; - my $hyQueue = $hHost->{hyQueue}; - - # If this process does not currently have a job assigned then find one - if (!defined($hLocal->{hJob})) - { - # Search queues for a new job - my $iQueueIdx = $hLocal->{iQueueIdx}; - my $hJob = shift(@{$$hyQueue[$iQueueIdx]}); - - while (!defined($hJob) && $iQueueIdx != $hLocal->{iQueueLastIdx}) - { - $iQueueIdx += $hLocal->{iDirection}; - - if ($iQueueIdx < 0) - { - $iQueueIdx = @{$hyQueue} - 1; - } - elsif ($iQueueIdx >= @{$hyQueue}) - { - $iQueueIdx = 0; - } - - $hJob = shift(@{$$hyQueue[$iQueueIdx]}); - } - - # If no job was found then stop the local process - if (!defined($hJob)) - { - logDebugMisc( - $strOperation, 'no jobs found, stop local', - {name => 'strHostType', value => $hLocal->{strHostType}}, - {name => 'iHostConfigIdx', value => $hLocal->{iHostConfigIdx}}, - {name => 'iHostIdx', value => $hLocal->{iHostIdx}}, - {name => 'iProcessId', value => $hLocal->{iProcessId}}); - - # Remove input handle from the select object - my $iHandleTotal = $self->{oSelect}->count(); - - $self->{oSelect}->remove($hLocal->{hndIn}); - - if ($iHandleTotal - $self->{oSelect}->count() != 1) - { - confess &log(ASSERT, - "iProcessId $hLocal->{iProcessId}, handle $hLocal->{hndIn} was not removed from select object"); - } - - # Remove input handle from the map - delete($self->{hLocalMap}{$hLocal->{hndIn}}); - - # Close the local process - $hLocal->{oLocal}->close(true); - - # Undefine local process so it is no longer checked for new jobs - undef(${$self->{hyLocal}}[$iLocalIdx]); - - # Skip to next local process - next; - } - - # Assign job to local process - $hLocal->{hJob} = $hJob; - $bFound = true; - $self->{iRunning}++; - $self->{iQueued}--; - - logDebugMisc( - $strOperation, 'get job from queue', - {name => 'iHostIdx', value => $hLocal->{iHostIdx}}, - {name => 'iProcessId', value => $hLocal->{iProcessId}}, - {name => 'strQueueIdx', value => $iQueueIdx}, - {name => 'strKey', value => $hLocal->{hJob}{strKey}}); - - # Send job to local process - $hLocal->{oLocal}->cmdWrite($hLocal->{hJob}{strOp}, $hLocal->{hJob}->{rParam}); - } - } - - # If nothing is running, no more jobs, and nothing to return, then processing is complete - if (!$bFound && !$self->{iRunning} && @hyResult == 0) - { - logDebugMisc($strOperation, 'all jobs complete'); - $self->reset(); - return; - } - } - - # Return job results - return \@hyResult; -} - -#################################################################################################################################### -# queueJob -# -# Queue a job for processing. -#################################################################################################################################### -sub queueJob -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $iHostConfigIdx, - $strQueue, - $strKey, - $strOp, - $rParam, - $rParamSecure, - ) = - logDebugParam - ( - __PACKAGE__ . '->queueJob', \@_, - {name => 'iHostConfigIdx'}, - {name => 'strQueue'}, - {name => 'strKey'}, - {name => 'strOp'}, - {name => 'rParam'}, - {name => 'rParamSecure', optional => true, redact => true}, - ); - - # Don't add jobs while in the middle of processing the current queue - if ($self->processing()) - { - confess &log(ASSERT, 'new jobs cannot be added until processing is complete'); - } - - # Copy the parameters to a new variable so we can push the secure parameters on - if (defined($rParamSecure)) - { - push(@{$rParam}, @{$rParamSecure}); - } - - # Build the hash - my $hJob = - { - iHostConfigIdx => $iHostConfigIdx, - strQueue => $strQueue, - strKey => $strKey, - strOp => $strOp, - rParam => $rParam, - }; - - # Get the host that will perform this job - my $iHostIdx = $self->{hHostMap}{$iHostConfigIdx}; - - if (!defined($iHostIdx)) - { - confess &log(ASSERT, "iHostConfigIdx = $iHostConfigIdx does not exist"); - } - - my $hHost = $self->{hyHost}[$iHostIdx]; - - # Get the queue to hold this job - my $iQueueIdx = $hHost->{hQueueMap}{$strQueue}; - - if (!defined($iQueueIdx)) - { - $iQueueIdx = defined($hHost->{hyQueue}) ? @{$hHost->{hyQueue}} : 0; - $hHost->{hQueueMap}{$strQueue} = $iQueueIdx; - } - - push(@{$hHost->{hyQueue}[$iQueueIdx]}, $hJob); - $self->{iQueued}++; - - # Return from function and log return values if any - return logDebugReturn($strOperation); -} - -#################################################################################################################################### -# dequeueJobs -# -# Dequeue all jobs from a queue. -#################################################################################################################################### -sub dequeueJobs -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $iHostConfigIdx, - $strQueue, - ) = - logDebugParam - ( - __PACKAGE__ . '->dequeueJobs', \@_, - {name => 'iHostConfigIdx'}, - {name => 'strQueue'}, - ); - - # Don't add jobs while in the middle of processing the current queue - if (!$self->processing()) - { - confess &log(ASSERT, 'unable to dequeue a job when not processing'); - } - - # Get the host that contains the queue to clear - my $iHostIdx = $self->{hHostMap}{$iHostConfigIdx}; - - if (!defined($iHostIdx)) - { - confess &log(ASSERT, "iHostConfigIdx = $iHostConfigIdx does not exist"); - } - - my $hHost = $self->{hyHost}[$iHostIdx]; - - # Get the queue to clear - my $iQueueIdx = $hHost->{hQueueMap}{$strQueue}; - - if (!defined($iQueueIdx)) - { - confess &log(ASSERT, "unable to find queue '${strQueue}'"); - } - - $hHost->{hyQueue}[$iQueueIdx] = []; - $self->{iQueued} = 0; - - # Return from function and log return values if any - return logDebugReturn($strOperation); -} - -#################################################################################################################################### -# jobTotal -# -# Total jobs in the queue. -#################################################################################################################################### -sub jobTotal -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my ($strOperation) = logDebugParam(__PACKAGE__ . '->jobTotal'); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'iJobTotal', value => $self->{iQueued} + $self->{iRunning}} - ); -} - -#################################################################################################################################### -# processing -# -# Are jobs being processed? -#################################################################################################################################### -sub processing -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my ($strOperation) = logDebugParam(__PACKAGE__ . '->processing'); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'bProcessing', value => $self->{bProcessing}, trace => true} - ); -} - -1; diff --git a/lib/pgBackRest/Protocol/Remote/Master.pm b/lib/pgBackRest/Protocol/Remote/Master.pm deleted file mode 100644 index 73f5137ae..000000000 --- a/lib/pgBackRest/Protocol/Remote/Master.pm +++ /dev/null @@ -1,76 +0,0 @@ -#################################################################################################################################### -# PROTOCOL REMOTE MASTER MODULE -#################################################################################################################################### -package pgBackRest::Protocol::Remote::Master; -use parent 'pgBackRest::Protocol::Command::Master'; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); - -use File::Basename qw(dirname); - -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::Protocol::Command::Master; - -#################################################################################################################################### -# CONSTRUCTOR -#################################################################################################################################### -sub new -{ - my $class = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strCommandSSH, # SSH client - $strCommand, # Command to execute on local/remote - $iBufferMax, # Maximum buffer size - $iCompressLevel, # Set compression level - $iCompressLevelNetwork, # Set compression level for network only compression - $strHost, # Host to connect to for remote (optional as this can also be used for local) - $strUser, # User to connect to for remote (must be set if strHost is set) - $iSshPort, # Specified if other than default port is needed for ssh - $iProtocolTimeout, # Protocol timeout - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'strCommandSSH'}, - {name => 'strCommand'}, - {name => 'iBufferMax'}, - {name => 'iCompressLevel'}, - {name => 'iCompressLevelNetwork'}, - {name => 'strHost'}, - {name => 'strUser'}, - {name => 'iSshPort', required => false}, - {name => 'iProtocolTimeout'}, - ); - - my $strCommandSshPort = defined($iSshPort) ? '-p ' . $iSshPort . ' ' : ''; - - # Create SSH command - $strCommand = - "${strCommandSSH} -o LogLevel=error -o Compression=no -o PasswordAuthentication=no $strCommandSshPort" . - "${strUser}\@${strHost} '${strCommand}'"; - - # Init object and store variables - my $self = $class->SUPER::new( - 'remote', "remote process on '$strHost'", $strCommand, $iBufferMax, $iCompressLevel, $iCompressLevelNetwork, - $iProtocolTimeout); - bless $self, $class; - - # Store the host - $self->{strHost} = $strHost; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self} - ); -} - -1; diff --git a/lib/pgBackRest/Protocol/Remote/Minion.pm b/lib/pgBackRest/Protocol/Remote/Minion.pm deleted file mode 100644 index 513e06b83..000000000 --- a/lib/pgBackRest/Protocol/Remote/Minion.pm +++ /dev/null @@ -1,122 +0,0 @@ -#################################################################################################################################### -# PROTOCOL REMOTE MINION MODULE -#################################################################################################################################### -package pgBackRest::Protocol::Remote::Minion; -use parent 'pgBackRest::Protocol::Command::Minion'; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); - -use File::Basename qw(dirname); - -use pgBackRest::Common::Log; -use pgBackRest::Common::Io::Buffered; -use pgBackRest::Common::Wait; -use pgBackRest::Config::Config; -use pgBackRest::Db; -use pgBackRest::Protocol::Command::Minion; -use pgBackRest::Protocol::Helper; -use pgBackRest::Protocol::Storage::Helper; - -#################################################################################################################################### -# CONSTRUCTOR -#################################################################################################################################### -sub new -{ - my $class = shift; # Class name - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $iBufferMax, # Maximum buffer size - $iProtocolTimeout # Protocol timeout - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'iBufferMax'}, - {name => 'iProtocolTimeout'} - ); - - # Init object and store variables - my $self = $class->SUPER::new(cfgCommandName(CFGCMD_REMOTE), $iBufferMax, $iProtocolTimeout); - bless $self, $class; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self} - ); -} - -#################################################################################################################################### -# init -#################################################################################################################################### -sub init -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my ($strOperation) = logDebugParam(__PACKAGE__ . '->init'); - - # Create objects - my $oStorage = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? storageDb() : storageRepo(); - - my $oDb = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? new pgBackRest::Db() : undef; - - # Create anonymous subs for each command - my $hCommandMap = - { - # Db commands - &OP_DB_CONNECT => sub {$oDb->connect()}, - &OP_DB_EXECUTE_SQL => sub {$oDb->executeSql(@{shift()})}, - &OP_DB_INFO => sub {$oDb->info(@{shift()})}, - - # File commands - &OP_STORAGE_OPEN_READ => sub - { - my $oSourceFileIo = $oStorage->openRead(@{shift()}); - - # If the source file exists - if (defined($oSourceFileIo) && (!defined($oSourceFileIo->{oStorageCRead}) || $oSourceFileIo->open())) - { - $self->outputWrite(true); - - $oStorage->copy( - $oSourceFileIo, new pgBackRest::Protocol::Storage::File($self, $oSourceFileIo), {bSourceOpen => true}); - - return true; - } - - return false; - }, - &OP_STORAGE_OPEN_WRITE => sub - { - my $oDestinationFileIo = $oStorage->openWrite(@{shift()}); - $oStorage->copy(new pgBackRest::Protocol::Storage::File($self, $oDestinationFileIo), $oDestinationFileIo); - }, - - &OP_STORAGE_CIPHER_PASS_USER => sub {$oStorage->cipherPassUser()}, - &OP_STORAGE_EXISTS => sub {$oStorage->exists(@{shift()})}, - &OP_STORAGE_LIST => sub {$oStorage->list(@{shift()})}, - &OP_STORAGE_MANIFEST => sub {$oStorage->manifestJson(@{shift()})}, - &OP_STORAGE_MOVE => sub {$oStorage->move(@{shift()})}, - &OP_STORAGE_PATH_GET => sub {$oStorage->pathGet(@{shift()})}, - &OP_STORAGE_HASH_SIZE => sub {$oStorage->hashSize(@{shift()})}, - - # Wait command - &OP_WAIT => sub {waitRemainder(@{shift()})}, - }; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'hCommandMap', value => $hCommandMap} - ); -} - -1; diff --git a/lib/pgBackRest/Protocol/Storage/File.pm b/lib/pgBackRest/Protocol/Storage/File.pm deleted file mode 100644 index 1bb47ee72..000000000 --- a/lib/pgBackRest/Protocol/Storage/File.pm +++ /dev/null @@ -1,180 +0,0 @@ -#################################################################################################################################### -# Protocol File -#################################################################################################################################### -package pgBackRest::Protocol::Storage::File; -use parent 'pgBackRest::Common::Io::Base'; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use Exporter qw(import); - our @EXPORT = qw(); - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Log; - -#################################################################################################################################### -# CONSTRUCTOR -#################################################################################################################################### -sub new -{ - my $class = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $oProtocol, # Master or minion protocol - $oFileIo, # File whose results will be returned via protocol - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'oProtocol', trace => true}, - {name => 'oFileIo', required => false, trace => true}, - ); - - # Create class - my $self = $class->SUPER::new($oProtocol->io()->id() . ' file'); - bless $self, $class; - - # Set variables - $self->{oProtocol} = $oProtocol; - $self->{oFileIo} = $oFileIo; - - # Set read/write - $self->{bWrite} = false; - - # Initialize EOF to false - $self->eofSet(false); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self} - ); -} - -#################################################################################################################################### -# eof - have reads reached eof? -#################################################################################################################################### -sub eof -{ - return shift->{bEOF}; -} - -#################################################################################################################################### -# eofSet - set eof -#################################################################################################################################### -sub eofSet -{ - my $self = shift; - my $bEOF = shift; - - $self->{bEOF} = $bEOF; -} - -#################################################################################################################################### -# read - read block from protocol -#################################################################################################################################### -sub read -{ - my $self = shift; - my $rtBuffer = shift; - - # After EOF always return 0 - return 0 if $self->eof(); - - my $lBlockSize; - - # Read the block header and make sure it's valid - my $strBlockHeader = $self->{oProtocol}->io()->readLine(); - - if ($strBlockHeader !~ /^BRBLOCK[0-9]+$/) - { - confess &log(ERROR, "invalid block header '${strBlockHeader}'", ERROR_FILE_READ); - } - - # Get block size from the header - $lBlockSize = substr($strBlockHeader, 7); - - # Read block if size > 0 - if ($lBlockSize > 0) - { - $self->{oProtocol}->io()->read($rtBuffer, $lBlockSize, true); - } - else - { - $self->eofSet(true); - } - - # Return the block size - return $lBlockSize; -} - -#################################################################################################################################### -# write - write block to protocol -#################################################################################################################################### -sub write -{ - my $self = shift; - my $rtBuffer = shift; - - # Set write - $self->{bWrite} = true; - - # Get the buffer size - my $lBlockSize = defined($rtBuffer) ? length($$rtBuffer) : 0; - - # Write if size > 0 (0 ends the copy stream so it should only be done in close()) - if ($lBlockSize > 0) - { - # Write block header to the protocol stream - $self->{oProtocol}->io()->writeLine("BRBLOCK${lBlockSize}"); - - # Write block if size - $self->{oProtocol}->io()->write($rtBuffer); - } - - return length($$rtBuffer); -} - -#################################################################################################################################### -# close - set the result hash -#################################################################################################################################### -sub close -{ - my $self = shift; - - # Close if protocol is defined (to prevent this from running more than once) - if (defined($self->{oProtocol})) - { - # If writing output terminator - if ($self->{bWrite}) - { - $self->{oProtocol}->io()->writeLine("BRBLOCK0"); - } - - # On master read the results - if ($self->{oProtocol}->master()) - { - ($self->{rhResult}) = $self->{oProtocol}->outputRead(); - - # Minion will send one more output message after file is closed which can be ignored - $self->{oProtocol}->outputRead(); - } - # On minion write the results - else - { - $self->{oProtocol}->outputWrite($self->{oFileIo}->resultAll()); - } - - # Delete protocol to prevent close from running again - delete($self->{oProtocol}); - } -} - -1; diff --git a/lib/pgBackRest/Protocol/Storage/Helper.pm b/lib/pgBackRest/Protocol/Storage/Helper.pm index 64c4cea62..d20df3232 100644 --- a/lib/pgBackRest/Protocol/Storage/Helper.pm +++ b/lib/pgBackRest/Protocol/Storage/Helper.pm @@ -14,8 +14,6 @@ use File::Basename qw(basename); use pgBackRest::Common::Log; use pgBackRest::Config::Config; use pgBackRest::LibC qw(:storage); -use pgBackRest::Protocol::Helper; -use pgBackRest::Protocol::Storage::Remote; use pgBackRest::Storage::Helper; #################################################################################################################################### @@ -45,35 +43,24 @@ sub storageDb my ( $strOperation, - $iRemoteIdx, ) = logDebugParam ( __PACKAGE__ . '::storageDb', \@_, - {name => 'iRemoteIdx', optional => true, default => cfgOptionValid(CFGOPT_HOST_ID) ? cfgOption(CFGOPT_HOST_ID) : 1, - trace => true}, ); # Create storage if not defined - if (!defined($hStorage->{&STORAGE_DB}{$iRemoteIdx})) + if (!defined($hStorage->{&STORAGE_DB})) { - if (isDbLocal({iRemoteIdx => $iRemoteIdx})) - { - $hStorage->{&STORAGE_DB}{$iRemoteIdx} = new pgBackRest::Storage::Storage( - STORAGE_DB, {lBufferMax => cfgOption(CFGOPT_BUFFER_SIZE)}); - } - else - { - $hStorage->{&STORAGE_DB}{$iRemoteIdx} = new pgBackRest::Protocol::Storage::Remote( - protocolGet(CFGOPTVAL_REMOTE_TYPE_DB, $iRemoteIdx)); - } + $hStorage->{&STORAGE_DB} = new pgBackRest::Storage::Storage( + STORAGE_DB, {lBufferMax => cfgOption(CFGOPT_BUFFER_SIZE)}); } # Return from function and log return values if any return logDebugReturn ( $strOperation, - {name => 'oStorageDb', value => $hStorage->{&STORAGE_DB}{$iRemoteIdx}, trace => true}, + {name => 'oStorageDb', value => $hStorage->{&STORAGE_DB}, trace => true}, ); } @@ -99,17 +86,8 @@ sub storageRepo # Create storage if not defined if (!defined($hStorage->{&STORAGE_REPO})) { - if (isRepoLocal()) - { - $hStorage->{&STORAGE_REPO} = new pgBackRest::Storage::Storage( - STORAGE_REPO, {lBufferMax => cfgOption(CFGOPT_BUFFER_SIZE)}); - } - else - { - # Create remote storage - $hStorage->{&STORAGE_REPO} = new pgBackRest::Protocol::Storage::Remote( - protocolGet(CFGOPTVAL_REMOTE_TYPE_BACKUP)); - } + $hStorage->{&STORAGE_REPO} = new pgBackRest::Storage::Storage( + STORAGE_REPO, {lBufferMax => cfgOption(CFGOPT_BUFFER_SIZE)}); } # Return from function and log return values if any diff --git a/lib/pgBackRest/Protocol/Storage/Remote.pm b/lib/pgBackRest/Protocol/Storage/Remote.pm deleted file mode 100644 index d6e378e02..000000000 --- a/lib/pgBackRest/Protocol/Storage/Remote.pm +++ /dev/null @@ -1,342 +0,0 @@ -#################################################################################################################################### -# Remote Storage -#################################################################################################################################### -package pgBackRest::Protocol::Storage::Remote; -use parent 'pgBackRest::Storage::Base'; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use JSON::PP; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::Protocol::Helper; -use pgBackRest::Protocol::Storage::File; -use pgBackRest::Storage::Base; - -#################################################################################################################################### -# new -#################################################################################################################################### -sub new -{ - my $class = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $oProtocol, - ) = - logDebugParam - ( - __PACKAGE__ . '->new', \@_, - {name => 'oProtocol'}, - ); - - # Init parent - my $self = $class->SUPER::new({lBufferMax => $oProtocol->io()->bufferMax()}); - bless $self, $class; - - # Set variables - $self->{oProtocol} = $oProtocol; - - # Create JSON object - $self->{oJSON} = JSON::PP->new()->allow_nonref(); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'self', value => $self} - ); -} - -#################################################################################################################################### -# exists -#################################################################################################################################### -sub exists -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strPathExp, - ) = - logDebugParam - ( - __PACKAGE__ . '->exists', \@_, - {name => 'strPathExp'}, - ); - - my $bExists = $self->{oProtocol}->cmdExecute(OP_STORAGE_EXISTS, [$strPathExp]); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'bExists', value => $bExists} - ); -} - -#################################################################################################################################### -# hashSize -#################################################################################################################################### -sub hashSize -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strPathExp, - $rhParam, - ) = - logDebugParam - ( - __PACKAGE__ . '->hashSize', \@_, - {name => 'strPathExp'}, - {name => 'rhParam', required => false}, - ); - - my ($strHash, $lSize) = $self->{oProtocol}->cmdExecute(OP_STORAGE_HASH_SIZE, [$strPathExp, $rhParam]); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'strHash', value => $strHash}, - {name => 'lSize', value => $lSize} - ); -} - -#################################################################################################################################### -# list -#################################################################################################################################### -sub list -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strPathExp, - $rhParam, - ) = - logDebugParam - ( - __PACKAGE__ . '->list', \@_, - {name => 'strPathExp'}, - {name => 'rhParam', required => false}, - ); - - my @stryFileList = $self->{oProtocol}->cmdExecute(OP_STORAGE_LIST, [$strPathExp, $rhParam]); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'stryFileList', value => \@stryFileList} - ); -} - -#################################################################################################################################### -# manifest -#################################################################################################################################### -sub manifest -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strPathExp, - $rhParam, - ) = - logDebugParam - ( - __PACKAGE__ . '->manifest', \@_, - {name => 'strPathExp'}, - {name => 'rhParam', required => false}, - ); - - my $hManifest = $self->{oJSON}->decode($self->{oProtocol}->cmdExecute(OP_STORAGE_MANIFEST, [$strPathExp, $rhParam])); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'hManifest', value => $hManifest, trace => true} - ); -} - -#################################################################################################################################### -# openRead -#################################################################################################################################### -sub openRead -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strFileExp, - $rhParam, - ) = - logDebugParam - ( - __PACKAGE__ . '->openRead', \@_, - {name => 'strFileExp'}, - {name => 'rhParam', required => false}, - ); - - my $oSourceFileIo = - $self->{oProtocol}->cmdExecute(OP_STORAGE_OPEN_READ, [$strFileExp, $rhParam]) ? - new pgBackRest::Protocol::Storage::File($self->{oProtocol}) : undef; - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'oFileIo', value => $oSourceFileIo, trace => true}, - ); -} - -#################################################################################################################################### -# openWrite -#################################################################################################################################### -sub openWrite -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strFileExp, - $rhParam, - ) = - logDebugParam - ( - __PACKAGE__ . '->openWrite', \@_, - {name => 'strFileExp'}, - {name => 'rhParam', required => false}, - ); - - # Open the remote file - $self->{oProtocol}->cmdWrite(OP_STORAGE_OPEN_WRITE, [$strFileExp, $rhParam]); - my $oDestinationFileIo = new pgBackRest::Protocol::Storage::File($self->{oProtocol}); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'oFileIo', value => $oDestinationFileIo, trace => true}, - ); -} - -#################################################################################################################################### -# pathGet -#################################################################################################################################### -sub pathGet -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strPathExp, - $rhParam, - ) = - logDebugParam - ( - __PACKAGE__ . '->pathGet', \@_, - {name => 'strPathExp', required => false}, - {name => 'rhParam', required => false}, - ); - - my $strPath = $self->{oProtocol}->cmdExecute(OP_STORAGE_PATH_GET, [$strPathExp, $rhParam]); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'strPath', value => $strPath} - ); -} - -#################################################################################################################################### -# move -#################################################################################################################################### -sub move -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - $strSourcePathExp, - $strDestinationPathExp, - $rhParam, - ) = - logDebugParam - ( - __PACKAGE__ . '->move', \@_, - {name => 'strSourcePathExp'}, - {name => 'strDestinationPathExp'}, - {name => 'rhParam', required => false}, - ); - - $self->{oProtocol}->cmdExecute(OP_STORAGE_MOVE, [$strSourcePathExp, $strDestinationPathExp, $rhParam], false); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation - ); -} - -#################################################################################################################################### -# cipherPassUser -#################################################################################################################################### -sub cipherPassUser -{ - my $self = shift; - - # Assign function parameters, defaults, and log debug info - my - ( - $strOperation, - ) = - logDebugParam - ( - __PACKAGE__ . '->cipherPassUser', \@_, - ); - - my $strCipherPassUser = $self->{oProtocol}->cmdExecute(OP_STORAGE_CIPHER_PASS_USER); - - # Return from function and log return values if any - return logDebugReturn - ( - $strOperation, - {name => 'strCipherPassUser', value => $strCipherPassUser, redact => true} - ); -} - -#################################################################################################################################### -# getters -#################################################################################################################################### -sub protocol {shift->{oProtocol}}; - -1; diff --git a/libc/LibC.xs b/libc/LibC.xs index 58c13dc83..d8abd44bc 100644 --- a/libc/LibC.xs +++ b/libc/LibC.xs @@ -56,7 +56,6 @@ These includes are from the src directory. There is no Perl-specific code in th #include "config/define.h" #include "config/load.h" #include "config/parse.h" -#include "perl/config.h" #include "postgres/pageChecksum.h" #include "storage/posix/storage.h" @@ -72,6 +71,7 @@ These includes define data structures that are required for the C to Perl interf ***********************************************************************************************************************************/ #include "xs/crypto/hash.xsh" #include "xs/common/encode.xsh" +#include "xs/config/configTest.xsh" #include "xs/postgres/client.xsh" #include "xs/storage/storage.xsh" #include "xs/storage/storageRead.xsh" diff --git a/libc/Makefile.PL b/libc/Makefile.PL index 197e8478e..8d1581467 100644 --- a/libc/Makefile.PL +++ b/libc/Makefile.PL @@ -93,7 +93,6 @@ my @stryCFile = 'config/define.c', 'config/load.c', 'config/parse.c', - 'perl/config.c', 'protocol/client.c', 'protocol/command.c', 'protocol/helper.c', diff --git a/src/perl/config.c b/libc/xs/config/configTest.xsh similarity index 96% rename from src/perl/config.c rename to libc/xs/config/configTest.xsh index 15fb89e55..5cd94e2cb 100644 --- a/src/perl/config.c +++ b/libc/xs/config/configTest.xsh @@ -1,11 +1,8 @@ /*********************************************************************************************************************************** -Perl Configuration +Config XS Header ***********************************************************************************************************************************/ -#include "build.auto.h" - #include -#include "common/debug.h" #include "common/memContext.h" #include "common/type/json.h" #include "config/config.h" @@ -16,8 +13,6 @@ Build JSON output from options String * perlOptionJson(void) { - FUNCTION_TEST_VOID(); - String *result = NULL; MEM_CONTEXT_TEMP_BEGIN() @@ -121,5 +116,5 @@ perlOptionJson(void) } MEM_CONTEXT_TEMP_END(); - FUNCTION_TEST_RETURN(result); + return result; } diff --git a/libc/xs/storage/storage.xs b/libc/xs/storage/storage.xs index 01d756f28..2d331610a 100644 --- a/libc/xs/storage/storage.xs +++ b/libc/xs/storage/storage.xs @@ -22,7 +22,6 @@ CODE: memContextSwitch(MEM_CONTEXT_XS_OLD()); RETVAL = storagePosixNew( path == NULL ? STRDEF("/") : path, STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL); - storagePathEnforceSet((Storage *)RETVAL, false); memContextSwitch(MEM_CONTEXT_XS_TEMP()); } else if (strEqZ(type, "")) @@ -36,7 +35,6 @@ CODE: memContextSwitch(MEM_CONTEXT_XS_OLD()); RETVAL = storagePosixNew(cfgOptionStr(cfgOptPgPath), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL); - storagePathEnforceSet((Storage *)RETVAL, false); memContextSwitch(MEM_CONTEXT_XS_TEMP()); } else diff --git a/src/Makefile.in b/src/Makefile.in index 909432d3d..6cc94a579 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -8,7 +8,7 @@ CC = @CC@ # Standards -CSTANDARD = -std=c99 -D_POSIX_C_SOURCE=200112L -D_DARWIN_C_SOURCE +CSTANDARD = -std=c99 -D_POSIX_C_SOURCE=200809L -D_DARWIN_C_SOURCE # Optimizations COPTIMIZE = @COPTIMIZE@ @@ -140,8 +140,6 @@ SRCS = \ info/infoBackup.c \ info/manifest.c \ info/infoPg.c \ - perl/config.c \ - perl/exec.c \ postgres/client.c \ postgres/interface.c \ postgres/interface/v083.c \ @@ -220,7 +218,7 @@ command/archive/common.o: command/archive/common.c build.auto.h command/archive/ command/archive/get/file.o: command/archive/get/file.c build.auto.h command/archive/common.h command/archive/get/file.h command/control/common.h common/assert.h common/compress/gzip/common.h common/compress/gzip/decompress.h common/crypto/cipherBlock.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/archive/get/file.c -o command/archive/get/file.o -command/archive/get/get.o: command/archive/get/get.c build.auto.h command/archive/common.h command/archive/get/file.h command/archive/get/protocol.h command/command.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/fork.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/exec.h perl/exec.h postgres/interface.h protocol/client.h protocol/command.h protocol/helper.h protocol/parallel.h protocol/parallelJob.h protocol/server.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h +command/archive/get/get.o: command/archive/get/get.c build.auto.h command/archive/common.h command/archive/get/file.h command/archive/get/protocol.h command/command.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/fork.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/exec.h postgres/interface.h protocol/client.h protocol/command.h protocol/helper.h protocol/parallel.h protocol/parallelJob.h protocol/server.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/archive/get/get.c -o command/archive/get/get.o command/archive/get/protocol.o: command/archive/get/protocol.c build.auto.h command/archive/get/file.h command/archive/get/protocol.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/io.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h protocol/server.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h @@ -274,7 +272,7 @@ command/expire/expire.o: command/expire/expire.c build.auto.h command/archive/co command/help/help.o: command/help/help.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/handleWrite.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h version.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/help/help.c -o command/help/help.o -command/info/info.o: command/info/info.c build.auto.h command/archive/common.h command/backup/common.h command/info/info.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/handleWrite.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h perl/exec.h postgres/interface.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h +command/info/info.o: command/info/info.c build.auto.h command/archive/common.h command/backup/common.h command/info/info.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/handleWrite.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/interface.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/info/info.c -o command/info/info.o command/local/local.o: command/local/local.c build.auto.h command/archive/get/protocol.h command/archive/push/protocol.h command/backup/protocol.h command/restore/protocol.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/handleRead.h common/io/handleWrite.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/protocol.h protocol/client.h protocol/command.h protocol/helper.h protocol/server.h @@ -340,7 +338,7 @@ common/error.o: common/error.c build.auto.h common/error.auto.c common/error.aut common/exec.o: common/exec.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/exec.h common/io/filter/filter.h common/io/filter/group.h common/io/handleRead.h common/io/handleWrite.h common/io/io.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringz.h common/type/variant.h common/type/variantList.h common/wait.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/exec.c -o common/exec.o -common/exit.o: common/exit.c build.auto.h command/command.h common/assert.h common/debug.h common/error.auto.h common/error.h common/exit.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h perl/exec.h protocol/client.h protocol/command.h protocol/helper.h +common/exit.o: common/exit.c build.auto.h command/command.h common/assert.h common/debug.h common/error.auto.h common/error.h common/exit.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h protocol/client.h protocol/command.h protocol/helper.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/exit.c -o common/exit.o common/fork.o: common/fork.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/stackTrace.h common/type/convert.h common/type/stringz.h @@ -502,15 +500,9 @@ info/infoPg.o: info/infoPg.c build.auto.h common/assert.h common/crypto/common.h info/manifest.o: info/manifest.c build.auto.h command/backup/common.h common/assert.h common/crypto/cipherBlock.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/mcv.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h info/info.h info/manifest.h postgres/interface.h postgres/version.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c info/manifest.c -o info/manifest.o -main.o: main.c build.auto.h command/archive/get/get.h command/archive/push/push.h command/backup/backup.h command/check/check.h command/command.h command/control/start.h command/control/stop.h command/expire/expire.h command/help/help.h command/info/info.h command/local/local.h command/remote/remote.h command/restore/restore.h command/stanza/create.h command/stanza/delete.h command/stanza/upgrade.h command/storage/list.h common/assert.h common/debug.h common/error.auto.h common/error.h common/exit.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h postgres/interface.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h +main.o: main.c build.auto.h command/archive/get/get.h command/archive/push/push.h command/backup/backup.h command/check/check.h command/command.h command/control/start.h command/control/stop.h command/expire/expire.h command/help/help.h command/info/info.h command/local/local.h command/remote/remote.h command/restore/restore.h command/stanza/create.h command/stanza/delete.h command/stanza/upgrade.h command/storage/list.h common/assert.h common/debug.h common/error.auto.h common/error.h common/exit.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h postgres/interface.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c main.c -o main.o -perl/config.o: perl/config.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h - $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c perl/config.c -o perl/config.o - -perl/exec.o: perl/exec.c ../libc/LibC.h build.auto.h common/assert.h common/compress/gzip/compress.h common/compress/gzip/decompress.h common/crypto/cipherBlock.h common/crypto/common.h common/crypto/hash.h common/debug.h common/encode.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/filter/size.h common/io/http/client.h common/io/http/header.h common/io/http/query.h common/io/io.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h config/parse.h perl/config.h perl/embed.auto.c perl/exec.h perl/libc.auto.c postgres/client.h postgres/interface.h postgres/pageChecksum.h storage/helper.h storage/info.h storage/posix/storage.h storage/read.h storage/read.intern.h storage/s3/storage.h storage/s3/storage.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h ../libc/xs/common/encode.xsh ../libc/xs/crypto/hash.xsh ../libc/xs/postgres/client.xsh ../libc/xs/storage/storage.xsh ../libc/xs/storage/storageRead.xsh ../libc/xs/storage/storageWrite.xsh - $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c perl/exec.c -o perl/exec.o - postgres/client.o: postgres/client.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/param.h common/type/string.h common/type/stringList.h common/type/stringz.h common/type/variant.h common/type/variantList.h common/wait.h postgres/client.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c postgres/client.c -o postgres/client.o diff --git a/src/build.auto.h.in b/src/build.auto.h.in index 2dc7ed84e..a61d3cb6b 100644 --- a/src/build.auto.h.in +++ b/src/build.auto.h.in @@ -3,6 +3,3 @@ Build Flags Generated by Configure ***********************************************************************************************************************************/ // Are test code and asserts disabled? #undef NDEBUG - -// Is libperl present? -#undef HAVE_LIBPERL diff --git a/src/command/archive/get/get.c b/src/command/archive/get/get.c index f518ee931..286c53e31 100644 --- a/src/command/archive/get/get.c +++ b/src/command/archive/get/get.c @@ -21,7 +21,6 @@ Archive Get Command #include "common/wait.h" #include "config/config.h" #include "config/exec.h" -#include "perl/exec.h" #include "postgres/interface.h" #include "protocol/helper.h" #include "protocol/parallel.h" diff --git a/src/command/backup/pageChecksum.c b/src/command/backup/pageChecksum.c index e740c7001..f8457e556 100644 --- a/src/command/backup/pageChecksum.c +++ b/src/command/backup/pageChecksum.c @@ -146,8 +146,8 @@ pageChecksumResult(THIS_VOID) VariantList *errorList = varLstNew(); unsigned int errorIdx = 0; - // Convert the full list to an abbreviated list that the Perl code can understand. In the future we want to return the - // entire list so pages can be verified in the WAL. + // Convert the full list to an abbreviated list. In the future we want to return the entire list so pages can be verified + // in the WAL. do { unsigned int pageId = varUInt(varLstGet(varVarLst(varLstGet(this->error, errorIdx)), 0)); diff --git a/src/command/info/info.c b/src/command/info/info.c index 940634290..76a3fc997 100644 --- a/src/command/info/info.c +++ b/src/command/info/info.c @@ -22,7 +22,6 @@ Info Command #include "info/infoBackup.h" #include "info/infoPg.h" #include "info/manifest.h" -#include "perl/exec.h" #include "postgres/interface.h" #include "storage/helper.h" diff --git a/src/common/exit.c b/src/common/exit.c index 161f36b80..8e14e8203 100644 --- a/src/common/exit.c +++ b/src/common/exit.c @@ -15,10 +15,6 @@ Exit Routines #include "config/config.h" #include "protocol/helper.h" -#ifdef HAVE_LIBPERL - #include "perl/exec.h" -#endif - /*********************************************************************************************************************************** Return signal names ***********************************************************************************************************************************/ @@ -106,32 +102,24 @@ exitSafe(int result, bool error, SignalType signalType) // Report error if one was thrown if (error) { - // Don't log the error if it has already been logged by Perl -#ifdef HAVE_LIBPERL - if (strcmp(errorMessage(), PERL_EMBED_ERROR) != 0) + LogLevel logLevel = errorCode() == errorTypeCode(&AssertError) ? logLevelAssert : logLevelError; + + // Assert errors always output a stack trace + if (logLevel == logLevelAssert) + LOG_FMT(logLevel, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), errorStackTrace()); + else { -#endif - LogLevel logLevel = errorCode() == errorTypeCode(&AssertError) ? logLevelAssert : logLevelError; + // Log just the error to non-debug levels + LOG_INTERNAL(logLevel, LOG_LEVEL_MIN, logLevelDetail, 0, errorCode(), errorMessage()); - // Assert errors always output a stack trace - if (logLevel == logLevelAssert) - LOG_FMT(logLevel, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), errorStackTrace()); - else + // Log the stack trace debug levels + if (logAny(logLevelDebug)) { - // Log just the error to non-debug levels - LOG_INTERNAL(logLevel, LOG_LEVEL_MIN, logLevelDetail, 0, errorCode(), errorMessage()); - - // Log the stack trace debug levels - if (logAny(logLevelDebug)) - { - LOG_INTERNAL_FMT( - logLevel, logLevelDebug, LOG_LEVEL_MAX, 0, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), - errorStackTrace()); - } + LOG_INTERNAL_FMT( + logLevel, logLevelDebug, LOG_LEVEL_MAX, 0, errorCode(), "%s\nSTACK TRACE:\n%s", errorMessage(), + errorStackTrace()); } -#ifdef HAVE_LIBPERL } -#endif result = errorCode(); } @@ -143,15 +131,6 @@ exitSafe(int result, bool error, SignalType signalType) } TRY_END(); - // Free Perl but ignore errors -#ifdef HAVE_LIBPERL - TRY_BEGIN() - { - perlFree(result); - } - TRY_END(); -#endif - // Log command end if a command is set if (cfgCommand() != cfgCmdNone) { diff --git a/src/config/config.auto.c b/src/config/config.auto.c index ed657dbbd..d190b3a09 100644 --- a/src/config/config.auto.c +++ b/src/config/config.auto.c @@ -310,7 +310,6 @@ STRING_EXTERN(CFGOPT_ARCHIVE_PUSH_QUEUE_MAX_STR, CFGOPT_ARCHI STRING_EXTERN(CFGOPT_ARCHIVE_TIMEOUT_STR, CFGOPT_ARCHIVE_TIMEOUT); STRING_EXTERN(CFGOPT_BACKUP_STANDBY_STR, CFGOPT_BACKUP_STANDBY); STRING_EXTERN(CFGOPT_BUFFER_SIZE_STR, CFGOPT_BUFFER_SIZE); -STRING_EXTERN(CFGOPT_C_STR, CFGOPT_C); STRING_EXTERN(CFGOPT_CHECKSUM_PAGE_STR, CFGOPT_CHECKSUM_PAGE); STRING_EXTERN(CFGOPT_CMD_SSH_STR, CFGOPT_CMD_SSH); STRING_EXTERN(CFGOPT_COMMAND_STR, CFGOPT_COMMAND); @@ -536,14 +535,6 @@ static ConfigOptionData configOptionData[CFG_OPTION_TOTAL] = CONFIG_OPTION_LIST CONFIG_OPTION_DEFINE_ID(cfgDefOptBufferSize) ) - //------------------------------------------------------------------------------------------------------------------------------ - CONFIG_OPTION - ( - CONFIG_OPTION_NAME(CFGOPT_C) - CONFIG_OPTION_INDEX(0) - CONFIG_OPTION_DEFINE_ID(cfgDefOptC) - ) - //------------------------------------------------------------------------------------------------------------------------------ CONFIG_OPTION ( diff --git a/src/config/config.auto.h b/src/config/config.auto.h index 5fd814b0d..d0bae6b78 100644 --- a/src/config/config.auto.h +++ b/src/config/config.auto.h @@ -69,8 +69,6 @@ Option constants STRING_DECLARE(CFGOPT_BACKUP_STANDBY_STR); #define CFGOPT_BUFFER_SIZE "buffer-size" STRING_DECLARE(CFGOPT_BUFFER_SIZE_STR); -#define CFGOPT_C "c" - STRING_DECLARE(CFGOPT_C_STR); #define CFGOPT_CHECKSUM_PAGE "checksum-page" STRING_DECLARE(CFGOPT_CHECKSUM_PAGE_STR); #define CFGOPT_CMD_SSH "cmd-ssh" @@ -382,7 +380,7 @@ Option constants #define CFGOPT_TYPE "type" STRING_DECLARE(CFGOPT_TYPE_STR); -#define CFG_OPTION_TOTAL 164 +#define CFG_OPTION_TOTAL 163 /*********************************************************************************************************************************** Command enum @@ -424,7 +422,6 @@ typedef enum cfgOptArchiveTimeout, cfgOptBackupStandby, cfgOptBufferSize, - cfgOptC, cfgOptChecksumPage, cfgOptCmdSsh, cfgOptCommand, diff --git a/src/config/config.h b/src/config/config.h index 980ae1cd3..73686757a 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -86,7 +86,7 @@ typedef enum Load Functions Used primarily by modules that need to manipulate the configuration. These modules include, but are not limited to, config/parse.c, -config/load.c, perl/config.c, and perl/exec.c. +config/load.c. ***********************************************************************************************************************************/ void cfgInit(void); diff --git a/src/config/define.auto.c b/src/config/define.auto.c index ebe2657eb..eb7b0171e 100644 --- a/src/config/define.auto.c +++ b/src/config/define.auto.c @@ -582,29 +582,6 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST ) ) - // ----------------------------------------------------------------------------------------------------------------------------- - CFGDEFDATA_OPTION - ( - CFGDEFDATA_OPTION_NAME("c") - CFGDEFDATA_OPTION_REQUIRED(true) - CFGDEFDATA_OPTION_SECTION(cfgDefSectionCommandLine) - CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeBoolean) - CFGDEFDATA_OPTION_INTERNAL(true) - - CFGDEFDATA_OPTION_INDEX_TOTAL(1) - CFGDEFDATA_OPTION_SECURE(false) - - CFGDEFDATA_OPTION_COMMAND_LIST - ( - CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRemote) - ) - - CFGDEFDATA_OPTION_OPTIONAL_LIST - ( - CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("0") - ) - ) - // ----------------------------------------------------------------------------------------------------------------------------- CFGDEFDATA_OPTION ( diff --git a/src/config/define.auto.h b/src/config/define.auto.h index 65b7d4de3..591b81e63 100644 --- a/src/config/define.auto.h +++ b/src/config/define.auto.h @@ -60,7 +60,6 @@ typedef enum cfgDefOptArchiveTimeout, cfgDefOptBackupStandby, cfgDefOptBufferSize, - cfgDefOptC, cfgDefOptChecksumPage, cfgDefOptCmdSsh, cfgDefOptCommand, diff --git a/src/config/load.c b/src/config/load.c index b9756e504..ad5598cd0 100644 --- a/src/config/load.c +++ b/src/config/load.c @@ -236,8 +236,7 @@ cfgLoadUpdateOption(void) } /*********************************************************************************************************************************** -Attempt to set the log file and turn file logging off if the file cannot be opened. This is so the Perl code won't attempt to open -the file again and error out. +Attempt to set the log file and turn file logging off if the file cannot be opened ***********************************************************************************************************************************/ void cfgLoadLogFile(void) diff --git a/src/config/parse.auto.c b/src/config/parse.auto.c index 89673a40a..43837c07d 100644 --- a/src/config/parse.auto.c +++ b/src/config/parse.auto.c @@ -126,13 +126,6 @@ static const struct option optionList[] = .val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | cfgOptBufferSize, }, - // c option - // ----------------------------------------------------------------------------------------------------------------------------- - { - .name = CFGOPT_C, - .val = PARSE_OPTION_FLAG | cfgOptC, - }, - // checksum-page option // ----------------------------------------------------------------------------------------------------------------------------- { @@ -2253,7 +2246,6 @@ static const ConfigOption optionResolveOrder[] = cfgOptArchiveTimeout, cfgOptBackupStandby, cfgOptBufferSize, - cfgOptC, cfgOptChecksumPage, cfgOptCmdSsh, cfgOptCommand, diff --git a/src/configure b/src/configure index c9b510161..5ef32912f 100755 --- a/src/configure +++ b/src/configure @@ -2807,61 +2807,8 @@ fi CINCLUDE="-I. -I../libc" -# Check required perl library -LIBS_BEFORE_PERL=$LIBS - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl_parse in -lperl" >&5 -$as_echo_n "checking for perl_parse in -lperl... " >&6; } -if ${ac_cv_lib_perl_perl_parse+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lperl `perl -MExtUtils::Embed -e ldopts` $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char perl_parse (); -int -main () -{ -return perl_parse (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_perl_perl_parse=yes -else - ac_cv_lib_perl_perl_parse=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_perl_perl_parse" >&5 -$as_echo "$ac_cv_lib_perl_perl_parse" >&6; } -if test "x$ac_cv_lib_perl_perl_parse" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBPERL 1 -_ACEOF - - LIBS="-lperl $LIBS" - -else - as_fn_error $? "library 'perl' is required" "$LINENO" 5 -fi - -LIBS="$LIBS_BEFORE_PERL `perl -MExtUtils::Embed -e ldopts`" -CLIBRARY="`perl -MExtUtils::Embed -e ccopts`" - - # Check required pq library + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQconnectdb in -lpq" >&5 $as_echo_n "checking for PQconnectdb in -lpq... " >&6; } if ${ac_cv_lib_pq_PQconnectdb+:} false; then : diff --git a/src/configure.ac b/src/configure.ac index c69b08c67..b052ce31b 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -33,12 +33,6 @@ fi # Set includes AC_SUBST(CINCLUDE, "-I. -I../libc") -# Check required perl library -LIBS_BEFORE_PERL=$LIBS -AC_CHECK_LIB([perl], [perl_parse], [], [AC_MSG_ERROR([library 'perl' is required])], [`perl -MExtUtils::Embed -e ldopts`]) -LIBS="$LIBS_BEFORE_PERL `perl -MExtUtils::Embed -e ldopts`" -AC_SUBST(CLIBRARY, "`perl -MExtUtils::Embed -e ccopts`") - # Check required pq library AC_CHECK_LIB([pq], [PQconnectdb], [], [AC_MSG_ERROR([library 'pq' is required])]) AC_SUBST(CINCLUDE, "$CINCLUDE -I`pg_config --includedir`") diff --git a/src/info/infoPg.c b/src/info/infoPg.c index 2f1bfcb7a..2ff166f56 100644 --- a/src/info/infoPg.c +++ b/src/info/infoPg.c @@ -297,7 +297,7 @@ infoPgSaveCallback(void *data, const String *sectionNext, InfoSave *infoSaveData InfoPgData pgData = infoPgDataCurrent(saveData->infoPg); - // These need to be saved because older Perl and C versions expect them + // These need to be saved because older pgBackRest versions expect them if (saveData->infoPg->type == infoPgBackup) { infoSaveValue( @@ -331,7 +331,7 @@ infoPgSaveCallback(void *data, const String *sectionNext, InfoSave *infoSaveData { kvPut(pgDataKv, INFO_KEY_DB_SYSTEM_ID_VAR, VARUINT64(pgData.systemId)); - // These need to be saved because older Perl and C versions expect them + // These need to be saved because older pgBackRest versions expect them kvPut(pgDataKv, INFO_KEY_DB_CATALOG_VERSION_VAR, VARUINT(pgCatalogVersion(pgData.version))); kvPut(pgDataKv, INFO_KEY_DB_CONTROL_VERSION_VAR, VARUINT(pgControlVersion(pgData.version))); } diff --git a/src/main.c b/src/main.c index e79321055..2a48ba4aa 100644 --- a/src/main.c +++ b/src/main.c @@ -30,7 +30,6 @@ Main #include "config/config.h" #include "config/load.h" #include "postgres/interface.h" -#include "perl/exec.h" #include "storage/helper.h" #include "version.h" @@ -166,13 +165,7 @@ main(int argListSize, const char *argList[]) // ----------------------------------------------------------------------------------------------------------------- case cfgCmdRemote: { - if (cfgOptionBool(cfgOptC)) - { - cmdRemote(STDIN_FILENO, STDOUT_FILENO); - } - else - perlExec(); - + cmdRemote(STDIN_FILENO, STDOUT_FILENO); break; } diff --git a/src/perl/config.h b/src/perl/config.h deleted file mode 100644 index d0f788b50..000000000 --- a/src/perl/config.h +++ /dev/null @@ -1,14 +0,0 @@ -/*********************************************************************************************************************************** -Perl Configuration -***********************************************************************************************************************************/ -#ifndef PERL_CONFIG_H -#define PERL_CONFIG_H - -#include "common/type/string.h" - -/*********************************************************************************************************************************** -Functions -***********************************************************************************************************************************/ -String *perlOptionJson(void); - -#endif diff --git a/src/perl/embed.auto.c b/src/perl/embed.auto.c deleted file mode 100644 index 6df43ea33..000000000 --- a/src/perl/embed.auto.c +++ /dev/null @@ -1,11537 +0,0 @@ -/*********************************************************************************************************************************** -Embed Perl modules - -Automatically generated by Build.pm -- do not modify directly. -***********************************************************************************************************************************/ - -/*********************************************************************************************************************************** -Embedded Perl modules -***********************************************************************************************************************************/ -static const EmbeddedModule embeddedModule[] = -{ - { - .name = "pgBackRest/Archive/Common.pm", - .data = - "\n\n\n" - "package pgBackRest::Archive::Common;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Config;\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use Fcntl qw(SEEK_CUR O_RDONLY);\n" - "use File::Basename qw(dirname);\n" - "\n" - "use pgBackRest::DbVersion;\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::Wait;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Protocol::Storage::Helper;\n" - "use pgBackRest::Storage::Helper;\n" - "\n\n\n\n" - "use constant REGEX_ARCHIVE_DIR_DB_VERSION => '^[0-9]+(\\.[0-9]+)*-[0-9]+$';\n" - "push @EXPORT, qw(REGEX_ARCHIVE_DIR_DB_VERSION);\n" - "use constant REGEX_ARCHIVE_DIR_WAL => '^[0-F]{16}$';\n" - "push @EXPORT, qw(REGEX_ARCHIVE_DIR_WAL);\n" - "\n\n\n\n" - "use constant PG_WAL_SYSTEM_ID_OFFSET_GTE_93 => 12 + $Config{ptrsize};\n" - "push @EXPORT, qw(PG_WAL_SYSTEM_ID_OFFSET_GTE_93);\n" - "use constant PG_WAL_SYSTEM_ID_OFFSET_LT_93 => 12;\n" - "push @EXPORT, qw(PG_WAL_SYSTEM_ID_OFFSET_LT_93);\n" - "\n\n\n\n" - "use constant PG_WAL_SEGMENT_SIZE => 16777216;\n" - "push @EXPORT, qw(PG_WAL_SEGMENT_SIZE);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Archive/Info.pm", - .data = - "\n\n\n\n\n\n\n" - "package pgBackRest::Archive::Info;\n" - "use parent 'pgBackRest::Common::Ini';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename qw(dirname basename);\n" - "\n" - "use pgBackRest::Archive::Common;\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Common::Ini;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::DbVersion;\n" - "use pgBackRest::InfoCommon;\n" - "use pgBackRest::Manifest;\n" - "use pgBackRest::Protocol::Storage::Helper;\n" - "use pgBackRest::Storage::Base;\n" - "use pgBackRest::Storage::Helper;\n" - "\n\n\n\n" - "use constant ARCHIVE_INFO_FILE => 'archive.info';\n" - "push @EXPORT, qw(ARCHIVE_INFO_FILE);\n" - "\n\n\n\n" - "use constant INFO_ARCHIVE_SECTION_DB => INFO_BACKUP_SECTION_DB;\n" - "push @EXPORT, qw(INFO_ARCHIVE_SECTION_DB);\n" - "use constant INFO_ARCHIVE_SECTION_DB_HISTORY => INFO_BACKUP_SECTION_DB_HISTORY;\n" - "push @EXPORT, qw(INFO_ARCHIVE_SECTION_DB_HISTORY);\n" - "\n" - "use constant INFO_ARCHIVE_KEY_DB_VERSION => MANIFEST_KEY_DB_VERSION;\n" - "push @EXPORT, qw(INFO_ARCHIVE_KEY_DB_VERSION);\n" - "use constant INFO_ARCHIVE_KEY_DB_ID => MANIFEST_KEY_DB_ID;\n" - "push @EXPORT, qw(INFO_ARCHIVE_KEY_DB_ID);\n" - "use constant INFO_ARCHIVE_KEY_DB_SYSTEM_ID => MANIFEST_KEY_SYSTEM_ID;\n" - "push @EXPORT, qw(INFO_ARCHIVE_KEY_DB_SYSTEM_ID);\n" - "\n\n\n\n" - "my $strArchiveInfoMissingMsg =\n" - "ARCHIVE_INFO_FILE . \" does not exist but is required to push/get WAL segments\\n\" .\n" - "\"HINT: is archive_command configured in postgresql.conf?\\n\" .\n" - "\"HINT: has a stanza-create been performed?\\n\" .\n" - "\"HINT: use --no-archive-check to disable archive checks during backup if you have an alternate archiving scheme.\";\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strArchiveClusterPath,\n" - "$bRequired,\n" - "$bLoad,\n" - "$bIgnoreMissing, # Don't error on missing files\n" - "$strCipherPassSub,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strArchiveClusterPath'},\n" - "{name => 'bRequired', default => true},\n" - "{name => 'bLoad', optional => true, default => true},\n" - "{name => 'bIgnoreMissing', optional => true, default => false},\n" - "{name => 'strCipherPassSub', optional => true},\n" - ");\n" - "\n\n" - "my $strArchiveInfoFile = \"${strArchiveClusterPath}/\" . ARCHIVE_INFO_FILE;\n" - "my $self = {};\n" - "my $iResult = 0;\n" - "my $strResultMessage;\n" - "\n\n" - "eval\n" - "{\n" - "$self = $class->SUPER::new($strArchiveInfoFile, {bLoad => $bLoad, bIgnoreMissing => $bIgnoreMissing,\n" - "oStorage => storageRepo(), strCipherPass => storageRepo()->cipherPassUser(),\n" - "strCipherPassSub => $strCipherPassSub});\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "\n" - "$iResult = exceptionCode($EVAL_ERROR);\n" - "$strResultMessage = exceptionMessage($EVAL_ERROR);\n" - "};\n" - "\n" - "if ($iResult != 0)\n" - "{\n" - "\n\n" - "if ($iResult == ERROR_FILE_MISSING)\n" - "{\n" - "if ($bRequired)\n" - "{\n" - "confess &log(ERROR, $strArchiveInfoMissingMsg, ERROR_FILE_MISSING);\n" - "}\n" - "}\n" - "elsif ($iResult == ERROR_CRYPTO && $strResultMessage =~ \"^unable to flush\")\n" - "{\n" - "confess &log(ERROR, \"unable to parse '$strArchiveInfoFile'\\nHINT: is or was the repo encrypted?\", $iResult);\n" - "}\n" - "else\n" - "{\n" - "confess $EVAL_ERROR;\n" - "}\n" - "}\n" - "\n" - "$self->{strArchiveClusterPath} = $strArchiveClusterPath;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n\n" - "sub check\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strDbVersion,\n" - "$ullDbSysId,\n" - "$bRequired,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->check', \\@_,\n" - "{name => 'strDbVersion'},\n" - "{name => 'ullDbSysId'},\n" - "{name => 'bRequired', default => true},\n" - ");\n" - "\n\n" - "if ($bRequired)\n" - "{\n" - "\n" - "$self->confirmExists();\n" - "}\n" - "\n" - "my $strError = undef;\n" - "\n" - "if (!$self->test(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION, undef, $strDbVersion))\n" - "{\n" - "$strError = \"WAL segment version ${strDbVersion} does not match archive version \" .\n" - "$self->get(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION);\n" - "}\n" - "\n" - "if (!$self->test(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_SYSTEM_ID, undef, $ullDbSysId))\n" - "{\n" - "$strError = (defined($strError) ? ($strError . \"\\n\") : \"\") .\n" - "\"WAL segment system-id ${ullDbSysId} does not match archive system-id \" .\n" - "$self->get(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_SYSTEM_ID);\n" - "}\n" - "\n" - "if (defined($strError))\n" - "{\n" - "confess &log(ERROR, \"${strError}\\nHINT: are you archiving to the correct stanza?\", ERROR_ARCHIVE_MISMATCH);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strArchiveId', value => $self->archiveId()}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub archiveId\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strDbVersion,\n" - "$ullDbSysId,\n" - ") = logDebugParam\n" - "(\n" - "__PACKAGE__ . '->archiveId', \\@_,\n" - "{name => 'strDbVersion', optional => true},\n" - "{name => 'ullDbSysId', optional => true},\n" - ");\n" - "\n" - "my $strArchiveId = undef;\n" - "\n\n" - "if (!defined($strDbVersion) && !defined($ullDbSysId))\n" - "{\n" - "$strArchiveId = $self->get(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION) . \"-\" .\n" - "$self->get(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_ID);\n" - "}\n" - "\n" - "elsif (defined($strDbVersion) && defined($ullDbSysId))\n" - "{\n" - "\n" - "$strArchiveId = ($self->archiveIdList($strDbVersion, $ullDbSysId))[0];\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strArchiveId', value => $strArchiveId}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub archiveIdList\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strDbVersion,\n" - "$ullDbSysId,\n" - ") = logDebugParam\n" - "(\n" - "__PACKAGE__ . '->archiveIdList', \\@_,\n" - "{name => 'strDbVersion'},\n" - "{name => 'ullDbSysId'},\n" - ");\n" - "\n" - "my @stryArchiveId;\n" - "\n\n" - "my $hDbList = $self->dbHistoryList();\n" - "\n" - "foreach my $iDbHistoryId (sort {$a <=> $b} keys %$hDbList)\n" - "{\n" - "\n" - "if (($hDbList->{$iDbHistoryId}{&INFO_DB_VERSION} eq $strDbVersion) &&\n" - "($hDbList->{$iDbHistoryId}{&INFO_SYSTEM_ID} eq $ullDbSysId))\n" - "{\n" - "unshift(@stryArchiveId, $strDbVersion . \"-\" . $iDbHistoryId);\n" - "}\n" - "}\n" - "\n\n" - "if (@stryArchiveId == 0)\n" - "{\n" - "confess &log(\n" - "ERROR, \"unable to retrieve the archive id for database version '$strDbVersion' and system-id '$ullDbSysId'\",\n" - "ERROR_ARCHIVE_MISMATCH);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'stryArchiveId', value => \\@stryArchiveId}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub create\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strDbVersion,\n" - "$ullDbSysId,\n" - "$bSave,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->create', \\@_,\n" - "{name => 'strDbVersion'},\n" - "{name => 'ullDbSysId'},\n" - "{name => 'bSave', default => true},\n" - ");\n" - "\n\n" - "$self->dbSectionSet($strDbVersion, $ullDbSysId, $self->dbHistoryIdGet(false));\n" - "\n" - "if ($bSave)\n" - "{\n" - "$self->save();\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub reconstruct\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strCurrentDbVersion,\n" - "$ullCurrentDbSysId,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->reconstruct', \\@_,\n" - "{name => 'strCurrentDbVersion'},\n" - "{name => 'ullCurrentDbSysId'},\n" - ");\n" - "\n" - "my $strInvalidFileStructure = undef;\n" - "\n" - "my @stryArchiveId = storageRepo()->list(\n" - "$self->{strArchiveClusterPath}, {strExpression => REGEX_ARCHIVE_DIR_DB_VERSION, bIgnoreMissing => true});\n" - "my %hDbHistoryVersion;\n" - "\n\n" - "foreach my $strArchiveId (@stryArchiveId)\n" - "{\n" - "my ($strDbVersion, $iDbHistoryId) = split(\"-\", $strArchiveId);\n" - "$hDbHistoryVersion{$iDbHistoryId} = $strDbVersion;\n" - "}\n" - "\n\n" - "foreach my $iDbHistoryId (sort {$a <=> $b} keys %hDbHistoryVersion)\n" - "{\n" - "my $strDbVersion = $hDbHistoryVersion{$iDbHistoryId};\n" - "my $strVersionDir = $strDbVersion . \"-\" . $iDbHistoryId;\n" - "\n\n" - "my $strArchiveDir = (storageRepo()->list(\n" - "$self->{strArchiveClusterPath} . \"/${strVersionDir}\",\n" - "{strExpression => REGEX_ARCHIVE_DIR_WAL, bIgnoreMissing => true}))[0];\n" - "\n\n" - "if (!defined($strArchiveDir))\n" - "{\n" - "$strInvalidFileStructure = \"found empty directory \" . $self->{strArchiveClusterPath} . \"/${strVersionDir}\";\n" - "next;\n" - "}\n" - "\n\n" - "my $strArchiveFile = (storageRepo()->list(\n" - "$self->{strArchiveClusterPath} . \"/${strVersionDir}/${strArchiveDir}\",\n" - "{strExpression => \"^[0-F]{24}(\\\\.partial){0,1}(-[0-f]+){0,1}(\\\\.\" . COMPRESS_EXT . \"){0,1}\\$\",\n" - "bIgnoreMissing => true}))[0];\n" - "\n\n" - "if (!defined($strArchiveFile))\n" - "{\n" - "$strInvalidFileStructure =\n" - "\"found empty directory \" . $self->{strArchiveClusterPath} . \"/${strVersionDir}/${strArchiveDir}\";\n" - "next;\n" - "}\n" - "\n\n" - "my $strArchiveFilePath = $self->{strArchiveClusterPath}.\"/${strVersionDir}/${strArchiveDir}/${strArchiveFile}\";\n" - "\n\n" - "my $iSysIdOffset = $strDbVersion >= PG_VERSION_93 ? PG_WAL_SYSTEM_ID_OFFSET_GTE_93 : PG_WAL_SYSTEM_ID_OFFSET_LT_93;\n" - "\n\n" - "if (!storageRepo()->encryptionValid(storageRepo()->encrypted($strArchiveFilePath)))\n" - "{\n" - "confess &log(ERROR, \"encryption incompatible for '$strArchiveFilePath'\" .\n" - "\"\\nHINT: is or was the repo encrypted?\", ERROR_CRYPTO);\n" - "}\n" - "\n\n" - "my $oFileIo = storageRepo()->openRead(\n" - "$strArchiveFilePath,\n" - "{rhyFilter => $strArchiveFile =~ ('\\.' . COMPRESS_EXT . '$') ?\n" - "[{strClass => STORAGE_FILTER_GZIP, rxyParam => [STORAGE_DECOMPRESS, false]}] : undef,\n" - "strCipherPass => $self->cipherPassSub()});\n" - "$oFileIo->open();\n" - "\n" - "my $tBlock;\n" - "$oFileIo->read(\\$tBlock, 512);\n" - "$oFileIo->close();\n" - "\n\n" - "my ($iMagic, $iFlag, $junk, $ullDbSysId) = unpack('SSa' . $iSysIdOffset . 'Q', $tBlock);\n" - "\n" - "if (!defined($ullDbSysId))\n" - "{\n" - "confess &log(ERROR, \"unable to read database system identifier\", ERROR_FILE_READ);\n" - "}\n" - "\n\n" - "$self->dbSectionSet($strDbVersion, $ullDbSysId, $iDbHistoryId);\n" - "}\n" - "\n\n" - "if (!$self->test(INFO_ARCHIVE_SECTION_DB))\n" - "{\n" - "$self->create($strCurrentDbVersion, $ullCurrentDbSysId, false);\n" - "}\n" - "\n" - "else\n" - "{\n" - "\n" - "logDisable();\n" - "\n" - "eval\n" - "{\n" - "$self->check($strCurrentDbVersion, $ullCurrentDbSysId, false);\n" - "logEnable();\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "\n" - "logEnable();\n" - "\n\n" - "confess $EVAL_ERROR if (exceptionCode($EVAL_ERROR) != ERROR_ARCHIVE_MISMATCH);\n" - "\n\n" - "$self->dbSectionSet($strCurrentDbVersion, $ullCurrentDbSysId, $self->dbHistoryIdGet(false)+1);\n" - "};\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strInvalidFileStructure', value => $strInvalidFileStructure}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub dbHistoryIdGet\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bFileRequired,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->dbHistoryIdGet', \\@_,\n" - "{name => 'bFileRequired', default => true},\n" - ");\n" - "\n\n" - "if ($bFileRequired)\n" - "{\n" - "$self->confirmExists();\n" - "}\n" - "\n\n" - "my $iDbHistoryId = (!$self->test(INFO_ARCHIVE_SECTION_DB))\n" - "? 1 : $self->numericGet(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_ID);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'iDbHistoryId', value => $iDbHistoryId}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub dbHistoryList\n" - "{\n" - "my $self = shift;\n" - "my\n" - "(\n" - "$strOperation,\n" - ") = logDebugParam\n" - "(\n" - "__PACKAGE__ . '->dbHistoryList',\n" - ");\n" - "\n" - "my %hDbHash;\n" - "\n" - "foreach my $iHistoryId ($self->keys(INFO_ARCHIVE_SECTION_DB_HISTORY))\n" - "{\n" - "$hDbHash{$iHistoryId}{&INFO_DB_VERSION} =\n" - "$self->get(INFO_ARCHIVE_SECTION_DB_HISTORY, $iHistoryId, INFO_ARCHIVE_KEY_DB_VERSION);\n" - "$hDbHash{$iHistoryId}{&INFO_SYSTEM_ID} =\n" - "$self->get(INFO_ARCHIVE_SECTION_DB_HISTORY, $iHistoryId, INFO_ARCHIVE_KEY_DB_ID);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'hDbHash', value => \\%hDbHash}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub dbSectionSet\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strDbVersion,\n" - "$ullDbSysId,\n" - "$iDbHistoryId,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->dbSectionSet', \\@_,\n" - "{name => 'strDbVersion', trace => true},\n" - "{name => 'ullDbSysId', trace => true},\n" - "{name => 'iDbHistoryId', trace => true}\n" - ");\n" - "\n\n" - "$self->numericSet(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_SYSTEM_ID, undef, $ullDbSysId);\n" - "\n" - "$self->set(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION, undef, $strDbVersion . '');\n" - "$self->numericSet(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_ID, undef, $iDbHistoryId);\n" - "\n\n" - "$self->numericSet(INFO_ARCHIVE_SECTION_DB_HISTORY, $iDbHistoryId, INFO_ARCHIVE_KEY_DB_ID, $ullDbSysId);\n" - "\n" - "$self->set(INFO_ARCHIVE_SECTION_DB_HISTORY, $iDbHistoryId, INFO_ARCHIVE_KEY_DB_VERSION, $strDbVersion . '');\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub confirmExists\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "if (!$self->test(INFO_ARCHIVE_SECTION_DB) || !$self->{bExists})\n" - "{\n" - "confess &log(ERROR, $strArchiveInfoMissingMsg, ERROR_FILE_MISSING);\n" - "}\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Backup/Common.pm", - .data = - "\n\n\n" - "package pgBackRest::Backup::Common;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename;\n" - "\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::String;\n" - "use pgBackRest::Common::Wait;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Protocol::Storage::Helper;\n" - "use pgBackRest::Storage::Helper;\n" - "use pgBackRest::Manifest;\n" - "\n\n\n\n" - "use constant LINK_LATEST => 'latest';\n" - "push @EXPORT, qw(LINK_LATEST);\n" - "\n\n\n\n\n\n" - "sub backupRegExpGet\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bFull,\n" - "$bDifferential,\n" - "$bIncremental,\n" - "$bAnchor\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::backupRegExpGet', \\@_,\n" - "{name => 'bFull', default => false},\n" - "{name => 'bDifferential', default => false},\n" - "{name => 'bIncremental', default => false},\n" - "{name => 'bAnchor', default => true}\n" - ");\n" - "\n\n" - "if (!($bFull || $bDifferential || $bIncremental))\n" - "{\n" - "confess &log(ASSERT, 'at least one backup type must be selected');\n" - "}\n" - "\n\n" - "my $strDateTimeRegExp = \"[0-9]{8}\\\\-[0-9]{6}\";\n" - "\n" - "my $strRegExp = ($bAnchor ? '^' : '') . $strDateTimeRegExp . 'F';\n" - "\n\n" - "if ($bDifferential || $bIncremental)\n" - "{\n" - "\n" - "if ($bFull)\n" - "{\n" - "$strRegExp .= \"(\\\\_\";\n" - "}\n" - "\n" - "else\n" - "{\n" - "$strRegExp .= \"\\\\_\";\n" - "}\n" - "\n\n" - "$strRegExp .= $strDateTimeRegExp;\n" - "\n\n" - "if ($bDifferential && $bIncremental)\n" - "{\n" - "$strRegExp .= '(D|I)';\n" - "}\n" - "\n" - "elsif ($bDifferential)\n" - "{\n" - "$strRegExp .= 'D';\n" - "}\n" - "\n" - "else\n" - "{\n" - "$strRegExp .= 'I';\n" - "}\n" - "\n\n" - "if ($bFull)\n" - "{\n" - "$strRegExp .= '){0,1}';\n" - "}\n" - "}\n" - "\n\n" - "$strRegExp .= $bAnchor ? \"\\$\" : '';\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strRegExp', value => $strRegExp}\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(backupRegExpGet);\n" - "\n\n\n\n\n\n" - "sub backupLabelFormat\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strType,\n" - "$strBackupLabelLast,\n" - "$lTimestampStart\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::backupLabelFormat', \\@_,\n" - "{name => 'strType', trace => true},\n" - "{name => 'strBackupLabelLast', required => false, trace => true},\n" - "{name => 'lTimestampTart', trace => true}\n" - ");\n" - "\n\n" - "my $strBackupLabel;\n" - "\n" - "if ($strType eq CFGOPTVAL_BACKUP_TYPE_FULL)\n" - "{\n" - "\n" - "if (defined($strBackupLabelLast))\n" - "{\n" - "confess &log(ASSERT, \"strBackupLabelLast must not be defined when strType = '${strType}'\");\n" - "}\n" - "\n\n" - "$strBackupLabel = timestampFileFormat(undef, $lTimestampStart) . 'F';\n" - "}\n" - "\n" - "else\n" - "{\n" - "\n" - "if (!defined($strBackupLabelLast))\n" - "{\n" - "confess &log(ASSERT, \"strBackupLabelLast must be defined when strType = '${strType}'\");\n" - "}\n" - "\n\n" - "$strBackupLabel = substr($strBackupLabelLast, 0, 16);\n" - "\n\n" - "$strBackupLabel .= '_' . timestampFileFormat(undef, $lTimestampStart);\n" - "\n\n" - "if ($strType eq CFGOPTVAL_BACKUP_TYPE_DIFF)\n" - "{\n" - "$strBackupLabel .= 'D';\n" - "}\n" - "\n" - "else\n" - "{\n" - "$strBackupLabel .= 'I';\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strBackupLabel', value => $strBackupLabel, trace => true}\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(backupLabelFormat);\n" - "\n\n\n\n\n\n" - "sub backupLabel\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$oStorageRepo,\n" - "$strType,\n" - "$strBackupLabelLast,\n" - "$lTimestampStart\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::backupLabelFormat', \\@_,\n" - "{name => 'oStorageRepo', trace => true},\n" - "{name => 'strType', trace => true},\n" - "{name => 'strBackupLabelLast', required => false, trace => true},\n" - "{name => 'lTimestampStart', trace => true}\n" - ");\n" - "\n\n" - "my $strBackupLabel = backupLabelFormat($strType, $strBackupLabelLast, $lTimestampStart);\n" - "\n\n\n\n\n" - "if ($oStorageRepo->list(\n" - "STORAGE_REPO_BACKUP,\n" - "{strExpression =>\n" - "($strType eq CFGOPTVAL_BACKUP_TYPE_FULL ? '^' : '_') . timestampFileFormat(undef, $lTimestampStart) .\n" - "($strType eq CFGOPTVAL_BACKUP_TYPE_FULL ? 'F' : '(D|I)$')}) ||\n" - "$oStorageRepo->list(\n" - "STORAGE_REPO_BACKUP . qw{/} . PATH_BACKUP_HISTORY . '/' . timestampFormat('%4d', $lTimestampStart),\n" - "{strExpression =>\n" - "($strType eq CFGOPTVAL_BACKUP_TYPE_FULL ? '^' : '_') . timestampFileFormat(undef, $lTimestampStart) .\n" - "($strType eq CFGOPTVAL_BACKUP_TYPE_FULL ? 'F' : '(D|I)\\.manifest\\.' . COMPRESS_EXT . qw{$}),\n" - "bIgnoreMissing => true}))\n" - "{\n" - "waitRemainder();\n" - "$strBackupLabel = backupLabelFormat($strType, $strBackupLabelLast, time());\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strBackupLabel', value => $strBackupLabel, trace => true}\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(backupLabel);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Backup/Info.pm", - .data = - "\n\n\n" - "package pgBackRest::Backup::Info;\n" - "use parent 'pgBackRest::Common::Ini';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename qw(dirname basename);\n" - "use File::stat;\n" - "\n" - "use pgBackRest::Archive::Info;\n" - "use pgBackRest::Backup::Common;\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Ini;\n" - "use pgBackRest::Common::Log;\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 FILE_BACKUP_INFO => 'backup.info';\n" - "push @EXPORT, qw(FILE_BACKUP_INFO);\n" - "\n\n\n\n" - "use constant INFO_BACKUP_SECTION_BACKUP => MANIFEST_SECTION_BACKUP;\n" - "push @EXPORT, qw(INFO_BACKUP_SECTION_BACKUP);\n" - "use constant INFO_BACKUP_SECTION_BACKUP_CURRENT => INFO_BACKUP_SECTION_BACKUP . ':current';\n" - "push @EXPORT, qw(INFO_BACKUP_SECTION_BACKUP_CURRENT);\n" - "\n" - "use constant INFO_BACKUP_KEY_ARCHIVE_CHECK => MANIFEST_KEY_ARCHIVE_CHECK;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_ARCHIVE_CHECK);\n" - "use constant INFO_BACKUP_KEY_ARCHIVE_COPY => MANIFEST_KEY_ARCHIVE_COPY;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_ARCHIVE_COPY);\n" - "use constant INFO_BACKUP_KEY_ARCHIVE_START => MANIFEST_KEY_ARCHIVE_START;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_ARCHIVE_START);\n" - "use constant INFO_BACKUP_KEY_ARCHIVE_STOP => MANIFEST_KEY_ARCHIVE_STOP;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_ARCHIVE_STOP);\n" - "use constant INFO_BACKUP_KEY_BACKUP_STANDBY => MANIFEST_KEY_BACKUP_STANDBY;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_BACKUP_STANDBY);\n" - "use constant INFO_BACKUP_KEY_BACKUP_REPO_SIZE => 'backup-info-repo-size';\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_BACKUP_REPO_SIZE);\n" - "use constant INFO_BACKUP_KEY_BACKUP_REPO_SIZE_DELTA => 'backup-info-repo-size-delta';\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_BACKUP_REPO_SIZE_DELTA);\n" - "use constant INFO_BACKUP_KEY_BACKUP_SIZE => 'backup-info-size';\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_BACKUP_SIZE);\n" - "use constant INFO_BACKUP_KEY_BACKUP_SIZE_DELTA => 'backup-info-size-delta';\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_BACKUP_SIZE_DELTA);\n" - "use constant INFO_BACKUP_KEY_CATALOG => MANIFEST_KEY_CATALOG;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_CATALOG);\n" - "use constant INFO_BACKUP_KEY_CONTROL => MANIFEST_KEY_CONTROL;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_CONTROL);\n" - "use constant INFO_BACKUP_KEY_COMPRESS => MANIFEST_KEY_COMPRESS;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_COMPRESS);\n" - "use constant INFO_BACKUP_KEY_CHECKSUM_PAGE => MANIFEST_KEY_CHECKSUM_PAGE;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_CHECKSUM_PAGE);\n" - "use constant INFO_BACKUP_KEY_DB_VERSION => MANIFEST_KEY_DB_VERSION;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_DB_VERSION);\n" - "use constant INFO_BACKUP_KEY_FORMAT => INI_KEY_FORMAT;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_FORMAT);\n" - "use constant INFO_BACKUP_KEY_HARDLINK => MANIFEST_KEY_HARDLINK;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_HARDLINK);\n" - "use constant INFO_BACKUP_KEY_HISTORY_ID => MANIFEST_KEY_DB_ID;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_HISTORY_ID);\n" - "use constant INFO_BACKUP_KEY_LABEL => MANIFEST_KEY_LABEL;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_LABEL);\n" - "use constant INFO_BACKUP_KEY_PRIOR => MANIFEST_KEY_PRIOR;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_PRIOR);\n" - "use constant INFO_BACKUP_KEY_REFERENCE => 'backup-reference';\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_REFERENCE);\n" - "use constant INFO_BACKUP_KEY_ONLINE => MANIFEST_KEY_ONLINE;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_ONLINE);\n" - "use constant INFO_BACKUP_KEY_SYSTEM_ID => MANIFEST_KEY_SYSTEM_ID;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_SYSTEM_ID);\n" - "use constant INFO_BACKUP_KEY_TIMESTAMP_START => MANIFEST_KEY_TIMESTAMP_START;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_TIMESTAMP_START);\n" - "use constant INFO_BACKUP_KEY_TIMESTAMP_STOP => MANIFEST_KEY_TIMESTAMP_STOP;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_TIMESTAMP_STOP);\n" - "use constant INFO_BACKUP_KEY_TYPE => MANIFEST_KEY_TYPE;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_TYPE);\n" - "use constant INFO_BACKUP_KEY_VERSION => INI_KEY_VERSION;\n" - "push @EXPORT, qw(INFO_BACKUP_KEY_VERSION);\n" - "\n\n\n\n" - "my $strBackupInfoMissingMsg =\n" - "FILE_BACKUP_INFO . \" does not exist and is required to perform a backup.\\n\" .\n" - "\"HINT: has a stanza-create been performed?\";\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strBackupClusterPath,\n" - "$bValidate,\n" - "$bRequired,\n" - "$oStorage,\n" - "$bLoad,\n" - "$bIgnoreMissing, # Don't error on missing files\n" - "$strCipherPassSub,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strBackupClusterPath'},\n" - "{name => 'bValidate', default => true},\n" - "{name => 'bRequired', default => true},\n" - "{name => 'oStorage', optional => true, default => storageRepo()},\n" - "{name => 'bLoad', optional => true, default => true},\n" - "{name => 'bIgnoreMissing', optional => true, default => false},\n" - "{name => 'strCipherPassSub', optional => true},\n" - ");\n" - "\n\n" - "my $strBackupInfoFile = \"${strBackupClusterPath}/\" . FILE_BACKUP_INFO;\n" - "my $self = {};\n" - "my $iResult = 0;\n" - "my $strResultMessage;\n" - "\n\n" - "eval\n" - "{\n" - "$self = $class->SUPER::new($strBackupInfoFile, {bLoad => $bLoad, bIgnoreMissing => $bIgnoreMissing,\n" - "oStorage => $oStorage, strCipherPass => $oStorage->cipherPassUser(),\n" - "strCipherPassSub => $strCipherPassSub});\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "\n" - "$iResult = exceptionCode($EVAL_ERROR);\n" - "$strResultMessage = exceptionMessage($EVAL_ERROR);\n" - "};\n" - "\n" - "if ($iResult != 0)\n" - "{\n" - "\n\n" - "if ($iResult == ERROR_FILE_MISSING)\n" - "{\n" - "if ($bRequired)\n" - "{\n" - "confess &log(ERROR, \"${strBackupClusterPath}/$strBackupInfoMissingMsg\", ERROR_FILE_MISSING);\n" - "}\n" - "}\n" - "elsif ($iResult == ERROR_CRYPTO && $strResultMessage =~ \"^unable to flush\")\n" - "{\n" - "confess &log(ERROR, \"unable to parse '$strBackupInfoFile'\\nHINT: is or was the repo encrypted?\", $iResult);\n" - "}\n" - "else\n" - "{\n" - "confess $EVAL_ERROR;\n" - "}\n" - "}\n" - "\n" - "$self->{strBackupClusterPath} = $strBackupClusterPath;\n" - "$self->{oStorage} = $oStorage;\n" - "\n\n" - "if ($bValidate)\n" - "{\n" - "$self->validate();\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub validate\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->validate');\n" - "\n\n" - "$self->confirmExists();\n" - "\n" - "$self->reconstruct();\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n\n" - "sub reconstruct\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bSave,\n" - "$bRequired,\n" - "$strDbVersion,\n" - "$ullDbSysId,\n" - "$iControlVersion,\n" - "$iCatalogVersion,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->reconstruct', \\@_,\n" - "{name => 'bSave', default => true},\n" - "{name => 'bRequired', default => true},\n" - "{name => 'strDbVersion', required => false},\n" - "{name => 'ullDbSysId', required => false},\n" - "{name => 'iControlVersion', required => false},\n" - "{name => 'iCatalogVersion', required => false},\n" - ");\n" - "\n\n" - "foreach my $strBackup ($self->{oStorage}->list(\n" - "$self->{strBackupClusterPath}, {strExpression => backupRegExpGet(true, true, true)}))\n" - "{\n" - "my $strManifestFile = \"$self->{strBackupClusterPath}/${strBackup}/\" . FILE_MANIFEST;\n" - "\n\n\n\n" - "if (!$self->current($strBackup) && $self->{oStorage}->exists($strManifestFile))\n" - "{\n" - "my $oManifest = pgBackRest::Manifest->new($strManifestFile,\n" - "{strCipherPass => ($self->{oStorage}->encrypted($strManifestFile)) ? $self->cipherPassSub() : undef});\n" - "\n\n\n" - "if (!$bRequired)\n" - "{\n" - "my $hDbList = $self->dbHistoryList();\n" - "my $iDbId = $oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID);\n" - "my $iDbIdMax = 0;\n" - "my $ullDbSysId = $oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_SYSTEM_ID);\n" - "my $strDbVersion = $oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION);\n" - "\n\n" - "foreach my $iDbHistoryId (keys %{$hDbList})\n" - "{\n" - "\n" - "if ($iDbHistoryId > $iDbIdMax)\n" - "{\n" - "$iDbIdMax = $iDbHistoryId;\n" - "}\n" - "}\n" - "\n" - "if ($iDbId >= $iDbIdMax)\n" - "{\n" - "$self->dbSectionSet($strDbVersion, $oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CONTROL),\n" - "$oManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG), $ullDbSysId, $iDbId);\n" - "}\n" - "}\n" - "\n" - "&log(WARN, \"backup ${strBackup} found in repository added to \" . FILE_BACKUP_INFO);\n" - "\n" - "$self->add($oManifest, $bSave, $bRequired);\n" - "}\n" - "}\n" - "\n\n" - "if (!$bRequired)\n" - "{\n" - "\n" - "if (!defined($strDbVersion) || !defined($ullDbSysId) || !defined($iControlVersion) || !defined($iCatalogVersion))\n" - "{\n" - "confess &log(ASSERT, \"backup info cannot be reconstructed without database information\");\n" - "}\n" - "\n" - "elsif (!$self->test(INFO_BACKUP_SECTION_DB))\n" - "{\n" - "$self->create($strDbVersion, $ullDbSysId, $iControlVersion, $iCatalogVersion, $bSave);\n" - "}\n" - "\n" - "else\n" - "{\n" - "\n" - "logDisable();\n" - "\n" - "eval\n" - "{\n" - "$self->check($strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId, $bRequired);\n" - "logEnable();\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "\n" - "logEnable();\n" - "\n\n" - "confess $EVAL_ERROR if (exceptionCode($EVAL_ERROR) != ERROR_BACKUP_MISMATCH);\n" - "\n\n" - "$self->dbSectionSet($strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId, $self->dbHistoryIdGet(false)+1);\n" - "};\n" - "}\n" - "}\n" - "\n\n" - "foreach my $strBackup ($self->keys(INFO_BACKUP_SECTION_BACKUP_CURRENT))\n" - "{\n" - "my $strManifestFile = \"$self->{strBackupClusterPath}/${strBackup}/\" . FILE_MANIFEST;\n" - "my $strBackupPath = \"$self->{strBackupClusterPath}/${strBackup}\";\n" - "\n" - "if (!$self->{oStorage}->pathExists($strBackupPath) || !$self->{oStorage}->exists($strManifestFile))\n" - "{\n" - "&log(WARN, \"backup '${strBackup}' missing manifest removed from \" . FILE_BACKUP_INFO);\n" - "$self->delete($strBackup);\n" - "}\n" - "}\n" - "\n\n\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub check\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strDbVersion,\n" - "$iControlVersion,\n" - "$iCatalogVersion,\n" - "$ullDbSysId,\n" - "$bRequired,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->check', \\@_,\n" - "{name => 'strDbVersion', trace => true},\n" - "{name => 'iControlVersion', trace => true},\n" - "{name => 'iCatalogVersion', trace => true},\n" - "{name => 'ullDbSysId', trace => true},\n" - "{name => 'bRequired', default => true},\n" - ");\n" - "\n\n" - "if ($bRequired)\n" - "{\n" - "$self->confirmExists();\n" - "}\n" - "\n" - "if (!$self->test(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_SYSTEM_ID, undef, $ullDbSysId) ||\n" - "!$self->test(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_DB_VERSION, undef, $strDbVersion))\n" - "{\n" - "confess &log(ERROR, \"database version = ${strDbVersion}, system-id ${ullDbSysId} does not match backup version = \" .\n" - "$self->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_DB_VERSION) . \", system-id = \" .\n" - "$self->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_SYSTEM_ID) . \"\\n\" .\n" - "\"HINT: is this the correct stanza?\", ERROR_BACKUP_MISMATCH);\n" - "}\n" - "\n" - "if (!$self->test(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_CATALOG, undef, $iCatalogVersion) ||\n" - "!$self->test(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_CONTROL, undef, $iControlVersion))\n" - "{\n" - "confess &log(ERROR, \"database control-version = ${iControlVersion}, catalog-version ${iCatalogVersion}\" .\n" - "\" does not match backup control-version = \" .\n" - "$self->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_CONTROL) . \", catalog-version = \" .\n" - "$self->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_CATALOG) . \"\\n\" .\n" - "\"HINT: this may be a symptom of database or repository corruption!\", ERROR_BACKUP_MISMATCH);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'iDbHistoryId', value => $self->numericGet(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_HISTORY_ID)}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub add\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$oBackupManifest,\n" - "$bSave,\n" - "$bRequired,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->add', \\@_,\n" - "{name => 'oBackupManifest', trace => true},\n" - "{name => 'bSave', default => true, trace => true},\n" - "{name => 'bRequired', default => true, trace => true},\n" - ");\n" - "\n\n" - "if ($bRequired)\n" - "{\n" - "$self->confirmExists();\n" - "}\n" - "\n\n" - "my $strBackupLabel = $oBackupManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL);\n" - "\n\n" - "my $lBackupSize = 0;\n" - "my $lBackupSizeDelta = 0;\n" - "my $lBackupRepoSize = 0;\n" - "my $lBackupRepoSizeDelta = 0;\n" - "my $oReferenceHash = undef;\n" - "\n" - "foreach my $strFileKey ($oBackupManifest->keys(MANIFEST_SECTION_TARGET_FILE))\n" - "{\n" - "my $lFileSize =\n" - "$oBackupManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFileKey, MANIFEST_SUBKEY_SIZE);\n" - "my $lRepoSize =\n" - "$oBackupManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFileKey, MANIFEST_SUBKEY_REPO_SIZE, false, $lFileSize);\n" - "my $strFileReference =\n" - "$oBackupManifest->get(MANIFEST_SECTION_TARGET_FILE, $strFileKey, MANIFEST_SUBKEY_REFERENCE, false);\n" - "\n\n" - "$lBackupSize += $lFileSize;\n" - "$lBackupRepoSize += $lRepoSize;\n" - "\n" - "if (defined($strFileReference))\n" - "{\n" - "$$oReferenceHash{$strFileReference} = true;\n" - "}\n" - "else\n" - "{\n" - "$lBackupSizeDelta += $lFileSize;\n" - "$lBackupRepoSizeDelta += $lRepoSize;\n" - "}\n" - "}\n" - "\n\n" - "$self->numericSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_BACKUP_SIZE, $lBackupSize);\n" - "$self->numericSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_BACKUP_SIZE_DELTA, $lBackupSizeDelta);\n" - "$self->numericSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_BACKUP_REPO_SIZE, $lBackupRepoSize);\n" - "$self->numericSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_BACKUP_REPO_SIZE_DELTA,\n" - "$lBackupRepoSizeDelta);\n" - "\n" - "$self->boolSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_ARCHIVE_CHECK,\n" - "$oBackupManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_CHECK));\n" - "$self->boolSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_ARCHIVE_COPY,\n" - "$oBackupManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_COPY));\n" - "$self->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_ARCHIVE_START,\n" - "$oBackupManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_START, undef, false));\n" - "$self->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_ARCHIVE_STOP,\n" - "$oBackupManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_STOP, undef, false));\n" - "$self->boolSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_BACKUP_STANDBY,\n" - "$oBackupManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_BACKUP_STANDBY));\n" - "$self->boolSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_CHECKSUM_PAGE,\n" - "$oBackupManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_CHECKSUM_PAGE));\n" - "$self->boolSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_COMPRESS,\n" - "$oBackupManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_COMPRESS));\n" - "$self->numericSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_FORMAT,\n" - "$oBackupManifest->numericGet(INI_SECTION_BACKREST, INI_KEY_FORMAT));\n" - "$self->boolSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_HARDLINK,\n" - "$oBackupManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_HARDLINK));\n" - "$self->boolSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_ONLINE,\n" - "$oBackupManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE));\n" - "$self->numericSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_TIMESTAMP_START,\n" - "$oBackupManifest->numericGet(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_START));\n" - "$self->numericSet(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_TIMESTAMP_STOP,\n" - "$oBackupManifest->numericGet(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_STOP));\n" - "$self->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_TYPE,\n" - "$oBackupManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TYPE));\n" - "$self->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_VERSION,\n" - "$oBackupManifest->get(INI_SECTION_BACKREST, INI_KEY_VERSION));\n" - "\n" - "if ($bRequired)\n" - "{\n" - "$self->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_HISTORY_ID,\n" - "$self->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_HISTORY_ID));\n" - "}\n" - "\n" - "else\n" - "{\n" - "$self->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_HISTORY_ID,\n" - "$oBackupManifest->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID));\n" - "}\n" - "\n" - "if (!$oBackupManifest->test(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TYPE, undef, CFGOPTVAL_BACKUP_TYPE_FULL))\n" - "{\n" - "my @stryReference = sort(keys(%$oReferenceHash));\n" - "\n" - "$self->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_PRIOR,\n" - "$oBackupManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_PRIOR));\n" - "$self->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_REFERENCE,\n" - "\\@stryReference);\n" - "}\n" - "\n" - "if ($bSave)\n" - "{\n" - "$self->save();\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub current\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strBackup\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->current', \\@_,\n" - "{name => 'strBackup'}\n" - ");\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bTest', value => $self->test(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup)}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub list\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strFilter,\n" - "$strOrder\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->list', \\@_,\n" - "{name => 'strFilter', required => false},\n" - "{name => 'strOrder', default => 'forward'}\n" - ");\n" - "\n\n" - "my @stryBackup;\n" - "\n\n" - "for my $strBackup ($self->keys(INFO_BACKUP_SECTION_BACKUP_CURRENT))\n" - "{\n" - "if (!defined($strFilter) || $strBackup =~ $strFilter)\n" - "{\n" - "if ($strOrder eq 'reverse')\n" - "{\n" - "unshift(@stryBackup, $strBackup)\n" - "}\n" - "else\n" - "{\n" - "push(@stryBackup, $strBackup)\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'stryBackup', value => \\@stryBackup}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub backupArchiveDbHistoryId\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strArchiveId,\n" - "$strPathBackupArchive,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->backupArchiveDbHistoryId', \\@_,\n" - "{name => 'strArchiveId'},\n" - "{name => 'strPathBackupArchive'},\n" - ");\n" - "\n\n" - "my @stryArchiveBackup;\n" - "\n\n" - "my $oArchiveInfo = new pgBackRest::Archive::Info($strPathBackupArchive, true);\n" - "my $hDbListArchive = $oArchiveInfo->dbHistoryList();\n" - "my $hDbListBackup = $self->dbHistoryList();\n" - "my $iDbHistoryId = undef;\n" - "\n\n" - "my ($strDbVersionArchive, $iDbIdArchive) = split(\"-\", $strArchiveId);\n" - "\n\n" - "if (exists($hDbListArchive->{$iDbIdArchive}))\n" - "{\n" - "my $ullDbSysIdArchive = $$hDbListArchive{$iDbIdArchive}{&INFO_SYSTEM_ID};\n" - "\n\n\n" - "foreach my $iDbIdBackup (sort {$b <=> $a} keys %{$hDbListBackup})\n" - "{\n" - "if ($$hDbListBackup{$iDbIdBackup}{&INFO_SYSTEM_ID} == $ullDbSysIdArchive &&\n" - "$$hDbListBackup{$iDbIdBackup}{&INFO_DB_VERSION} eq $strDbVersionArchive)\n" - "{\n" - "$iDbHistoryId = $iDbIdBackup;\n" - "last;\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "if (!defined($iDbHistoryId))\n" - "{\n" - "\n" - "if (!($oArchiveInfo->test(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_VERSION, undef,\n" - "($self->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_DB_VERSION)))) ||\n" - "!($oArchiveInfo->test(INFO_ARCHIVE_SECTION_DB, INFO_ARCHIVE_KEY_DB_SYSTEM_ID, undef,\n" - "($self->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_SYSTEM_ID)))))\n" - "{\n" - "\n" - "confess &log(ASSERT, \"the archive and backup database sections do not match\", ERROR_FILE_INVALID);\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'iDbHistoryId', value => $iDbHistoryId}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub listByArchiveId\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strArchiveId,\n" - "$strPathBackupArchive,\n" - "$stryBackup,\n" - "$strOrder,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->listByArchiveId', \\@_,\n" - "{name => 'strArchiveId'},\n" - "{name => 'strPathBackupArchive'},\n" - "{name => 'stryBackup'},\n" - "{name => 'strOrder', default => 'forward'}\n" - ");\n" - "\n\n" - "my @stryArchiveBackup;\n" - "\n" - "my $iDbHistoryId = $self->backupArchiveDbHistoryId($strArchiveId, $strPathBackupArchive);\n" - "\n\n" - "if (defined($iDbHistoryId))\n" - "{\n" - "\n" - "foreach my $strBackup (@$stryBackup)\n" - "{\n" - "\n" - "if ($self->test(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_HISTORY_ID, $iDbHistoryId))\n" - "{\n" - "if ($strOrder eq 'reverse')\n" - "{\n" - "unshift(@stryArchiveBackup, $strBackup)\n" - "}\n" - "else\n" - "{\n" - "push(@stryArchiveBackup, $strBackup)\n" - "}\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'stryArchiveBackup', value => \\@stryArchiveBackup}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub last\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strType\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->last', \\@_,\n" - "{name => 'strType'}\n" - ");\n" - "\n" - "my $strFilter = backupRegExpGet(true, $strType ne CFGOPTVAL_BACKUP_TYPE_FULL, $strType eq CFGOPTVAL_BACKUP_TYPE_INCR);\n" - "my $strBackup = ($self->list($strFilter, 'reverse'))[0];\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strBackup', value => $strBackup}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub delete\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strBackupLabel\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->delete', \\@_,\n" - "{name => 'strBackupLabel'}\n" - ");\n" - "\n" - "$self->remove(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel);\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub create\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strDbVersion,\n" - "$ullDbSysId,\n" - "$iControlVersion,\n" - "$iCatalogVersion,\n" - "$bSave,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->create', \\@_,\n" - "{name => 'strDbVersion'},\n" - "{name => 'ullDbSysId'},\n" - "{name => 'iControlVersion'},\n" - "{name => 'iCatalogVersion'},\n" - "{name => 'bSave', default => true},\n" - ");\n" - "\n\n" - "$self->dbSectionSet($strDbVersion, $iControlVersion, $iCatalogVersion, $ullDbSysId, $self->dbHistoryIdGet(false));\n" - "\n" - "if ($bSave)\n" - "{\n" - "$self->save();\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub dbHistoryIdGet\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bFileRequired,\n" - ") = logDebugParam\n" - "(\n" - "__PACKAGE__ . '->dbHistoryIdGet', \\@_,\n" - "{name => 'bFileRequired', default => true},\n" - ");\n" - "\n\n" - "if ($bFileRequired)\n" - "{\n" - "$self->confirmExists();\n" - "}\n" - "\n\n" - "my $iDbHistoryId = (!$self->test(INFO_BACKUP_SECTION_DB))\n" - "? 1 : $self->numericGet(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_HISTORY_ID);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'iDbHistoryId', value => $iDbHistoryId}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub dbHistoryList\n" - "{\n" - "my $self = shift;\n" - "my\n" - "(\n" - "$strOperation,\n" - ") = logDebugParam\n" - "(\n" - "__PACKAGE__ . '->dbHistoryList',\n" - ");\n" - "\n" - "my %hDbHash;\n" - "\n" - "foreach my $iHistoryId ($self->keys(INFO_BACKUP_SECTION_DB_HISTORY))\n" - "{\n" - "$hDbHash{$iHistoryId}{&INFO_DB_VERSION} =\n" - "$self->get(INFO_BACKUP_SECTION_DB_HISTORY, $iHistoryId, INFO_BACKUP_KEY_DB_VERSION);\n" - "$hDbHash{$iHistoryId}{&INFO_SYSTEM_ID} =\n" - "$self->get(INFO_BACKUP_SECTION_DB_HISTORY, $iHistoryId, INFO_BACKUP_KEY_SYSTEM_ID);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'hDbHash', value => \\%hDbHash}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub dbSectionSet\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strDbVersion,\n" - "$iControlVersion,\n" - "$iCatalogVersion,\n" - "$ullDbSysId,\n" - "$iDbHistoryId,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->dbSectionSet', \\@_,\n" - "{name => 'strDbVersion', trace => true},\n" - "{name => 'iControlVersion', trace => true},\n" - "{name => 'iCatalogVersion', trace => true},\n" - "{name => 'ullDbSysId', trace => true},\n" - "{name => 'iDbHistoryId', trace => true},\n" - ");\n" - "\n\n" - "$self->numericSet(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_CATALOG, undef, $iCatalogVersion);\n" - "$self->numericSet(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_CONTROL, undef, $iControlVersion);\n" - "$self->numericSet(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_SYSTEM_ID, undef, $ullDbSysId);\n" - "\n" - "$self->set(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_DB_VERSION, undef, $strDbVersion . '');\n" - "$self->numericSet(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_HISTORY_ID, undef, $iDbHistoryId);\n" - "\n\n" - "$self->numericSet(INFO_BACKUP_SECTION_DB_HISTORY, $iDbHistoryId, INFO_BACKUP_KEY_CATALOG, $iCatalogVersion);\n" - "$self->numericSet(INFO_BACKUP_SECTION_DB_HISTORY, $iDbHistoryId, INFO_BACKUP_KEY_CONTROL, $iControlVersion);\n" - "$self->numericSet(INFO_BACKUP_SECTION_DB_HISTORY, $iDbHistoryId, INFO_BACKUP_KEY_SYSTEM_ID, $ullDbSysId);\n" - "$self->set(INFO_BACKUP_SECTION_DB_HISTORY, $iDbHistoryId, INFO_BACKUP_KEY_DB_VERSION, $strDbVersion . '');\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n\n" - "sub confirmDb\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strBackup,\n" - "$strDbVersion,\n" - "$ullDbSysId,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->confirmDb', \\@_,\n" - "{name => 'strBackup', trace => true},\n" - "{name => 'strDbVersion', trace => true},\n" - "{name => 'ullDbSysId', trace => true},\n" - ");\n" - "\n" - "my $bConfirmDb = undef;\n" - "\n\n" - "my $iDbHistoryId = $self->get(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackup, INFO_BACKUP_KEY_HISTORY_ID);\n" - "\n\n" - "my $hDbList = $self->dbHistoryList();\n" - "\n\n" - "if (exists $hDbList->{$iDbHistoryId})\n" - "{\n" - "\n" - "if (($hDbList->{$iDbHistoryId}{&INFO_DB_VERSION} eq $strDbVersion) &&\n" - "($hDbList->{$iDbHistoryId}{&INFO_SYSTEM_ID} eq $ullDbSysId))\n" - "{\n" - "$bConfirmDb = true;\n" - "}\n" - "else\n" - "{\n" - "$bConfirmDb = false;\n" - "}\n" - "}\n" - "\n" - "else\n" - "{\n" - "confess &log(ERROR, \"backup info file is missing database history information for an existing backup\", ERROR_FILE_INVALID);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bConfirmDb', value => $bConfirmDb}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub confirmExists\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "if (!$self->test(INFO_BACKUP_SECTION_DB) || !$self->{bExists})\n" - "{\n" - "confess &log(ERROR, $self->{strBackupClusterPath} . \"/\" . $strBackupInfoMissingMsg, ERROR_FILE_MISSING);\n" - "}\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Cipher.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Cipher;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::LibC qw(:random :encode);\n" - "\n\n\n\n" - "sub cipherPassGen\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$iKeySizeInBytes,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::cipherPassGen', \\@_,\n" - "{name => 'iKeySizeInBytes', default => 48},\n" - ");\n" - "\n\n" - "my $strCipherPass = encodeToStr(ENCODE_TYPE_BASE64, cryptoRandomBytes($iKeySizeInBytes));\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strCipherPass', value => $strCipherPass, redact => true}\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(cipherPassGen);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Exception.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Exception;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess longmess);\n" - "\n" - "use Scalar::Util qw(blessed);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "\n" - "use pgBackRest::Common::ExceptionAuto;\n" - "\n\n\n\n" - "push(@EXPORT, @pgBackRest::Common::ExceptionAuto::EXPORT);\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "my $strLevel = shift;\n" - "my $iCode = shift;\n" - "my $strMessage = shift;\n" - "my $strTrace = shift;\n" - "my $rExtra = shift;\n" - "my $bErrorC = shift;\n" - "\n" - "if ($iCode < ERROR_MINIMUM || $iCode > ERROR_MAXIMUM)\n" - "{\n" - "$iCode = ERROR_INVALID;\n" - "}\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "$self->{strLevel} = $strLevel;\n" - "$self->{iCode} = $iCode;\n" - "$self->{strMessage} = $strMessage;\n" - "$self->{strTrace} = $strTrace;\n" - "$self->{rExtra} = $rExtra;\n" - "$self->{bErrorC} = $bErrorC ? 1 : 0;\n" - "\n" - "return $self;\n" - "}\n" - "\n\n\n\n" - "sub level\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->{strLevel};\n" - "}\n" - "\n\n\n\n" - "sub code\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->{iCode};\n" - "}\n" - "\n\n\n\n" - "sub errorC\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->{bErrorC};\n" - "}\n" - "\n\n\n\n" - "sub extra\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->{rExtra};\n" - "}\n" - "\n\n\n\n" - "sub message\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->{strMessage};\n" - "}\n" - "\n\n\n\n" - "sub trace\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->{strTrace};\n" - "}\n" - "\n\n\n\n" - "sub isException\n" - "{\n" - "my $roException = shift;\n" - "\n\n" - "if (defined($roException) && defined($$roException))\n" - "{\n" - "\n" - "if (blessed($$roException))\n" - "{\n" - "return $$roException->isa('pgBackRest::Common::Exception') ? 1 : 0;\n" - "}\n" - "\n" - "elsif ($$roException =~ /^PGBRCLIB\\:[0-9]+\\:/)\n" - "{\n" - "\n" - "my @stryException = split(/\\:/, $$roException);\n" - "shift(@stryException);\n" - "\n\n" - "my $iCode = shift(@stryException) + 0;\n" - "my $strTrace = shift(@stryException) . qw{:} . shift(@stryException);\n" - "my $strMessage = join(':', @stryException);\n" - "\n\n" - "$$roException = new pgBackRest::Common::Exception(\"ERROR\", $iCode, $strMessage, $strTrace, undef, 1);\n" - "\n" - "return 1;\n" - "}\n" - "}\n" - "\n" - "return 0;\n" - "}\n" - "\n" - "push @EXPORT, qw(isException);\n" - "\n\n\n\n\n\n" - "sub exceptionCode\n" - "{\n" - "my $oException = shift;\n" - "\n" - "return isException(\\$oException) ? $oException->code() : ERROR_UNKNOWN;\n" - "}\n" - "\n" - "push @EXPORT, qw(exceptionCode);\n" - "\n\n\n\n\n\n" - "sub exceptionMessage\n" - "{\n" - "my $oException = shift;\n" - "\n" - "return isException(\\$oException) ? $oException->message() : $oException;\n" - "}\n" - "\n" - "push @EXPORT, qw(exceptionMessage);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/ExceptionAuto.pm", - .data = - "\n\n\n\n\n" - "package pgBackRest::Common::ExceptionAuto;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "\n\n\n\n" - "use constant ERROR_MINIMUM => 25;\n" - "push @EXPORT, qw(ERROR_MINIMUM);\n" - "use constant ERROR_MAXIMUM => 125;\n" - "push @EXPORT, qw(ERROR_MAXIMUM);\n" - "\n" - "use constant ERROR_ASSERT => 25;\n" - "push @EXPORT, qw(ERROR_ASSERT);\n" - "use constant ERROR_CHECKSUM => 26;\n" - "push @EXPORT, qw(ERROR_CHECKSUM);\n" - "use constant ERROR_CONFIG => 27;\n" - "push @EXPORT, qw(ERROR_CONFIG);\n" - "use constant ERROR_FILE_INVALID => 28;\n" - "push @EXPORT, qw(ERROR_FILE_INVALID);\n" - "use constant ERROR_FORMAT => 29;\n" - "push @EXPORT, qw(ERROR_FORMAT);\n" - "use constant ERROR_COMMAND_REQUIRED => 30;\n" - "push @EXPORT, qw(ERROR_COMMAND_REQUIRED);\n" - "use constant ERROR_OPTION_INVALID => 31;\n" - "push @EXPORT, qw(ERROR_OPTION_INVALID);\n" - "use constant ERROR_OPTION_INVALID_VALUE => 32;\n" - "push @EXPORT, qw(ERROR_OPTION_INVALID_VALUE);\n" - "use constant ERROR_OPTION_INVALID_RANGE => 33;\n" - "push @EXPORT, qw(ERROR_OPTION_INVALID_RANGE);\n" - "use constant ERROR_OPTION_INVALID_PAIR => 34;\n" - "push @EXPORT, qw(ERROR_OPTION_INVALID_PAIR);\n" - "use constant ERROR_OPTION_DUPLICATE_KEY => 35;\n" - "push @EXPORT, qw(ERROR_OPTION_DUPLICATE_KEY);\n" - "use constant ERROR_OPTION_NEGATE => 36;\n" - "push @EXPORT, qw(ERROR_OPTION_NEGATE);\n" - "use constant ERROR_OPTION_REQUIRED => 37;\n" - "push @EXPORT, qw(ERROR_OPTION_REQUIRED);\n" - "use constant ERROR_POSTMASTER_RUNNING => 38;\n" - "push @EXPORT, qw(ERROR_POSTMASTER_RUNNING);\n" - "use constant ERROR_PROTOCOL => 39;\n" - "push @EXPORT, qw(ERROR_PROTOCOL);\n" - "use constant ERROR_PATH_NOT_EMPTY => 40;\n" - "push @EXPORT, qw(ERROR_PATH_NOT_EMPTY);\n" - "use constant ERROR_FILE_OPEN => 41;\n" - "push @EXPORT, qw(ERROR_FILE_OPEN);\n" - "use constant ERROR_FILE_READ => 42;\n" - "push @EXPORT, qw(ERROR_FILE_READ);\n" - "use constant ERROR_PARAM_REQUIRED => 43;\n" - "push @EXPORT, qw(ERROR_PARAM_REQUIRED);\n" - "use constant ERROR_ARCHIVE_MISMATCH => 44;\n" - "push @EXPORT, qw(ERROR_ARCHIVE_MISMATCH);\n" - "use constant ERROR_ARCHIVE_DUPLICATE => 45;\n" - "push @EXPORT, qw(ERROR_ARCHIVE_DUPLICATE);\n" - "use constant ERROR_VERSION_NOT_SUPPORTED => 46;\n" - "push @EXPORT, qw(ERROR_VERSION_NOT_SUPPORTED);\n" - "use constant ERROR_PATH_CREATE => 47;\n" - "push @EXPORT, qw(ERROR_PATH_CREATE);\n" - "use constant ERROR_COMMAND_INVALID => 48;\n" - "push @EXPORT, qw(ERROR_COMMAND_INVALID);\n" - "use constant ERROR_HOST_CONNECT => 49;\n" - "push @EXPORT, qw(ERROR_HOST_CONNECT);\n" - "use constant ERROR_LOCK_ACQUIRE => 50;\n" - "push @EXPORT, qw(ERROR_LOCK_ACQUIRE);\n" - "use constant ERROR_BACKUP_MISMATCH => 51;\n" - "push @EXPORT, qw(ERROR_BACKUP_MISMATCH);\n" - "use constant ERROR_FILE_SYNC => 52;\n" - "push @EXPORT, qw(ERROR_FILE_SYNC);\n" - "use constant ERROR_PATH_OPEN => 53;\n" - "push @EXPORT, qw(ERROR_PATH_OPEN);\n" - "use constant ERROR_PATH_SYNC => 54;\n" - "push @EXPORT, qw(ERROR_PATH_SYNC);\n" - "use constant ERROR_FILE_MISSING => 55;\n" - "push @EXPORT, qw(ERROR_FILE_MISSING);\n" - "use constant ERROR_DB_CONNECT => 56;\n" - "push @EXPORT, qw(ERROR_DB_CONNECT);\n" - "use constant ERROR_DB_QUERY => 57;\n" - "push @EXPORT, qw(ERROR_DB_QUERY);\n" - "use constant ERROR_DB_MISMATCH => 58;\n" - "push @EXPORT, qw(ERROR_DB_MISMATCH);\n" - "use constant ERROR_DB_TIMEOUT => 59;\n" - "push @EXPORT, qw(ERROR_DB_TIMEOUT);\n" - "use constant ERROR_FILE_REMOVE => 60;\n" - "push @EXPORT, qw(ERROR_FILE_REMOVE);\n" - "use constant ERROR_PATH_REMOVE => 61;\n" - "push @EXPORT, qw(ERROR_PATH_REMOVE);\n" - "use constant ERROR_STOP => 62;\n" - "push @EXPORT, qw(ERROR_STOP);\n" - "use constant ERROR_TERM => 63;\n" - "push @EXPORT, qw(ERROR_TERM);\n" - "use constant ERROR_FILE_WRITE => 64;\n" - "push @EXPORT, qw(ERROR_FILE_WRITE);\n" - "use constant ERROR_PROTOCOL_TIMEOUT => 66;\n" - "push @EXPORT, qw(ERROR_PROTOCOL_TIMEOUT);\n" - "use constant ERROR_FEATURE_NOT_SUPPORTED => 67;\n" - "push @EXPORT, qw(ERROR_FEATURE_NOT_SUPPORTED);\n" - "use constant ERROR_ARCHIVE_COMMAND_INVALID => 68;\n" - "push @EXPORT, qw(ERROR_ARCHIVE_COMMAND_INVALID);\n" - "use constant ERROR_LINK_EXPECTED => 69;\n" - "push @EXPORT, qw(ERROR_LINK_EXPECTED);\n" - "use constant ERROR_LINK_DESTINATION => 70;\n" - "push @EXPORT, qw(ERROR_LINK_DESTINATION);\n" - "use constant ERROR_HOST_INVALID => 72;\n" - "push @EXPORT, qw(ERROR_HOST_INVALID);\n" - "use constant ERROR_PATH_MISSING => 73;\n" - "push @EXPORT, qw(ERROR_PATH_MISSING);\n" - "use constant ERROR_FILE_MOVE => 74;\n" - "push @EXPORT, qw(ERROR_FILE_MOVE);\n" - "use constant ERROR_BACKUP_SET_INVALID => 75;\n" - "push @EXPORT, qw(ERROR_BACKUP_SET_INVALID);\n" - "use constant ERROR_TABLESPACE_MAP => 76;\n" - "push @EXPORT, qw(ERROR_TABLESPACE_MAP);\n" - "use constant ERROR_PATH_TYPE => 77;\n" - "push @EXPORT, qw(ERROR_PATH_TYPE);\n" - "use constant ERROR_LINK_MAP => 78;\n" - "push @EXPORT, qw(ERROR_LINK_MAP);\n" - "use constant ERROR_FILE_CLOSE => 79;\n" - "push @EXPORT, qw(ERROR_FILE_CLOSE);\n" - "use constant ERROR_DB_MISSING => 80;\n" - "push @EXPORT, qw(ERROR_DB_MISSING);\n" - "use constant ERROR_DB_INVALID => 81;\n" - "push @EXPORT, qw(ERROR_DB_INVALID);\n" - "use constant ERROR_ARCHIVE_TIMEOUT => 82;\n" - "push @EXPORT, qw(ERROR_ARCHIVE_TIMEOUT);\n" - "use constant ERROR_FILE_MODE => 83;\n" - "push @EXPORT, qw(ERROR_FILE_MODE);\n" - "use constant ERROR_OPTION_MULTIPLE_VALUE => 84;\n" - "push @EXPORT, qw(ERROR_OPTION_MULTIPLE_VALUE);\n" - "use constant ERROR_PROTOCOL_OUTPUT_REQUIRED => 85;\n" - "push @EXPORT, qw(ERROR_PROTOCOL_OUTPUT_REQUIRED);\n" - "use constant ERROR_LINK_OPEN => 86;\n" - "push @EXPORT, qw(ERROR_LINK_OPEN);\n" - "use constant ERROR_ARCHIVE_DISABLED => 87;\n" - "push @EXPORT, qw(ERROR_ARCHIVE_DISABLED);\n" - "use constant ERROR_FILE_OWNER => 88;\n" - "push @EXPORT, qw(ERROR_FILE_OWNER);\n" - "use constant ERROR_USER_MISSING => 89;\n" - "push @EXPORT, qw(ERROR_USER_MISSING);\n" - "use constant ERROR_OPTION_COMMAND => 90;\n" - "push @EXPORT, qw(ERROR_OPTION_COMMAND);\n" - "use constant ERROR_GROUP_MISSING => 91;\n" - "push @EXPORT, qw(ERROR_GROUP_MISSING);\n" - "use constant ERROR_PATH_EXISTS => 92;\n" - "push @EXPORT, qw(ERROR_PATH_EXISTS);\n" - "use constant ERROR_FILE_EXISTS => 93;\n" - "push @EXPORT, qw(ERROR_FILE_EXISTS);\n" - "use constant ERROR_MEMORY => 94;\n" - "push @EXPORT, qw(ERROR_MEMORY);\n" - "use constant ERROR_CRYPTO => 95;\n" - "push @EXPORT, qw(ERROR_CRYPTO);\n" - "use constant ERROR_PARAM_INVALID => 96;\n" - "push @EXPORT, qw(ERROR_PARAM_INVALID);\n" - "use constant ERROR_PATH_CLOSE => 97;\n" - "push @EXPORT, qw(ERROR_PATH_CLOSE);\n" - "use constant ERROR_FILE_INFO => 98;\n" - "push @EXPORT, qw(ERROR_FILE_INFO);\n" - "use constant ERROR_JSON_FORMAT => 99;\n" - "push @EXPORT, qw(ERROR_JSON_FORMAT);\n" - "use constant ERROR_KERNEL => 100;\n" - "push @EXPORT, qw(ERROR_KERNEL);\n" - "use constant ERROR_SERVICE => 101;\n" - "push @EXPORT, qw(ERROR_SERVICE);\n" - "use constant ERROR_EXECUTE => 102;\n" - "push @EXPORT, qw(ERROR_EXECUTE);\n" - "use constant ERROR_RUNTIME => 122;\n" - "push @EXPORT, qw(ERROR_RUNTIME);\n" - "use constant ERROR_INVALID => 123;\n" - "push @EXPORT, qw(ERROR_INVALID);\n" - "use constant ERROR_UNHANDLED => 124;\n" - "push @EXPORT, qw(ERROR_UNHANDLED);\n" - "use constant ERROR_UNKNOWN => 125;\n" - "push @EXPORT, qw(ERROR_UNKNOWN);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Ini.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Ini;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename qw(dirname);\n" - "use JSON::PP;\n" - "use Storable qw(dclone);\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::String;\n" - "use pgBackRest::LibC qw(:crypto);\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "use constant INI_TRUE => JSON::PP::true;\n" - "push @EXPORT, qw(INI_TRUE);\n" - "use constant INI_FALSE => JSON::PP::false;\n" - "push @EXPORT, qw(INI_FALSE);\n" - "\n\n\n\n" - "use constant INI_SECTION_BACKREST => 'backrest';\n" - "push @EXPORT, qw(INI_SECTION_BACKREST);\n" - "\n" - "use constant INI_KEY_CHECKSUM => 'backrest-checksum';\n" - "push @EXPORT, qw(INI_KEY_CHECKSUM);\n" - "use constant INI_KEY_FORMAT => 'backrest-format';\n" - "push @EXPORT, qw(INI_KEY_FORMAT);\n" - "use constant INI_KEY_VERSION => 'backrest-version';\n" - "push @EXPORT, qw(INI_KEY_VERSION);\n" - "\n" - "use constant INI_SECTION_CIPHER => 'cipher';\n" - "push @EXPORT, qw(INI_SECTION_CIPHER);\n" - "\n" - "use constant INI_KEY_CIPHER_PASS => 'cipher-pass';\n" - "push @EXPORT, qw(INI_KEY_CIPHER_PASS);\n" - "\n\n\n\n" - "use constant INI_COPY_EXT => '.copy';\n" - "push @EXPORT, qw(INI_COPY_EXT);\n" - "\n\n\n\n" - "use constant INI_SORT_FORWARD => 'forward';\n" - "push @EXPORT, qw(INI_SORT_FORWARD);\n" - "use constant INI_SORT_REVERSE => 'reverse';\n" - "push @EXPORT, qw(INI_SORT_REVERSE);\n" - "use constant INI_SORT_NONE => 'none';\n" - "push @EXPORT, qw(INI_SORT_NONE);\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "require pgBackRest::Storage::Helper;\n" - "pgBackRest::Storage::Helper->import();\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{strFileName},\n" - "my $bLoad,\n" - "my $strContent,\n" - "$self->{oStorage},\n" - "$self->{iInitFormat},\n" - "$self->{strInitVersion},\n" - "my $bIgnoreMissing,\n" - "$self->{strCipherPass},\n" - "my $strCipherPassSub,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strFileName', trace => true},\n" - "{name => 'bLoad', optional => true, default => true, trace => true},\n" - "{name => 'strContent', optional => true, trace => true},\n" - "{name => 'oStorage', optional => true, default => storageLocal(), trace => true},\n" - "{name => 'iInitFormat', optional => true, default => REPOSITORY_FORMAT, trace => true},\n" - "{name => 'strInitVersion', optional => true, default => PROJECT_VERSION, trace => true},\n" - "{name => 'bIgnoreMissing', optional => true, default => false, trace => true},\n" - "{name => 'strCipherPass', optional => true, trace => true},\n" - "{name => 'strCipherPassSub', optional => true, trace => true},\n" - ");\n" - "\n" - "if (defined($self->{oStorage}->cipherPassUser()) && !defined($self->{strCipherPass}))\n" - "{\n" - "confess &log(ERROR, 'passphrase is required when storage is encrypted', ERROR_CRYPTO);\n" - "}\n" - "\n\n" - "$self->{bModified} = false;\n" - "\n\n" - "$self->{bExists} = false;\n" - "\n\n" - "if ($bLoad)\n" - "{\n" - "$self->load($bIgnoreMissing);\n" - "}\n" - "\n" - "elsif (defined($strContent))\n" - "{\n" - "$self->{oContent} = iniParse($strContent);\n" - "$self->headerCheck();\n" - "}\n" - "\n\n" - "if (!$self->{bExists} && !defined($strContent))\n" - "{\n" - "$self->numericSet(INI_SECTION_BACKREST, INI_KEY_FORMAT, undef, $self->{iInitFormat});\n" - "$self->set(INI_SECTION_BACKREST, INI_KEY_VERSION, undef, $self->{strInitVersion});\n" - "\n\n" - "if (defined($self->{strCipherPass}) && defined($strCipherPassSub))\n" - "{\n" - "$self->set(INI_SECTION_CIPHER, INI_KEY_CIPHER_PASS, undef, $strCipherPassSub);\n" - "}\n" - "elsif ((defined($self->{strCipherPass}) && !defined($strCipherPassSub)) ||\n" - "(!defined($self->{strCipherPass}) && defined($strCipherPassSub)))\n" - "{\n" - "confess &log(ASSERT, 'a user passphrase and sub passphrase are both required when encrypting');\n" - "}\n" - "}\n" - "\n" - "return $self;\n" - "}\n" - "\n\n\n\n" - "sub loadVersion\n" - "{\n" - "my $self = shift;\n" - "my $bCopy = shift;\n" - "my $bIgnoreError = shift;\n" - "\n\n" - "if ($self->{oStorage}->encryptionValid($self->{oStorage}->encrypted($self->{strFileName} . ($bCopy ? INI_COPY_EXT : ''),\n" - "{bIgnoreMissing => $bIgnoreError})))\n" - "{\n" - "\n" - "my $rstrContent = $self->{oStorage}->get(\n" - "$self->{oStorage}->openRead($self->{strFileName} . ($bCopy ? INI_COPY_EXT : ''),\n" - "{bIgnoreMissing => $bIgnoreError, strCipherPass => $self->{strCipherPass}}));\n" - "\n\n" - "if (defined($rstrContent))\n" - "{\n" - "my $rhContent = iniParse($$rstrContent, {bIgnoreInvalid => $bIgnoreError});\n" - "\n\n" - "if (defined($rhContent))\n" - "{\n" - "$self->{oContent} = $rhContent;\n" - "\n\n" - "if (!$self->headerCheck({bIgnoreInvalid => $bIgnoreError}))\n" - "{\n" - "delete($self->{oContent});\n" - "}\n" - "}\n" - "}\n" - "}\n" - "else\n" - "{\n" - "confess &log(ERROR, \"unable to parse '$self->{strFileName}\" . ($bCopy ? INI_COPY_EXT : '') . \"'\" .\n" - "\"\\nHINT: is or was the repo encrypted?\", ERROR_CRYPTO);\n" - "}\n" - "\n" - "return defined($self->{oContent});\n" - "}\n" - "\n\n\n\n" - "sub load\n" - "{\n" - "my $self = shift;\n" - "my $bIgnoreMissing = shift;\n" - "\n\n" - "if (!$self->loadVersion(false, true))\n" - "{\n" - "if (!$self->loadVersion(true, true))\n" - "{\n" - "return if $bIgnoreMissing;\n" - "\n" - "confess &log(ERROR, \"unable to open $self->{strFileName} or $self->{strFileName}\" . INI_COPY_EXT, ERROR_FILE_MISSING);\n" - "}\n" - "}\n" - "\n" - "$self->{bExists} = true;\n" - "}\n" - "\n\n\n\n" - "sub headerCheck\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bIgnoreInvalid,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->headerCheck', \\@_,\n" - "{name => 'bIgnoreInvalid', optional => true, default => false, trace => true},\n" - ");\n" - "\n\n" - "my $bValid = true;\n" - "\n" - "eval\n" - "{\n" - "\n\n" - "my $strChecksum = $self->get(INI_SECTION_BACKREST, INI_KEY_CHECKSUM, undef, false);\n" - "my $strTestChecksum = $self->hash();\n" - "\n" - "if (!defined($strChecksum) || $strChecksum ne $strTestChecksum)\n" - "{\n" - "confess &log(ERROR,\n" - "\"invalid checksum in '$self->{strFileName}', expected '${strTestChecksum}' but found \" .\n" - "(defined($strChecksum) ? \"'${strChecksum}'\" : '[undef]'),\n" - "ERROR_CHECKSUM);\n" - "}\n" - "\n\n" - "my $iFormat = $self->get(INI_SECTION_BACKREST, INI_KEY_FORMAT, undef, false, 0);\n" - "\n" - "if ($iFormat != $self->{iInitFormat})\n" - "{\n" - "confess &log(ERROR,\n" - "\"invalid format in '$self->{strFileName}', expected $self->{iInitFormat} but found ${iFormat}\", ERROR_FORMAT);\n" - "}\n" - "\n\n" - "if (!$self->test(INI_SECTION_BACKREST, INI_KEY_VERSION, undef, $self->{strInitVersion}))\n" - "{\n" - "$self->set(INI_SECTION_BACKREST, INI_KEY_VERSION, undef, $self->{strInitVersion});\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "\n" - "if (!$bIgnoreInvalid)\n" - "{\n" - "confess $EVAL_ERROR;\n" - "}\n" - "\n\n" - "$bValid = false;\n" - "};\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bValid', value => $bValid, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "push @EXPORT, qw(iniParse);\n" - "\n" - "sub iniParse\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strContent,\n" - "$bRelaxed,\n" - "$bIgnoreInvalid,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::iniParse', \\@_,\n" - "{name => 'strContent', required => false, trace => true},\n" - "{name => 'bRelaxed', optional => true, default => false, trace => true},\n" - "{name => 'bIgnoreInvalid', optional => true, default => false, trace => true},\n" - ");\n" - "\n\n" - "my $oContent = undef;\n" - "my $strSection;\n" - "\n\n" - "my $oJSON = JSON::PP->new()->allow_nonref();\n" - "\n\n" - "eval\n" - "{\n" - "\n" - "foreach my $strLine (split(\"\\n\", defined($strContent) ? $strContent : ''))\n" - "{\n" - "$strLine = trim($strLine);\n" - "\n\n" - "if ($strLine ne '' && $strLine !~ '^[ ]*#.*')\n" - "{\n" - "\n" - "if (index($strLine, '[') == 0)\n" - "{\n" - "$strSection = substr($strLine, 1, length($strLine) - 2);\n" - "}\n" - "else\n" - "{\n" - "if (!defined($strSection))\n" - "{\n" - "confess &log(ERROR, \"key/value pair '${strLine}' found outside of a section\", ERROR_CONFIG);\n" - "}\n" - "\n\n" - "my $iIndex = index($strLine, '=');\n" - "\n" - "if ($iIndex == -1)\n" - "{\n" - "confess &log(ERROR, \"unable to find '=' in '${strLine}'\", ERROR_CONFIG);\n" - "}\n" - "\n" - "my $strKey = substr($strLine, 0, $iIndex);\n" - "my $strValue = substr($strLine, $iIndex + 1);\n" - "\n\n" - "if ($bRelaxed)\n" - "{\n" - "if (defined($oContent->{$strSection}{$strKey}))\n" - "{\n" - "if (ref($oContent->{$strSection}{$strKey}) ne 'ARRAY')\n" - "{\n" - "$oContent->{$strSection}{$strKey} = [$oContent->{$strSection}{$strKey}];\n" - "}\n" - "\n" - "push(@{$oContent->{$strSection}{$strKey}}, $strValue);\n" - "}\n" - "else\n" - "{\n" - "$oContent->{$strSection}{$strKey} = $strValue;\n" - "}\n" - "}\n" - "\n" - "else\n" - "{\n" - "${$oContent}{$strSection}{$strKey} = $oJSON->decode($strValue);\n" - "}\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "if (!($bRelaxed || defined($oContent)))\n" - "{\n" - "confess &log(ERROR, 'no key/value pairs found', ERROR_CONFIG);\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "\n" - "if (!$bIgnoreInvalid)\n" - "{\n" - "confess $EVAL_ERROR;\n" - "}\n" - "\n\n" - "undef($oContent);\n" - "};\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oContent', value => $oContent, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub save\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "if ($self->{bModified})\n" - "{\n" - "\n" - "$self->hash();\n" - "\n\n" - "$self->{oStorage}->put($self->{strFileName}, iniRender($self->{oContent}), {strCipherPass => $self->{strCipherPass}});\n" - "$self->{oStorage}->pathSync(dirname($self->{strFileName}));\n" - "$self->{oStorage}->put($self->{strFileName} . INI_COPY_EXT, iniRender($self->{oContent}),\n" - "{strCipherPass => $self->{strCipherPass}});\n" - "$self->{oStorage}->pathSync(dirname($self->{strFileName}));\n" - "$self->{bModified} = false;\n" - "\n\n" - "$self->{bExists} = true;\n" - "\n\n" - "return true;\n" - "}\n" - "\n\n" - "return false;\n" - "}\n" - "\n\n\n\n" - "sub saveCopy\n" - "{\n" - "my $self = shift;\n" - "\n" - "if ($self->{oStorage}->exists($self->{strFileName}))\n" - "{\n" - "confess &log(ASSERT, \"cannot save copy only when '$self->{strFileName}' exists\");\n" - "}\n" - "\n" - "$self->hash();\n" - "$self->{oStorage}->put($self->{strFileName} . INI_COPY_EXT, iniRender($self->{oContent}),\n" - "{strCipherPass => $self->{strCipherPass}});\n" - "}\n" - "\n\n\n\n" - "push @EXPORT, qw(iniRender);\n" - "\n" - "sub iniRender\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$oContent,\n" - "$bRelaxed,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::iniRender', \\@_,\n" - "{name => 'oContent', trace => true},\n" - "{name => 'bRelaxed', default => false, trace => true},\n" - ");\n" - "\n\n" - "my $strContent = '';\n" - "my $bFirst = true;\n" - "\n\n" - "my $oJSON = JSON::PP->new()->canonical()->allow_nonref();\n" - "\n\n" - "foreach my $strSection (sort(keys(%$oContent)))\n" - "{\n" - "\n" - "if (!$bFirst)\n" - "{\n" - "$strContent .= \"\\n\";\n" - "}\n" - "\n\n" - "$strContent .= \"[${strSection}]\\n\";\n" - "\n\n" - "foreach my $strKey (sort(keys(%{$oContent->{$strSection}})))\n" - "{\n" - "\n" - "my $strValue = ${$oContent}{$strSection}{$strKey};\n" - "\n\n" - "if ($bRelaxed)\n" - "{\n" - "\n" - "if (ref($strValue) eq 'ARRAY')\n" - "{\n" - "foreach my $strArrayValue (@{$strValue})\n" - "{\n" - "$strContent .= \"${strKey}=${strArrayValue}\\n\";\n" - "}\n" - "}\n" - "\n" - "else\n" - "{\n" - "$strContent .= \"${strKey}=${strValue}\\n\";\n" - "}\n" - "}\n" - "\n" - "else\n" - "{\n" - "\n" - "if (!($strSection eq INI_SECTION_BACKREST && $strKey eq INI_KEY_CHECKSUM))\n" - "{\n" - "$strContent .= \"${strKey}=\" . $oJSON->encode($strValue) . \"\\n\";\n" - "}\n" - "}\n" - "}\n" - "\n" - "$bFirst = false;\n" - "}\n" - "\n\n\n" - "if (!$bRelaxed && defined($oContent->{&INI_SECTION_BACKREST}) && defined($oContent->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM}))\n" - "{\n" - "$strContent .=\n" - "\"\\n[\" . INI_SECTION_BACKREST . \"]\\n\" .\n" - "INI_KEY_CHECKSUM . '=' . $oJSON->encode($oContent->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM}) . \"\\n\";\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strContent', value => $strContent, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub hash\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "delete($self->{oContent}{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM});\n" - "\n\n" - "$self->{oContent}{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} =\n" - "cryptoHashOne('sha1', JSON::PP->new()->canonical()->allow_nonref()->encode($self->{oContent}));\n" - "\n" - "return $self->{oContent}{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM};\n" - "}\n" - "\n\n\n\n" - "sub get\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strKey = shift;\n" - "my $strSubKey = shift;\n" - "my $bRequired = shift;\n" - "my $oDefault = shift;\n" - "\n\n" - "if (!defined($strSection))\n" - "{\n" - "confess &log(ASSERT, 'strSection is required');\n" - "}\n" - "\n" - "if (defined($strSubKey) && !defined($strKey))\n" - "{\n" - "confess &log(ASSERT, \"strKey is required when strSubKey '${strSubKey}' is requested\");\n" - "}\n" - "\n\n" - "my $oResult = $self->{oContent}->{$strSection};\n" - "\n" - "if (defined($strKey) && defined($oResult))\n" - "{\n" - "$oResult = $oResult->{$strKey};\n" - "\n" - "if (defined($strSubKey) && defined($oResult))\n" - "{\n" - "$oResult = $oResult->{$strSubKey};\n" - "}\n" - "}\n" - "\n\n" - "if (!defined($oResult))\n" - "{\n" - "\n" - "if (!defined($bRequired) || $bRequired)\n" - "{\n" - "confess &log(ASSERT, \"strSection '$strSection'\" . (defined($strKey) ? \", strKey '$strKey'\" : '') .\n" - "(defined($strSubKey) ? \", strSubKey '$strSubKey'\" : '') . ' is required but not defined');\n" - "}\n" - "\n\n" - "if (defined($oDefault))\n" - "{\n" - "return $oDefault;\n" - "}\n" - "}\n" - "\n" - "return $oResult\n" - "}\n" - "\n\n\n\n" - "sub boolGet\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strKey = shift;\n" - "my $strSubKey = shift;\n" - "my $bRequired = shift;\n" - "my $bDefault = shift;\n" - "\n" - "return $self->get(\n" - "$strSection, $strKey, $strSubKey, $bRequired,\n" - "defined($bDefault) ? ($bDefault ? INI_TRUE : INI_FALSE) : undef) ? true : false;\n" - "}\n" - "\n\n\n\n" - "sub numericGet\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strKey = shift;\n" - "my $strSubKey = shift;\n" - "my $bRequired = shift;\n" - "my $nDefault = shift;\n" - "\n" - "return $self->get($strSection, $strKey, $strSubKey, $bRequired, defined($nDefault) ? $nDefault + 0 : undef) + 0;\n" - "}\n" - "\n\n\n\n" - "sub set\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strKey = shift;\n" - "my $strSubKey = shift;\n" - "my $oValue = shift;\n" - "\n\n" - "if (!(defined($strSection) && defined($strKey)))\n" - "{\n" - "confess &log(ASSERT, 'strSection and strKey are required');\n" - "}\n" - "\n" - "my $oCurrentValue;\n" - "\n" - "if (defined($strSubKey))\n" - "{\n" - "$oCurrentValue = \\$self->{oContent}{$strSection}{$strKey}{$strSubKey};\n" - "}\n" - "else\n" - "{\n" - "$oCurrentValue = \\$self->{oContent}{$strSection}{$strKey};\n" - "}\n" - "\n" - "if (!defined($$oCurrentValue) ||\n" - "defined($oCurrentValue) != defined($oValue) ||\n" - "${dclone($oCurrentValue)} ne ${dclone(\\$oValue)})\n" - "{\n" - "$$oCurrentValue = $oValue;\n" - "\n" - "if (!$self->{bModified})\n" - "{\n" - "$self->{bModified} = true;\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "\n" - "return false;\n" - "}\n" - "\n\n\n\n" - "sub boolSet\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strKey = shift;\n" - "my $strSubKey = shift;\n" - "my $bValue = shift;\n" - "\n" - "$self->set($strSection, $strKey, $strSubKey, $bValue ? INI_TRUE : INI_FALSE);\n" - "}\n" - "\n\n\n\n" - "sub numericSet\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strKey = shift;\n" - "my $strSubKey = shift;\n" - "my $nValue = shift;\n" - "\n" - "$self->set($strSection, $strKey, $strSubKey, defined($nValue) ? $nValue + 0 : undef);\n" - "}\n" - "\n\n\n\n" - "sub remove\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strKey = shift;\n" - "my $strSubKey = shift;\n" - "\n\n" - "if ($self->test($strSection, $strKey, $strSubKey))\n" - "{\n" - "\n" - "if (defined($strSubKey))\n" - "{\n" - "delete($self->{oContent}{$strSection}{$strKey}{$strSubKey});\n" - "}\n" - "\n\n" - "if (defined($strKey))\n" - "{\n" - "if (!defined($strSubKey))\n" - "{\n" - "delete($self->{oContent}{$strSection}{$strKey});\n" - "}\n" - "\n\n" - "if (keys(%{$self->{oContent}{$strSection}}) == 0)\n" - "{\n" - "delete($self->{oContent}{$strSection});\n" - "}\n" - "}\n" - "\n\n" - "if (!defined($strKey))\n" - "{\n" - "delete($self->{oContent}{$strSection});\n" - "}\n" - "\n\n" - "if (!$self->{bModified})\n" - "{\n" - "$self->{bModified} = true;\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "\n" - "return false;\n" - "}\n" - "\n\n\n\n" - "sub keys\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strSortOrder = shift;\n" - "\n" - "if ($self->test($strSection))\n" - "{\n" - "if (!defined($strSortOrder) || $strSortOrder eq INI_SORT_FORWARD)\n" - "{\n" - "return (sort(keys(%{$self->get($strSection)})));\n" - "}\n" - "elsif ($strSortOrder eq INI_SORT_REVERSE)\n" - "{\n" - "return (sort {$b cmp $a} (keys(%{$self->get($strSection)})));\n" - "}\n" - "elsif ($strSortOrder eq INI_SORT_NONE)\n" - "{\n" - "return (keys(%{$self->get($strSection)}));\n" - "}\n" - "else\n" - "{\n" - "confess &log(ASSERT, \"invalid strSortOrder '${strSortOrder}'\");\n" - "}\n" - "}\n" - "\n" - "my @stryEmptyArray;\n" - "return @stryEmptyArray;\n" - "}\n" - "\n\n\n\n\n\n\n" - "sub test\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strValue = shift;\n" - "my $strSubValue = shift;\n" - "my $strTest = shift;\n" - "\n\n" - "my $strResult = $self->get($strSection, $strValue, $strSubValue, false);\n" - "\n\n" - "if (defined($strResult))\n" - "{\n" - "\n" - "if (defined($strTest))\n" - "{\n" - "\n" - "return ($strResult . '') eq ($strTest . '') ? true : false;\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "\n" - "return false;\n" - "}\n" - "\n\n\n\n" - "sub boolTest\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strValue = shift;\n" - "my $strSubValue = shift;\n" - "my $bTest = shift;\n" - "\n" - "return $self->test($strSection, $strValue, $strSubValue, defined($bTest) ? ($bTest ? INI_TRUE : INI_FALSE) : undef);\n" - "}\n" - "\n\n\n\n" - "sub cipherPassSub\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->get(INI_SECTION_CIPHER, INI_KEY_CIPHER_PASS, undef, false);\n" - "}\n" - "\n\n\n\n" - "sub modified {shift->{bModified}}\n" - "sub exists {shift->{bExists}}\n" - "sub cipherPass {shift->{strCipherPass}}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Io/Base.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Io::Base;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use Scalar::Util qw(blessed);\n" - "\n" - "use pgBackRest::Common::Log;\n" - "\n\n\n\n" - "use constant COMMON_IO_BASE => __PACKAGE__;\n" - "push @EXPORT, qw(COMMON_IO_BASE);\n" - "\n\n\n\n" - "use constant COMMON_IO_BUFFER_MAX => 4194304;\n" - "push @EXPORT, qw(COMMON_IO_BUFFER_MAX);\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{strId},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strId', trace => true},\n" - ");\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub error\n" - "{\n" - "my $self = shift;\n" - "my $iCode = shift;\n" - "my $strMessage = shift;\n" - "my $strDetail = shift;\n" - "\n" - "logErrorResult($iCode, $strMessage, $strDetail);\n" - "}\n" - "\n\n\n\n" - "sub result\n" - "{\n" - "my $self = shift;\n" - "my $strModule = shift;\n" - "\n" - "if (!defined($strModule))\n" - "{\n" - "return $self->{rhResult};\n" - "}\n" - "\n" - "return $self->{rhResult}{$strModule};\n" - "}\n" - "\n\n\n\n" - "sub resultAll\n" - "{\n" - "shift->{rhResult};\n" - "}\n" - "\n\n\n\n" - "sub resultSet\n" - "{\n" - "my $self = shift;\n" - "my $strModule = shift;\n" - "my $xResult = shift;\n" - "\n" - "$self->{rhResult}{$strModule} = $xResult;\n" - "}\n" - "\n\n\n\n" - "sub className {blessed(shift)}\n" - "sub id {shift->{strId}}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Io/Buffered.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Io::Buffered;\n" - "use parent 'pgBackRest::Common::Io::Filter';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use IO::Select;\n" - "use Time::HiRes qw(gettimeofday);\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Io::Base;\n" - "use pgBackRest::Common::Io::Handle;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::Wait;\n" - "\n\n\n\n" - "use constant COMMON_IO_BUFFERED => __PACKAGE__;\n" - "push @EXPORT, qw(COMMON_IO_BUFFERED);\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$oParent,\n" - "$iTimeout,\n" - "$lBufferMax,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'oParent', trace => true},\n" - "{name => 'iTimeout', default => 0, trace => true},\n" - "{name => 'lBufferMax', default => COMMON_IO_BUFFER_MAX, trace => true},\n" - ");\n" - "\n\n" - "my $self = $class->SUPER::new($oParent);\n" - "bless $self, $class;\n" - "\n\n" - "$self->handleReadSet($self->handleRead());\n" - "\n\n" - "$self->{iTimeout} = $iTimeout;\n" - "$self->{lBufferMax} = $lBufferMax;\n" - "\n\n" - "$self->{tBuffer} = '';\n" - "$self->{lBufferSize} = 0;\n" - "$self->{lBufferPos} = 0;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub read\n" - "{\n" - "my $self = shift;\n" - "my $tBufferRef = shift;\n" - "my $iRequestSize = shift;\n" - "my $bBlock = shift;\n" - "\n\n" - "my $iRemainingSize = $iRequestSize;\n" - "\n\n" - "my $lBufferRemaining = $self->{lBufferSize} - $self->{lBufferPos};\n" - "\n" - "if ($lBufferRemaining > 0)\n" - "{\n" - "my $iReadSize = $iRequestSize < $lBufferRemaining ? $iRequestSize : $lBufferRemaining;\n" - "\n" - "$$tBufferRef .= substr($self->{tBuffer}, $self->{lBufferPos}, $iReadSize);\n" - "$self->{lBufferPos} += $iReadSize;\n" - "\n" - "$iRemainingSize -= $iReadSize;\n" - "}\n" - "\n\n\n" - "my $fTimeStart = gettimeofday();\n" - "my $fRemaining = $self->timeout();\n" - "\n" - "while ($iRemainingSize > 0 && $fRemaining > 0)\n" - "{\n" - "\n" - "if ($self->pending() || $self->{oReadSelect}->can_read($fRemaining))\n" - "{\n" - "\n" - "my $iReadSize = $self->parent()->read($tBufferRef, $iRemainingSize);\n" - "\n\n" - "if ($iReadSize == 0)\n" - "{\n" - "if ($bBlock)\n" - "{\n" - "$self->error(ERROR_FILE_READ, \"unable to read ${iRequestSize} byte(s) due to EOF from \" . $self->id());\n" - "}\n" - "else\n" - "{\n" - "return $iRequestSize - $iRemainingSize;\n" - "}\n" - "}\n" - "\n\n" - "$iRemainingSize -= $iReadSize;\n" - "}\n" - "\n\n" - "$fRemaining = $self->timeout() - (gettimeofday() - $fTimeStart);\n" - "};\n" - "\n\n" - "if ($iRemainingSize != 0 && $bBlock)\n" - "{\n" - "$self->error(\n" - "ERROR_FILE_READ, \"unable to read ${iRequestSize} byte(s) after \" . $self->timeout() . ' second(s) from ' . $self->id());\n" - "}\n" - "\n" - "return $iRequestSize - $iRemainingSize;\n" - "}\n" - "\n\n\n\n" - "sub readLine\n" - "{\n" - "my $self = shift;\n" - "my $bIgnoreEOF = shift;\n" - "my $bError = shift;\n" - "\n\n" - "my $iLineFeedPos = index($self->{tBuffer}, \"\\n\", $self->{lBufferPos});\n" - "\n\n" - "if ($iLineFeedPos == -1)\n" - "{\n" - "my $fRemaining = $self->timeout();\n" - "my $fTimeStart = gettimeofday();\n" - "\n\n" - "do\n" - "{\n" - "\n" - "if ($self->{lBufferPos} != 0)\n" - "{\n" - "$self->{tBuffer} = substr($self->{tBuffer}, $self->{lBufferPos});\n" - "$self->{lBufferSize} = $self->{lBufferSize} - $self->{lBufferPos};\n" - "$self->{lBufferPos} = 0;\n" - "}\n" - "\n\n" - "my $iBufferRead = 0;\n" - "\n" - "if ($self->pending() || $self->{oReadSelect}->can_read($fRemaining))\n" - "{\n" - "$iBufferRead = $self->parent()->read(\n" - "\\$self->{tBuffer},\n" - "$self->{lBufferSize} >= $self->bufferMax() ? $self->bufferMax() : $self->bufferMax() - $self->{lBufferSize});\n" - "\n\n" - "if ($iBufferRead == 0)\n" - "{\n" - "\n" - "if (defined($bIgnoreEOF) && $bIgnoreEOF)\n" - "{\n" - "return;\n" - "}\n" - "\n\n" - "$self->error(ERROR_FILE_READ, 'unexpected EOF reading line from ' . $self->id());\n" - "}\n" - "}\n" - "\n\n" - "if ($iBufferRead > 0)\n" - "{\n" - "$self->{lBufferSize} += $iBufferRead;\n" - "\n" - "$iLineFeedPos = index($self->{tBuffer}, \"\\n\");\n" - "}\n" - "\n\n" - "if ($iLineFeedPos == -1)\n" - "{\n" - "$fRemaining = $self->timeout() - (gettimeofday() - $fTimeStart);\n" - "}\n" - "}\n" - "while ($iLineFeedPos == -1 && $fRemaining > 0);\n" - "\n\n" - "if ($iLineFeedPos == -1)\n" - "{\n" - "if (!defined($bError) || $bError)\n" - "{\n" - "$self->error(\n" - "ERROR_FILE_READ, 'unable to read line after ' . $self->timeout() . ' second(s) from ' . $self->id());\n" - "}\n" - "\n" - "return;\n" - "}\n" - "}\n" - "\n\n" - "my $strLine = substr($self->{tBuffer}, $self->{lBufferPos}, $iLineFeedPos - $self->{lBufferPos});\n" - "$self->{lBufferPos} = $iLineFeedPos + 1;\n" - "\n" - "return $strLine;\n" - "}\n" - "\n\n\n\n" - "sub writeLine\n" - "{\n" - "my $self = shift;\n" - "my $strBuffer = shift;\n" - "\n" - "$strBuffer .= \"\\n\";\n" - "return $self->parent()->write(\\$strBuffer);\n" - "}\n" - "\n\n\n\n" - "sub timeout {shift->{iTimeout}};\n" - "sub bufferMax {shift->{lBufferMax}};\n" - "\n\n\n\n" - "sub handleReadSet\n" - "{\n" - "my $self = shift;\n" - "my $fhRead = shift;\n" - "\n" - "$self->parent()->handleReadSet($fhRead);\n" - "\n\n" - "$self->{oReadSelect} = IO::Select->new();\n" - "$self->{oReadSelect}->add($self->handleRead());\n" - "\n\n" - "$self->{bPending} = defined($fhRead) && $fhRead->can('pending') ? true : false;\n" - "}\n" - "\n\n\n\n" - "sub pending\n" - "{\n" - "my $self = shift;\n" - "\n" - "return ($self->{bPending} && $self->handleRead()->pending() ? true : false);\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Io/Filter.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Io::Filter;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use Scalar::Util qw(blessed);\n" - "\n" - "use pgBackRest::Common::Log;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{oParent},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'oParent', trace => true},\n" - ");\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub bufferMax {shift->{oParent}->bufferMax()};\n" - "sub className {shift->{oParent}->className()};\n" - "sub close {shift->{oParent}->close()};\n" - "sub eof {shift->{oParent}->eof()};\n" - "sub eofSet {shift->{oParent}->eofSet(@_)};\n" - "sub error {shift->{oParent}->error(@_)};\n" - "sub id {shift->{oParent}->id()};\n" - "sub handleRead {shift->{oParent}->handleRead()};\n" - "sub handleReadSet {shift->{oParent}->handleReadSet(@_)};\n" - "sub handleWrite {shift->{oParent}->handleWrite()};\n" - "sub handleWriteSet {shift->{oParent}->handleWriteSet(@_)};\n" - "sub name {shift->{oParent}->name()};\n" - "sub read {shift->{oParent}->read(@_)};\n" - "sub readLine {shift->{oParent}->readLine(@_)};\n" - "sub result {shift->{oParent}->result(@_)};\n" - "sub resultAll {shift->{oParent}->resultAll()};\n" - "sub resultSet {shift->{oParent}->resultSet(@_)};\n" - "sub size {shift->{oParent}->size()};\n" - "sub timeout {shift->{oParent}->timeout()};\n" - "sub write {shift->{oParent}->write(@_)};\n" - "sub writeLine {shift->{oParent}->writeLine(@_)};\n" - "\n\n\n\n" - "sub parent {shift->{oParent}}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Io/Handle.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Io::Handle;\n" - "use parent 'pgBackRest::Common::Io::Base';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "\n\n\n\n" - "use constant COMMON_IO_HANDLE => __PACKAGE__;\n" - "push @EXPORT, qw(COMMON_IO_HANDLE);\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strId,\n" - "$fhRead,\n" - "$fhWrite,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strId', trace => true},\n" - "{name => 'fhRead', required => false, trace => true},\n" - "{name => 'fhWrite', required => false, trace => true},\n" - ");\n" - "\n\n" - "my $self = $class->SUPER::new($strId);\n" - "bless $self, $class;\n" - "\n\n" - "$self->handleReadSet($fhRead) if defined($fhRead);\n" - "$self->handleWriteSet($fhWrite) if defined($fhWrite);\n" - "\n\n" - "$self->{lSize} = 0;\n" - "\n\n" - "$self->eofSet(false);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n\n" - "sub eof\n" - "{\n" - "return shift->{bEOF};\n" - "}\n" - "\n\n\n\n" - "sub eofSet\n" - "{\n" - "my $self = shift;\n" - "my $bEOF = shift;\n" - "\n" - "$self->{bEOF} = $bEOF;\n" - "}\n" - "\n\n\n\n" - "sub read\n" - "{\n" - "my $self = shift;\n" - "my $rtBuffer = shift;\n" - "my $iSize = shift;\n" - "\n\n" - "my $iActualSize;\n" - "\n" - "eval\n" - "{\n" - "$iActualSize = sysread($self->handleRead(), $$rtBuffer, $iSize, defined($$rtBuffer) ? length($$rtBuffer) : 0);\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "$self->error(ERROR_FILE_READ, 'unable to read from ' . $self->id(), $EVAL_ERROR);\n" - "};\n" - "\n\n\n" - "defined($iActualSize)\n" - "or $self->error(ERROR_FILE_READ, 'unable to read from ' . $self->id(), $OS_ERROR);\n" - "\n\n" - "$self->{lSize} += $iActualSize;\n" - "\n\n" - "$self->eofSet($iActualSize == 0 ? true : false);\n" - "\n" - "return $iActualSize;\n" - "}\n" - "\n\n\n\n" - "sub write\n" - "{\n" - "my $self = shift;\n" - "my $rtBuffer = shift;\n" - "\n\n" - "my $iActualSize;\n" - "\n" - "eval\n" - "{\n" - "$iActualSize = syswrite($self->handleWrite(), $$rtBuffer);\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "$self->error(ERROR_FILE_WRITE, 'unable to write to ' . $self->id(), $EVAL_ERROR);\n" - "};\n" - "\n\n\n" - "defined($iActualSize)\n" - "or $self->error(ERROR_FILE_WRITE, 'unable to write to ' . $self->id(), $OS_ERROR);\n" - "\n\n" - "$self->{lSize} += $iActualSize;\n" - "\n" - "return $iActualSize;\n" - "}\n" - "\n\n\n\n" - "sub close\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "if (defined($self->{lSize}))\n" - "{\n" - "$self->resultSet(COMMON_IO_HANDLE, $self->{lSize});\n" - "undef($self->{lSize});\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "\n\n\n\n" - "sub handleRead {return shift->{fhHandleRead}}\n" - "sub handleReadSet {my $self = shift; $self->{fhHandleRead} = shift}\n" - "sub handleWrite {return shift->{fhHandleWrite}}\n" - "sub handleWriteSet {my $self = shift; $self->{fhHandleWrite} = shift}\n" - "sub size {shift->{lSize}}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Io/Process.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Io::Process;\n" - "use parent 'pgBackRest::Common::Io::Filter';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use IPC::Open3 qw(open3);\n" - "use POSIX qw(:sys_wait_h);\n" - "use Symbol 'gensym';\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Io::Buffered;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::Wait;\n" - "\n\n\n\n" - "use constant COMMON_IO_PROCESS => __PACKAGE__;\n" - "push @EXPORT, qw(COMMON_IO_PROCESS);\n" - "\n\n\n\n" - "use constant IO_ERROR_TIMEOUT => 5;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$oParent,\n" - "$strCommand,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'oParent', trace => true},\n" - "{name => 'strCommand', trace => true},\n" - ");\n" - "\n\n" - "my $self = $class->SUPER::new($oParent);\n" - "bless $self, $class;\n" - "\n\n" - "my ($iProcessId, $fhRead, $fhWrite, $fhReadError);\n" - "$fhReadError = gensym;\n" - "\n" - "$iProcessId = IPC::Open3::open3($fhWrite, $fhRead, $fhReadError, $strCommand);\n" - "\n\n" - "$self->handleReadSet($fhRead);\n" - "$self->handleWriteSet($fhWrite);\n" - "\n\n" - "$self->{iProcessId} = $iProcessId;\n" - "$self->{fhReadError} = $fhReadError;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub error\n" - "{\n" - "my $self = shift;\n" - "my $iCode = shift;\n" - "my $strMessage = shift;\n" - "my $strDetail = shift;\n" - "my $bClose = shift;\n" - "\n" - "if (defined($self->{iProcessId}))\n" - "{\n" - "my $oWait = waitInit(defined($iCode) ? IO_ERROR_TIMEOUT : 0);\n" - "\n" - "do\n" - "{\n" - "\n" - "my $iResult = waitpid($self->{iProcessId}, $bClose ? 0 : WNOHANG);\n" - "\n\n" - "if ($iResult != 0)\n" - "{\n" - "\n" - "my $iExitStatus = $iResult == -1 ? 255 : ${^CHILD_ERROR_NATIVE} >> 8;\n" - "\n\n" - "my $strError;\n" - "my $oIoError = new pgBackRest::Common::Io::Buffered(\n" - "new pgBackRest::Common::Io::Handle($self->id(), $self->{fhReadError}), 5, $self->bufferMax());\n" - "\n" - "while (defined(my $strLine = $oIoError->readLine(true, false)))\n" - "{\n" - "$strError .= (defined($strError) ? \"\\n\" : '') . $strLine;\n" - "}\n" - "\n" - "delete($self->{iProcessId});\n" - "\n" - "if (!$bClose || $iExitStatus != 0 || defined($strError))\n" - "{\n" - "my $iErrorCode =\n" - "$iExitStatus >= ERROR_MINIMUM && $iExitStatus <= ERROR_MAXIMUM ? $iExitStatus : ERROR_FILE_READ;\n" - "\n" - "logErrorResult(\n" - "$iErrorCode, $self->id() . ' terminated unexpectedly' .\n" - "($iExitStatus != 255 ? sprintf(' [%03d]', $iExitStatus) : ''),\n" - "$strError);\n" - "}\n" - "}\n" - "}\n" - "while (waitMore($oWait));\n" - "\n" - "if (defined($iCode))\n" - "{\n" - "$self->parent()->error($iCode, $strMessage, $strDetail);\n" - "}\n" - "}\n" - "else\n" - "{\n" - "confess &log(ASSERT, 'cannot call error() after process has been closed');\n" - "}\n" - "}\n" - "\n\n\n\n" - "sub processId\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->{iProcessId};\n" - "}\n" - "\n\n\n\n" - "sub writeLine\n" - "{\n" - "my $self = shift;\n" - "my $strBuffer = shift;\n" - "\n\n\n" - "$self->error();\n" - "\n" - "return $self->parent()->writeLine($strBuffer);\n" - "}\n" - "\n\n\n\n" - "sub close\n" - "{\n" - "my $self = shift;\n" - "\n" - "if (defined($self->{iProcessId}))\n" - "{\n" - "$self->error(undef, undef, undef, true);\n" - "\n\n" - "$self->parent()->close();\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Lock.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Lock;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use Fcntl qw(:DEFAULT :flock);\n" - "use File::Basename qw(dirname);\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::String;\n" - "use pgBackRest::Common::Wait;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Storage::Helper;\n" - "\n\n\n\n\n\n" - "sub lockStopFileName\n" - "{\n" - "my $strStanza = shift;\n" - "\n" - "return cfgOption(CFGOPT_LOCK_PATH) . (defined($strStanza) ? \"/${strStanza}\" : '/all') . '.stop';\n" - "}\n" - "\n\n\n\n\n\n" - "sub lockStopTest\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bStanzaStopRequired,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::lockStopTest', \\@_,\n" - "{name => 'bStanzaStopRequired', optional => true, default => false}\n" - ");\n" - "\n" - "my $bStopExists = false;\n" - "\n\n" - "if (cfgOptionTest(CFGOPT_STANZA))\n" - "{\n" - "\n" - "my $strStopFile = lockStopFileName(cfgOption(CFGOPT_STANZA));\n" - "\n" - "if (-e $strStopFile)\n" - "{\n" - "\n" - "if ($bStanzaStopRequired)\n" - "{\n" - "$bStopExists = true;\n" - "}\n" - "else\n" - "{\n" - "confess &log(ERROR, 'stop file exists for stanza ' . cfgOption(CFGOPT_STANZA), ERROR_STOP);\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "if (!$bStanzaStopRequired)\n" - "{\n" - "\n" - "my $strStopFile = lockStopFileName();\n" - "\n" - "if (-e $strStopFile)\n" - "{\n" - "confess &log(ERROR, 'stop file exists for all stanzas', ERROR_STOP);\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bStopExists', value => $bStopExists}\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(lockStopTest);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Log.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Log;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess longmess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use Fcntl qw(:DEFAULT :flock);\n" - "use File::Basename qw(dirname);\n" - "use Scalar::Util qw(blessed reftype);\n" - "use Time::HiRes qw(gettimeofday usleep);\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::String;\n" - "\n\n\n\n" - "use constant true => 1;\n" - "push @EXPORT, qw(true);\n" - "use constant false => 0;\n" - "push @EXPORT, qw(false);\n" - "\n\n\n\n" - "use constant TRACE => 'TRACE';\n" - "push @EXPORT, qw(TRACE);\n" - "use constant DEBUG => 'DEBUG';\n" - "push @EXPORT, qw(DEBUG);\n" - "use constant DETAIL => 'DETAIL';\n" - "push @EXPORT, qw(DETAIL);\n" - "use constant INFO => 'INFO';\n" - "push @EXPORT, qw(INFO);\n" - "use constant WARN => 'WARN';\n" - "push @EXPORT, qw(WARN);\n" - "use constant PROTOCOL => 'PROTOCOL';\n" - "push @EXPORT, qw(PROTOCOL);\n" - "use constant ERROR => 'ERROR';\n" - "push @EXPORT, qw(ERROR);\n" - "use constant ASSERT => 'ASSERT';\n" - "push @EXPORT, qw(ASSERT);\n" - "use constant OFF => 'OFF';\n" - "push @EXPORT, qw(OFF);\n" - "\n\n\n\n" - "my %oLogLevelRank;\n" - "\n" - "$oLogLevelRank{TRACE}{rank} = 8;\n" - "$oLogLevelRank{DEBUG}{rank} = 7;\n" - "$oLogLevelRank{DETAIL}{rank} = 6;\n" - "$oLogLevelRank{INFO}{rank} = 5;\n" - "$oLogLevelRank{WARN}{rank} = 4;\n" - "$oLogLevelRank{PROTOCOL}{rank} = 3;\n" - "$oLogLevelRank{ERROR}{rank} = 2;\n" - "$oLogLevelRank{ASSERT}{rank} = 1;\n" - "$oLogLevelRank{OFF}{rank} = 0;\n" - "\n\n\n\n" - "my $hLogFile = undef;\n" - "my $strLogFileCache = undef;\n" - "\n" - "my $strLogLevelFile = OFF;\n" - "my $strLogLevelConsole = OFF;\n" - "my $strLogLevelStdErr = WARN;\n" - "my $bLogTimestamp = true;\n" - "\n\n" - "my $iLogProcessSize = 2;\n" - "\n\n" - "my $bLogFileExists;\n" - "my $bLogFileFirst;\n" - "\n\n" - "my $bLogDisable = 0;\n" - "\n\n" - "my $bLogWarnOnError = 0;\n" - "\n\n" - "my $oErrorLast;\n" - "\n\n\n\n" - "sub logFileSet\n" - "{\n" - "my $oStorage = shift;\n" - "my $strFile = shift;\n" - "my $bLogFileFirstParam = shift;\n" - "\n\n" - "if ($strLogLevelFile ne OFF)\n" - "{\n" - "$oStorage->pathCreate(dirname($strFile), {strMode => '0750', bIgnoreExists => true, bCreateParent => true});\n" - "\n" - "$strFile .= '.log';\n" - "$bLogFileExists = -e $strFile ? true : false;\n" - "$bLogFileFirst = defined($bLogFileFirstParam) ? $bLogFileFirstParam : false;\n" - "\n" - "if (!sysopen($hLogFile, $strFile, O_WRONLY | O_CREAT | O_APPEND, oct('0640')))\n" - "{\n" - "logErrorResult(ERROR_FILE_OPEN, \"unable to open log file '${strFile}'\", $OS_ERROR);\n" - "}\n" - "\n\n" - "if (defined($strLogFileCache))\n" - "{\n" - "logBanner();\n" - "syswrite($hLogFile, $strLogFileCache);\n" - "undef($strLogFileCache);\n" - "}\n" - "}\n" - "}\n" - "\n" - "push @EXPORT, qw(logFileSet);\n" - "\n\n\n\n\n\n" - "sub logBanner\n" - "{\n" - "if ($bLogFileFirst)\n" - "{\n" - "if ($bLogFileExists)\n" - "{\n" - "syswrite($hLogFile, \"\\n\");\n" - "}\n" - "\n" - "syswrite($hLogFile, \"-------------------PROCESS START-------------------\\n\");\n" - "}\n" - "\n" - "$bLogFileFirst = false;\n" - "}\n" - "\n\n\n\n" - "sub logLevelSet\n" - "{\n" - "my $strLevelFileParam = shift;\n" - "my $strLevelConsoleParam = shift;\n" - "my $strLevelStdErrParam = shift;\n" - "my $bLogTimestampParam = shift;\n" - "my $iLogProcessMax = shift;\n" - "\n" - "if (defined($strLevelFileParam))\n" - "{\n" - "if (!defined($oLogLevelRank{uc($strLevelFileParam)}{rank}))\n" - "{\n" - "confess &log(ERROR, \"file log level ${strLevelFileParam} does not exist\");\n" - "}\n" - "\n" - "$strLogLevelFile = uc($strLevelFileParam);\n" - "}\n" - "\n" - "if (defined($strLevelConsoleParam))\n" - "{\n" - "if (!defined($oLogLevelRank{uc($strLevelConsoleParam)}{rank}))\n" - "{\n" - "confess &log(ERROR, \"console log level ${strLevelConsoleParam} does not exist\");\n" - "}\n" - "\n" - "$strLogLevelConsole = uc($strLevelConsoleParam);\n" - "}\n" - "\n" - "if (defined($strLevelStdErrParam))\n" - "{\n" - "if (!defined($oLogLevelRank{uc($strLevelStdErrParam)}{rank}))\n" - "{\n" - "confess &log(ERROR, \"stdout log level ${strLevelStdErrParam} does not exist\");\n" - "}\n" - "\n" - "$strLogLevelStdErr = uc($strLevelStdErrParam);\n" - "}\n" - "\n" - "if (defined($bLogTimestampParam))\n" - "{\n" - "$bLogTimestamp = $bLogTimestampParam;\n" - "}\n" - "\n" - "if (defined($iLogProcessMax))\n" - "{\n" - "$iLogProcessSize = $iLogProcessMax > 99 ? 3 : 2;\n" - "}\n" - "}\n" - "\n" - "push @EXPORT, qw(logLevelSet);\n" - "\n\n\n\n" - "sub logDisable\n" - "{\n" - "$bLogDisable++;\n" - "}\n" - "\n" - "push @EXPORT, qw(logDisable);\n" - "\n\n\n\n" - "sub logEnable\n" - "{\n" - "$bLogDisable--;\n" - "}\n" - "\n" - "push @EXPORT, qw(logEnable);\n" - "\n\n\n\n" - "sub logWarnOnErrorDisable\n" - "{\n" - "$bLogWarnOnError--;\n" - "}\n" - "\n" - "push @EXPORT, qw(logWarnOnErrorDisable);\n" - "\n\n\n\n" - "sub logWarnOnErrorEnable\n" - "{\n" - "$bLogWarnOnError++;\n" - "}\n" - "\n" - "push @EXPORT, qw(logWarnOnErrorEnable);\n" - "\n\n\n\n\n\n" - "use constant DEBUG_PARAM => '()';\n" - "\n" - "sub logDebugParam\n" - "{\n" - "my $strFunction = shift;\n" - "my $oyParamRef = shift;\n" - "\n" - "return logDebugProcess($strFunction, DEBUG_PARAM, undef, $oyParamRef, @_);\n" - "}\n" - "\n" - "push @EXPORT, qw(logDebugParam);\n" - "\n\n\n\n\n\n" - "use constant DEBUG_RETURN => '=>';\n" - "\n" - "sub logDebugReturn\n" - "{\n" - "my $strFunction = shift;\n" - "\n" - "return logDebugProcess($strFunction, DEBUG_RETURN, undef, undef, @_);\n" - "}\n" - "\n" - "push @EXPORT, qw(logDebugReturn);\n" - "\n\n\n\n\n\n" - "use constant DEBUG_MISC => '';\n" - "\n" - "sub logDebugMisc\n" - "{\n" - "my $strFunction = shift;\n" - "my $strDetail = shift;\n" - "\n" - "return logDebugProcess($strFunction, DEBUG_MISC, $strDetail, undef, @_);\n" - "}\n" - "\n" - "push @EXPORT, qw(logDebugMisc);\n" - "\n\n\n\n" - "sub logDebugProcess\n" - "{\n" - "my $strFunction = shift;\n" - "my $strType = shift;\n" - "my $strDetail = shift;\n" - "my $oyParamRef = shift;\n" - "\n" - "my $iIndex = 0;\n" - "my $oParamHash = {};\n" - "my @oyResult;\n" - "my $bLogTrace = true;\n" - "\n" - "if ($strType eq DEBUG_PARAM)\n" - "{\n" - "push @oyResult, $strFunction;\n" - "}\n" - "\n\n" - "my $oParam = shift;\n" - "my $bOptionalBlock = false;\n" - "\n\n" - "$strFunction =~ s/^pgBackRest[^\\:]*\\:\\://;\n" - "\n" - "while (defined($oParam))\n" - "{\n" - "my $strParamName = $$oParam{name};\n" - "my $bParamOptional = defined($oParam->{optional}) && $oParam->{optional};\n" - "my $bParamRequired = !defined($oParam->{required}) || $oParam->{required};\n" - "my $oValue;\n" - "\n\n" - "$oParamHash->{$strParamName}{redact} = $oParam->{redact} ? true : false;\n" - "\n\n" - "if ($bParamOptional)\n" - "{\n" - "if (defined($oParam->{required}))\n" - "{\n" - "confess &log(ASSERT, \"cannot define 'required' for optional parameter '${strParamName}'\");\n" - "}\n" - "\n" - "$bParamRequired = false;\n" - "$bOptionalBlock = true;\n" - "}\n" - "\n\n" - "if ($bParamOptional != $bOptionalBlock)\n" - "{\n" - "confess &log(ASSERT, \"non-optional parameter '${strParamName}' invalid after optional parameters\");\n" - "}\n" - "\n\n" - "if ($strType eq DEBUG_PARAM)\n" - "{\n" - "if ($bParamOptional)\n" - "{\n" - "$oValue = $$oyParamRef[$iIndex]->{$strParamName};\n" - "}\n" - "else\n" - "{\n" - "$oValue = $$oyParamRef[$iIndex];\n" - "}\n" - "\n" - "if (defined($oValue))\n" - "{\n" - "push(@oyResult, $oValue);\n" - "}\n" - "else\n" - "{\n" - "push(@oyResult, $${oParam}{default});\n" - "$$oParamHash{$strParamName}{default} = true;\n" - "}\n" - "\n" - "$oValue = $oyResult[-1];\n" - "\n" - "if (!defined($oValue) && $bParamRequired)\n" - "{\n" - "confess &log(ASSERT, \"${strParamName} is required in ${strFunction}\");\n" - "}\n" - "}\n" - "else\n" - "{\n" - "if (ref($$oParam{value}) eq 'ARRAY')\n" - "{\n" - "if (defined($$oParam{ref}) && $$oParam{ref})\n" - "{\n" - "push(@oyResult, $$oParam{value});\n" - "}\n" - "else\n" - "{\n" - "push(@oyResult, @{$$oParam{value}});\n" - "}\n" - "}\n" - "else\n" - "{\n" - "push(@oyResult, $$oParam{value});\n" - "}\n" - "\n" - "$oValue = $$oParam{value};\n" - "}\n" - "\n" - "if (!defined($$oParam{log}) || $$oParam{log})\n" - "{\n" - "\n\n" - "if (ref($oValue) eq 'HASH' && !blessed($oValue))\n" - "{\n" - "$$oParamHash{$strParamName}{value} = '[hash]';\n" - "}\n" - "\n" - "else\n" - "{\n" - "$$oParamHash{$strParamName}{value} = $oValue;\n" - "}\n" - "\n\n" - "if (!($strParamName eq 'self') &&\n" - "(!defined($$oParam{trace}) || !$$oParam{trace}))\n" - "{\n" - "$bLogTrace = false;\n" - "}\n" - "}\n" - "\n\n" - "$oParam = shift;\n" - "\n" - "if (!$bParamOptional)\n" - "{\n" - "$iIndex++;\n" - "}\n" - "}\n" - "\n" - "if (defined($strDetail) && $iIndex == 0)\n" - "{\n" - "$bLogTrace = false;\n" - "}\n" - "\n" - "logDebugOut($strFunction, $strType, $strDetail, $oParamHash, $bLogTrace ? TRACE : DEBUG);\n" - "\n\n" - "if (@oyResult == 1)\n" - "{\n" - "return $oyResult[0];\n" - "}\n" - "\n\n" - "return @oyResult;\n" - "}\n" - "\n\n\n\n" - "sub logDebugBuild\n" - "{\n" - "my $strValue = shift;\n" - "\n" - "my $rResult;\n" - "\n\n" - "if (!defined($strValue))\n" - "{\n" - "$rResult = \\'[undef]';\n" - "}\n" - "\n" - "elsif (!ref($strValue))\n" - "{\n" - "$rResult = \\$strValue;\n" - "}\n" - "\n" - "elsif (ref($strValue) eq 'HASH')\n" - "{\n" - "my $strValueHash;\n" - "\n" - "for my $strSubValue (sort(keys(%{$strValue})))\n" - "{\n" - "$strValueHash .=\n" - "(defined($strValueHash) ? ', ' : '{') . \"${strSubValue} => \" . ${logDebugBuild($strValue->{$strSubValue})};\n" - "}\n" - "\n" - "$rResult = \\(defined($strValueHash) ? $strValueHash . '}' : '{}');\n" - "}\n" - "\n" - "elsif (ref($strValue) eq 'ARRAY')\n" - "{\n" - "my $strValueArray;\n" - "\n" - "for my $strSubValue (@{$strValue})\n" - "{\n" - "$strValueArray .= (defined($strValueArray) ? ', ' : '(') . ${logDebugBuild($strSubValue)};\n" - "}\n" - "\n" - "$rResult = \\(defined($strValueArray) ? $strValueArray . ')' : '()');\n" - "}\n" - "\n" - "else\n" - "{\n" - "$rResult = \\('[object]');\n" - "}\n" - "\n" - "return $rResult;\n" - "}\n" - "\n" - "push @EXPORT, qw(logDebugBuild);\n" - "\n\n\n\n" - "use constant DEBUG_STRING_MAX_LEN => 1024;\n" - "\n" - "sub logDebugOut\n" - "{\n" - "my $strFunction = shift;\n" - "my $strType = shift;\n" - "my $strMessage = shift;\n" - "my $oParamHash = shift;\n" - "my $strLevel = shift;\n" - "\n" - "$strLevel = defined($strLevel) ? $strLevel : DEBUG;\n" - "\n" - "if ($oLogLevelRank{$strLevel}{rank} <= $oLogLevelRank{$strLogLevelConsole}{rank} ||\n" - "$oLogLevelRank{$strLevel}{rank} <= $oLogLevelRank{$strLogLevelFile}{rank} ||\n" - "$oLogLevelRank{$strLevel}{rank} <= $oLogLevelRank{$strLogLevelStdErr}{rank})\n" - "{\n" - "if (defined($oParamHash))\n" - "{\n" - "my $strParamSet;\n" - "\n" - "foreach my $strParam (sort(keys(%$oParamHash)))\n" - "{\n" - "if (defined($strParamSet))\n" - "{\n" - "$strParamSet .= ', ';\n" - "}\n" - "\n" - "my $strValueRef = defined($oParamHash->{$strParam}{value}) ? logDebugBuild($oParamHash->{$strParam}{value}) : undef;\n" - "my $bDefault =\n" - "defined($$strValueRef) && defined($$oParamHash{$strParam}{default}) ? $$oParamHash{$strParam}{default} : false;\n" - "\n" - "$strParamSet .=\n" - "\"${strParam} = \" .\n" - "($oParamHash->{$strParam}{redact} && defined($$strValueRef) ? '' :\n" - "($bDefault ? '<' : '') .\n" - "(defined($$strValueRef) ?\n" - "($strParam =~ /^(b|is)/ ? ($$strValueRef ? 'true' : 'false'):\n" - "(length($$strValueRef) > DEBUG_STRING_MAX_LEN ?\n" - "substr($$strValueRef, 0, DEBUG_STRING_MAX_LEN) . ' ... ':\n" - "$$strValueRef)) : '[undef]') .\n" - "($bDefault ? '>' : ''));\n" - "}\n" - "\n" - "if (defined($strMessage))\n" - "{\n" - "$strMessage = $strMessage . (defined($strParamSet) ? \": ${strParamSet}\" : '');\n" - "}\n" - "else\n" - "{\n" - "$strMessage = $strParamSet;\n" - "}\n" - "}\n" - "\n" - "&log($strLevel, \"${strFunction}${strType}\" . (defined($strMessage) ? \": $strMessage\" : ''));\n" - "}\n" - "}\n" - "\n\n\n\n" - "sub logException\n" - "{\n" - "my $oException = shift;\n" - "\n" - "return &log($oException->level(), $oException->message(), $oException->code(), undef, undef, undef, $oException->extra());\n" - "}\n" - "\n" - "push @EXPORT, qw(logException);\n" - "\n\n\n\n" - "sub logErrorResult\n" - "{\n" - "my $iCode = shift;\n" - "my $strMessage = shift;\n" - "my $strResult = shift;\n" - "\n" - "confess &log(ERROR, $strMessage . (defined($strResult) ? ': ' . trim($strResult) : ''), $iCode);\n" - "}\n" - "\n" - "push @EXPORT, qw(logErrorResult);\n" - "\n\n\n\n" - "sub log\n" - "{\n" - "my $strLevel = shift;\n" - "my $strMessage = shift;\n" - "my $iCode = shift;\n" - "my $bSuppressLog = shift;\n" - "my $iIndent = shift;\n" - "my $iProcessId = shift;\n" - "my $rExtra = shift;\n" - "\n\n" - "$bSuppressLog = defined($bSuppressLog) ? $bSuppressLog : false;\n" - "\n\n" - "if (!defined($rExtra))\n" - "{\n" - "$rExtra =\n" - "{\n" - "bLogFile => false,\n" - "bLogConsole => false,\n" - "};\n" - "}\n" - "\n\n" - "my $strMessageFormat = $strMessage;\n" - "my $iLogLevelRank = $oLogLevelRank{$strLevel}{rank};\n" - "\n\n" - "if (!defined($iLogLevelRank))\n" - "{\n" - "confess &log(ASSERT, \"log level ${strLevel} does not exist\");\n" - "}\n" - "\n\n" - "if (!defined($strMessageFormat))\n" - "{\n" - "$strMessageFormat = '(undefined)';\n" - "}\n" - "\n\n" - "if ($strLevel eq ASSERT)\n" - "{\n" - "$iCode = ERROR_ASSERT;\n" - "}\n" - "elsif ($strLevel eq ERROR && !defined($iCode))\n" - "{\n" - "$iCode = ERROR_UNKNOWN;\n" - "}\n" - "\n" - "$strMessageFormat = (defined($iCode) ? sprintf('[%03d]: ', $iCode) : '') . $strMessageFormat;\n" - "\n\n" - "if (defined($iIndent))\n" - "{\n" - "my $strIndent = ' ' x $iIndent;\n" - "$strMessageFormat =~ s/\\n/\\n${strIndent}/g;\n" - "}\n" - "else\n" - "{\n" - "\n" - "$bLogTimestamp ?\n" - "$strMessageFormat =~ s/\\n/\\n /g :\n" - "$strMessageFormat =~ s/\\n/\\n /g\n" - "}\n" - "\n\n" - "if ($strLevel eq TRACE)\n" - "{\n" - "$strMessageFormat =~ s/\\n/\\n /g;\n" - "$strMessageFormat = ' ' . $strMessageFormat;\n" - "}\n" - "elsif ($strLevel eq DEBUG)\n" - "{\n" - "$strMessageFormat =~ s/\\n/\\n /g;\n" - "$strMessageFormat = ' ' . $strMessageFormat;\n" - "}\n" - "\n\n" - "my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);\n" - "\n\n\n" - "my $strDisplayLevel = ($bLogWarnOnError && $strLevel eq ERROR ? WARN : $strLevel);\n" - "my $iLogDisplayLevelRank = ($bLogWarnOnError && $strLevel eq ERROR ? $oLogLevelRank{$strDisplayLevel}{rank} : $iLogLevelRank);\n" - "\n" - "$strMessageFormat =\n" - "($bLogTimestamp ? timestampFormat() . sprintf('.%03d ', (gettimeofday() - int(gettimeofday())) * 1000) : '') .\n" - "sprintf('P%0*d', $iLogProcessSize, defined($iProcessId) ? $iProcessId : 0) .\n" - "(' ' x (7 - length($strDisplayLevel))) . \"${strDisplayLevel}: ${strMessageFormat}\\n\";\n" - "\n\n" - "if (!$bLogDisable)\n" - "{\n" - "\n" - "if (!$rExtra->{bLogConsole} && $iLogDisplayLevelRank <= $oLogLevelRank{$strLogLevelStdErr}{rank})\n" - "{\n" - "if ($strLogLevelStdErr ne PROTOCOL)\n" - "{\n" - "syswrite(*STDERR, $strDisplayLevel . (defined($iCode) ? sprintf(' [%03d]: ', $iCode) : '') . ': ');\n" - "}\n" - "\n" - "syswrite(*STDERR, \"${strMessage}\\n\");\n" - "$rExtra->{bLogConsole} = true;\n" - "}\n" - "\n" - "elsif (!$rExtra->{bLogConsole} && $iLogDisplayLevelRank <= $oLogLevelRank{$strLogLevelConsole}{rank})\n" - "{\n" - "if (!$bSuppressLog)\n" - "{\n" - "syswrite(*STDOUT, $strMessageFormat);\n" - "\n\n\n\n\n\n\n\n" - "}\n" - "\n" - "$rExtra->{bLogConsole} = true;\n" - "}\n" - "\n\n" - "if (!$rExtra->{bLogLogFile} && $iLogDisplayLevelRank <= $oLogLevelRank{$strLogLevelFile}{rank})\n" - "{\n" - "if (defined($hLogFile) || (defined($strLogLevelFile) && $strLogLevelFile ne OFF))\n" - "{\n" - "if (!$bSuppressLog)\n" - "{\n" - "if (defined($hLogFile))\n" - "{\n" - "logBanner();\n" - "syswrite($hLogFile, $strMessageFormat);\n" - "}\n" - "else\n" - "{\n" - "$strLogFileCache .= $strMessageFormat;\n" - "}\n" - "\n" - "if ($strDisplayLevel eq ASSERT ||\n" - "($strDisplayLevel eq ERROR && ($strLogLevelFile eq DEBUG || $strLogLevelFile eq TRACE)))\n" - "{\n" - "my $strStackTrace = longmess() . \"\\n\";\n" - "$strStackTrace =~ s/\\n/\\n /g;\n" - "\n" - "if (defined($hLogFile))\n" - "{\n" - "syswrite($hLogFile, $strStackTrace);\n" - "}\n" - "else\n" - "{\n" - "$strLogFileCache .= $strStackTrace;\n" - "}\n" - "}\n" - "}\n" - "}\n" - "\n" - "$rExtra->{bLogFile} = true;\n" - "}\n" - "}\n" - "\n\n" - "if (defined($iCode))\n" - "{\n" - "$oErrorLast = new pgBackRest::Common::Exception($strLevel, $iCode, $strMessage, longmess(), $rExtra);\n" - "return $oErrorLast;\n" - "}\n" - "\n\n" - "return $strMessage;\n" - "}\n" - "\n" - "push @EXPORT, qw(log);\n" - "\n\n\n\n" - "sub logErrorLast\n" - "{\n" - "return $oErrorLast;\n" - "}\n" - "\n" - "push @EXPORT, qw(logErrorLast);\n" - "\n\n\n\n" - "sub logLevel\n" - "{\n" - "return ($strLogLevelFile, $strLogLevelConsole, $strLogLevelStdErr, $bLogTimestamp);\n" - "}\n" - "\n" - "push @EXPORT, qw(logLevel);\n" - "\n\n\n\n" - "sub logFileCacheClear\n" - "{\n" - "undef($strLogFileCache);\n" - "}\n" - "\n" - "push @EXPORT, qw(logFileCacheClear);\n" - "\n\n\n\n" - "sub logFileCache\n" - "{\n" - "return $strLogFileCache;\n" - "}\n" - "\n" - "push @EXPORT, qw(logFileCache);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/String.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::String;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess longmess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename qw(dirname);\n" - "\n\n\n\n\n\n" - "sub trim\n" - "{\n" - "my $strBuffer = shift;\n" - "\n" - "if (!defined($strBuffer))\n" - "{\n" - "return;\n" - "}\n" - "\n" - "$strBuffer =~ s/^\\s+|\\s+$//g;\n" - "\n" - "return $strBuffer;\n" - "}\n" - "\n" - "push @EXPORT, qw(trim);\n" - "\n\n\n\n" - "sub coalesce\n" - "{\n" - "foreach my $strParam (@_)\n" - "{\n" - "if (defined($strParam))\n" - "{\n" - "return $strParam;\n" - "}\n" - "}\n" - "\n" - "return;\n" - "}\n" - "\n" - "push @EXPORT, qw(coalesce);\n" - "\n\n\n\n\n\n" - "sub commonPrefix\n" - "{\n" - "my $strString1 = shift;\n" - "my $strString2 = shift;\n" - "\n" - "my $iCommonLen = 0;\n" - "my $iCompareLen = length($strString1) < length($strString2) ? length($strString1) : length($strString2);\n" - "\n" - "for (my $iIndex = 0; $iIndex < $iCompareLen; $iIndex++)\n" - "{\n" - "if (substr($strString1, $iIndex, 1) ne substr($strString2, $iIndex, 1))\n" - "{\n" - "last;\n" - "}\n" - "\n" - "$iCommonLen++;\n" - "}\n" - "\n" - "return $iCommonLen;\n" - "}\n" - "\n" - "push @EXPORT, qw(commonPrefix);\n" - "\n\n\n\n\n\n" - "sub boolFormat\n" - "{\n" - "return shift() ? 'true' : 'false';\n" - "}\n" - "\n" - "push @EXPORT, qw(boolFormat);\n" - "\n\n\n\n\n\n" - "sub fileSizeFormat\n" - "{\n" - "my $lFileSize = shift;\n" - "\n" - "if ($lFileSize < 1024)\n" - "{\n" - "return $lFileSize . 'B';\n" - "}\n" - "\n" - "if ($lFileSize < (1024 * 1024))\n" - "{\n" - "return (int($lFileSize / 102.4) / 10) . 'KB';\n" - "}\n" - "\n" - "if ($lFileSize < (1024 * 1024 * 1024))\n" - "{\n" - "return (int($lFileSize / 1024 / 102.4) / 10) . 'MB';\n" - "}\n" - "\n" - "return (int($lFileSize / 1024 / 1024 / 102.4) / 10) . 'GB';\n" - "}\n" - "\n" - "push @EXPORT, qw(fileSizeFormat);\n" - "\n\n\n\n\n\n" - "sub timestampFormat\n" - "{\n" - "my $strFormat = shift;\n" - "my $lTime = shift;\n" - "\n" - "if (!defined($strFormat))\n" - "{\n" - "$strFormat = '%4d-%02d-%02d %02d:%02d:%02d';\n" - "}\n" - "\n" - "if (!defined($lTime))\n" - "{\n" - "$lTime = time();\n" - "}\n" - "\n" - "my ($iSecond, $iMinute, $iHour, $iMonthDay, $iMonth, $iYear, $iWeekDay, $iYearDay, $bIsDst) = localtime($lTime);\n" - "\n" - "if ($strFormat eq \"%4d\")\n" - "{\n" - "return sprintf($strFormat, $iYear + 1900)\n" - "}\n" - "else\n" - "{\n" - "return sprintf($strFormat, $iYear + 1900, $iMonth + 1, $iMonthDay, $iHour, $iMinute, $iSecond);\n" - "}\n" - "}\n" - "\n" - "push @EXPORT, qw(timestampFormat);\n" - "\n\n\n\n" - "sub timestampFileFormat\n" - "{\n" - "my $strFormat = shift;\n" - "my $lTime = shift;\n" - "\n" - "return timestampFormat(defined($strFormat) ? $strFormat : '%4d%02d%02d-%02d%02d%02d', $lTime);\n" - "}\n" - "\n" - "push @EXPORT, qw(timestampFileFormat);\n" - "\n\n\n\n" - "sub stringSplit\n" - "{\n" - "my $strString = shift;\n" - "my $strChar = shift;\n" - "my $iLength = shift;\n" - "\n" - "if (length($strString) <= $iLength)\n" - "{\n" - "return $strString, undef;\n" - "}\n" - "\n" - "my $iPos = index($strString, $strChar);\n" - "\n" - "if ($iPos == -1)\n" - "{\n" - "return $strString, undef;\n" - "}\n" - "\n" - "my $iNewPos = $iPos;\n" - "\n" - "while ($iNewPos != -1 && $iNewPos + 1 < $iLength)\n" - "{\n" - "$iPos = $iNewPos;\n" - "$iNewPos = index($strString, $strChar, $iPos + 1);\n" - "}\n" - "\n" - "return substr($strString, 0, $iPos + 1), substr($strString, $iPos + 1);\n" - "}\n" - "\n" - "push @EXPORT, qw(stringSplit);\n" - "\n\n\n\n\n\n" - "sub regexPrefix\n" - "{\n" - "my $strExpression = shift;\n" - "my $strPrefix;\n" - "\n\n" - "if (defined($strExpression) && $strExpression =~ /^\\^/)\n" - "{\n" - "($strPrefix) = substr($strExpression, 1) =~ /^[^\\.\\^\\$\\*\\+\\-\\?\\(\\)\\[\\]\\{\\}\\\\\\|\\ ]+/g;\n" - "}\n" - "\n" - "return $strPrefix;\n" - "}\n" - "\n" - "push @EXPORT, qw(regexPrefix);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Common/Wait.pm", - .data = - "\n\n\n" - "package pgBackRest::Common::Wait;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename qw(dirname);\n" - "use POSIX qw(ceil);\n" - "use Time::HiRes qw(gettimeofday usleep);\n" - "\n" - "use pgBackRest::Common::Log;\n" - "\n\n\n\n" - "use constant WAIT_TIME_MINIMUM => .1;\n" - "push @EXPORT, qw(WAIT_TIME_MINIMUM);\n" - "\n\n\n\n" - "sub waitRemainder\n" - "{\n" - "my $bWait = shift;\n" - "\n" - "my $lTimeBegin = gettimeofday();\n" - "\n" - "if (!defined($bWait) || $bWait)\n" - "{\n" - "my $lSleepMs = ceil(((int($lTimeBegin) + 1.05) - $lTimeBegin) * 1000);\n" - "\n" - "usleep($lSleepMs * 1000);\n" - "\n" - "&log(TRACE, \"WAIT_REMAINDER: slept ${lSleepMs}ms: begin ${lTimeBegin}, end \" . gettimeofday());\n" - "}\n" - "\n" - "return int($lTimeBegin);\n" - "}\n" - "\n" - "push @EXPORT, qw(waitRemainder);\n" - "\n\n\n\n" - "sub waitHiRes\n" - "{\n" - "my $fSecond = shift;\n" - "\n" - "return usleep($fSecond * 1000000);\n" - "}\n" - "\n" - "push @EXPORT, qw(waitHiRes);\n" - "\n\n\n\n" - "sub waitInit\n" - "{\n" - "my $fWaitTime = shift;\n" - "my $fSleep = shift;\n" - "\n\n" - "my $oWait = {};\n" - "\n\n" - "if (!defined($fWaitTime) || $fWaitTime == 0)\n" - "{\n" - "return;\n" - "}\n" - "\n\n" - "if ($fWaitTime < .1)\n" - "{\n" - "confess &log(ASSERT, 'fWaitTime cannot be < .1');\n" - "}\n" - "\n\n" - "if (!defined($fSleep))\n" - "{\n" - "if ($fWaitTime >= 1)\n" - "{\n" - "$$oWait{sleep} = .1;\n" - "}\n" - "else\n" - "{\n" - "$$oWait{sleep} = $fWaitTime / 10;\n" - "}\n" - "}\n" - "\n" - "else\n" - "{\n" - "\n" - "if ($fSleep >= $fWaitTime)\n" - "{\n" - "confess &log(ASSERT, 'fSleep > fWaitTime - this is useless');\n" - "}\n" - "}\n" - "\n\n" - "$$oWait{wait_time} = $fWaitTime;\n" - "$$oWait{time_begin} = gettimeofday();\n" - "$$oWait{time_end} = $$oWait{time_begin};\n" - "\n" - "return $oWait;\n" - "}\n" - "\n" - "push @EXPORT, qw(waitInit);\n" - "\n\n\n\n" - "sub waitMore\n" - "{\n" - "my $oWait = shift;\n" - "\n\n" - "if (!defined($oWait))\n" - "{\n" - "return false;\n" - "}\n" - "\n\n" - "waitHiRes($$oWait{sleep});\n" - "\n\n" - "$$oWait{time_end} = gettimeofday();\n" - "\n\n" - "if ((gettimeofday() - $$oWait{time_begin}) < $$oWait{wait_time})\n" - "{\n" - "return true;\n" - "}\n" - "\n\n" - "my $fSleepNext = $$oWait{sleep} + (defined($$oWait{sleep_prev}) ? $$oWait{sleep_prev} : 0);\n" - "\n" - "if ($fSleepNext > $$oWait{wait_time} - ($$oWait{time_end} - $$oWait{time_begin}))\n" - "{\n" - "$fSleepNext = ($$oWait{wait_time} - ($$oWait{time_end} - $$oWait{time_begin})) + .001\n" - "}\n" - "\n" - "$$oWait{sleep_prev} = $$oWait{sleep};\n" - "$$oWait{sleep} = $fSleepNext;\n" - "\n" - "return false;\n" - "}\n" - "\n" - "push @EXPORT, qw(waitMore);\n" - "\n\n\n\n" - "sub waitInterval\n" - "{\n" - "my $oWait = shift;\n" - "\n\n" - "if (!defined($oWait))\n" - "{\n" - "confess &log(ERROR, \"oWait is not defined\");\n" - "}\n" - "\n" - "return int(($$oWait{time_end} - $$oWait{time_begin}) * 1000) / 1000;\n" - "}\n" - "\n" - "push @EXPORT, qw(waitInterval);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Config/Config.pm", - .data = - "\n\n\n" - "package pgBackRest::Config::Config;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use JSON::PP;\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Ini;\n" - "use pgBackRest::Common::Io::Base;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::String;\n" - "use pgBackRest::Common::Wait;\n" - "use pgBackRest::LibC qw(:config :configDefine);\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "push(@EXPORT, @{$pgBackRest::LibC::EXPORT_TAGS{config}});\n" - "push(@EXPORT, @{$pgBackRest::LibC::EXPORT_TAGS{configDefine}});\n" - "\n\n\n\n" - "use constant CFGDEF_SOURCE_CONFIG => 'config';\n" - "push @EXPORT, qw(CFGDEF_SOURCE_CONFIG);\n" - "use constant CFGDEF_SOURCE_PARAM => 'param';\n" - "push @EXPORT, qw(CFGDEF_SOURCE_PARAM);\n" - "use constant CFGDEF_SOURCE_DEFAULT => 'default';\n" - "push @EXPORT, qw(CFGDEF_SOURCE_DEFAULT);\n" - "\n\n\n\n" - "use constant CFGDEF_SECTION_GLOBAL => 'global';\n" - "push @EXPORT, qw(CFGDEF_SECTION_GLOBAL);\n" - "use constant CFGDEF_SECTION_STANZA => 'stanza';\n" - "push @EXPORT, qw(CFGDEF_SECTION_STANZA);\n" - "\n\n\n\n" - "my %oOption;\n" - "my $strCommand;\n" - "my $bInitLog = false;\n" - "\n\n\n\n" - "sub configLogging\n" - "{\n" - "my $bLogInitForce = shift;\n" - "\n" - "if ($bInitLog || (defined($bLogInitForce) && $bLogInitForce))\n" - "{\n" - "logLevelSet(\n" - "cfgOptionValid(CFGOPT_LOG_LEVEL_FILE) ? cfgOption(CFGOPT_LOG_LEVEL_FILE) : OFF,\n" - "cfgOptionValid(CFGOPT_LOG_LEVEL_CONSOLE) ? cfgOption(CFGOPT_LOG_LEVEL_CONSOLE) : OFF,\n" - "cfgOptionValid(CFGOPT_LOG_LEVEL_STDERR) ? cfgOption(CFGOPT_LOG_LEVEL_STDERR) : OFF,\n" - "cfgOptionValid(CFGOPT_LOG_TIMESTAMP) ? cfgOption(CFGOPT_LOG_TIMESTAMP) : undef,\n" - "cfgOptionValid(CFGOPT_PROCESS_MAX) ? cfgOption(CFGOPT_PROCESS_MAX) : undef);\n" - "\n" - "$bInitLog = true;\n" - "}\n" - "}\n" - "\n" - "push @EXPORT, qw(configLogging);\n" - "\n\n\n\n\n\n" - "sub configLoad\n" - "{\n" - "my $bInitLogging = shift;\n" - "my $strBackRestBin = shift;\n" - "my $strCommandName = shift;\n" - "my $rstrConfigJson = shift;\n" - "\n\n" - "projectBinSet($strBackRestBin);\n" - "\n\n" - "$strCommand = $strCommandName;\n" - "\n" - "eval\n" - "{\n" - "%oOption = %{(JSON::PP->new()->allow_nonref())->decode($$rstrConfigJson)};\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "confess &log(ASSERT, \"unable to parse config JSON\");\n" - "};\n" - "\n\n" - "for (my $iOptionId = 0; $iOptionId < cfgOptionTotal(); $iOptionId++)\n" - "{\n" - "my $strOptionName = cfgOptionName($iOptionId);\n" - "\n\n" - "if (defined($oOption{$strOptionName}))\n" - "{\n" - "\n" - "if (cfgDefOptionType($iOptionId) eq CFGDEF_TYPE_BOOLEAN && defined($oOption{$strOptionName}{value}))\n" - "{\n" - "$oOption{$strOptionName}{value} = $oOption{$strOptionName}{value} eq INI_TRUE ? true : false;\n" - "}\n" - "}\n" - "\n" - "else\n" - "{\n" - "$oOption{$strOptionName}{valid} = false;\n" - "}\n" - "}\n" - "\n\n\n\n" - "if (!defined($bInitLogging) || $bInitLogging)\n" - "{\n" - "configLogging(true);\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "\n" - "push @EXPORT, qw(configLoad);\n" - "\n\n\n\n" - "sub cfgOptionIdFromIndex\n" - "{\n" - "my $iOptionId = shift;\n" - "my $iIndex = shift;\n" - "\n\n" - "$iIndex = defined($iIndex) ? $iIndex : 1;\n" - "my $strPrefix = cfgDefOptionPrefix($iOptionId);\n" - "\n" - "if (!defined($strPrefix))\n" - "{\n" - "if ($iIndex > 1)\n" - "{\n" - "confess &log(ASSERT, \"'\" . cfgOptionName($iOptionId) . \"' option does not allow indexing\");\n" - "}\n" - "\n" - "return $iOptionId;\n" - "}\n" - "\n" - "return cfgOptionId(\"${strPrefix}${iIndex}\" . substr(cfgOptionName($iOptionId), index(cfgOptionName($iOptionId), '-')));\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgOptionIdFromIndex);\n" - "\n\n\n\n" - "sub cfgOptionSource\n" - "{\n" - "my $iOptionId = shift;\n" - "\n" - "cfgOptionValid($iOptionId, true);\n" - "\n" - "return $oOption{cfgOptionName($iOptionId)}{source};\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgOptionSource);\n" - "\n\n\n\n" - "sub cfgOptionValid\n" - "{\n" - "my $iOptionId = shift;\n" - "my $bError = shift;\n" - "\n\n" - "my $iCommandId;\n" - "\n" - "if (defined($strCommand))\n" - "{\n" - "$iCommandId = cfgCommandId($strCommand);\n" - "}\n" - "\n" - "if (defined($iCommandId) && cfgDefOptionValid($iCommandId, $iOptionId))\n" - "{\n" - "return true;\n" - "}\n" - "\n" - "if (defined($bError) && $bError)\n" - "{\n" - "my $strOption = cfgOptionName($iOptionId);\n" - "\n" - "if (!defined($oOption{$strOption}))\n" - "{\n" - "confess &log(ASSERT, \"option '${strOption}' does not exist\");\n" - "}\n" - "\n" - "confess &log(ASSERT, \"option '${strOption}' not valid for command '\" . cfgCommandName(cfgCommandGet()) . \"'\");\n" - "}\n" - "\n" - "return false;\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgOptionValid);\n" - "\n\n\n\n" - "sub cfgOption\n" - "{\n" - "my $iOptionId = shift;\n" - "my $bRequired = shift;\n" - "\n" - "cfgOptionValid($iOptionId, true);\n" - "\n" - "my $strOption = cfgOptionName($iOptionId);\n" - "\n" - "if (!defined($oOption{$strOption}{value}) && (!defined($bRequired) || $bRequired))\n" - "{\n" - "confess &log(ASSERT, \"option ${strOption} is required\");\n" - "}\n" - "\n" - "return $oOption{$strOption}{value};\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgOption);\n" - "\n\n\n\n" - "sub cfgOptionDefault\n" - "{\n" - "my $iOptionId = shift;\n" - "\n" - "cfgOptionValid($iOptionId, true);\n" - "\n" - "return cfgDefOptionDefault(cfgCommandId($strCommand), $iOptionId);\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgOptionDefault);\n" - "\n\n\n\n" - "sub cfgOptionSet\n" - "{\n" - "my $iOptionId = shift;\n" - "my $oValue = shift;\n" - "my $bForce = shift;\n" - "\n" - "my $strOption = cfgOptionName($iOptionId);\n" - "\n" - "if (!cfgOptionValid($iOptionId, !defined($bForce) || !$bForce))\n" - "{\n" - "$oOption{$strOption}{valid} = true;\n" - "}\n" - "\n" - "$oOption{$strOption}{source} = CFGDEF_SOURCE_PARAM;\n" - "$oOption{$strOption}{value} = $oValue;\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgOptionSet);\n" - "\n\n\n\n" - "sub cfgOptionTest\n" - "{\n" - "my $iOptionId = shift;\n" - "my $strValue = shift;\n" - "\n" - "if (!cfgOptionValid($iOptionId))\n" - "{\n" - "return false;\n" - "}\n" - "\n" - "if (defined($strValue))\n" - "{\n" - "return cfgOption($iOptionId) eq $strValue ? true : false;\n" - "}\n" - "\n" - "return defined($oOption{cfgOptionName($iOptionId)}{value}) ? true : false;\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgOptionTest);\n" - "\n\n\n\n" - "sub cfgCommandGet\n" - "{\n" - "return cfgCommandId($strCommand);\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgCommandGet);\n" - "\n\n\n\n" - "sub cfgCommandTest\n" - "{\n" - "my $iCommandIdTest = shift;\n" - "\n" - "return cfgCommandName($iCommandIdTest) eq $strCommand;\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgCommandTest);\n" - "\n\n\n\n" - "sub cfgCommandSet\n" - "{\n" - "my $iCommandId = shift;\n" - "\n" - "$strCommand = cfgCommandName($iCommandId);\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgCommandSet);\n" - "\n\n\n\n\n\n" - "sub cfgCommandWrite\n" - "{\n" - "my $iNewCommandId = shift;\n" - "my $bIncludeConfig = shift;\n" - "my $strExeString = shift;\n" - "my $bIncludeCommand = shift;\n" - "my $oOptionOverride = shift;\n" - "my $bDisplayOnly = shift;\n" - "\n\n" - "$strExeString = defined($strExeString) ? $strExeString : projectBin();\n" - "$bIncludeConfig = defined($bIncludeConfig) ? $bIncludeConfig : false;\n" - "$bIncludeCommand = defined($bIncludeCommand) ? $bIncludeCommand : true;\n" - "\n\n" - "for (my $iOptionId = 0; $iOptionId < cfgOptionTotal(); $iOptionId++)\n" - "{\n" - "my $strOption = cfgOptionName($iOptionId);\n" - "my $bSecure = cfgDefOptionSecure($iOptionId);\n" - "\n\n" - "next if (($bSecure || $iOptionId == CFGOPT_REPO_CIPHER_TYPE) && !$bDisplayOnly);\n" - "\n\n" - "if (defined($oOptionOverride->{$iOptionId}))\n" - "{\n" - "if (defined($oOptionOverride->{$iOptionId}{value}))\n" - "{\n" - "$strExeString .= cfgCommandWriteOptionFormat(\n" - "$strOption, false, $bSecure, {value => $oOptionOverride->{$iOptionId}{value}});\n" - "}\n" - "}\n" - "\n" - "elsif (defined($oOptionOverride->{$strOption}))\n" - "{\n" - "if (defined($oOptionOverride->{$strOption}{value}))\n" - "{\n" - "$strExeString .= cfgCommandWriteOptionFormat(\n" - "$strOption, false, $bSecure, {value => $oOptionOverride->{$strOption}{value}});\n" - "}\n" - "}\n" - "\n" - "elsif (cfgDefOptionValid($iNewCommandId, $iOptionId) &&\n" - "defined($oOption{$strOption}{value}) &&\n" - "($bIncludeConfig ?\n" - "$oOption{$strOption}{source} ne CFGDEF_SOURCE_DEFAULT : $oOption{$strOption}{source} eq CFGDEF_SOURCE_PARAM))\n" - "{\n" - "my $oValue;\n" - "my $bMulti = false;\n" - "\n\n" - "if (ref($oOption{$strOption}{value}) eq 'HASH')\n" - "{\n" - "$oValue = $oOption{$strOption}{value};\n" - "$bMulti = true;\n" - "}\n" - "\n" - "else\n" - "{\n" - "$oValue = {value => $oOption{$strOption}{value}};\n" - "}\n" - "\n" - "$strExeString .= cfgCommandWriteOptionFormat($strOption, $bMulti, $bSecure, $oValue);\n" - "}\n" - "\n" - "elsif (cfgDefOptionValid($iNewCommandId, $iOptionId) && $oOption{$strOption}{reset})\n" - "{\n" - "$strExeString .= \" --reset-${strOption}\";\n" - "}\n" - "}\n" - "\n" - "if ($bIncludeCommand)\n" - "{\n" - "$strExeString .= ' ' . cfgCommandName($iNewCommandId);\n" - "}\n" - "\n" - "return $strExeString;\n" - "}\n" - "\n" - "push @EXPORT, qw(cfgCommandWrite);\n" - "\n\n" - "sub cfgCommandWriteOptionFormat\n" - "{\n" - "my $strOption = shift;\n" - "my $bMulti = shift;\n" - "my $bSecure = shift;\n" - "my $oValue = shift;\n" - "\n\n" - "my $strOptionFormat = '';\n" - "my $strParam;\n" - "\n" - "foreach my $strKey (sort(keys(%$oValue)))\n" - "{\n" - "\n" - "my $strValue = $bSecure ? '' : ($bMulti ? \"${strKey}=\" : '') . $$oValue{$strKey};\n" - "\n\n" - "if (cfgDefOptionType(cfgOptionId($strOption)) eq CFGDEF_TYPE_BOOLEAN)\n" - "{\n" - "$strParam = '--' . ($strValue ? '' : 'no-') . $strOption;\n" - "}\n" - "else\n" - "{\n" - "$strParam = \"--${strOption}=${strValue}\";\n" - "}\n" - "\n\n" - "$strOptionFormat .= ' ' . (index($strValue, \" \") != -1 ? \"\\\"${strParam}\\\"\" : $strParam);\n" - "}\n" - "\n" - "return $strOptionFormat;\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Db.pm", - .data = - "\n\n\n" - "package pgBackRest::Db;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use Fcntl qw(O_RDONLY);\n" - "use File::Basename qw(dirname);\n" - "use JSON::PP;\n" - "\n" - "use pgBackRest::DbVersion;\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::String;\n" - "use pgBackRest::Common::Wait;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Manifest;\n" - "use pgBackRest::Protocol::Helper;\n" - "use pgBackRest::Protocol::Storage::Helper;\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "use constant DB_BACKUP_ADVISORY_LOCK => '12340078987004321';\n" - "push @EXPORT, qw(DB_BACKUP_ADVISORY_LOCK);\n" - "\n\n\n\n\n\n\n\n" - "my $oPgControlVersionHash =\n" - "{\n" - "\n" - "833 => {200711281 => PG_VERSION_83},\n" - "843 => {200904091 => PG_VERSION_84},\n" - "903 =>\n" - "{\n" - "201008051 => PG_VERSION_90,\n" - "201105231 => PG_VERSION_91,\n" - "},\n" - "922 => {201204301 => PG_VERSION_92},\n" - "937 => {201306121 => PG_VERSION_93},\n" - "942 =>\n" - "{\n" - "201409291 => PG_VERSION_94,\n" - "201510051 => PG_VERSION_95,\n" - "},\n" - "960 =>\n" - "{\n" - "201608131 => PG_VERSION_96,\n" - "},\n" - "1002 =>\n" - "{\n" - "201707211 => PG_VERSION_10,\n" - "},\n" - "1100 =>\n" - "{\n" - "201809051 => PG_VERSION_11,\n" - "},\n" - "1201 =>\n" - "{\n" - "201909212 => PG_VERSION_12,\n" - "},\n" - "};\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{iRemoteIdx},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'iRemoteIdx', required => false},\n" - ");\n" - "\n" - "if (defined($self->{iRemoteIdx}))\n" - "{\n" - "$self->{strDbPath} = cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $self->{iRemoteIdx}));\n" - "\n" - "if (!isDbLocal({iRemoteIdx => $self->{iRemoteIdx}}))\n" - "{\n" - "$self->{oProtocol} = protocolGet(CFGOPTVAL_REMOTE_TYPE_DB, $self->{iRemoteIdx});\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub DESTROY\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->DESTROY');\n" - "\n" - "if (defined($self->{oDb}))\n" - "{\n" - "$self->{oDb}->close();\n" - "undef($self->{oDb});\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n" - "sub connect\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bWarnOnError,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::connect', \\@_,\n" - "{name => 'bWarnOnError', default => false},\n" - ");\n" - "\n\n" - "my $bResult = true;\n" - "\n\n" - "if (defined($self->{oProtocol}))\n" - "{\n" - "\n" - "$bResult = $self->{oProtocol}->cmdExecute(OP_DB_CONNECT, undef, false, $bWarnOnError) ? true : false;\n" - "}\n" - "\n" - "else\n" - "{\n" - "if (!defined($self->{oDb}))\n" - "{\n" - "$self->{oDb} = new pgBackRest::LibC::PgClient(\n" - "cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $self->{iRemoteIdx}), false),\n" - "cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $self->{iRemoteIdx})), 'postgres',\n" - "cfgOption(CFGOPT_DB_TIMEOUT) * 1000);\n" - "\n" - "if ($bWarnOnError)\n" - "{\n" - "eval\n" - "{\n" - "$self->{oDb}->open();\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "&log(WARN, exceptionMessage($EVAL_ERROR));\n" - "$bResult = false;\n" - "\n" - "undef($self->{oDb});\n" - "}\n" - "}\n" - "else\n" - "{\n" - "$self->{oDb}->open();\n" - "}\n" - "\n" - "if (defined($self->{oDb}))\n" - "{\n" - "my ($fDbVersion) = $self->versionGet();\n" - "\n" - "if ($fDbVersion >= PG_VERSION_APPLICATION_NAME)\n" - "{\n" - "\n" - "$self->{oDb}->query(\n" - "\"set application_name = '\" . PROJECT_NAME . ' [' .\n" - "(cfgOptionValid(CFGOPT_COMMAND) ? cfgOption(CFGOPT_COMMAND) : cfgCommandName(cfgCommandGet())) . \"]'\");\n" - "\n\n" - "$self->{oDb}->query(\"set search_path = 'pg_catalog'\");\n" - "}\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bResult', value => $bResult}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub executeSql\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strSql,\n" - "$bIgnoreError,\n" - "$bResult,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::executeSql', \\@_,\n" - "{name => 'strSql'},\n" - "{name => 'bIgnoreError', default => false},\n" - "{name => 'bResult', default => true},\n" - ");\n" - "\n\n" - "my @stryResult;\n" - "\n\n" - "if (defined($self->{oProtocol}))\n" - "{\n" - "\n" - "@stryResult = @{$self->{oProtocol}->cmdExecute(OP_DB_EXECUTE_SQL, [$strSql, $bIgnoreError, $bResult], $bResult)};\n" - "}\n" - "\n" - "else\n" - "{\n" - "$self->connect();\n" - "my $strResult = $self->{oDb}->query($strSql);\n" - "\n" - "if (defined($strResult))\n" - "{\n" - "@stryResult = @{JSON::PP->new()->allow_nonref()->decode($strResult)};\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'stryResult', value => \\@stryResult, ref => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub executeSqlRow\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strSql\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->executeSqlRow', \\@_,\n" - "{name => 'strSql'}\n" - ");\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'stryResult', value => @{$self->executeSql($strSql)}[0]}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub executeSqlOne\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strSql\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->executeSqlOne', \\@_,\n" - "{name => 'strSql'}\n" - ");\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strResult', value => @{@{$self->executeSql($strSql)}[0]}[0]}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub info\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strDbPath\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->info', \\@_,\n" - "{name => 'strDbPath', default => $self->{strDbPath}}\n" - ");\n" - "\n\n\n" - "if (!defined($self->{info}{$strDbPath}))\n" - "{\n" - "\n\n" - "if (defined($self->{oProtocol}))\n" - "{\n" - "\n" - "($self->{info}{$strDbPath}{strDbVersion}, $self->{info}{$strDbPath}{iDbControlVersion},\n" - "$self->{info}{$strDbPath}{iDbCatalogVersion}, $self->{info}{$strDbPath}{ullDbSysId}) =\n" - "$self->{oProtocol}->cmdExecute(OP_DB_INFO, [$strDbPath], true);\n" - "}\n" - "\n\n" - "else\n" - "{\n" - "\n\n" - "my $strControlFile = \"${strDbPath}/\" . DB_FILE_PGCONTROL;\n" - "my $hFile;\n" - "my $tBlock;\n" - "\n" - "sysopen($hFile, $strControlFile, O_RDONLY)\n" - "or confess &log(ERROR, \"unable to open ${strControlFile}\", ERROR_FILE_OPEN);\n" - "\n\n" - "sysread($hFile, $tBlock, 8) == 8\n" - "or confess &log(ERROR, \"unable to read database system identifier\");\n" - "\n" - "$self->{info}{$strDbPath}{ullDbSysId} = unpack('Q', $tBlock);\n" - "\n\n" - "sysread($hFile, $tBlock, 4) == 4\n" - "or confess &log(ERROR, \"unable to read control version\");\n" - "\n" - "$self->{info}{$strDbPath}{iDbControlVersion} = unpack('L', $tBlock);\n" - "\n\n" - "sysread($hFile, $tBlock, 4) == 4\n" - "or confess &log(ERROR, \"unable to read catalog version\");\n" - "\n" - "$self->{info}{$strDbPath}{iDbCatalogVersion} = unpack('L', $tBlock);\n" - "\n\n" - "close($hFile);\n" - "\n\n" - "$self->{info}{$strDbPath}{strDbVersion} =\n" - "$oPgControlVersionHash->{$self->{info}{$strDbPath}{iDbControlVersion}}\n" - "{$self->{info}{$strDbPath}{iDbCatalogVersion}};\n" - "\n" - "if (!defined($self->{info}{$strDbPath}{strDbVersion}))\n" - "{\n" - "confess &log(\n" - "ERROR,\n" - "'unexpected control version = ' . $self->{info}{$strDbPath}{iDbControlVersion} .\n" - "' and catalog version = ' . $self->{info}{$strDbPath}{iDbCatalogVersion} . \"\\n\" .\n" - "'HINT: is this version of PostgreSQL supported?',\n" - "ERROR_VERSION_NOT_SUPPORTED);\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strDbVersion', value => $self->{info}{$strDbPath}{strDbVersion}},\n" - "{name => 'iDbControlVersion', value => $self->{info}{$strDbPath}{iDbControlVersion}},\n" - "{name => 'iDbCatalogVersion', value => $self->{info}{$strDbPath}{iDbCatalogVersion}},\n" - "{name => 'ullDbSysId', value => $self->{info}{$strDbPath}{ullDbSysId}}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub versionGet\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->versionGet');\n" - "\n\n" - "if (defined($self->{strDbVersion}) && defined($self->{strDbPath}))\n" - "{\n" - "return $self->{strDbVersion}, $self->{strDbPath};\n" - "}\n" - "\n\n" - "my ($strVersionNum, $strDbPath) =\n" - "$self->executeSqlRow(\n" - "\"select (select setting from pg_settings where name = 'server_version_num'), \" .\n" - "\" (select setting from pg_settings where name = 'data_directory')\");\n" - "\n\n" - "$self->{strDbVersion} = substr($strVersionNum, 0, length($strVersionNum) - 4);\n" - "\n\n" - "if ($self->{strDbVersion} < PG_VERSION_10)\n" - "{\n" - "$self->{strDbVersion} .= qw{.} . int(substr($strVersionNum, 1, 2));\n" - "}\n" - "\n\n" - "my @stryVersionSupport = versionSupport();\n" - "\n" - "if ($self->{strDbVersion} < $stryVersionSupport[0])\n" - "{\n" - "confess &log(ERROR, 'unsupported Postgres version' . $self->{strDbVersion}, ERROR_VERSION_NOT_SUPPORTED);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strDbVersion', value => $self->{strDbVersion}},\n" - "{name => 'strDbPath', value => $strDbPath}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub configValidate\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->configValidate', \\@_,\n" - ");\n" - "\n\n" - "my ($strDbVersion) = $self->info();\n" - "\n\n" - "my ($fCompareDbVersion, $strCompareDbPath) = $self->versionGet();\n" - "\n\n" - "if (!($strDbVersion == $fCompareDbVersion && $self->{strDbPath} eq $strCompareDbPath))\n" - "{\n" - "confess &log(ERROR,\n" - "\"version '${fCompareDbVersion}' and path '${strCompareDbPath}' queried from cluster do not match version\" .\n" - "\" '${strDbVersion}' and \" . cfgOptionName(CFGOPT_PG_PATH) . \" '$self->{strDbPath}' read from\" .\n" - "\" '$self->{strDbPath}/\" . DB_FILE_PGCONTROL . \"'\\n\" .\n" - "\"HINT: the \" . cfgOptionName(CFGOPT_PG_PATH) . \" and \" . cfgOptionName(CFGOPT_PG_PORT) .\n" - "\" settings likely reference different clusters.\",\n" - "ERROR_DB_MISMATCH);\n" - "}\n" - "\n\n" - "if (!$self->isStandby() && cfgOptionValid(CFGOPT_ARCHIVE_CHECK) && cfgOption(CFGOPT_ARCHIVE_CHECK))\n" - "{\n" - "my $strArchiveMode = $self->executeSqlOne('show archive_mode');\n" - "\n\n" - "if ($strArchiveMode eq 'off')\n" - "{\n" - "confess &log(ERROR, 'archive_mode must be enabled', ERROR_ARCHIVE_DISABLED);\n" - "}\n" - "\n\n" - "if ($strArchiveMode eq 'always')\n" - "{\n" - "confess &log(ERROR, \"archive_mode=always not supported\", ERROR_FEATURE_NOT_SUPPORTED);\n" - "}\n" - "\n\n" - "my $strArchiveCommand = $self->executeSqlOne('show archive_command');\n" - "\n" - "if (index($strArchiveCommand, PROJECT_EXE) == -1)\n" - "{\n" - "confess &log(ERROR,\n" - "'archive_command ' . (defined($strArchiveCommand) ? \"'${strArchiveCommand}'\" : '[null]') . ' must contain \\'' .\n" - "PROJECT_EXE . '\\'', ERROR_ARCHIVE_COMMAND_INVALID);\n" - "}\n" - "}\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub walId\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->{strDbVersion} >= PG_VERSION_10 ? 'wal' : 'xlog';\n" - "}\n" - "\n\n\n\n\n\n" - "sub isStandby\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->isStandby');\n" - "\n" - "if (!defined($self->{bStandby}))\n" - "{\n" - "my ($strDbVersion) = $self->versionGet();\n" - "\n" - "if ($strDbVersion <= PG_VERSION_90)\n" - "{\n" - "$self->{bStandby} = false;\n" - "}\n" - "else\n" - "{\n" - "$self->{bStandby} = $self->executeSqlOne('select pg_is_in_recovery()') ? true : false;\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bStandby', value => $self->{bStandby}}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n\n\n" - "sub dbObjectGet\n" - "{\n" - "\n" - "my (\n" - "$strOperation,\n" - "$bMasterOnly,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::dbObjectGet', \\@_,\n" - "{name => 'bMasterOnly', optional => true, default => false},\n" - ");\n" - "\n" - "my $iStandbyIdx = undef;\n" - "my $iMasterRemoteIdx = 1;\n" - "my $oDbMaster = undef;\n" - "my $oDbStandby = undef;\n" - "\n\n\n" - "if (!$bMasterOnly && cfgOptionTest(CFGOPT_ONLINE) && cfgOption(CFGOPT_ONLINE) && multipleDb())\n" - "{\n" - "for (my $iRemoteIdx = 1; $iRemoteIdx <= cfgOptionIndexTotal(CFGOPT_PG_HOST); $iRemoteIdx++)\n" - "{\n" - "\n" - "if (cfgOptionTest(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)) ||\n" - "cfgOptionTest(cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iRemoteIdx)))\n" - "{\n" - "\n" - "my $oDb;\n" - "\n" - "logWarnOnErrorEnable();\n" - "eval\n" - "{\n" - "$oDb = new pgBackRest::Db($iRemoteIdx);\n" - "return true;\n" - "}\n" - "or do {};\n" - "\n" - "logWarnOnErrorDisable();\n" - "my $bAssigned = false;\n" - "\n" - "if (defined($oDb))\n" - "{\n" - "\n\n" - "if ($oDb->connect(true))\n" - "{\n" - "\n" - "if ($oDb->isStandby())\n" - "{\n" - "\n" - "if (cfgOption(CFGOPT_BACKUP_STANDBY) && !defined($oDbStandby))\n" - "{\n" - "$oDbStandby = $oDb;\n" - "$iStandbyIdx = $iRemoteIdx;\n" - "$bAssigned = true;\n" - "}\n" - "}\n" - "\n" - "else\n" - "{\n" - "\n" - "if (defined($oDbMaster))\n" - "{\n" - "confess &log(ERROR, 'more than one master database found');\n" - "}\n" - "\n" - "$oDbMaster = $oDb;\n" - "$iMasterRemoteIdx = $iRemoteIdx;\n" - "$bAssigned = true;\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "if (!$bAssigned)\n" - "{\n" - "protocolDestroy(CFGOPTVAL_REMOTE_TYPE_DB, $iRemoteIdx, true);\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "if (cfgOption(CFGOPT_BACKUP_STANDBY) && !defined($oDbStandby))\n" - "{\n" - "\n" - "confess &log(ERROR, 'unable to find standby database - cannot proceed', ERROR_HOST_CONNECT);\n" - "}\n" - "\n\n" - "if (!defined($oDbMaster))\n" - "{\n" - "\n" - "confess &log(ERROR, 'unable to find master database - cannot proceed', ERROR_DB_CONNECT);\n" - "}\n" - "}\n" - "\n\n" - "if (!defined($oDbMaster))\n" - "{\n" - "$oDbMaster = new pgBackRest::Db($iMasterRemoteIdx);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oDbMaster', value => $oDbMaster},\n" - "{name => 'iDbMasterIdx', value => $iMasterRemoteIdx},\n" - "{name => 'oDbStandby', value => $oDbStandby},\n" - "{name => 'iDbStandbyIdx', value => $iStandbyIdx},\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(dbObjectGet);\n" - "\n\n\n\n\n\n\n" - "sub dbMasterGet\n" - "{\n" - "\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '::dbMasterGet');\n" - "\n" - "my ($oDbMaster) = dbObjectGet({bMasterOnly => true});\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oDbMaster', value => $oDbMaster, trace => true},\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(dbMasterGet);\n" - "\n\n\n\n\n\n" - "sub multipleDb\n" - "{\n" - "for (my $iDbPathIdx = 2; $iDbPathIdx <= cfgOptionIndexTotal(CFGOPT_PG_PATH); $iDbPathIdx++)\n" - "{\n" - "\n" - "if (cfgOptionTest(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iDbPathIdx)))\n" - "{\n" - "return true;\n" - "}\n" - "}\n" - "\n" - "return false;\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/DbVersion.pm", - .data = - "\n\n\n" - "package pgBackRest::DbVersion;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "\n" - "use pgBackRest::Common::Log;\n" - "\n\n\n\n" - "use constant PG_PAGE_SIZE => 8192;\n" - "push @EXPORT, qw(PG_PAGE_SIZE);\n" - "\n\n\n\n" - "use constant PG_VERSION_83 => '8.3';\n" - "push @EXPORT, qw(PG_VERSION_83);\n" - "use constant PG_VERSION_84 => '8.4';\n" - "push @EXPORT, qw(PG_VERSION_84);\n" - "use constant PG_VERSION_90 => '9.0';\n" - "push @EXPORT, qw(PG_VERSION_90);\n" - "use constant PG_VERSION_91 => '9.1';\n" - "push @EXPORT, qw(PG_VERSION_91);\n" - "use constant PG_VERSION_92 => '9.2';\n" - "push @EXPORT, qw(PG_VERSION_92);\n" - "use constant PG_VERSION_93 => '9.3';\n" - "push @EXPORT, qw(PG_VERSION_93);\n" - "use constant PG_VERSION_94 => '9.4';\n" - "push @EXPORT, qw(PG_VERSION_94);\n" - "use constant PG_VERSION_95 => '9.5';\n" - "push @EXPORT, qw(PG_VERSION_95);\n" - "use constant PG_VERSION_96 => '9.6';\n" - "push @EXPORT, qw(PG_VERSION_96);\n" - "use constant PG_VERSION_10 => '10';\n" - "push @EXPORT, qw(PG_VERSION_10);\n" - "use constant PG_VERSION_11 => '11';\n" - "push @EXPORT, qw(PG_VERSION_11);\n" - "use constant PG_VERSION_12 => '12';\n" - "push @EXPORT, qw(PG_VERSION_12);\n" - "\n" - "use constant PG_VERSION_APPLICATION_NAME => PG_VERSION_90;\n" - "push @EXPORT, qw(PG_VERSION_APPLICATION_NAME);\n" - "use constant PG_VERSION_HOT_STANDBY => PG_VERSION_91;\n" - "push @EXPORT, qw(PG_VERSION_HOT_STANDBY);\n" - "use constant PG_VERSION_BACKUP_STANDBY => PG_VERSION_92;\n" - "push @EXPORT, qw(PG_VERSION_BACKUP_STANDBY);\n" - "\n\n\n\n\n\n" - "sub versionSupport\n" - "{\n" - "\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->versionSupport');\n" - "\n" - "my @strySupportVersion = (PG_VERSION_83, PG_VERSION_84, PG_VERSION_90, PG_VERSION_91, PG_VERSION_92, PG_VERSION_93,\n" - "PG_VERSION_94, PG_VERSION_95, PG_VERSION_96, PG_VERSION_10, PG_VERSION_11, PG_VERSION_12);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strySupportVersion', value => \\@strySupportVersion}\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(versionSupport);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/InfoCommon.pm", - .data = - "\n\n\n\n" - "package pgBackRest::InfoCommon;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "\n\n\n\n" - "use constant INFO_BACKUP_SECTION_DB => 'db';\n" - "push @EXPORT, qw(INFO_BACKUP_SECTION_DB);\n" - "use constant INFO_BACKUP_SECTION_DB_HISTORY => INFO_BACKUP_SECTION_DB . ':history';\n" - "push @EXPORT, qw(INFO_BACKUP_SECTION_DB_HISTORY);\n" - "\n\n\n\n" - "use constant INFO_HISTORY_ID => 'id';\n" - "push @EXPORT, qw(INFO_HISTORY_ID);\n" - "use constant INFO_DB_VERSION => 'version';\n" - "push @EXPORT, qw(INFO_DB_VERSION);\n" - "use constant INFO_SYSTEM_ID => 'system-id';\n" - "push @EXPORT, qw(INFO_SYSTEM_ID);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/LibC.pm", - .data = - "\n\n\n" - "package pgBackRest::LibC;\n" - "use base 'Exporter';\n" - "\n" - "use 5.010001;\n" - "use strict;\n" - "use warnings;\n" - "use Carp;\n" - "\n" - "use pgBackRest::LibCAuto;\n" - "\n\n" - "my $rhConstant = pgBackRest::LibCAuto::libcAutoConstant();\n" - "\n" - "foreach my $strConstant (keys(%{$rhConstant}))\n" - "{\n" - "eval \"use constant ${strConstant} => '\" . $rhConstant->{$strConstant} . \"'\";\n" - "}\n" - "\n\n" - "our %EXPORT_TAGS = %{pgBackRest::LibCAuto::libcAutoExportTag()};\n" - "our @EXPORT_OK;\n" - "\n" - "foreach my $strSection (keys(%EXPORT_TAGS))\n" - "{\n" - "\n\n" - "my $strPrefixLast = 'XXXXXXXX';\n" - "my $iConstantIdx = 0;\n" - "\n" - "foreach my $strConstant (@{$EXPORT_TAGS{$strSection}})\n" - "{\n" - "my $strPrefix = ($strConstant =~ m/^[A-Z0-9]+/g)[0];\n" - "\n" - "if (defined($strPrefix))\n" - "{\n" - "if ($strPrefix ne $strPrefixLast)\n" - "{\n" - "$iConstantIdx = 0;\n" - "}\n" - "else\n" - "{\n" - "$iConstantIdx++;\n" - "}\n" - "\n" - "if ($strPrefix eq 'CFGCMD' || $strPrefix eq 'CFGOPT')\n" - "{\n" - "eval \"use constant ${strConstant} => ${iConstantIdx}\";\n" - "}\n" - "\n" - "$strPrefixLast = $strPrefix;\n" - "}\n" - "}\n" - "\n\n" - "push(@EXPORT_OK, @{$EXPORT_TAGS{$strSection}});\n" - "}\n" - "\n\n" - "our @EXPORT = ();\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/LibCAuto.pm", - .data = - "\n\n\n" - "package pgBackRest::LibCAuto;\n" - "\n" - "use strict;\n" - "use warnings;\n" - "\n\n" - "sub libcAutoConstant\n" - "{\n" - "return\n" - "{\n" - "CFGOPTVAL_INFO_OUTPUT_TEXT => 'text',\n" - "CFGOPTVAL_INFO_OUTPUT_JSON => 'json',\n" - "\n" - "CFGOPTVAL_LS_OUTPUT_TEXT => 'text',\n" - "CFGOPTVAL_LS_OUTPUT_JSON => 'json',\n" - "\n" - "CFGOPTVAL_REPO_CIPHER_TYPE_NONE => 'none',\n" - "CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC => 'aes-256-cbc',\n" - "\n" - "CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_FULL => 'full',\n" - "CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_DIFF => 'diff',\n" - "CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_INCR => 'incr',\n" - "\n" - "CFGOPTVAL_REPO_TYPE_CIFS => 'cifs',\n" - "CFGOPTVAL_REPO_TYPE_POSIX => 'posix',\n" - "CFGOPTVAL_REPO_TYPE_S3 => 's3',\n" - "\n" - "CFGOPTVAL_SORT_NONE => 'none',\n" - "CFGOPTVAL_SORT_ASC => 'asc',\n" - "CFGOPTVAL_SORT_DESC => 'desc',\n" - "\n" - "CFGOPTVAL_RESTORE_TARGET_ACTION_PAUSE => 'pause',\n" - "CFGOPTVAL_RESTORE_TARGET_ACTION_PROMOTE => 'promote',\n" - "CFGOPTVAL_RESTORE_TARGET_ACTION_SHUTDOWN => 'shutdown',\n" - "\n" - "CFGOPTVAL_BACKUP_TYPE_FULL => 'full',\n" - "CFGOPTVAL_BACKUP_TYPE_DIFF => 'diff',\n" - "CFGOPTVAL_BACKUP_TYPE_INCR => 'incr',\n" - "\n" - "CFGOPTVAL_LOCAL_TYPE_DB => 'db',\n" - "CFGOPTVAL_LOCAL_TYPE_BACKUP => 'backup',\n" - "\n" - "CFGOPTVAL_REMOTE_TYPE_DB => 'db',\n" - "CFGOPTVAL_REMOTE_TYPE_BACKUP => 'backup',\n" - "\n" - "CFGOPTVAL_RESTORE_TYPE_NAME => 'name',\n" - "CFGOPTVAL_RESTORE_TYPE_TIME => 'time',\n" - "CFGOPTVAL_RESTORE_TYPE_XID => 'xid',\n" - "CFGOPTVAL_RESTORE_TYPE_PRESERVE => 'preserve',\n" - "CFGOPTVAL_RESTORE_TYPE_NONE => 'none',\n" - "CFGOPTVAL_RESTORE_TYPE_IMMEDIATE => 'immediate',\n" - "CFGOPTVAL_RESTORE_TYPE_DEFAULT => 'default',\n" - "CFGOPTVAL_RESTORE_TYPE_STANDBY => 'standby',\n" - "\n" - "CFGDEF_TYPE_BOOLEAN => 0,\n" - "CFGDEF_TYPE_FLOAT => 1,\n" - "CFGDEF_TYPE_HASH => 2,\n" - "CFGDEF_TYPE_INTEGER => 3,\n" - "CFGDEF_TYPE_LIST => 4,\n" - "CFGDEF_TYPE_PATH => 5,\n" - "CFGDEF_TYPE_SIZE => 6,\n" - "CFGDEF_TYPE_STRING => 7,\n" - "\n" - "ENCODE_TYPE_BASE64 => 0,\n" - "\n" - "CIPHER_MODE_ENCRYPT => 0,\n" - "CIPHER_MODE_DECRYPT => 1,\n" - "}\n" - "}\n" - "\n\n" - "sub libcAutoExportTag\n" - "{\n" - "return\n" - "{\n" - "checksum =>\n" - "[\n" - "'pageChecksum',\n" - "],\n" - "\n" - "config =>\n" - "[\n" - "'CFGOPTVAL_INFO_OUTPUT_TEXT',\n" - "'CFGOPTVAL_INFO_OUTPUT_JSON',\n" - "'CFGOPTVAL_LS_OUTPUT_TEXT',\n" - "'CFGOPTVAL_LS_OUTPUT_JSON',\n" - "'CFGOPTVAL_REPO_CIPHER_TYPE_NONE',\n" - "'CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC',\n" - "'CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_FULL',\n" - "'CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_DIFF',\n" - "'CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_INCR',\n" - "'CFGOPTVAL_REPO_TYPE_CIFS',\n" - "'CFGOPTVAL_REPO_TYPE_POSIX',\n" - "'CFGOPTVAL_REPO_TYPE_S3',\n" - "'CFGOPTVAL_SORT_NONE',\n" - "'CFGOPTVAL_SORT_ASC',\n" - "'CFGOPTVAL_SORT_DESC',\n" - "'CFGOPTVAL_RESTORE_TARGET_ACTION_PAUSE',\n" - "'CFGOPTVAL_RESTORE_TARGET_ACTION_PROMOTE',\n" - "'CFGOPTVAL_RESTORE_TARGET_ACTION_SHUTDOWN',\n" - "'CFGOPTVAL_BACKUP_TYPE_FULL',\n" - "'CFGOPTVAL_BACKUP_TYPE_DIFF',\n" - "'CFGOPTVAL_BACKUP_TYPE_INCR',\n" - "'CFGOPTVAL_LOCAL_TYPE_DB',\n" - "'CFGOPTVAL_LOCAL_TYPE_BACKUP',\n" - "'CFGOPTVAL_REMOTE_TYPE_DB',\n" - "'CFGOPTVAL_REMOTE_TYPE_BACKUP',\n" - "'CFGOPTVAL_RESTORE_TYPE_NAME',\n" - "'CFGOPTVAL_RESTORE_TYPE_TIME',\n" - "'CFGOPTVAL_RESTORE_TYPE_XID',\n" - "'CFGOPTVAL_RESTORE_TYPE_PRESERVE',\n" - "'CFGOPTVAL_RESTORE_TYPE_NONE',\n" - "'CFGOPTVAL_RESTORE_TYPE_IMMEDIATE',\n" - "'CFGOPTVAL_RESTORE_TYPE_DEFAULT',\n" - "'CFGOPTVAL_RESTORE_TYPE_STANDBY',\n" - "'CFGCMD_ARCHIVE_GET',\n" - "'CFGCMD_ARCHIVE_GET_ASYNC',\n" - "'CFGCMD_ARCHIVE_PUSH',\n" - "'CFGCMD_ARCHIVE_PUSH_ASYNC',\n" - "'CFGCMD_BACKUP',\n" - "'CFGCMD_CHECK',\n" - "'CFGCMD_EXPIRE',\n" - "'CFGCMD_HELP',\n" - "'CFGCMD_INFO',\n" - "'CFGCMD_LOCAL',\n" - "'CFGCMD_LS',\n" - "'CFGCMD_REMOTE',\n" - "'CFGCMD_RESTORE',\n" - "'CFGCMD_STANZA_CREATE',\n" - "'CFGCMD_STANZA_DELETE',\n" - "'CFGCMD_STANZA_UPGRADE',\n" - "'CFGCMD_START',\n" - "'CFGCMD_STOP',\n" - "'CFGCMD_VERSION',\n" - "'CFGOPT_ARCHIVE_ASYNC',\n" - "'CFGOPT_ARCHIVE_CHECK',\n" - "'CFGOPT_ARCHIVE_COPY',\n" - "'CFGOPT_ARCHIVE_GET_QUEUE_MAX',\n" - "'CFGOPT_ARCHIVE_PUSH_QUEUE_MAX',\n" - "'CFGOPT_ARCHIVE_TIMEOUT',\n" - "'CFGOPT_BACKUP_STANDBY',\n" - "'CFGOPT_BUFFER_SIZE',\n" - "'CFGOPT_C',\n" - "'CFGOPT_CHECKSUM_PAGE',\n" - "'CFGOPT_CMD_SSH',\n" - "'CFGOPT_COMMAND',\n" - "'CFGOPT_COMPRESS',\n" - "'CFGOPT_COMPRESS_LEVEL',\n" - "'CFGOPT_COMPRESS_LEVEL_NETWORK',\n" - "'CFGOPT_CONFIG',\n" - "'CFGOPT_CONFIG_INCLUDE_PATH',\n" - "'CFGOPT_CONFIG_PATH',\n" - "'CFGOPT_DB_INCLUDE',\n" - "'CFGOPT_DB_TIMEOUT',\n" - "'CFGOPT_DELTA',\n" - "'CFGOPT_EXCLUDE',\n" - "'CFGOPT_FILTER',\n" - "'CFGOPT_FORCE',\n" - "'CFGOPT_HOST_ID',\n" - "'CFGOPT_LINK_ALL',\n" - "'CFGOPT_LINK_MAP',\n" - "'CFGOPT_LOCK_PATH',\n" - "'CFGOPT_LOG_LEVEL_CONSOLE',\n" - "'CFGOPT_LOG_LEVEL_FILE',\n" - "'CFGOPT_LOG_LEVEL_STDERR',\n" - "'CFGOPT_LOG_PATH',\n" - "'CFGOPT_LOG_SUBPROCESS',\n" - "'CFGOPT_LOG_TIMESTAMP',\n" - "'CFGOPT_MANIFEST_SAVE_THRESHOLD',\n" - "'CFGOPT_NEUTRAL_UMASK',\n" - "'CFGOPT_ONLINE',\n" - "'CFGOPT_OUTPUT',\n" - "'CFGOPT_PG_HOST',\n" - "'CFGOPT_PG_HOST2',\n" - "'CFGOPT_PG_HOST3',\n" - "'CFGOPT_PG_HOST4',\n" - "'CFGOPT_PG_HOST5',\n" - "'CFGOPT_PG_HOST6',\n" - "'CFGOPT_PG_HOST7',\n" - "'CFGOPT_PG_HOST8',\n" - "'CFGOPT_PG_HOST_CMD',\n" - "'CFGOPT_PG_HOST_CMD2',\n" - "'CFGOPT_PG_HOST_CMD3',\n" - "'CFGOPT_PG_HOST_CMD4',\n" - "'CFGOPT_PG_HOST_CMD5',\n" - "'CFGOPT_PG_HOST_CMD6',\n" - "'CFGOPT_PG_HOST_CMD7',\n" - "'CFGOPT_PG_HOST_CMD8',\n" - "'CFGOPT_PG_HOST_CONFIG',\n" - "'CFGOPT_PG_HOST_CONFIG2',\n" - "'CFGOPT_PG_HOST_CONFIG3',\n" - "'CFGOPT_PG_HOST_CONFIG4',\n" - "'CFGOPT_PG_HOST_CONFIG5',\n" - "'CFGOPT_PG_HOST_CONFIG6',\n" - "'CFGOPT_PG_HOST_CONFIG7',\n" - "'CFGOPT_PG_HOST_CONFIG8',\n" - "'CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH',\n" - "'CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH2',\n" - "'CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH3',\n" - "'CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH4',\n" - "'CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH5',\n" - "'CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH6',\n" - "'CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH7',\n" - "'CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH8',\n" - "'CFGOPT_PG_HOST_CONFIG_PATH',\n" - "'CFGOPT_PG_HOST_CONFIG_PATH2',\n" - "'CFGOPT_PG_HOST_CONFIG_PATH3',\n" - "'CFGOPT_PG_HOST_CONFIG_PATH4',\n" - "'CFGOPT_PG_HOST_CONFIG_PATH5',\n" - "'CFGOPT_PG_HOST_CONFIG_PATH6',\n" - "'CFGOPT_PG_HOST_CONFIG_PATH7',\n" - "'CFGOPT_PG_HOST_CONFIG_PATH8',\n" - "'CFGOPT_PG_HOST_PORT',\n" - "'CFGOPT_PG_HOST_PORT2',\n" - "'CFGOPT_PG_HOST_PORT3',\n" - "'CFGOPT_PG_HOST_PORT4',\n" - "'CFGOPT_PG_HOST_PORT5',\n" - "'CFGOPT_PG_HOST_PORT6',\n" - "'CFGOPT_PG_HOST_PORT7',\n" - "'CFGOPT_PG_HOST_PORT8',\n" - "'CFGOPT_PG_HOST_USER',\n" - "'CFGOPT_PG_HOST_USER2',\n" - "'CFGOPT_PG_HOST_USER3',\n" - "'CFGOPT_PG_HOST_USER4',\n" - "'CFGOPT_PG_HOST_USER5',\n" - "'CFGOPT_PG_HOST_USER6',\n" - "'CFGOPT_PG_HOST_USER7',\n" - "'CFGOPT_PG_HOST_USER8',\n" - "'CFGOPT_PG_PATH',\n" - "'CFGOPT_PG_PATH2',\n" - "'CFGOPT_PG_PATH3',\n" - "'CFGOPT_PG_PATH4',\n" - "'CFGOPT_PG_PATH5',\n" - "'CFGOPT_PG_PATH6',\n" - "'CFGOPT_PG_PATH7',\n" - "'CFGOPT_PG_PATH8',\n" - "'CFGOPT_PG_PORT',\n" - "'CFGOPT_PG_PORT2',\n" - "'CFGOPT_PG_PORT3',\n" - "'CFGOPT_PG_PORT4',\n" - "'CFGOPT_PG_PORT5',\n" - "'CFGOPT_PG_PORT6',\n" - "'CFGOPT_PG_PORT7',\n" - "'CFGOPT_PG_PORT8',\n" - "'CFGOPT_PG_SOCKET_PATH',\n" - "'CFGOPT_PG_SOCKET_PATH2',\n" - "'CFGOPT_PG_SOCKET_PATH3',\n" - "'CFGOPT_PG_SOCKET_PATH4',\n" - "'CFGOPT_PG_SOCKET_PATH5',\n" - "'CFGOPT_PG_SOCKET_PATH6',\n" - "'CFGOPT_PG_SOCKET_PATH7',\n" - "'CFGOPT_PG_SOCKET_PATH8',\n" - "'CFGOPT_PROCESS',\n" - "'CFGOPT_PROCESS_MAX',\n" - "'CFGOPT_PROTOCOL_TIMEOUT',\n" - "'CFGOPT_RECOVERY_OPTION',\n" - "'CFGOPT_RECURSE',\n" - "'CFGOPT_REPO_CIPHER_PASS',\n" - "'CFGOPT_REPO_CIPHER_TYPE',\n" - "'CFGOPT_REPO_HARDLINK',\n" - "'CFGOPT_REPO_HOST',\n" - "'CFGOPT_REPO_HOST_CMD',\n" - "'CFGOPT_REPO_HOST_CONFIG',\n" - "'CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH',\n" - "'CFGOPT_REPO_HOST_CONFIG_PATH',\n" - "'CFGOPT_REPO_HOST_PORT',\n" - "'CFGOPT_REPO_HOST_USER',\n" - "'CFGOPT_REPO_PATH',\n" - "'CFGOPT_REPO_RETENTION_ARCHIVE',\n" - "'CFGOPT_REPO_RETENTION_ARCHIVE_TYPE',\n" - "'CFGOPT_REPO_RETENTION_DIFF',\n" - "'CFGOPT_REPO_RETENTION_FULL',\n" - "'CFGOPT_REPO_S3_BUCKET',\n" - "'CFGOPT_REPO_S3_CA_FILE',\n" - "'CFGOPT_REPO_S3_CA_PATH',\n" - "'CFGOPT_REPO_S3_ENDPOINT',\n" - "'CFGOPT_REPO_S3_HOST',\n" - "'CFGOPT_REPO_S3_KEY',\n" - "'CFGOPT_REPO_S3_KEY_SECRET',\n" - "'CFGOPT_REPO_S3_PORT',\n" - "'CFGOPT_REPO_S3_REGION',\n" - "'CFGOPT_REPO_S3_TOKEN',\n" - "'CFGOPT_REPO_S3_VERIFY_TLS',\n" - "'CFGOPT_REPO_TYPE',\n" - "'CFGOPT_RESUME',\n" - "'CFGOPT_SET',\n" - "'CFGOPT_SORT',\n" - "'CFGOPT_SPOOL_PATH',\n" - "'CFGOPT_STANZA',\n" - "'CFGOPT_START_FAST',\n" - "'CFGOPT_STOP_AUTO',\n" - "'CFGOPT_TABLESPACE_MAP',\n" - "'CFGOPT_TABLESPACE_MAP_ALL',\n" - "'CFGOPT_TARGET',\n" - "'CFGOPT_TARGET_ACTION',\n" - "'CFGOPT_TARGET_EXCLUSIVE',\n" - "'CFGOPT_TARGET_TIMELINE',\n" - "'CFGOPT_TYPE',\n" - "'cfgCommandName',\n" - "'cfgOptionIndex',\n" - "'cfgOptionIndexTotal',\n" - "'cfgOptionName',\n" - "],\n" - "\n" - "configDefine =>\n" - "[\n" - "'CFGDEF_TYPE_BOOLEAN',\n" - "'CFGDEF_TYPE_FLOAT',\n" - "'CFGDEF_TYPE_HASH',\n" - "'CFGDEF_TYPE_INTEGER',\n" - "'CFGDEF_TYPE_LIST',\n" - "'CFGDEF_TYPE_PATH',\n" - "'CFGDEF_TYPE_SIZE',\n" - "'CFGDEF_TYPE_STRING',\n" - "'cfgCommandId',\n" - "'cfgDefOptionDefault',\n" - "'cfgDefOptionPrefix',\n" - "'cfgDefOptionSecure',\n" - "'cfgDefOptionType',\n" - "'cfgDefOptionValid',\n" - "'cfgOptionId',\n" - "'cfgOptionTotal',\n" - "],\n" - "\n" - "crypto =>\n" - "[\n" - "'CIPHER_MODE_ENCRYPT',\n" - "'CIPHER_MODE_DECRYPT',\n" - "'cryptoHashOne',\n" - "],\n" - "\n" - "debug =>\n" - "[\n" - "'libcUvSize',\n" - "],\n" - "\n" - "encode =>\n" - "[\n" - "'ENCODE_TYPE_BASE64',\n" - "'decodeToBin',\n" - "'encodeToStr',\n" - "],\n" - "\n" - "lock =>\n" - "[\n" - "'lockAcquire',\n" - "'lockRelease',\n" - "],\n" - "\n" - "random =>\n" - "[\n" - "'cryptoRandomBytes',\n" - "],\n" - "\n" - "storage =>\n" - "[\n" - "'storageRepoFree',\n" - "],\n" - "\n" - "test =>\n" - "[\n" - "'cfgParseTest',\n" - "],\n" - "}\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Main.pm", - .data = - "\n\n\n" - "package pgBackRest::Main;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n\n" - "$SIG{__DIE__} = sub {Carp::confess @_};\n" - "\n" - "use File::Basename qw(dirname);\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Lock;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Protocol::Helper;\n" - "use pgBackRest::Protocol::Storage::Helper;\n" - "use pgBackRest::Storage::Helper;\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "my $strConfigJson;\n" - "my $strConfigBin;\n" - "my $bConfigLoaded = false;\n" - "\n" - "sub mainConfigSet\n" - "{\n" - "$strConfigBin = shift;\n" - "$strConfigJson = shift;\n" - "}\n" - "\n\n\n\n" - "sub main\n" - "{\n" - "my $strCommand = shift;\n" - "my @stryCommandArg = @_;\n" - "\n\n\n" - "my $iResult = 0;\n" - "my $bErrorC = false;\n" - "my $strMessage = '';\n" - "\n" - "eval\n" - "{\n" - "\n\n" - "if (!$bConfigLoaded)\n" - "{\n" - "configLoad(undef, $strConfigBin, $strCommand, \\$strConfigJson);\n" - "$bConfigLoaded = true;\n" - "}\n" - "else\n" - "{\n" - "cfgCommandSet(cfgCommandId($strCommand));\n" - "}\n" - "\n\n\n" - "if (cfgCommandTest(CFGCMD_REMOTE))\n" - "{\n" - "\n" - "cfgOptionSet(CFGOPT_LOG_LEVEL_STDERR, PROTOCOL, true);\n" - "logLevelSet(cfgOption(CFGOPT_LOG_LEVEL_FILE), OFF, cfgOption(CFGOPT_LOG_LEVEL_STDERR));\n" - "\n" - "logFileSet(\n" - "storageLocal(),\n" - "cfgOption(CFGOPT_LOG_PATH) . '/' . (cfgOptionTest(CFGOPT_STANZA) ? cfgOption(CFGOPT_STANZA) : 'all') . '-' .\n" - "lc(cfgOption(CFGOPT_COMMAND)) . '-' . lc(cfgCommandName(cfgCommandGet())) . '-' .\n" - "sprintf(\"%03d\", cfgOption(CFGOPT_PROCESS)));\n" - "\n" - "if (cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP) &&\n" - "!cfgOptionTest(CFGOPT_REPO_TYPE, CFGOPTVAL_REPO_TYPE_S3) &&\n" - "!-e cfgOption(CFGOPT_REPO_PATH))\n" - "{\n" - "confess &log(ERROR,\n" - "cfgOptionName(CFGOPT_REPO_PATH) . ' \\'' . cfgOption(CFGOPT_REPO_PATH) . '\\' does not exist',\n" - "ERROR_PATH_MISSING);\n" - "}\n" - "\n\n" - "require pgBackRest::Protocol::Remote::Minion;\n" - "pgBackRest::Protocol::Remote::Minion->import();\n" - "\n\n" - "my $oRemote = new pgBackRest::Protocol::Remote::Minion(\n" - "cfgOption(CFGOPT_BUFFER_SIZE), cfgOption(CFGOPT_PROTOCOL_TIMEOUT));\n" - "\n\n" - "$oRemote->process(\n" - "cfgOption(CFGOPT_LOCK_PATH), cfgOption(CFGOPT_COMMAND), cfgOption(CFGOPT_STANZA, false), cfgOption(CFGOPT_PROCESS));\n" - "}\n" - "else\n" - "{\n" - "\n" - "require pgBackRest::Protocol::Storage::Helper;\n" - "pgBackRest::Protocol::Storage::Helper->import();\n" - "\n" - "if (isRepoLocal() && !cfgOptionTest(CFGOPT_REPO_TYPE, CFGOPTVAL_REPO_TYPE_S3) && !storageRepo()->pathExists(''))\n" - "{\n" - "confess &log(ERROR,\n" - "cfgOptionName(CFGOPT_REPO_PATH) . ' \\'' . cfgOption(CFGOPT_REPO_PATH) . '\\' does not exist',\n" - "ERROR_PATH_MISSING);\n" - "}\n" - "\n" - "logFileSet(\n" - "storageLocal(),\n" - "cfgOption(CFGOPT_LOG_PATH) . '/' . cfgOption(CFGOPT_STANZA) . '-' . lc(cfgCommandName(cfgCommandGet())));\n" - "}\n" - "\n" - "return 1;\n" - "}\n" - "\n\n\n" - "or do\n" - "{\n" - "\n\n\n" - "my $oException = defined($EVAL_ERROR) && length($EVAL_ERROR) > 0 ? $EVAL_ERROR : logErrorLast();\n" - "\n\n" - "if (isException(\\$oException))\n" - "{\n" - "$iResult = $oException->code();\n" - "$bErrorC = $oException->errorC();\n" - "\n\n" - "if (!$bConfigLoaded && cfgOption(CFGOPT_ARCHIVE_ASYNC))\n" - "{\n" - "$strMessage = $oException->message();\n" - "}\n" - "}\n" - "\n" - "else\n" - "{\n" - "$iResult = ERROR_UNHANDLED;\n" - "$strMessage =\n" - "'process terminated due to an unhandled exception' .\n" - "(defined($oException) ? \":\\n${oException}\" : ': [exception not defined]');\n" - "}\n" - "};\n" - "\n\n" - "return $iResult, $bErrorC, $strMessage;\n" - "}\n" - "\n\n\n\n" - "sub mainCleanup\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$iExitCode,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::mainCleanup', \\@_,\n" - "{name => 'iExitCode', required => false},\n" - ");\n" - "\n\n" - "eval\n" - "{\n" - "protocolDestroy(undef, undef, defined($iExitCode) && ($iExitCode == 0 || $iExitCode == 1));\n" - "return true;\n" - "}\n" - "\n" - "or do {};\n" - "\n\n" - "eval\n" - "{\n" - "lockRelease(false);\n" - "return true;\n" - "}\n" - "\n" - "or do {};\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Manifest.pm", - .data = - "\n\n\n" - "package pgBackRest::Manifest;\n" - "use parent 'pgBackRest::Common::Ini';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename qw(dirname basename);\n" - "use Time::Local qw(timelocal);\n" - "\n" - "use pgBackRest::DbVersion;\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Ini;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::Wait;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Protocol::Helper;\n" - "use pgBackRest::Protocol::Storage::Helper;\n" - "use pgBackRest::Storage::Helper;\n" - "\n\n\n\n" - "use constant PATH_BACKUP_HISTORY => 'backup.history';\n" - "push @EXPORT, qw(PATH_BACKUP_HISTORY);\n" - "use constant FILE_MANIFEST => 'backup.manifest';\n" - "push @EXPORT, qw(FILE_MANIFEST);\n" - "use constant FILE_MANIFEST_COPY => FILE_MANIFEST . INI_COPY_EXT;\n" - "push @EXPORT, qw(FILE_MANIFEST_COPY);\n" - "\n\n\n\n" - "use constant MANIFEST_DEFAULT_MATCH_FACTOR => 0.1;\n" - "push @EXPORT, qw(MANIFEST_DEFAULT_MATCH_FACTOR);\n" - "\n\n\n\n" - "use constant MANIFEST_TARGET_PGDATA => 'pg_data';\n" - "push @EXPORT, qw(MANIFEST_TARGET_PGDATA);\n" - "use constant MANIFEST_TARGET_PGTBLSPC => 'pg_tblspc';\n" - "push @EXPORT, qw(MANIFEST_TARGET_PGTBLSPC);\n" - "\n" - "use constant MANIFEST_VALUE_PATH => 'path';\n" - "push @EXPORT, qw(MANIFEST_VALUE_PATH);\n" - "use constant MANIFEST_VALUE_LINK => 'link';\n" - "push @EXPORT, qw(MANIFEST_VALUE_LINK);\n" - "\n\n" - "use constant MANIFEST_SECTION_BACKUP => 'backup';\n" - "push @EXPORT, qw(MANIFEST_SECTION_BACKUP);\n" - "use constant MANIFEST_SECTION_BACKUP_DB => 'backup:db';\n" - "push @EXPORT, qw(MANIFEST_SECTION_BACKUP_DB);\n" - "use constant MANIFEST_SECTION_BACKUP_INFO => 'backup:info';\n" - "push @EXPORT, qw(MANIFEST_SECTION_BACKUP_INFO);\n" - "use constant MANIFEST_SECTION_BACKUP_OPTION => 'backup:option';\n" - "push @EXPORT, qw(MANIFEST_SECTION_BACKUP_OPTION);\n" - "use constant MANIFEST_SECTION_BACKUP_TARGET => 'backup:target';\n" - "push @EXPORT, qw(MANIFEST_SECTION_BACKUP_TARGET);\n" - "use constant MANIFEST_SECTION_DB => 'db';\n" - "push @EXPORT, qw(MANIFEST_SECTION_DB);\n" - "use constant MANIFEST_SECTION_TARGET_PATH => 'target:path';\n" - "push @EXPORT, qw(MANIFEST_SECTION_TARGET_PATH);\n" - "use constant MANIFEST_SECTION_TARGET_FILE => 'target:file';\n" - "push @EXPORT, qw(MANIFEST_SECTION_TARGET_FILE);\n" - "use constant MANIFEST_SECTION_TARGET_LINK => 'target:link';\n" - "push @EXPORT, qw(MANIFEST_SECTION_TARGET_LINK);\n" - "\n\n" - "use constant MANIFEST_KEY_ARCHIVE_START => 'backup-archive-start';\n" - "push @EXPORT, qw(MANIFEST_KEY_ARCHIVE_START);\n" - "use constant MANIFEST_KEY_ARCHIVE_STOP => 'backup-archive-stop';\n" - "push @EXPORT, qw(MANIFEST_KEY_ARCHIVE_STOP);\n" - "use constant MANIFEST_KEY_LABEL => 'backup-label';\n" - "push @EXPORT, qw(MANIFEST_KEY_LABEL);\n" - "use constant MANIFEST_KEY_LSN_START => 'backup-lsn-start';\n" - "push @EXPORT, qw(MANIFEST_KEY_LSN_START);\n" - "use constant MANIFEST_KEY_LSN_STOP => 'backup-lsn-stop';\n" - "push @EXPORT, qw(MANIFEST_KEY_LSN_STOP);\n" - "use constant MANIFEST_KEY_PRIOR => 'backup-prior';\n" - "push @EXPORT, qw(MANIFEST_KEY_PRIOR);\n" - "use constant MANIFEST_KEY_TIMESTAMP_COPY_START => 'backup-timestamp-copy-start';\n" - "push @EXPORT, qw(MANIFEST_KEY_TIMESTAMP_COPY_START);\n" - "use constant MANIFEST_KEY_TIMESTAMP_START => 'backup-timestamp-start';\n" - "push @EXPORT, qw(MANIFEST_KEY_TIMESTAMP_START);\n" - "use constant MANIFEST_KEY_TIMESTAMP_STOP => 'backup-timestamp-stop';\n" - "push @EXPORT, qw(MANIFEST_KEY_TIMESTAMP_STOP);\n" - "use constant MANIFEST_KEY_TYPE => 'backup-type';\n" - "push @EXPORT, qw(MANIFEST_KEY_TYPE);\n" - "\n\n" - "use constant MANIFEST_KEY_BACKUP_STANDBY => 'option-' . cfgOptionName(CFGOPT_BACKUP_STANDBY);\n" - "push @EXPORT, qw(MANIFEST_KEY_BACKUP_STANDBY);\n" - "use constant MANIFEST_KEY_HARDLINK => 'option-hardlink';\n" - "push @EXPORT, qw(MANIFEST_KEY_HARDLINK);\n" - "use constant MANIFEST_KEY_ARCHIVE_CHECK => 'option-' . cfgOptionName(CFGOPT_ARCHIVE_CHECK);\n" - "push @EXPORT, qw(MANIFEST_KEY_ARCHIVE_CHECK);\n" - "use constant MANIFEST_KEY_ARCHIVE_COPY => 'option-' .cfgOptionName(CFGOPT_ARCHIVE_COPY);\n" - "push @EXPORT, qw(MANIFEST_KEY_ARCHIVE_COPY);\n" - "use constant MANIFEST_KEY_BUFFER_SIZE => 'option-' . cfgOptionName(CFGOPT_BUFFER_SIZE);\n" - "push @EXPORT, qw(MANIFEST_KEY_BUFFER_SIZE);\n" - "use constant MANIFEST_KEY_CHECKSUM_PAGE => 'option-' . cfgOptionName(CFGOPT_CHECKSUM_PAGE);\n" - "push @EXPORT, qw(MANIFEST_KEY_CHECKSUM_PAGE);\n" - "use constant MANIFEST_KEY_COMPRESS => 'option-' . cfgOptionName(CFGOPT_COMPRESS);\n" - "push @EXPORT, qw(MANIFEST_KEY_COMPRESS);\n" - "use constant MANIFEST_KEY_COMPRESS_LEVEL => 'option-' . cfgOptionName(CFGOPT_COMPRESS_LEVEL);\n" - "push @EXPORT, qw(MANIFEST_KEY_COMPRESS_LEVEL);\n" - "use constant MANIFEST_KEY_COMPRESS_LEVEL_NETWORK => 'option-' . cfgOptionName(CFGOPT_COMPRESS_LEVEL_NETWORK);\n" - "push @EXPORT, qw(MANIFEST_KEY_COMPRESS_LEVEL_NETWORK);\n" - "use constant MANIFEST_KEY_ONLINE => 'option-' . cfgOptionName(CFGOPT_ONLINE);\n" - "push @EXPORT, qw(MANIFEST_KEY_ONLINE);\n" - "use constant MANIFEST_KEY_DELTA => 'option-' . cfgOptionName(CFGOPT_DELTA);\n" - "push @EXPORT, qw(MANIFEST_KEY_DELTA);\n" - "use constant MANIFEST_KEY_PROCESS_MAX => 'option-' . cfgOptionName(CFGOPT_PROCESS_MAX);\n" - "push @EXPORT, qw(MANIFEST_KEY_PROCESS_MAX);\n" - "\n\n" - "use constant MANIFEST_KEY_DB_ID => 'db-id';\n" - "push @EXPORT, qw(MANIFEST_KEY_DB_ID);\n" - "use constant MANIFEST_KEY_SYSTEM_ID => 'db-system-id';\n" - "push @EXPORT, qw(MANIFEST_KEY_SYSTEM_ID);\n" - "use constant MANIFEST_KEY_CATALOG => 'db-catalog-version';\n" - "push @EXPORT, qw(MANIFEST_KEY_CATALOG);\n" - "use constant MANIFEST_KEY_CONTROL => 'db-control-version';\n" - "push @EXPORT, qw(MANIFEST_KEY_CONTROL);\n" - "use constant MANIFEST_KEY_DB_LAST_SYSTEM_ID => 'db-last-system-id';\n" - "push @EXPORT, qw(MANIFEST_KEY_DB_LAST_SYSTEM_ID);\n" - "use constant MANIFEST_KEY_DB_VERSION => 'db-version';\n" - "push @EXPORT, qw(MANIFEST_KEY_DB_VERSION);\n" - "\n\n" - "use constant MANIFEST_SUBKEY_CHECKSUM => 'checksum';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_CHECKSUM);\n" - "use constant MANIFEST_SUBKEY_CHECKSUM_PAGE => 'checksum-page';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_CHECKSUM_PAGE);\n" - "use constant MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR => 'checksum-page-error';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR);\n" - "use constant MANIFEST_SUBKEY_DESTINATION => 'destination';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_DESTINATION);\n" - "use constant MANIFEST_SUBKEY_FILE => 'file';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_FILE);\n" - "use constant MANIFEST_SUBKEY_FUTURE => 'future';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_FUTURE);\n" - "use constant MANIFEST_SUBKEY_GROUP => 'group';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_GROUP);\n" - "use constant MANIFEST_SUBKEY_MASTER => 'master';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_MASTER);\n" - "use constant MANIFEST_SUBKEY_MODE => 'mode';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_MODE);\n" - "use constant MANIFEST_SUBKEY_TIMESTAMP => 'timestamp';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_TIMESTAMP);\n" - "use constant MANIFEST_SUBKEY_TYPE => 'type';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_TYPE);\n" - "use constant MANIFEST_SUBKEY_PATH => 'path';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_PATH);\n" - "use constant MANIFEST_SUBKEY_REFERENCE => 'reference';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_REFERENCE);\n" - "use constant MANIFEST_SUBKEY_REPO_SIZE => 'repo-size';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_REPO_SIZE);\n" - "use constant MANIFEST_SUBKEY_SIZE => 'size';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_SIZE);\n" - "use constant MANIFEST_SUBKEY_TABLESPACE_ID => 'tablespace-id';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_TABLESPACE_ID);\n" - "use constant MANIFEST_SUBKEY_TABLESPACE_NAME => 'tablespace-name';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_TABLESPACE_NAME);\n" - "use constant MANIFEST_SUBKEY_USER => 'user';\n" - "push @EXPORT, qw(MANIFEST_SUBKEY_USER);\n" - "\n\n\n\n" - "use constant DB_PATH_ARCHIVESTATUS => 'archive_status';\n" - "push @EXPORT, qw(DB_PATH_ARCHIVESTATUS);\n" - "use constant DB_PATH_BASE => 'base';\n" - "push @EXPORT, qw(DB_PATH_BASE);\n" - "use constant DB_PATH_GLOBAL => 'global';\n" - "push @EXPORT, qw(DB_PATH_GLOBAL);\n" - "use constant DB_PATH_PGDYNSHMEM => 'pg_dynshmem';\n" - "push @EXPORT, qw(DB_PATH_PGDYNSHMEM);\n" - "use constant DB_PATH_PGMULTIXACT => 'pg_multixact';\n" - "push @EXPORT, qw(DB_PATH_PGMULTIXACT);\n" - "use constant DB_PATH_PGNOTIFY => 'pg_notify';\n" - "push @EXPORT, qw(DB_PATH_PGNOTIFY);\n" - "use constant DB_PATH_PGREPLSLOT => 'pg_replslot';\n" - "push @EXPORT, qw(DB_PATH_PGREPLSLOT);\n" - "use constant DB_PATH_PGSERIAL => 'pg_serial';\n" - "push @EXPORT, qw(DB_PATH_PGSERIAL);\n" - "use constant DB_PATH_PGSNAPSHOTS => 'pg_snapshots';\n" - "push @EXPORT, qw(DB_PATH_PGSNAPSHOTS);\n" - "use constant DB_PATH_PGSTATTMP => 'pg_stat_tmp';\n" - "push @EXPORT, qw(DB_PATH_PGSTATTMP);\n" - "use constant DB_PATH_PGSUBTRANS => 'pg_subtrans';\n" - "push @EXPORT, qw(DB_PATH_PGSUBTRANS);\n" - "use constant DB_PATH_PGTBLSPC => 'pg_tblspc';\n" - "push @EXPORT, qw(DB_PATH_PGTBLSPC);\n" - "\n" - "use constant DB_FILE_BACKUPLABEL => 'backup_label';\n" - "push @EXPORT, qw(DB_FILE_BACKUPLABEL);\n" - "use constant DB_FILE_BACKUPLABELOLD => DB_FILE_BACKUPLABEL . '.old';\n" - "push @EXPORT, qw(DB_FILE_BACKUPLABELOLD);\n" - "use constant DB_FILE_PGCONTROL => DB_PATH_GLOBAL . '/pg_control';\n" - "push @EXPORT, qw(DB_FILE_PGCONTROL);\n" - "use constant DB_FILE_PGFILENODEMAP => 'pg_filenode.map';\n" - "push @EXPORT, qw(DB_FILE_PGFILENODEMAP);\n" - "use constant DB_FILE_PGINTERNALINIT => 'pg_internal.init';\n" - "push @EXPORT, qw(DB_FILE_PGINTERNALINIT);\n" - "use constant DB_FILE_PGVERSION => 'PG_VERSION';\n" - "push @EXPORT, qw(DB_FILE_PGVERSION);\n" - "use constant DB_FILE_POSTGRESQLAUTOCONFTMP => 'postgresql.auto.conf.tmp';\n" - "push @EXPORT, qw(DB_FILE_POSTGRESQLAUTOCONFTMP);\n" - "use constant DB_FILE_POSTMASTEROPTS => 'postmaster.opts';\n" - "push @EXPORT, qw(DB_FILE_POSTMASTEROPTS);\n" - "use constant DB_FILE_POSTMASTERPID => 'postmaster.pid';\n" - "push @EXPORT, qw(DB_FILE_POSTMASTERPID);\n" - "use constant DB_FILE_RECOVERYCONF => 'recovery.conf';\n" - "push @EXPORT, qw(DB_FILE_RECOVERYCONF);\n" - "use constant DB_FILE_RECOVERYSIGNAL => 'recovery.signal';\n" - "push @EXPORT, qw(DB_FILE_RECOVERYSIGNAL);\n" - "use constant DB_FILE_RECOVERYDONE => 'recovery.done';\n" - "push @EXPORT, qw(DB_FILE_RECOVERYDONE);\n" - "use constant DB_FILE_STANDBYSIGNAL => 'standby.signal';\n" - "push @EXPORT, qw(DB_FILE_STANDBYSIGNAL);\n" - "use constant DB_FILE_TABLESPACEMAP => 'tablespace_map';\n" - "push @EXPORT, qw(DB_FILE_TABLESPACEMAP);\n" - "\n" - "use constant DB_FILE_PREFIX_TMP => 'pgsql_tmp';\n" - "push @EXPORT, qw(DB_FILE_PREFIX_TMP);\n" - "\n\n\n\n" - "use constant MANIFEST_PATH_BASE => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE;\n" - "push @EXPORT, qw(MANIFEST_PATH_BASE);\n" - "use constant MANIFEST_PATH_GLOBAL => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_GLOBAL;\n" - "push @EXPORT, qw(MANIFEST_PATH_GLOBAL);\n" - "use constant MANIFEST_PATH_PGDYNSHMEM => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGDYNSHMEM;\n" - "push @EXPORT, qw(MANIFEST_PATH_PGDYNSHMEM);\n" - "use constant MANIFEST_PATH_PGMULTIXACT => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGMULTIXACT;\n" - "push @EXPORT, qw(MANIFEST_PATH_PGMULTIXACT);\n" - "use constant MANIFEST_PATH_PGNOTIFY => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGNOTIFY;\n" - "push @EXPORT, qw(MANIFEST_PATH_PGNOTIFY);\n" - "use constant MANIFEST_PATH_PGREPLSLOT => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGREPLSLOT;\n" - "push @EXPORT, qw(MANIFEST_PATH_PGREPLSLOT);\n" - "use constant MANIFEST_PATH_PGSERIAL => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGSERIAL;\n" - "push @EXPORT, qw(MANIFEST_PATH_PGSERIAL);\n" - "use constant MANIFEST_PATH_PGSNAPSHOTS => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGSNAPSHOTS;\n" - "push @EXPORT, qw(MANIFEST_PATH_PGSNAPSHOTS);\n" - "use constant MANIFEST_PATH_PGSTATTMP => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGSTATTMP;\n" - "push @EXPORT, qw(MANIFEST_PATH_PGSTATTMP);\n" - "use constant MANIFEST_PATH_PGSUBTRANS => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGSUBTRANS;\n" - "push @EXPORT, qw(MANIFEST_PATH_PGSUBTRANS);\n" - "use constant MANIFEST_PATH_PGTBLSPC => MANIFEST_TARGET_PGDATA . '/' . DB_PATH_PGTBLSPC;\n" - "push @EXPORT, qw(MANIFEST_PATH_PGTBLSPC);\n" - "\n" - "use constant MANIFEST_FILE_BACKUPLABEL => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_BACKUPLABEL;\n" - "push @EXPORT, qw(MANIFEST_FILE_BACKUPLABEL);\n" - "use constant MANIFEST_FILE_BACKUPLABELOLD => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_BACKUPLABELOLD;\n" - "push @EXPORT, qw(MANIFEST_FILE_BACKUPLABELOLD);\n" - "use constant MANIFEST_FILE_PGCONTROL => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_PGCONTROL;\n" - "push @EXPORT, qw(MANIFEST_FILE_PGCONTROL);\n" - "use constant MANIFEST_FILE_POSTGRESQLAUTOCONFTMP => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_POSTGRESQLAUTOCONFTMP;\n" - "push @EXPORT, qw(MANIFEST_FILE_PGCONTROL);\n" - "use constant MANIFEST_FILE_POSTMASTEROPTS => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_POSTMASTEROPTS;\n" - "push @EXPORT, qw(MANIFEST_FILE_POSTMASTEROPTS);\n" - "use constant MANIFEST_FILE_POSTMASTERPID => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_POSTMASTERPID;\n" - "push @EXPORT, qw(MANIFEST_FILE_POSTMASTERPID);\n" - "use constant MANIFEST_FILE_RECOVERYCONF => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_RECOVERYCONF;\n" - "push @EXPORT, qw(MANIFEST_FILE_RECOVERYCONF);\n" - "use constant MANIFEST_FILE_RECOVERYSIGNAL => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_RECOVERYSIGNAL;\n" - "push @EXPORT, qw(MANIFEST_FILE_RECOVERYSIGNAL);\n" - "use constant MANIFEST_FILE_RECOVERYDONE => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_RECOVERYDONE;\n" - "push @EXPORT, qw(MANIFEST_FILE_RECOVERYDONE);\n" - "use constant MANIFEST_FILE_STANDBYSIGNAL => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_STANDBYSIGNAL;\n" - "push @EXPORT, qw(MANIFEST_FILE_STANDBYSIGNAL);\n" - "use constant MANIFEST_FILE_TABLESPACEMAP => MANIFEST_TARGET_PGDATA . '/' . DB_FILE_TABLESPACEMAP;\n" - "push @EXPORT, qw(MANIFEST_FILE_TABLESPACEMAP);\n" - "\n\n\n\n" - "use constant DB_USER_OBJECT_MINIMUM_ID => 16384;\n" - "push @EXPORT, qw(DB_USER_OBJECT_MINIMUM_ID);\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strFileName,\n" - "$bLoad,\n" - "$oStorage,\n" - "$strDbVersion,\n" - "$iDbCatalogVersion,\n" - "$strCipherPass,\n" - "$strCipherPassSub,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strFileName', trace => true},\n" - "{name => 'bLoad', optional => true, default => true, trace => true},\n" - "{name => 'oStorage', optional => true, default => storageRepo(), trace => true},\n" - "{name => 'strDbVersion', optional => true, trace => true},\n" - "{name => 'iDbCatalogVersion', optional => true, trace => true},\n" - "{name => 'strCipherPass', optional => true, redact => true},\n" - "{name => 'strCipherPassSub', optional => true, redact => true},\n" - ");\n" - "\n\n" - "my $self = $class->SUPER::new($strFileName, {bLoad => $bLoad, oStorage => $oStorage, strCipherPass => $strCipherPass,\n" - "strCipherPassSub => $strCipherPassSub});\n" - "\n\n" - "if (!$bLoad)\n" - "{\n" - "if (!(defined($strDbVersion) && defined($iDbCatalogVersion)))\n" - "{\n" - "confess &log(ASSERT, 'strDbVersion and iDbCatalogVersion must be provided with bLoad = false');\n" - "}\n" - "\n\n" - "$self->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, $strDbVersion . '');\n" - "$self->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, $iDbCatalogVersion);\n" - "}\n" - "\n\n" - "$self->{bBuilt} = $bLoad;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub save\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->save');\n" - "\n\n" - "$self->SUPER::save();\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub get\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strKey = shift;\n" - "my $strSubKey = shift;\n" - "my $bRequired = shift;\n" - "my $oDefault = shift;\n" - "\n" - "my $oValue = $self->SUPER::get($strSection, $strKey, $strSubKey, false);\n" - "\n" - "if (!defined($oValue) && defined($strKey) && defined($strSubKey) &&\n" - "($strSection eq MANIFEST_SECTION_TARGET_FILE || $strSection eq MANIFEST_SECTION_TARGET_PATH ||\n" - "$strSection eq MANIFEST_SECTION_TARGET_LINK) &&\n" - "($strSubKey eq MANIFEST_SUBKEY_USER || $strSubKey eq MANIFEST_SUBKEY_GROUP ||\n" - "$strSubKey eq MANIFEST_SUBKEY_MODE || $strSubKey eq MANIFEST_SUBKEY_MASTER) &&\n" - "$self->test($strSection, $strKey))\n" - "{\n" - "$oValue = $self->SUPER::get(\"${strSection}:default\", $strSubKey, undef, $bRequired, $oDefault);\n" - "}\n" - "else\n" - "{\n" - "$oValue = $self->SUPER::get($strSection, $strKey, $strSubKey, $bRequired, $oDefault);\n" - "}\n" - "\n" - "return $oValue;\n" - "}\n" - "\n\n\n\n\n\n" - "sub boolGet\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strValue = shift;\n" - "my $strSubValue = shift;\n" - "my $bRequired = shift;\n" - "my $bDefault = shift;\n" - "\n" - "return $self->get($strSection, $strValue, $strSubValue, $bRequired,\n" - "defined($bDefault) ? ($bDefault ? INI_TRUE : INI_FALSE) : undef) ? true : false;\n" - "}\n" - "\n\n\n\n\n\n" - "sub numericGet\n" - "{\n" - "my $self = shift;\n" - "my $strSection = shift;\n" - "my $strValue = shift;\n" - "my $strSubValue = shift;\n" - "my $bRequired = shift;\n" - "my $nDefault = shift;\n" - "\n" - "return $self->get($strSection, $strValue, $strSubValue, $bRequired,\n" - "defined($nDefault) ? $nDefault + 0 : undef) + 0;\n" - "}\n" - "\n\n\n\n\n\n" - "sub tablespacePathGet\n" - "{\n" - "my $self = shift;\n" - "\n" - "return('PG_' . $self->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION) .\n" - "'_' . $self->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG));\n" - "}\n" - "\n\n\n\n\n\n" - "sub dbPathGet\n" - "{\n" - "my $self = shift;\n" - "my $strDbPath = shift;\n" - "my $strFile = shift;\n" - "\n" - "my $strDbFile = defined($strDbPath) ? \"${strDbPath}/\" : '';\n" - "\n" - "if (index($strFile, MANIFEST_TARGET_PGDATA . '/') == 0)\n" - "{\n" - "$strDbFile .= substr($strFile, length(MANIFEST_TARGET_PGDATA) + 1);\n" - "}\n" - "else\n" - "{\n" - "$strDbFile .= $strFile;\n" - "}\n" - "\n" - "return $strDbFile;\n" - "}\n" - "\n\n\n\n\n\n" - "sub repoPathGet\n" - "{\n" - "my $self = shift;\n" - "my $strTarget = shift;\n" - "my $strFile = shift;\n" - "\n" - "my $strRepoFile = $strTarget;\n" - "\n" - "if ($self->isTargetTablespace($strTarget) &&\n" - "($self->dbVersion() >= PG_VERSION_90))\n" - "{\n" - "$strRepoFile .= '/' . $self->tablespacePathGet();\n" - "}\n" - "\n" - "if (defined($strFile))\n" - "{\n" - "$strRepoFile .= \"/${strFile}\";\n" - "}\n" - "\n" - "return $strRepoFile;\n" - "}\n" - "\n\n\n\n\n\n" - "sub isTargetValid\n" - "{\n" - "my $self = shift;\n" - "my $strTarget = shift;\n" - "my $bError = shift;\n" - "\n" - "if (!defined($strTarget))\n" - "{\n" - "confess &log(ASSERT, 'target is not defined');\n" - "}\n" - "\n" - "if (!$self->test(MANIFEST_SECTION_BACKUP_TARGET, $strTarget))\n" - "{\n" - "if (defined($bError) && $bError)\n" - "{\n" - "confess &log(ASSERT, \"${strTarget} is not a valid target\");\n" - "}\n" - "\n" - "return false;\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "\n\n\n\n\n\n" - "sub isTargetLink\n" - "{\n" - "my $self = shift;\n" - "my $strTarget = shift;\n" - "\n" - "$self->isTargetValid($strTarget, true);\n" - "\n" - "return $self->test(MANIFEST_SECTION_BACKUP_TARGET, $strTarget, MANIFEST_SUBKEY_TYPE, MANIFEST_VALUE_LINK);\n" - "}\n" - "\n\n\n\n\n\n" - "sub isTargetFile\n" - "{\n" - "my $self = shift;\n" - "my $strTarget = shift;\n" - "\n" - "$self->isTargetValid($strTarget, true);\n" - "\n" - "return $self->test(MANIFEST_SECTION_BACKUP_TARGET, $strTarget, MANIFEST_SUBKEY_FILE);\n" - "}\n" - "\n\n\n\n\n\n" - "sub isTargetTablespace\n" - "{\n" - "my $self = shift;\n" - "my $strTarget = shift;\n" - "\n" - "$self->isTargetValid($strTarget, true);\n" - "\n" - "return $self->test(MANIFEST_SECTION_BACKUP_TARGET, $strTarget, MANIFEST_SUBKEY_TABLESPACE_ID);\n" - "}\n" - "\n\n\n\n\n\n" - "sub checkDelta\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strLastBackupSource,\n" - "$bOnlineSame,\n" - "$strTimelineCurrent,\n" - "$strTimelineLast,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->checkDelta', \\@_,\n" - "{name => 'strLastBackupSource'},\n" - "{name => 'bOnlineSame'},\n" - "{name => 'strTimelineCurrent', required => false},\n" - "{name => 'strTimelineLast', required => false},\n" - ");\n" - "\n" - "my $bDelta = false;\n" - "\n\n" - "if (defined($strTimelineLast) && defined($strTimelineCurrent))\n" - "{\n" - "\n" - "if ($strTimelineLast ne $strTimelineCurrent)\n" - "{\n" - "&log(WARN, \"a timeline switch has occurred since the ${strLastBackupSource} backup, enabling delta checksum\");\n" - "$bDelta = true;\n" - "}\n" - "}\n" - "\n\n" - "if (!$bDelta && !$bOnlineSame)\n" - "{\n" - "&log(WARN, \"the online option has changed since the ${strLastBackupSource} backup, enabling delta checksum\");\n" - "$bDelta = true;\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bDelta', value => $bDelta, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub checkDeltaFile\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$stryFileList,\n" - "$oPriorManifest,\n" - "$lTimeBegin,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->checkDeltaFile', \\@_,\n" - "{name => 'stryFileList'},\n" - "{name => 'oPriorManifest', required => false},\n" - "{name => 'lTimeBegin', required => false},\n" - ");\n" - "\n" - "my $bDelta = false;\n" - "\n\n" - "foreach my $strName (@{$stryFileList})\n" - "{\n" - "\n\n" - "if (defined($lTimeBegin) &&\n" - "($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP) > $lTimeBegin ||\n" - "(defined($oPriorManifest) &&\n" - "$oPriorManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_FUTURE, 'y'))))\n" - "{\n" - "&log(WARN, \"file $strName has timestamp in the future, enabling delta checksum\");\n" - "$bDelta = true;\n" - "last;\n" - "}\n" - "\n\n\n" - "if (defined($oPriorManifest) && $oPriorManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName) &&\n" - "($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP) <\n" - "$oPriorManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP) ||\n" - "($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) !=\n" - "$oPriorManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) &&\n" - "$self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP) ==\n" - "$oPriorManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP))))\n" - "{\n" - "&log(WARN, \"file $strName timestamp in the past or size changed but timestamp did not, enabling delta checksum\");\n" - "$bDelta = true;\n" - "last;\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bDelta', value => $bDelta, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub build\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$oStorageDbMaster,\n" - "$strPath,\n" - "$oLastManifest,\n" - "$bOnline,\n" - "$bDelta,\n" - "$hTablespaceMap,\n" - "$hDatabaseMap,\n" - "$rhExclude,\n" - "$strTimelineCurrent,\n" - "$strTimelineLast,\n" - "$strLevel,\n" - "$bTablespace,\n" - "$strParentPath,\n" - "$strFilter,\n" - "$iLevel,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->build', \\@_,\n" - "{name => 'oStorageDbMaster'},\n" - "{name => 'strPath'},\n" - "{name => 'oLastManifest', required => false},\n" - "{name => 'bOnline'},\n" - "{name => 'bDelta'},\n" - "{name => 'hTablespaceMap', required => false},\n" - "{name => 'hDatabaseMap', required => false},\n" - "{name => 'rhExclude', required => false},\n" - "{name => 'strTimelineCurrent', required => false},\n" - "{name => 'strTimelineLast', required => false},\n" - "{name => 'strLevel', required => false},\n" - "{name => 'bTablespace', required => false},\n" - "{name => 'strParentPath', required => false},\n" - "{name => 'strFilter', required => false},\n" - "{name => 'iLevel', required => false, default => 0},\n" - ");\n" - "\n\n" - "if ($iLevel >= 16)\n" - "{\n" - "confess &log(\n" - "ERROR,\n" - "\"recursion in manifest build exceeds depth of ${iLevel}: ${strLevel}\\n\" .\n" - "'HINT: is there a link loop in $PGDATA?',\n" - "ERROR_FORMAT);\n" - "}\n" - "\n" - "if (!defined($strLevel))\n" - "{\n" - "\n" - "if ($self->{bBuilt})\n" - "{\n" - "confess &log(ASSERT, \"manifest has already been built\");\n" - "}\n" - "\n" - "$self->{bBuilt} = true;\n" - "\n\n" - "$strLevel = MANIFEST_TARGET_PGDATA;\n" - "\n\n" - "if (!$bOnline && !defined($hTablespaceMap))\n" - "{\n" - "my $hTablespaceManifest = $oStorageDbMaster->manifest($strPath . '/' . DB_PATH_PGTBLSPC);\n" - "$hTablespaceMap = {};\n" - "\n" - "foreach my $strOid (sort(CORE::keys(%{$hTablespaceManifest})))\n" - "{\n" - "if ($strOid eq '.' or $strOid eq '..')\n" - "{\n" - "next;\n" - "}\n" - "\n" - "logDebugMisc($strOperation, \"found tablespace ${strOid} in offline mode\");\n" - "\n" - "$hTablespaceMap->{$strOid} = \"ts${strOid}\";\n" - "}\n" - "}\n" - "\n\n" - "if (defined($oLastManifest) && !$bDelta)\n" - "{\n" - "$bDelta = $self->checkDelta(\n" - "'last', $oLastManifest->boolTest(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef, $bOnline),\n" - "$strTimelineCurrent, $strTimelineLast);\n" - "}\n" - "}\n" - "\n" - "$self->set(MANIFEST_SECTION_BACKUP_TARGET, $strLevel, MANIFEST_SUBKEY_PATH, $strPath);\n" - "$self->set(MANIFEST_SECTION_BACKUP_TARGET, $strLevel, MANIFEST_SUBKEY_TYPE,\n" - "$strLevel eq MANIFEST_TARGET_PGDATA ? MANIFEST_VALUE_PATH : MANIFEST_VALUE_LINK);\n" - "\n" - "if ($bTablespace)\n" - "{\n" - "my $iTablespaceId = (split('\\/', $strLevel))[1];\n" - "\n" - "if (!defined($hTablespaceMap->{$iTablespaceId}))\n" - "{\n" - "confess &log(ASSERT, \"tablespace with oid ${iTablespaceId} not found in tablespace map\\n\" .\n" - "\"HINT: was a tablespace created or dropped during the backup?\");\n" - "}\n" - "\n" - "$self->set(MANIFEST_SECTION_BACKUP_TARGET, $strLevel, MANIFEST_SUBKEY_TABLESPACE_ID, $iTablespaceId);\n" - "$self->set(MANIFEST_SECTION_BACKUP_TARGET, $strLevel, MANIFEST_SUBKEY_TABLESPACE_NAME,\n" - "$hTablespaceMap->{$iTablespaceId});\n" - "}\n" - "\n" - "if (index($strPath, '/') != 0)\n" - "{\n" - "if (!defined($strParentPath))\n" - "{\n" - "confess &log(ASSERT, \"cannot get manifest for '${strPath}' when no parent path is specified\");\n" - "}\n" - "\n" - "$strPath = $oStorageDbMaster->pathAbsolute($strParentPath, $strPath);\n" - "}\n" - "\n\n" - "my $hManifest = $oStorageDbMaster->manifest($strPath, {strFilter => $strFilter});\n" - "my $strManifestType = MANIFEST_VALUE_LINK;\n" - "\n\n" - "foreach my $strName (sort(CORE::keys(%{$hManifest})))\n" - "{\n" - "my $strFile = $strLevel;\n" - "\n" - "if ($strName ne '.')\n" - "{\n" - "if ($strManifestType eq MANIFEST_VALUE_LINK && $hManifest->{$strName}{type} eq 'l')\n" - "{\n" - "confess &log(ERROR, 'link \\'' .\n" - "$self->dbPathGet(\n" - "$self->get(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_PATH), $strLevel) .\n" - "'\\' -> \\'' . $self->get(MANIFEST_SECTION_BACKUP_TARGET, $strLevel, MANIFEST_SUBKEY_PATH) .\n" - "'\\' cannot reference another link', ERROR_LINK_DESTINATION);\n" - "}\n" - "\n" - "if ($strManifestType eq MANIFEST_VALUE_LINK)\n" - "{\n" - "$strFile = dirname($strFile);\n" - "$self->set(MANIFEST_SECTION_BACKUP_TARGET, $strLevel, MANIFEST_SUBKEY_PATH,\n" - "dirname($self->get(MANIFEST_SECTION_BACKUP_TARGET, $strLevel, MANIFEST_SUBKEY_PATH)));\n" - "$self->set(MANIFEST_SECTION_BACKUP_TARGET, $strLevel, MANIFEST_SUBKEY_FILE, $strName);\n" - "}\n" - "\n" - "$strFile .= \"/${strName}\";\n" - "}\n" - "else\n" - "{\n" - "$strManifestType = MANIFEST_VALUE_PATH;\n" - "}\n" - "\n\n\n" - "next if ($bOnline && $strFile =~ (qw{^} . MANIFEST_TARGET_PGDATA . qw{/} . $self->walPath() . '\\/') &&\n" - "$strFile !~ ('^' . MANIFEST_TARGET_PGDATA . qw{/} . $self->walPath() . qw{/} . DB_PATH_ARCHIVESTATUS . '$'));\n" - "\n\n\n" - "next if $strName =~ ('(^|\\/)' . DB_FILE_PREFIX_TMP);\n" - "\n\n" - "next if $strFile =~ ('^' . MANIFEST_PATH_PGDYNSHMEM . '\\/') && $self->dbVersion() >= PG_VERSION_94;\n" - "\n\n" - "next if $strFile =~ ('^' . MANIFEST_PATH_PGNOTIFY . '\\/') && $self->dbVersion() >= PG_VERSION_90;\n" - "\n\n" - "next if $strFile =~ ('^' . MANIFEST_PATH_PGREPLSLOT . '\\/') && $self->dbVersion() >= PG_VERSION_94;\n" - "\n\n" - "next if $strFile =~ ('^' . MANIFEST_PATH_PGSERIAL . '\\/') && $self->dbVersion() >= PG_VERSION_91;\n" - "\n\n" - "next if $strFile =~ ('^' . MANIFEST_PATH_PGSNAPSHOTS . '\\/') && $self->dbVersion() >= PG_VERSION_92;\n" - "\n\n\n" - "next if $strFile =~ ('^' . MANIFEST_PATH_PGSTATTMP . '\\/') && $self->dbVersion() >= PG_VERSION_84;\n" - "\n\n" - "next if $strFile =~ ('^' . MANIFEST_PATH_PGSUBTRANS . '\\/');\n" - "\n\n" - "next if $strFile =~ (DB_FILE_PGINTERNALINIT . '$');\n" - "\n\n" - "if ($self->dbVersion() >= PG_VERSION_12)\n" - "{\n" - "next if ($strFile eq MANIFEST_FILE_RECOVERYSIGNAL || $strFile eq MANIFEST_FILE_STANDBYSIGNAL);\n" - "}\n" - "else\n" - "{\n" - "next if ($strFile eq MANIFEST_FILE_RECOVERYDONE || $strFile eq MANIFEST_FILE_RECOVERYCONF);\n" - "}\n" - "\n\n" - "if ($strFile eq MANIFEST_FILE_POSTGRESQLAUTOCONFTMP ||\n" - "$strFile eq MANIFEST_FILE_BACKUPLABELOLD ||\n" - "$strFile eq MANIFEST_FILE_POSTMASTEROPTS ||\n" - "$strFile eq MANIFEST_FILE_POSTMASTERPID)\n" - "{\n" - "next;\n" - "}\n" - "\n\n" - "if ($self->dbVersion() >= PG_VERSION_90 && $hManifest->{$strName}{type} eq 'f')\n" - "{\n" - "\n" - "my $strDir = dirname($strName);\n" - "\n\n" - "if ($strDir =~ '^base\\/[0-9]+$' ||\n" - "$strDir =~ ('^' . $self->tablespacePathGet() . '\\/[0-9]+$'))\n" - "{\n" - "\n" - "my $strBaseName = basename($strName);\n" - "\n\n\n" - "if ($strBaseName =~ '^t[0-9]+\\_[0-9]+(|\\_(fsm|vm)){0,1}(\\.[0-9]+){0,1}$')\n" - "{\n" - "next;\n" - "}\n" - "\n\n" - "if ($self->dbVersion() >= PG_VERSION_91)\n" - "{\n" - "\n" - "if ($strBaseName =~ '^[0-9]+(|\\_(fsm|vm)){0,1}(\\.[0-9]+){0,1}$')\n" - "{\n" - "\n" - "my ($strFileNode) = $strBaseName =~ '^(\\d+)';\n" - "\n\n" - "$strFileNode = $strDir. \"/\" . $strFileNode . \"_init\";\n" - "\n\n" - "if (exists($hManifest->{$strFileNode}) && $hManifest->{$strFileNode}{type} eq 'f')\n" - "{\n" - "next;\n" - "}\n" - "}\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "if (defined($rhExclude))\n" - "{\n" - "\n" - "my $strPgFile = $self->dbPathGet(undef, $strFile);\n" - "my $bExclude = false;\n" - "\n\n" - "foreach my $strExclude (sort(keys(%{$rhExclude})))\n" - "{\n" - "\n" - "if ($strExclude =~ /\\/$/)\n" - "{\n" - "if (index($strPgFile, $strExclude) == 0)\n" - "{\n" - "$bExclude = true;\n" - "}\n" - "}\n" - "\n" - "elsif ($strPgFile eq $strExclude || index($strPgFile, \"${strExclude}/\") == 0)\n" - "{\n" - "$bExclude = true;\n" - "}\n" - "\n\n" - "if ($bExclude)\n" - "{\n" - "&log(INFO, \"exclude ${strPgFile} from backup using '${strExclude}' exclusion\");\n" - "last;\n" - "}\n" - "}\n" - "\n\n" - "next if $bExclude;\n" - "}\n" - "\n" - "my $cType = $hManifest->{$strName}{type};\n" - "my $strSection = MANIFEST_SECTION_TARGET_PATH;\n" - "\n" - "if ($cType eq 'f')\n" - "{\n" - "$strSection = MANIFEST_SECTION_TARGET_FILE;\n" - "}\n" - "elsif ($cType eq 'l')\n" - "{\n" - "$strSection = MANIFEST_SECTION_TARGET_LINK;\n" - "}\n" - "elsif ($cType ne 'd')\n" - "{\n" - "&log(WARN, \"exclude special file '\" . $self->dbPathGet(undef, $strFile) . \"' from backup\");\n" - "next;\n" - "}\n" - "\n\n" - "my $bTablespace = false;\n" - "\n" - "if (index($strName, DB_PATH_PGTBLSPC . '/') == 0 && $strLevel eq MANIFEST_TARGET_PGDATA)\n" - "{\n" - "$bTablespace = true;\n" - "$strFile = MANIFEST_TARGET_PGDATA . '/' . $strName;\n" - "\n\n" - "if ($hManifest->{$strName}{type} ne 'l')\n" - "{\n" - "confess &log(ERROR, \"${strName} is not a symlink - \" . DB_PATH_PGTBLSPC . ' should contain only symlinks',\n" - "ERROR_LINK_EXPECTED);\n" - "}\n" - "\n\n" - "if (index($hManifest->{$strName}{link_destination}, \"${strPath}/\") == 0 ||\n" - "(index($hManifest->{$strName}{link_destination}, '/') != 0 &&\n" - "index($oStorageDbMaster->pathAbsolute($strPath . '/' . DB_PATH_PGTBLSPC,\n" - "$hManifest->{$strName}{link_destination}) . '/', \"${strPath}/\") == 0))\n" - "{\n" - "confess &log(ERROR, 'tablespace symlink ' . $hManifest->{$strName}{link_destination} .\n" - "' destination must not be in $PGDATA', ERROR_LINK_DESTINATION);\n" - "}\n" - "}\n" - "\n\n" - "if (defined($hManifest->{$strName}{user}))\n" - "{\n" - "$self->set($strSection, $strFile, MANIFEST_SUBKEY_USER, $hManifest->{$strName}{user});\n" - "}\n" - "else\n" - "{\n" - "$self->boolSet($strSection, $strFile, MANIFEST_SUBKEY_USER, false);\n" - "}\n" - "\n" - "if (defined($hManifest->{$strName}{group}))\n" - "{\n" - "$self->set($strSection, $strFile, MANIFEST_SUBKEY_GROUP, $hManifest->{$strName}{group});\n" - "}\n" - "else\n" - "{\n" - "$self->boolSet($strSection, $strFile, MANIFEST_SUBKEY_GROUP, false);\n" - "}\n" - "\n\n" - "if ($cType eq 'f' || $cType eq 'd')\n" - "{\n" - "$self->set($strSection, $strFile, MANIFEST_SUBKEY_MODE, $hManifest->{$strName}{mode});\n" - "}\n" - "\n\n" - "if ($cType eq 'f')\n" - "{\n" - "$self->set($strSection, $strFile, MANIFEST_SUBKEY_TIMESTAMP,\n" - "$hManifest->{$strName}{modification_time} + 0);\n" - "$self->set($strSection, $strFile, MANIFEST_SUBKEY_SIZE, $hManifest->{$strName}{size} + 0);\n" - "$self->boolSet($strSection, $strFile, MANIFEST_SUBKEY_MASTER,\n" - "($strFile eq MANIFEST_FILE_PGCONTROL || $self->isMasterFile($strFile)));\n" - "}\n" - "\n\n" - "if ($cType eq 'l')\n" - "{\n" - "my $strLinkDestination = $hManifest->{$strName}{link_destination};\n" - "$self->set($strSection, $strFile, MANIFEST_SUBKEY_DESTINATION, $strLinkDestination);\n" - "\n\n" - "my $strFilter;\n" - "\n" - "if ($bTablespace)\n" - "{\n" - "\n\n" - "if ($self->dbVersion() >= PG_VERSION_90)\n" - "{\n" - "$strFilter = $self->tablespacePathGet();\n" - "}\n" - "\n" - "$self->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGTBLSPC, undef,\n" - "$self->get(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA));\n" - "\n\n" - "$strFile = substr($strFile, length(MANIFEST_TARGET_PGDATA) + 1);\n" - "}\n" - "\n" - "$bDelta = $self->build(\n" - "$oStorageDbMaster, $strLinkDestination, undef, $bOnline, $bDelta, $hTablespaceMap, $hDatabaseMap, $rhExclude, undef,\n" - "undef, $strFile, $bTablespace, dirname(\"${strPath}/${strName}\"), $strFilter, $iLevel + 1);\n" - "}\n" - "}\n" - "\n\n" - "if ($strLevel eq MANIFEST_TARGET_PGDATA)\n" - "{\n" - "my $bTimeInFuture = false;\n" - "\n\n\n\n\n\n" - "my $lTimeBegin =\n" - "$oStorageDbMaster->can('protocol') ?\n" - "$oStorageDbMaster->protocol()->cmdExecute(OP_WAIT, [$bOnline]) : waitRemainder($bOnline);\n" - "\n\n" - "$self->linkCheck();\n" - "\n" - "if (defined($oLastManifest))\n" - "{\n" - "$self->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_PRIOR, undef,\n" - "$oLastManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL));\n" - "}\n" - "\n\n" - "foreach my $strDbName (sort(keys(%{$hDatabaseMap})))\n" - "{\n" - "$self->numericSet(MANIFEST_SECTION_DB, $strDbName, MANIFEST_KEY_DB_ID,\n" - "$hDatabaseMap->{$strDbName}{&MANIFEST_KEY_DB_ID});\n" - "$self->numericSet(MANIFEST_SECTION_DB, $strDbName, MANIFEST_KEY_DB_LAST_SYSTEM_ID,\n" - "$hDatabaseMap->{$strDbName}{&MANIFEST_KEY_DB_LAST_SYSTEM_ID});\n" - "}\n" - "\n\n" - "if (!$bDelta)\n" - "{\n" - "my @stryFileList = $self->keys(MANIFEST_SECTION_TARGET_FILE);\n" - "\n" - "if (@stryFileList)\n" - "{\n" - "$bDelta = $self->checkDeltaFile(\\@stryFileList, $oLastManifest, $lTimeBegin);\n" - "}\n" - "}\n" - "\n\n" - "foreach my $strName ($self->keys(MANIFEST_SECTION_TARGET_FILE))\n" - "{\n" - "\n\n" - "if ($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP) > $lTimeBegin ||\n" - "(defined($oLastManifest) &&\n" - "$oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_FUTURE, 'y')))\n" - "{\n" - "$bTimeInFuture = true;\n" - "\n\n" - "if ($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP) > $lTimeBegin)\n" - "{\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_FUTURE, 'y');\n" - "}\n" - "}\n" - "\n\n\n\n\n" - "elsif (defined($oLastManifest) && $oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName) &&\n" - "$self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) ==\n" - "$oLastManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) &&\n" - "($bDelta || ($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_SIZE) == 0 ||\n" - "$self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP) ==\n" - "$oLastManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_TIMESTAMP))))\n" - "{\n" - "\n" - "if ($oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REFERENCE))\n" - "{\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REFERENCE,\n" - "$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REFERENCE));\n" - "}\n" - "\n" - "else\n" - "{\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REFERENCE,\n" - "$oLastManifest->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL));\n" - "}\n" - "\n\n" - "if ($oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM))\n" - "{\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM,\n" - "$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM));\n" - "}\n" - "\n\n" - "if ($oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REPO_SIZE))\n" - "{\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REPO_SIZE,\n" - "$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_REPO_SIZE));\n" - "}\n" - "\n\n" - "if ($oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_MASTER))\n" - "{\n" - "$self->set(\n" - "MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_MASTER,\n" - "$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_MASTER));\n" - "}\n" - "\n\n" - "my $bChecksumPage = $oLastManifest->get(\n" - "MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE, false);\n" - "\n" - "if (defined($bChecksumPage))\n" - "{\n" - "$self->boolSet(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE, $bChecksumPage);\n" - "\n" - "if (!$bChecksumPage &&\n" - "$oLastManifest->test(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR))\n" - "{\n" - "$self->set(\n" - "MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR,\n" - "$oLastManifest->get(MANIFEST_SECTION_TARGET_FILE, $strName, MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR));\n" - "}\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "if ($bTimeInFuture)\n" - "{\n" - "&log(WARN, \"some files have timestamps in the future - they will be copied to prevent possible race conditions\");\n" - "}\n" - "\n\n" - "$self->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_COPY_START, undef, $lTimeBegin + ($bOnline ? 1 : 0));\n" - "\n\n" - "$self->buildDefault();\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bDelta', value => $bDelta, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n\n\n\n" - "sub linkCheck\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->linkCheck');\n" - "\n\n" - "my $strBasePath = $self->get(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_PATH);\n" - "\n" - "foreach my $strTargetParent ($self->keys(MANIFEST_SECTION_BACKUP_TARGET))\n" - "{\n" - "if ($self->isTargetLink($strTargetParent))\n" - "{\n" - "my $strParentPath = $self->get(MANIFEST_SECTION_BACKUP_TARGET, $strTargetParent, MANIFEST_SUBKEY_PATH);\n" - "my $strParentFile = $self->get(MANIFEST_SECTION_BACKUP_TARGET, $strTargetParent, MANIFEST_SUBKEY_FILE, false);\n" - "\n" - "foreach my $strTargetChild ($self->keys(MANIFEST_SECTION_BACKUP_TARGET))\n" - "{\n" - "if ($self->isTargetLink($strTargetChild) && $strTargetParent ne $strTargetChild)\n" - "{\n" - "my $strChildPath = $self->get(MANIFEST_SECTION_BACKUP_TARGET, $strTargetChild, MANIFEST_SUBKEY_PATH);\n" - "my $strChildFile = $self->get(MANIFEST_SECTION_BACKUP_TARGET, $strTargetParent, MANIFEST_SUBKEY_FILE, false);\n" - "\n" - "if (!(defined($strParentFile) && defined($strChildFile)) &&\n" - "index(\n" - "storageLocal()->pathAbsolute($strBasePath, $strChildPath) . '/',\n" - "storageLocal()->pathAbsolute($strBasePath, $strParentPath) . '/') == 0)\n" - "{\n" - "confess &log(ERROR, 'link ' . $self->dbPathGet($strBasePath, $strTargetChild) .\n" - "\" (${strChildPath}) references a subdirectory of or\" .\n" - "\" the same directory as link \" . $self->dbPathGet($strBasePath, $strTargetParent) .\n" - "\" (${strParentPath})\", ERROR_LINK_DESTINATION);\n" - "}\n" - "}\n" - "}\n" - "}\n" - "}\n" - "}\n" - "\n\n\n\n\n\n\n" - "sub fileAdd\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strManifestFile,\n" - "$lModificationTime,\n" - "$lSize,\n" - "$strChecksum,\n" - "$bMaster,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->fileAdd', \\@_,\n" - "{name => 'strManifestFile'},\n" - "{name => 'lModificationTime'},\n" - "{name => 'lSize'},\n" - "{name => 'lChecksum'},\n" - "{name => 'bMaster'},\n" - ");\n" - "\n\n" - "if (!$self->test(MANIFEST_SECTION_TARGET_FILE . ':default', MANIFEST_SUBKEY_USER) ||\n" - "!$self->test(MANIFEST_SECTION_TARGET_FILE . ':default', MANIFEST_SUBKEY_USER, undef,\n" - "$self->get(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_USER)))\n" - "{\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strManifestFile, MANIFEST_SUBKEY_USER,\n" - "$self->get(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_USER));\n" - "}\n" - "\n" - "if (!$self->test(MANIFEST_SECTION_TARGET_FILE . ':default', MANIFEST_SUBKEY_GROUP) ||\n" - "!$self->test(MANIFEST_SECTION_TARGET_FILE . ':default', MANIFEST_SUBKEY_GROUP, undef,\n" - "$self->get(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_GROUP)))\n" - "{\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strManifestFile, MANIFEST_SUBKEY_GROUP,\n" - "$self->get(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_GROUP));\n" - "}\n" - "\n" - "if (!$self->test(MANIFEST_SECTION_TARGET_FILE . ':default', MANIFEST_SUBKEY_MODE) ||\n" - "!$self->test(MANIFEST_SECTION_TARGET_FILE . ':default', MANIFEST_SUBKEY_MODE, undef, '0600'))\n" - "{\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strManifestFile, MANIFEST_SUBKEY_MODE, '0600');\n" - "}\n" - "\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strManifestFile, MANIFEST_SUBKEY_TIMESTAMP, $lModificationTime);\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strManifestFile, MANIFEST_SUBKEY_SIZE, $lSize);\n" - "$self->set(MANIFEST_SECTION_TARGET_FILE, $strManifestFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksum);\n" - "$self->boolSet(MANIFEST_SECTION_TARGET_FILE, $strManifestFile, MANIFEST_SUBKEY_MASTER, $bMaster);\n" - "}\n" - "\n\n\n\n\n\n" - "sub buildDefault\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->buildDefault');\n" - "\n\n" - "foreach my $strSection (&MANIFEST_SECTION_TARGET_FILE, &MANIFEST_SECTION_TARGET_PATH, &MANIFEST_SECTION_TARGET_LINK)\n" - "{\n" - "foreach my $strSubKey (&MANIFEST_SUBKEY_USER, &MANIFEST_SUBKEY_GROUP, &MANIFEST_SUBKEY_MODE, &MANIFEST_SUBKEY_MASTER)\n" - "{\n" - "\n" - "next if ($strSection eq MANIFEST_SECTION_TARGET_LINK && $strSubKey eq &MANIFEST_SUBKEY_MODE);\n" - "\n\n" - "next if ($strSection ne MANIFEST_SECTION_TARGET_FILE && $strSubKey eq &MANIFEST_SUBKEY_MASTER);\n" - "\n" - "my %oDefault;\n" - "my $iSectionTotal = 0;\n" - "\n" - "foreach my $strFile ($self->keys($strSection))\n" - "{\n" - "\n" - "next if (($strSubKey eq MANIFEST_SUBKEY_USER || $strSubKey eq MANIFEST_SUBKEY_GROUP) &&\n" - "$self->boolTest($strSection, $strFile, $strSubKey, false));\n" - "\n" - "my $strValue = $self->get($strSection, $strFile, $strSubKey);\n" - "\n" - "if (defined($oDefault{$strValue}))\n" - "{\n" - "$oDefault{$strValue}++;\n" - "}\n" - "else\n" - "{\n" - "$oDefault{$strValue} = 1;\n" - "}\n" - "\n" - "$iSectionTotal++;\n" - "}\n" - "\n" - "my $strMaxValue;\n" - "my $iMaxValueTotal = 0;\n" - "\n" - "foreach my $strValue (sort(keys(%oDefault)))\n" - "{\n" - "if ($oDefault{$strValue} > $iMaxValueTotal)\n" - "{\n" - "$iMaxValueTotal = $oDefault{$strValue};\n" - "$strMaxValue = $strValue;\n" - "}\n" - "}\n" - "\n" - "if (defined($strMaxValue) > 0 && $iMaxValueTotal > $iSectionTotal * MANIFEST_DEFAULT_MATCH_FACTOR)\n" - "{\n" - "if ($strSubKey eq MANIFEST_SUBKEY_MASTER)\n" - "{\n" - "$self->boolSet(\"${strSection}:default\", $strSubKey, undef, $strMaxValue);\n" - "}\n" - "else\n" - "{\n" - "$self->set(\"${strSection}:default\", $strSubKey, undef, $strMaxValue);\n" - "}\n" - "\n" - "foreach my $strFile ($self->keys($strSection))\n" - "{\n" - "if ($self->test($strSection, $strFile, $strSubKey, $strMaxValue))\n" - "{\n" - "$self->remove($strSection, $strFile, $strSubKey);\n" - "}\n" - "}\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub validate\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . 'validate');\n" - "\n\n\n" - "foreach my $strFile ($self->keys(MANIFEST_SECTION_TARGET_FILE))\n" - "{\n" - "\n" - "if (!$self->test(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE))\n" - "{\n" - "confess &log(ASSERT, \"manifest subvalue 'size' not set for file '${strFile}'\");\n" - "}\n" - "\n\n" - "if ($self->numericGet(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE) > 0 &&\n" - "!$self->test(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_CHECKSUM))\n" - "{\n" - "confess &log(ASSERT, \"manifest subvalue 'checksum' not set for file '${strFile}'\");\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n" - "sub dbVersion\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->get(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION);\n" - "}\n" - "\n\n\n\n" - "sub xactPath\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->dbVersion() >= PG_VERSION_10 ? 'pg_xact' : 'pg_clog';\n" - "}\n" - "\n\n\n\n" - "sub walPath\n" - "{\n" - "my $self = shift;\n" - "\n" - "return $self->dbVersion() >= PG_VERSION_10 ? 'pg_wal' : 'pg_xlog';\n" - "}\n" - "\n\n\n\n\n\n" - "sub isMasterFile\n" - "{\n" - "my $self = shift;\n" - "my $strFile = shift;\n" - "\n" - "return\n" - "$strFile !~ ('^(' . MANIFEST_TARGET_PGDATA . '\\/' . '(' . DB_PATH_BASE . '|' . DB_PATH_GLOBAL . '|' .\n" - "$self->xactPath() . '|' . DB_PATH_PGMULTIXACT . ')|' . DB_PATH_PGTBLSPC . ')\\/');\n" - "}\n" - "\n\n\n\n\n\n" - "sub isChecksumPage\n" - "{\n" - "my $strFile = shift;\n" - "\n" - "if (($strFile =~ ('^' . MANIFEST_TARGET_PGDATA . '\\/' . DB_PATH_BASE . '\\/[0-9]+\\/|^' . MANIFEST_TARGET_PGTBLSPC .\n" - "'\\/[0-9]+\\/[^\\/]+\\/[0-9]+\\/') &&\n" - "$strFile !~ ('(' . DB_FILE_PGFILENODEMAP . '|' . DB_FILE_PGINTERNALINIT . '|' . DB_FILE_PGVERSION . ')$')) ||\n" - "($strFile =~ ('^' . MANIFEST_TARGET_PGDATA . '\\/' . DB_PATH_GLOBAL . '\\/') &&\n" - "$strFile !~ ('(' . DB_FILE_PGFILENODEMAP . '|' . DB_FILE_PGINTERNALINIT . '|' . DB_FILE_PGVERSION . '|' .\n" - "DB_FILE_PGCONTROL . ')$')))\n" - "{\n" - "return true;\n" - "}\n" - "\n" - "return false;\n" - "}\n" - "\n" - "push @EXPORT, qw(isChecksumPage);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Base/Master.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Base::Master;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use Time::HiRes qw(gettimeofday);\n" - "use JSON::PP;\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Ini;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "use constant OP_NOOP => 'noop';\n" - "push @EXPORT, qw(OP_NOOP);\n" - "use constant OP_EXIT => 'exit';\n" - "push @EXPORT, qw(OP_EXIT);\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{strName},\n" - "$self->{strId},\n" - "$self->{oIo},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strName', trace => true},\n" - "{name => 'strId', trace => true},\n" - "{name => 'oIo', trace => true},\n" - ");\n" - "\n\n" - "$self->{oJSON} = JSON::PP->new()->allow_nonref();\n" - "\n\n" - "$self->{fKeepAliveTimeout} = $self->io()->timeout() / 2 > 120 ? 120 : $self->io()->timeout() / 2;\n" - "$self->{fKeepAliveTime} = gettimeofday();\n" - "\n\n" - "$self->{strErrorPrefix} = 'raised from ' . $self->{strId};\n" - "\n\n" - "$self->greetingRead();\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub DESTROY\n" - "{\n" - "my $self = shift;\n" - "\n" - "$self->close();\n" - "}\n" - "\n\n\n\n\n\n" - "sub greetingRead\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my $strGreeting = $self->io()->readLine(true);\n" - "\n\n" - "my $hGreeting;\n" - "\n" - "eval\n" - "{\n" - "$hGreeting = $self->{oJSON}->decode($strGreeting);\n" - "\n" - "return true;\n" - "}\n" - "\n" - "or do\n" - "{\n" - "$self->io()->error(ERROR_PROTOCOL, 'invalid protocol greeting', $strGreeting);\n" - "};\n" - "\n\n" - "for my $hParam ({strName => 'name', strExpected => PROJECT_NAME},\n" - "{strName => 'version', strExpected => PROJECT_VERSION},\n" - "{strName => 'service', strExpected => $self->{strName}})\n" - "{\n" - "if (!defined($hGreeting->{$hParam->{strName}}) || $hGreeting->{$hParam->{strName}} ne $hParam->{strExpected})\n" - "{\n" - "confess &log(ERROR,\n" - "'found name \\'' . (defined($hGreeting->{$hParam->{strName}}) ? $hGreeting->{$hParam->{strName}} : '[undef]') .\n" - "\"' in protocol greeting instead of expected '$hParam->{strExpected}'\", ERROR_HOST_CONNECT);\n" - "}\n" - "}\n" - "\n\n" - "$self->noOp();\n" - "}\n" - "\n\n\n\n\n\n" - "sub outputRead\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bOutputRequired,\n" - "$bSuppressLog,\n" - "$bWarnOnError,\n" - "$bRef,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->outputRead', \\@_,\n" - "{name => 'bOutputRequired', default => false, trace => true},\n" - "{name => 'bSuppressLog', required => false, trace => true},\n" - "{name => 'bWarnOnError', default => false, trace => true},\n" - "{name => 'bRef', default => false, trace => true},\n" - ");\n" - "\n" - "my $strProtocolResult = $self->io()->readLine();\n" - "\n" - "logDebugMisc\n" - "(\n" - "$strOperation, undef,\n" - "{name => 'strProtocolResult', value => $strProtocolResult, trace => true}\n" - ");\n" - "\n" - "my $hResult = $self->{oJSON}->decode($strProtocolResult);\n" - "\n\n" - "if (defined($hResult->{err}))\n" - "{\n" - "my $strError = $self->{strErrorPrefix} . (defined($hResult->{out}) ? \": $hResult->{out}\" : '');\n" - "\n\n" - "if (!$bWarnOnError)\n" - "{\n" - "confess &log(\n" - "ERROR, $strError . (defined($hResult->{errStack}) ? \"\\n$hResult->{errStack}\" : ''), $hResult->{err}, $bSuppressLog);\n" - "}\n" - "\n" - "&log(WARN, $strError, $hResult->{err});\n" - "undef($hResult->{out});\n" - "}\n" - "\n\n" - "$self->{fKeepAliveTime} = gettimeofday();\n" - "\n\n" - "if ($bOutputRequired && !defined($hResult->{out}))\n" - "{\n" - "confess &log(ERROR, \"$self->{strErrorPrefix}: output is not defined\", ERROR_PROTOCOL_OUTPUT_REQUIRED);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'hOutput', value => $hResult->{out}, ref => $bRef, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub cmdWrite\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strCommand,\n" - "$hParam,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->cmdWrite', \\@_,\n" - "{name => 'strCommand', trace => true},\n" - "{name => 'hParam', required => false, trace => true},\n" - ");\n" - "\n" - "my $strProtocolCommand = $self->{oJSON}->encode({cmd => $strCommand, param => $hParam});\n" - "\n" - "logDebugMisc\n" - "(\n" - "$strOperation, undef,\n" - "{name => 'strProtocolCommand', value => $strProtocolCommand, trace => true}\n" - ");\n" - "\n\n" - "$self->io()->writeLine($strProtocolCommand);\n" - "\n\n" - "$self->{fKeepAliveTime} = gettimeofday();\n" - "\n\n" - "logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub cmdExecute\n" - "{\n" - "my $self = shift;\n" - "my $strCommand = shift;\n" - "my $oParamRef = shift;\n" - "my $bOutputRequired = shift;\n" - "my $bWarnOnError = shift;\n" - "\n" - "$self->cmdWrite($strCommand, $oParamRef);\n" - "\n" - "return $self->outputRead($bOutputRequired, undef, $bWarnOnError);\n" - "}\n" - "\n\n\n\n\n\n" - "sub keepAlive\n" - "{\n" - "my $self = shift;\n" - "\n" - "if (gettimeofday() - $self->{fKeepAliveTimeout} > $self->{fKeepAliveTime})\n" - "{\n" - "$self->noOp();\n" - "}\n" - "}\n" - "\n\n\n\n\n\n" - "sub noOp\n" - "{\n" - "my $self = shift;\n" - "\n" - "$self->cmdExecute(OP_NOOP, undef, false);\n" - "$self->{fKeepAliveTime} = gettimeofday();\n" - "}\n" - "\n\n\n\n" - "sub io {shift->{oIo}}\n" - "sub master {true}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Base/Minion.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Base::Minion;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use JSON::PP;\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Ini;\n" - "use pgBackRest::Common::Lock;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::String;\n" - "use pgBackRest::LibC qw(:lock);\n" - "use pgBackRest::Protocol::Base::Master;\n" - "use pgBackRest::Protocol::Helper;\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "use constant OP_POST => 'post';\n" - "push @EXPORT, qw(OP_POST);\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{strName},\n" - "$self->{oIo},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strName', trace => true},\n" - "{name => 'oIo', trace => true},\n" - ");\n" - "\n\n" - "$self->{oJSON} = JSON::PP->new()->allow_nonref();\n" - "\n\n" - "$self->greetingWrite();\n" - "\n\n" - "$self->{hCommandMap} = $self->can('init') ? $self->init() : undef;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub greetingWrite\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "$self->io()->writeLine((JSON::PP->new()->canonical()->allow_nonref())->encode(\n" - "{name => PROJECT_NAME, service => $self->{strName}, version => PROJECT_VERSION}));\n" - "}\n" - "\n\n\n\n\n\n" - "sub errorWrite\n" - "{\n" - "my $self = shift;\n" - "my $oException = shift;\n" - "\n\n" - "if (!isException(\\$oException))\n" - "{\n" - "confess &log(ERROR, 'unknown error: ' . $oException, ERROR_UNKNOWN);\n" - "}\n" - "\n\n" - "$self->io()->writeLine($self->{oJSON}->encode({err => $oException->code(), out => $oException->message()}));\n" - "}\n" - "\n\n\n\n\n\n" - "sub outputWrite\n" - "{\n" - "my $self = shift;\n" - "\n" - "$self->io()->writeLine($self->{oJSON}->encode({out => \\@_}));\n" - "}\n" - "\n\n\n\n\n\n" - "sub cmdRead\n" - "{\n" - "my $self = shift;\n" - "\n" - "my $hCommand = $self->{oJSON}->decode($self->io()->readLine());\n" - "\n" - "return $hCommand->{cmd}, $hCommand->{param};\n" - "}\n" - "\n\n\n\n" - "sub process\n" - "{\n" - "my $self = shift;\n" - "my $strLockPath = shift;\n" - "my $strLockCommand = shift;\n" - "my $strLockStanza = shift;\n" - "my $iProcessId = shift;\n" - "\n\n" - "logLevelSet(undef, undef, OFF);\n" - "\n\n\n" - "my $oPermanentError;\n" - "\n\n" - "eval\n" - "{\n" - "\n\n" - "if (defined($strLockPath) && defined($strLockStanza) && $iProcessId == 0)\n" - "{\n" - "eval\n" - "{\n" - "if (lockAcquire($strLockPath, $strLockCommand, $strLockStanza, 30, true))\n" - "{\n" - "\n" - "lockStopTest();\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "$oPermanentError = $EVAL_ERROR;\n" - "};\n" - "}\n" - "\n" - "while (true)\n" - "{\n" - "my ($strCommand, $rParam) = $self->cmdRead();\n" - "\n" - "last if ($strCommand eq OP_EXIT);\n" - "\n\n" - "if (defined($oPermanentError))\n" - "{\n" - "$self->errorWrite($oPermanentError);\n" - "}\n" - "\n" - "else\n" - "{\n" - "eval\n" - "{\n" - "\n" - "if (defined($self->{hCommandMap}{$strCommand}))\n" - "{\n" - "$self->outputWrite($self->{hCommandMap}{$strCommand}->($rParam));\n" - "}\n" - "\n" - "elsif ($strCommand eq OP_NOOP)\n" - "{\n" - "protocolKeepAlive();\n" - "$self->outputWrite();\n" - "}\n" - "else\n" - "{\n" - "confess \"invalid command: ${strCommand}\";\n" - "}\n" - "\n\n" - "if (defined($self->{hCommandMap}{&OP_POST}))\n" - "{\n" - "$self->{hCommandMap}{&OP_POST}->();\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "\n" - "or do\n" - "{\n" - "$self->errorWrite($EVAL_ERROR);\n" - "};\n" - "}\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "my $oException = $EVAL_ERROR;\n" - "\n\n" - "logLevelSet(undef, undef, PROTOCOL);\n" - "\n\n" - "if (isException(\\$oException))\n" - "{\n" - "confess &log($oException->level(), $oException->message(), $oException->code());\n" - "}\n" - "\n\n" - "confess &log(ERROR, 'unknown error: ' . $oException, ERROR_UNKNOWN);\n" - "};\n" - "}\n" - "\n\n\n\n" - "sub io {shift->{oIo}}\n" - "sub master {false}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Command/Master.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Command::Master;\n" - "use parent 'pgBackRest::Protocol::Base::Master';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use File::Basename qw(dirname);\n" - "use Time::HiRes qw(gettimeofday);\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Ini;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::Io::Process;\n" - "use pgBackRest::Protocol::Base::Master;\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strName,\n" - "$strId,\n" - "$strCommand,\n" - "$iBufferMax,\n" - "$iCompressLevel,\n" - "$iCompressLevelNetwork,\n" - "$iProtocolTimeout,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strName'},\n" - "{name => 'strId'},\n" - "{name => 'strCommand'},\n" - "{name => 'iBufferMax'},\n" - "{name => 'iCompressLevel'},\n" - "{name => 'iCompressLevelNetwork'},\n" - "{name => 'iProtocolTimeout'},\n" - ");\n" - "\n\n" - "if (!defined($strCommand))\n" - "{\n" - "confess &log(ASSERT, 'strCommand must be set');\n" - "}\n" - "\n\n" - "my $oIo = new pgBackRest::Common::Io::Process(\n" - "new pgBackRest::Common::Io::Buffered(\n" - "new pgBackRest::Common::Io::Handle($strId), $iProtocolTimeout, $iBufferMax), $strCommand);\n" - "\n\n" - "my $self = $class->SUPER::new($strName, $strId, $oIo);\n" - "bless $self, $class;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub close\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bComplete,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->close', \\@_,\n" - "{name => 'bComplete', default => false, trace => true},\n" - ");\n" - "\n\n" - "my $iExitStatus = 0;\n" - "my $bClosed = false;\n" - "\n\n" - "if (defined($self->io()) && defined($self->io()->processId()))\n" - "{\n" - "&log(TRACE, \"sending exit command to process\");\n" - "\n" - "eval\n" - "{\n" - "$self->cmdWrite(OP_EXIT);\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "my $oException = $EVAL_ERROR;\n" - "my $strError = 'unable to shutdown protocol';\n" - "my $strHint = 'HINT: the process completed all operations successfully but protocol-timeout may need to be increased.';\n" - "\n" - "if (isException(\\$oException))\n" - "{\n" - "$iExitStatus = $oException->code();\n" - "}\n" - "else\n" - "{\n" - "if (!defined($oException))\n" - "{\n" - "$oException = 'unknown error';\n" - "}\n" - "\n" - "$iExitStatus = ERROR_UNKNOWN;\n" - "}\n" - "\n" - "&log(WARN,\n" - "$strError . ($iExitStatus == ERROR_UNKNOWN ? '' : sprintf(' [%03d]', $oException->code())) . ': ' .\n" - "($iExitStatus == ERROR_UNKNOWN ? $oException : $oException->message()) .\n" - "($bComplete ? \"\\n${strHint}\" : ''));\n" - "};\n" - "\n" - "$self->{oIo}->close();\n" - "undef($self->{oIo});\n" - "$bClosed = true;\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'iExitStatus', value => $iExitStatus, trace => !$bClosed}\n" - ");\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Command/Minion.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Command::Minion;\n" - "use parent 'pgBackRest::Protocol::Base::Minion';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use JSON::PP;\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Ini;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::String;\n" - "use pgBackRest::Protocol::Base::Minion;\n" - "use pgBackRest::Common::Io::Buffered;\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strName,\n" - "$iBufferMax,\n" - "$iProtocolTimeout,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strName'},\n" - "{name => 'iBufferMax'},\n" - "{name => 'iProtocolTimeout'},\n" - ");\n" - "\n\n" - "my $oIo =\n" - "new pgBackRest::Common::Io::Buffered(\n" - "new pgBackRest::Common::Io::Handle('stdio', *STDIN, *STDOUT), $iProtocolTimeout, $iBufferMax);\n" - "\n\n" - "my $self = $class->SUPER::new($strName, $oIo);\n" - "bless $self, $class;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Helper.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Helper;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Protocol::Remote::Master;\n" - "use pgBackRest::Version;\n" - "\n\n\n\n\n" - "use constant OP_BACKUP_FILE => 'backupFile';\n" - "push @EXPORT, qw(OP_BACKUP_FILE);\n" - "\n\n" - "use constant OP_ARCHIVE_GET_CHECK => 'archiveCheck';\n" - "push @EXPORT, qw(OP_ARCHIVE_GET_CHECK);\n" - "\n\n" - "use constant OP_DB_CONNECT => 'dbConnect';\n" - "push @EXPORT, qw(OP_DB_CONNECT);\n" - "use constant OP_DB_EXECUTE_SQL => 'dbExecSql';\n" - "push @EXPORT, qw(OP_DB_EXECUTE_SQL);\n" - "use constant OP_DB_INFO => 'dbInfo';\n" - "push @EXPORT, qw(OP_DB_INFO);\n" - "\n\n" - "use constant OP_STORAGE_OPEN_READ => 'storageOpenRead';\n" - "push @EXPORT, qw(OP_STORAGE_OPEN_READ);\n" - "use constant OP_STORAGE_OPEN_WRITE => 'storageOpenWrite';\n" - "push @EXPORT, qw(OP_STORAGE_OPEN_WRITE);\n" - "use constant OP_STORAGE_CIPHER_PASS_USER => 'storageCipherPassUser';\n" - "push @EXPORT, qw(OP_STORAGE_CIPHER_PASS_USER);\n" - "use constant OP_STORAGE_EXISTS => 'storageExists';\n" - "push @EXPORT, qw(OP_STORAGE_EXISTS);\n" - "use constant OP_STORAGE_HASH_SIZE => 'storageHashSize';\n" - "push @EXPORT, qw(OP_STORAGE_HASH_SIZE);\n" - "use constant OP_STORAGE_LIST => 'storageList';\n" - "push @EXPORT, qw(OP_STORAGE_LIST);\n" - "use constant OP_STORAGE_MANIFEST => 'storageManifest';\n" - "push @EXPORT, qw(OP_STORAGE_MANIFEST);\n" - "use constant OP_STORAGE_MOVE => 'storageMove';\n" - "push @EXPORT, qw(OP_STORAGE_MOVE);\n" - "use constant OP_STORAGE_PATH_GET => 'storagePathGet';\n" - "push @EXPORT, qw(OP_STORAGE_PATH_GET);\n" - "\n\n" - "use constant OP_RESTORE_FILE => 'restoreFile';\n" - "push @EXPORT, qw(OP_RESTORE_FILE);\n" - "\n\n" - "use constant OP_WAIT => 'wait';\n" - "push @EXPORT, qw(OP_WAIT);\n" - "\n\n\n\n" - "my $hProtocol = {};\n" - "\n\n\n\n\n\n" - "sub isRepoLocal\n" - "{\n" - "\n" - "if (cfgCommandTest(CFGCMD_REMOTE) && !cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_BACKUP))\n" - "{\n" - "confess &log(ASSERT, 'isRepoLocal() not valid on ' . cfgOption(CFGOPT_TYPE) . ' remote');\n" - "}\n" - "\n" - "return cfgOptionTest(CFGOPT_REPO_HOST) ? false : true;\n" - "}\n" - "\n" - "push @EXPORT, qw(isRepoLocal);\n" - "\n\n\n\n" - "sub isDbLocal\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$iRemoteIdx,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::isDbLocal', \\@_,\n" - "{name => 'iRemoteIdx', optional => true, default => cfgOptionValid(CFGOPT_HOST_ID) ? cfgOption(CFGOPT_HOST_ID) : 1,\n" - "trace => true},\n" - ");\n" - "\n\n" - "if (cfgCommandTest(CFGCMD_REMOTE) && !cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB))\n" - "{\n" - "confess &log(ASSERT, 'isDbLocal() not valid on ' . cfgOption(CFGOPT_TYPE) . ' remote');\n" - "}\n" - "\n" - "my $bLocal = cfgOptionTest(cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iRemoteIdx)) ? false : true;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bLocal', value => $bLocal, trace => true}\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(isDbLocal);\n" - "\n\n\n\n" - "sub protocolParam\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strCommand,\n" - "$strRemoteType,\n" - "$iRemoteIdx,\n" - "$strBackRestBin,\n" - "$iProcessIdx,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::protocolParam', \\@_,\n" - "{name => 'strCommand'},\n" - "{name => 'strRemoteType'},\n" - "{name => 'iRemoteIdx', default => cfgOptionValid(CFGOPT_HOST_ID) ? cfgOption(CFGOPT_HOST_ID) : 1},\n" - "{name => 'strBackRestBin', optional => true},\n" - "{name => 'iProcessIdx', optional => true,\n" - "default => cfgOptionValid(CFGOPT_PROCESS) ? cfgOption(CFGOPT_PROCESS, false) : undef},\n" - ");\n" - "\n\n" - "my $iOptionIdCmd = CFGOPT_REPO_HOST_CMD;\n" - "my $iOptionIdConfig = CFGOPT_REPO_HOST_CONFIG;\n" - "my $iOptionIdConfigIncludePath = CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH;\n" - "my $iOptionIdConfigPath = CFGOPT_REPO_HOST_CONFIG_PATH;\n" - "my $iOptionIdHost = CFGOPT_REPO_HOST;\n" - "my $iOptionIdUser = CFGOPT_REPO_HOST_USER;\n" - "my $strOptionDbPath = undef;\n" - "my $strOptionDbPort = undef;\n" - "my $strOptionDbSocketPath = undef;\n" - "my $strOptionSshPort = CFGOPT_REPO_HOST_PORT;\n" - "\n" - "if ($strRemoteType eq CFGOPTVAL_REMOTE_TYPE_DB)\n" - "{\n" - "$iOptionIdCmd = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CMD, $iRemoteIdx);\n" - "$iOptionIdConfig = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG, $iRemoteIdx);\n" - "$iOptionIdConfigIncludePath = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH, $iRemoteIdx);\n" - "$iOptionIdConfigPath = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_PATH, $iRemoteIdx);\n" - "$iOptionIdHost = cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iRemoteIdx);\n" - "$iOptionIdUser = cfgOptionIdFromIndex(CFGOPT_PG_HOST_USER, $iRemoteIdx);\n" - "$strOptionSshPort = cfgOptionIdFromIndex(CFGOPT_PG_HOST_PORT, $iRemoteIdx);\n" - "}\n" - "\n\n" - "if (cfgOptionValid(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)))\n" - "{\n" - "$strOptionDbPath =\n" - "cfgOptionSource(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx)) eq CFGDEF_SOURCE_DEFAULT ?\n" - "undef : cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iRemoteIdx));\n" - "}\n" - "\n\n" - "if (cfgOptionValid(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $iRemoteIdx)))\n" - "{\n" - "$strOptionDbPort =\n" - "cfgOptionSource(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $iRemoteIdx)) eq CFGDEF_SOURCE_DEFAULT ?\n" - "undef : cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $iRemoteIdx));\n" - "}\n" - "\n\n" - "if (cfgOptionValid(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $iRemoteIdx)))\n" - "{\n" - "$strOptionDbSocketPath =\n" - "cfgOptionSource(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $iRemoteIdx)) eq CFGDEF_SOURCE_DEFAULT ?\n" - "undef : cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $iRemoteIdx));\n" - "}\n" - "\n\n" - "my $rhCommandOption =\n" - "{\n" - "&CFGOPT_COMMAND => {value => $strCommand},\n" - "&CFGOPT_PROCESS => {value => defined($iProcessIdx) ? $iProcessIdx : 0},\n" - "&CFGOPT_CONFIG =>\n" - "{value => cfgOptionValid($iOptionIdConfig) && cfgOptionSource($iOptionIdConfig) eq CFGDEF_SOURCE_DEFAULT ?\n" - "undef : cfgOption($iOptionIdConfig)},\n" - "&CFGOPT_CONFIG_INCLUDE_PATH =>\n" - "{value => cfgOptionValid($iOptionIdConfigIncludePath) &&\n" - "cfgOptionSource($iOptionIdConfigIncludePath) eq CFGDEF_SOURCE_DEFAULT ?\n" - "undef : cfgOption($iOptionIdConfigIncludePath)},\n" - "&CFGOPT_CONFIG_PATH =>\n" - "{value => cfgOptionValid($iOptionIdConfigPath) && cfgOptionSource($iOptionIdConfigPath) eq CFGDEF_SOURCE_DEFAULT ?\n" - "undef : cfgOption($iOptionIdConfigPath)},\n" - "&CFGOPT_TYPE => {value => $strRemoteType},\n" - "&CFGOPT_LOG_PATH => {},\n" - "&CFGOPT_LOCK_PATH => {},\n" - "\n\n" - "&CFGOPT_LOG_LEVEL_FILE => {value => cfgOption(CFGOPT_LOG_SUBPROCESS) ? cfgOption(CFGOPT_LOG_LEVEL_FILE) : lc(OFF)},\n" - "\n\n\n" - "&CFGOPT_LOG_LEVEL_STDERR => {},\n" - "\n" - "cfgOptionIdFromIndex(CFGOPT_PG_PATH, 1) => {value => $strOptionDbPath},\n" - "cfgOptionIdFromIndex(CFGOPT_PG_PORT, 1) => {value => $strOptionDbPort},\n" - "cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, 1) => {value => $strOptionDbSocketPath},\n" - "\n\n" - "&CFGOPT_BUFFER_SIZE => {value => cfgOption(CFGOPT_BUFFER_SIZE)},\n" - "&CFGOPT_COMPRESS_LEVEL => {value => cfgOption(CFGOPT_COMPRESS_LEVEL)},\n" - "&CFGOPT_COMPRESS_LEVEL_NETWORK => {value => cfgOption(CFGOPT_COMPRESS_LEVEL_NETWORK)},\n" - "&CFGOPT_PROTOCOL_TIMEOUT => {value => cfgOption(CFGOPT_PROTOCOL_TIMEOUT)}\n" - "};\n" - "\n\n\n" - "for (my $iOptionIdx = 1; $iOptionIdx <= cfgOptionIndexTotal(CFGOPT_PG_HOST); $iOptionIdx++)\n" - "{\n" - "if ($iOptionIdx != 1)\n" - "{\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG, $iOptionIdx)} = {};\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH, $iOptionIdx)} = {};\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_PATH, $iOptionIdx)} = {};\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iOptionIdx)} = {};\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iOptionIdx)} = {};\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_PORT, $iOptionIdx)} = {};\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $iOptionIdx)} = {};\n" - "}\n" - "\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CMD, $iOptionIdx)} = {};\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_USER, $iOptionIdx)} = {};\n" - "$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_PORT, $iOptionIdx)} = {};\n" - "}\n" - "\n\n" - "my $strRemoteCommand = cfgCommandWrite(\n" - "CFGCMD_REMOTE, true, defined($strBackRestBin) ? $strBackRestBin : cfgOption($iOptionIdCmd), undef, $rhCommandOption);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strRemoteHost', value => cfgOption($iOptionIdHost)},\n" - "{name => 'strRemoteHostUser', value => cfgOption($iOptionIdUser)},\n" - "{name => 'strRemoteHostSshPort', value => cfgOption($strOptionSshPort, false)},\n" - "{name => 'strRemoteCommand', value => $strRemoteCommand},\n" - ");\n" - "}\n" - "\n\n\n\n\n\n\n" - "sub protocolGet\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strRemoteType,\n" - "$iRemoteIdx,\n" - "$bCache,\n" - "$strBackRestBin,\n" - "$iProcessIdx,\n" - "$strCommand,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::protocolGet', \\@_,\n" - "{name => 'strRemoteType'},\n" - "{name => 'iRemoteIdx', default => cfgOptionValid(CFGOPT_HOST_ID) ? cfgOption(CFGOPT_HOST_ID) : 1},\n" - "{name => 'bCache', optional => true, default => true},\n" - "{name => 'strBackRestBin', optional => true},\n" - "{name => 'iProcessIdx', optional => true},\n" - "{name => 'strCommand', optional => true,\n" - "default => cfgOptionValid(CFGOPT_COMMAND) ? cfgOption(CFGOPT_COMMAND) : cfgCommandName(cfgCommandGet())},\n" - ");\n" - "\n\n" - "my $oProtocol;\n" - "\n\n" - "if (!cfgOptionTest(\n" - "cfgOptionIdFromIndex($strRemoteType eq CFGOPTVAL_REMOTE_TYPE_DB ? CFGOPT_PG_HOST : CFGOPT_REPO_HOST, $iRemoteIdx)))\n" - "{\n" - "confess &log(ASSERT, 'protocol cannot be created when remote host is not specified');\n" - "}\n" - "\n" - "else\n" - "{\n" - "\n" - "$oProtocol =\n" - "$bCache && defined($$hProtocol{$strRemoteType}{$iRemoteIdx}) ? $$hProtocol{$strRemoteType}{$iRemoteIdx} : undef;\n" - "\n" - "if ($bCache && $$hProtocol{$strRemoteType}{$iRemoteIdx})\n" - "{\n" - "$oProtocol = $$hProtocol{$strRemoteType}{$iRemoteIdx};\n" - "logDebugMisc($strOperation, 'found cached protocol');\n" - "\n\n\n" - "$oProtocol->noOp();\n" - "}\n" - "\n\n" - "if (!defined($oProtocol))\n" - "{\n" - "logDebugMisc($strOperation, 'create (' . ($bCache ? '' : 'un') . 'cached) remote protocol');\n" - "\n" - "my ($strRemoteHost, $strRemoteHostUser, $strRemoteHostSshPort, $strRemoteCommand) = protocolParam(\n" - "$strCommand, $strRemoteType, $iRemoteIdx, {strBackRestBin => $strBackRestBin, iProcessIdx => $iProcessIdx});\n" - "\n" - "$oProtocol = new pgBackRest::Protocol::Remote::Master\n" - "(\n" - "cfgOption(CFGOPT_CMD_SSH),\n" - "$strRemoteCommand,\n" - "cfgOption(CFGOPT_BUFFER_SIZE),\n" - "cfgOption(CFGOPT_COMPRESS_LEVEL),\n" - "cfgOption(CFGOPT_COMPRESS_LEVEL_NETWORK),\n" - "$strRemoteHost,\n" - "$strRemoteHostUser,\n" - "$strRemoteHostSshPort,\n" - "cfgOption(CFGOPT_PROTOCOL_TIMEOUT)\n" - ");\n" - "\n\n" - "if ($bCache)\n" - "{\n" - "$$hProtocol{$strRemoteType}{$iRemoteIdx} = $oProtocol;\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oProtocol', value => $oProtocol, trace => true}\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(protocolGet);\n" - "\n\n\n\n" - "sub protocolList\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strRemoteType,\n" - "$iRemoteIdx,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::protocolList', \\@_,\n" - "{name => 'strRemoteType', required => false, trace => true},\n" - "{name => 'iRemoteIdx', required => false, trace => true},\n" - ");\n" - "\n" - "my @oyProtocol;\n" - "\n" - "if (!defined($strRemoteType))\n" - "{\n" - "foreach my $strRemoteType (sort(keys(%{$hProtocol})))\n" - "{\n" - "push(@oyProtocol, protocolList($strRemoteType));\n" - "}\n" - "}\n" - "elsif (!defined($iRemoteIdx))\n" - "{\n" - "foreach my $iRemoteIdx (sort(keys(%{$hProtocol->{$strRemoteType}})))\n" - "{\n" - "push(@oyProtocol, protocolList($strRemoteType, $iRemoteIdx));\n" - "}\n" - "}\n" - "elsif (defined($hProtocol->{$strRemoteType}{$iRemoteIdx}))\n" - "{\n" - "push(@oyProtocol, {strRemoteType => $strRemoteType, iRemoteIdx => $iRemoteIdx});\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oyProtocol', value => \\@oyProtocol, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub protocolDestroy\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strRemoteType,\n" - "$iRemoteIdx,\n" - "$bComplete,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::protocolDestroy', \\@_,\n" - "{name => 'strRemoteType', required => false},\n" - "{name => 'iRemoteIdx', required => false},\n" - "{name => 'bComplete', default => false},\n" - ");\n" - "\n" - "my $iExitStatus = 0;\n" - "\n" - "foreach my $rhProtocol (protocolList($strRemoteType, $iRemoteIdx))\n" - "{\n" - "logDebugMisc(\n" - "$strOperation, 'found cached protocol',\n" - "{name => 'strRemoteType', value => $rhProtocol->{strRemoteType}},\n" - "{name => 'iRemoteIdx', value => $rhProtocol->{iRemoteIdx}});\n" - "\n" - "$iExitStatus = $hProtocol->{$rhProtocol->{strRemoteType}}{$rhProtocol->{iRemoteIdx}}->close($bComplete);\n" - "delete($hProtocol->{$rhProtocol->{strRemoteType}}{$rhProtocol->{iRemoteIdx}});\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'iExitStatus', value => $iExitStatus}\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(protocolDestroy);\n" - "\n\n\n\n" - "sub protocolKeepAlive\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strRemoteType,\n" - "$iRemoteIdx,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::protocolDestroy', \\@_,\n" - "{name => 'strRemoteType', required => false, trace => true},\n" - "{name => 'iRemoteIdx', required => false, trace => true},\n" - ");\n" - "\n" - "foreach my $rhProtocol (protocolList($strRemoteType, $iRemoteIdx))\n" - "{\n" - "$hProtocol->{$rhProtocol->{strRemoteType}}{$rhProtocol->{iRemoteIdx}}->keepAlive();\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n" - "push @EXPORT, qw(protocolKeepAlive);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Local/Master.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Local::Master;\n" - "use parent 'pgBackRest::Protocol::Command::Master';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Protocol::Command::Master;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strCommand,\n" - "$iProcessIdx,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strCommand'},\n" - "{name => 'iProcessIdx', default => 1},\n" - ");\n" - "\n\n" - "my $self = $class->SUPER::new(\n" - "'local', \"local-${iProcessIdx} process\", $strCommand, cfgOption(CFGOPT_BUFFER_SIZE),\n" - "cfgOption(CFGOPT_COMPRESS_LEVEL), cfgOption(CFGOPT_COMPRESS_LEVEL_NETWORK), cfgOption(CFGOPT_PROTOCOL_TIMEOUT));\n" - "\n" - "bless $self, $class;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Local/Process.pm", - .data = - "\n\n\n\n\n" - "package pgBackRest::Protocol::Local::Process;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use IO::Select;\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Protocol::Local::Master;\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{strHostType},\n" - "$self->{iSelectTimeout},\n" - "$self->{strBackRestBin},\n" - "$self->{bConfessError},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strHostType'},\n" - "{name => 'iSelectTimeout', default => int(cfgOption(CFGOPT_PROTOCOL_TIMEOUT) / 2)},\n" - "{name => 'strBackRestBin', default => projectBin()},\n" - "{name => 'bConfessError', default => true},\n" - ");\n" - "\n\n" - "$self->{hHostMap} = {};\n" - "$self->{hyHost} = undef;\n" - "\n\n" - "$self->reset();\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub reset\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->reset');\n" - "\n\n" - "$self->{oSelect} = undef;\n" - "\n\n" - "$self->{hyLocalMap} = undef;\n" - "$self->{hyLocal} = undef;\n" - "\n\n" - "$self->{bProcessing} = false;\n" - "\n\n" - "$self->{iQueued} = 0;\n" - "\n\n" - "$self->{iRunning} = 0;\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub hostAdd\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$iHostConfigIdx,\n" - "$iProcessMax,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->hostAdd', \\@_,\n" - "{name => 'iHostConfigIdx'},\n" - "{name => 'iProcessMax'},\n" - ");\n" - "\n" - "my $iHostIdx = $self->{hHostMap}{$iHostConfigIdx};\n" - "\n" - "if (!defined($iHostIdx))\n" - "{\n" - "$iHostIdx = defined($self->{hyHost}) ? @{$self->{hyHost}} : 0;\n" - "$self->{hHostMap}{$iHostConfigIdx} = $iHostIdx;\n" - "}\n" - "\n" - "my $hHost =\n" - "{\n" - "iHostConfigIdx => $iHostConfigIdx,\n" - "iProcessMax => $iProcessMax,\n" - "};\n" - "\n" - "push(@{$self->{hyHost}}, $hHost);\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub hostConnect\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->hostConnect');\n" - "\n\n" - "$self->{oSelect} = IO::Select->new();\n" - "\n\n" - "my $iHostIdx = 0;\n" - "\n" - "foreach my $hHost (@{$self->{hyHost}})\n" - "{\n" - "\n" - "if (!defined($hHost->{hyQueue}))\n" - "{\n" - "logDebugMisc(\n" - "$strOperation, \"no jobs for host\",\n" - "{name => 'strHostType', value => $self->{strHostType}},\n" - "{name => 'iHostConfigIdx', value => $hHost->{iHostConfigIdx}});\n" - "next;\n" - "}\n" - "\n" - "for (my $iHostProcessIdx = 0; $iHostProcessIdx < $hHost->{iProcessMax}; $iHostProcessIdx++)\n" - "{\n" - "my $iLocalIdx = defined($self->{hyLocal}) ? @{$self->{hyLocal}} : 0;\n" - "my $iProcessId = $iLocalIdx + 1;\n" - "\n" - "logDebugMisc(\n" - "$strOperation, 'start local process',\n" - "{name => 'strHostType', value => $self->{strHostType}},\n" - "{name => 'iHostProcessIdx', value => $iHostProcessIdx},\n" - "{name => 'iHostConfigIdx', value => $hHost->{iHostConfigIdx}},\n" - "{name => 'iHostIdx', value => $iHostIdx},\n" - "{name => 'iProcessId', value => $iProcessId});\n" - "\n" - "my $oLocal = new pgBackRest::Protocol::Local::Master\n" - "(\n" - "cfgCommandWrite(\n" - "CFGCMD_LOCAL, true, $self->{strBackRestBin}, undef,\n" - "{\n" - "&CFGOPT_COMMAND => {value => cfgCommandName(cfgCommandGet())},\n" - "&CFGOPT_PROCESS => {value => $iProcessId},\n" - "&CFGOPT_TYPE => {value => $self->{strHostType}},\n" - "&CFGOPT_HOST_ID => {value => $hHost->{iHostConfigIdx}},\n" - "\n\n" - "&CFGOPT_LOG_LEVEL_FILE =>\n" - "{value => cfgOption(CFGOPT_LOG_SUBPROCESS) ? cfgOption(CFGOPT_LOG_LEVEL_FILE) : lc(OFF)},\n" - "&CFGOPT_LOG_LEVEL_STDERR => {},\n" - "}),\n" - "$iLocalIdx + 1\n" - ");\n" - "\n" - "my $hLocal =\n" - "{\n" - "iHostIdx => $iHostIdx,\n" - "iProcessId => $iProcessId,\n" - "iHostProcessIdx => $iHostProcessIdx,\n" - "oLocal => $oLocal,\n" - "hndIn => fileno($oLocal->io()->handleRead()),\n" - "};\n" - "\n" - "push(@{$self->{hyLocal}}, $hLocal);\n" - "\n" - "$self->{hLocalMap}{$hLocal->{hndIn}} = $hLocal;\n" - "$self->{oSelect}->add($hLocal->{hndIn});\n" - "}\n" - "\n" - "$iHostIdx++;\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bResult', value => $iHostIdx > 0 ? true : false}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub init\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->init');\n" - "\n" - "if ($self->hostConnect())\n" - "{\n" - "foreach my $hLocal (@{$self->{hyLocal}})\n" - "{\n" - "my $hHost = $self->{hyHost}[$hLocal->{iHostIdx}];\n" - "my $hyQueue = $hHost->{hyQueue};\n" - "\n\n" - "$hLocal->{iDirection} = $hLocal->{iHostProcessIdx} % 2 == 0 ? 1 : -1;\n" - "$hLocal->{iQueueIdx} = int((@{$hyQueue} / $hHost->{iProcessMax}) * $hLocal->{iHostProcessIdx});\n" - "\n\n" - "$hLocal->{iQueueLastIdx} = $hLocal->{iQueueIdx} + ($hLocal->{iDirection} * -1);\n" - "\n" - "if ($hLocal->{iQueueLastIdx} < 0)\n" - "{\n" - "$hLocal->{iQueueLastIdx} = @{$hyQueue} - 1;\n" - "}\n" - "elsif ($hLocal->{iQueueLastIdx} >= @{$hyQueue})\n" - "{\n" - "$hLocal->{iQueueLastIdx} = 0;\n" - "}\n" - "\n" - "logDebugMisc(\n" - "$strOperation, 'init local process',\n" - "{name => 'iHostIdx', value => $hLocal->{iHostIdx}},\n" - "{name => 'iProcessId', value => $hLocal->{iProcessId}},\n" - "{name => 'iDirection', value => $hLocal->{iDirection}},\n" - "{name => 'iQueueIdx', value => $hLocal->{iQueueIdx}},\n" - "{name => 'iQueueLastIdx', value => $hLocal->{iQueueLastIdx}});\n" - "}\n" - "\n" - "$self->{bProcessing} = true;\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bResult', value => $self->processing()}\n" - ");\n" - "}\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" - "if (!$self->processing())\n" - "{\n" - "if (!$self->init())\n" - "{\n" - "logDebugMisc($strOperation, 'no jobs to run');\n" - "$self->reset();\n" - "return;\n" - "}\n" - "}\n" - "\n\n" - "my @hyResult = ();\n" - "my $iCompleted = 0;\n" - "\n" - "if ($self->{iRunning} > 0)\n" - "{\n" - "&logDebugMisc(\n" - "$strOperation, 'check running jobs',\n" - "{name => 'iRunning', value => $self->{iRunning}, trace => true});\n" - "\n\n" - "my @hndyIn = $self->{oSelect}->can_read($self->{iSelectTimeout});\n" - "\n\n" - "foreach my $hndIn (@hndyIn)\n" - "{\n" - "\n" - "my $hLocal = $self->{hLocalMap}{$hndIn};\n" - "\n" - "if (!defined($hLocal))\n" - "{\n" - "confess &log(ASSERT, \"unable to map from fileno ${hndIn} to local\");\n" - "}\n" - "\n\n" - "my $hJob = $hLocal->{hJob};\n" - "\n" - "eval\n" - "{\n" - "$hJob->{rResult} = $hLocal->{oLocal}->outputRead(true, undef, undef, true);\n" - "\n\n\n" - "if (ref($hJob->{rResult}) ne 'ARRAY')\n" - "{\n" - "my @resultArray = (${$hJob->{rResult}});\n" - "$hJob->{rResult} = \\@resultArray;\n" - "}\n" - "\n" - "return true;\n" - "}\n" - "or do\n" - "{\n" - "my $oException = $EVAL_ERROR;\n" - "\n\n" - "confess $oException if (!isException(\\$oException));\n" - "\n\n" - "if (!defined($hLocal->{oLocal}->io()->processId()))\n" - "{\n" - "confess logException($oException);\n" - "}\n" - "\n\n" - "if ($self->{bConfessError})\n" - "{\n" - "confess logException($oException);\n" - "}\n" - "\n" - "else\n" - "{\n" - "$hJob->{oException} = $oException;\n" - "}\n" - "};\n" - "\n" - "$hJob->{iProcessId} = $hLocal->{iProcessId};\n" - "push(@hyResult, $hJob);\n" - "\n" - "logDebugMisc(\n" - "$strOperation, 'job complete',\n" - "{name => 'iProcessId', value => $hJob->{iProcessId}},\n" - "{name => 'strKey', value => $hJob->{strKey}},\n" - "{name => 'rResult', value => $hJob->{rResult}});\n" - "\n\n" - "$hLocal->{hJob} = undef;\n" - "$self->{iRunning}--;\n" - "$iCompleted++;\n" - "}\n" - "}\n" - "\n\n" - "if ($self->{iRunning} == 0 || $iCompleted > 0)\n" - "{\n" - "&logDebugMisc(\n" - "$strOperation, 'get new jobs',\n" - "{name => 'iRunning', value => $self->{iRunning}, trace => true},\n" - "{name => 'iCompleted', value => $iCompleted, trace => true});\n" - "\n" - "my $bFound = false;\n" - "my $iLocalIdx = -1;\n" - "\n\n" - "foreach my $hLocal (@{$self->{hyLocal}})\n" - "{\n" - "\n" - "$iLocalIdx++;\n" - "next if (!defined($hLocal));\n" - "\n" - "my $hHost = $self->{hyHost}[$hLocal->{iHostIdx}];\n" - "my $hyQueue = $hHost->{hyQueue};\n" - "\n\n" - "if (!defined($hLocal->{hJob}))\n" - "{\n" - "\n" - "my $iQueueIdx = $hLocal->{iQueueIdx};\n" - "my $hJob = shift(@{$$hyQueue[$iQueueIdx]});\n" - "\n" - "while (!defined($hJob) && $iQueueIdx != $hLocal->{iQueueLastIdx})\n" - "{\n" - "$iQueueIdx += $hLocal->{iDirection};\n" - "\n" - "if ($iQueueIdx < 0)\n" - "{\n" - "$iQueueIdx = @{$hyQueue} - 1;\n" - "}\n" - "elsif ($iQueueIdx >= @{$hyQueue})\n" - "{\n" - "$iQueueIdx = 0;\n" - "}\n" - "\n" - "$hJob = shift(@{$$hyQueue[$iQueueIdx]});\n" - "}\n" - "\n\n" - "if (!defined($hJob))\n" - "{\n" - "logDebugMisc(\n" - "$strOperation, 'no jobs found, stop local',\n" - "{name => 'strHostType', value => $hLocal->{strHostType}},\n" - "{name => 'iHostConfigIdx', value => $hLocal->{iHostConfigIdx}},\n" - "{name => 'iHostIdx', value => $hLocal->{iHostIdx}},\n" - "{name => 'iProcessId', value => $hLocal->{iProcessId}});\n" - "\n\n" - "my $iHandleTotal = $self->{oSelect}->count();\n" - "\n" - "$self->{oSelect}->remove($hLocal->{hndIn});\n" - "\n" - "if ($iHandleTotal - $self->{oSelect}->count() != 1)\n" - "{\n" - "confess &log(ASSERT,\n" - "\"iProcessId $hLocal->{iProcessId}, handle $hLocal->{hndIn} was not removed from select object\");\n" - "}\n" - "\n\n" - "delete($self->{hLocalMap}{$hLocal->{hndIn}});\n" - "\n\n" - "$hLocal->{oLocal}->close(true);\n" - "\n\n" - "undef(${$self->{hyLocal}}[$iLocalIdx]);\n" - "\n\n" - "next;\n" - "}\n" - "\n\n" - "$hLocal->{hJob} = $hJob;\n" - "$bFound = true;\n" - "$self->{iRunning}++;\n" - "$self->{iQueued}--;\n" - "\n" - "logDebugMisc(\n" - "$strOperation, 'get job from queue',\n" - "{name => 'iHostIdx', value => $hLocal->{iHostIdx}},\n" - "{name => 'iProcessId', value => $hLocal->{iProcessId}},\n" - "{name => 'strQueueIdx', value => $iQueueIdx},\n" - "{name => 'strKey', value => $hLocal->{hJob}{strKey}});\n" - "\n\n" - "$hLocal->{oLocal}->cmdWrite($hLocal->{hJob}{strOp}, $hLocal->{hJob}->{rParam});\n" - "}\n" - "}\n" - "\n\n" - "if (!$bFound && !$self->{iRunning} && @hyResult == 0)\n" - "{\n" - "logDebugMisc($strOperation, 'all jobs complete');\n" - "$self->reset();\n" - "return;\n" - "}\n" - "}\n" - "\n\n" - "return \\@hyResult;\n" - "}\n" - "\n\n\n\n\n\n" - "sub queueJob\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$iHostConfigIdx,\n" - "$strQueue,\n" - "$strKey,\n" - "$strOp,\n" - "$rParam,\n" - "$rParamSecure,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->queueJob', \\@_,\n" - "{name => 'iHostConfigIdx'},\n" - "{name => 'strQueue'},\n" - "{name => 'strKey'},\n" - "{name => 'strOp'},\n" - "{name => 'rParam'},\n" - "{name => 'rParamSecure', optional => true, redact => true},\n" - ");\n" - "\n\n" - "if ($self->processing())\n" - "{\n" - "confess &log(ASSERT, 'new jobs cannot be added until processing is complete');\n" - "}\n" - "\n\n" - "if (defined($rParamSecure))\n" - "{\n" - "push(@{$rParam}, @{$rParamSecure});\n" - "}\n" - "\n\n" - "my $hJob =\n" - "{\n" - "iHostConfigIdx => $iHostConfigIdx,\n" - "strQueue => $strQueue,\n" - "strKey => $strKey,\n" - "strOp => $strOp,\n" - "rParam => $rParam,\n" - "};\n" - "\n\n" - "my $iHostIdx = $self->{hHostMap}{$iHostConfigIdx};\n" - "\n" - "if (!defined($iHostIdx))\n" - "{\n" - "confess &log(ASSERT, \"iHostConfigIdx = $iHostConfigIdx does not exist\");\n" - "}\n" - "\n" - "my $hHost = $self->{hyHost}[$iHostIdx];\n" - "\n\n" - "my $iQueueIdx = $hHost->{hQueueMap}{$strQueue};\n" - "\n" - "if (!defined($iQueueIdx))\n" - "{\n" - "$iQueueIdx = defined($hHost->{hyQueue}) ? @{$hHost->{hyQueue}} : 0;\n" - "$hHost->{hQueueMap}{$strQueue} = $iQueueIdx;\n" - "}\n" - "\n" - "push(@{$hHost->{hyQueue}[$iQueueIdx]}, $hJob);\n" - "$self->{iQueued}++;\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub dequeueJobs\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$iHostConfigIdx,\n" - "$strQueue,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->dequeueJobs', \\@_,\n" - "{name => 'iHostConfigIdx'},\n" - "{name => 'strQueue'},\n" - ");\n" - "\n\n" - "if (!$self->processing())\n" - "{\n" - "confess &log(ASSERT, 'unable to dequeue a job when not processing');\n" - "}\n" - "\n\n" - "my $iHostIdx = $self->{hHostMap}{$iHostConfigIdx};\n" - "\n" - "if (!defined($iHostIdx))\n" - "{\n" - "confess &log(ASSERT, \"iHostConfigIdx = $iHostConfigIdx does not exist\");\n" - "}\n" - "\n" - "my $hHost = $self->{hyHost}[$iHostIdx];\n" - "\n\n" - "my $iQueueIdx = $hHost->{hQueueMap}{$strQueue};\n" - "\n" - "if (!defined($iQueueIdx))\n" - "{\n" - "confess &log(ASSERT, \"unable to find queue '${strQueue}'\");\n" - "}\n" - "\n" - "$hHost->{hyQueue}[$iQueueIdx] = [];\n" - "$self->{iQueued} = 0;\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n\n\n" - "sub jobTotal\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->jobTotal');\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'iJobTotal', value => $self->{iQueued} + $self->{iRunning}}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub processing\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->processing');\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bProcessing', value => $self->{bProcessing}, trace => true}\n" - ");\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Remote/Master.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Remote::Master;\n" - "use parent 'pgBackRest::Protocol::Command::Master';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use File::Basename qw(dirname);\n" - "\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Protocol::Command::Master;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strCommandSSH,\n" - "$strCommand,\n" - "$iBufferMax,\n" - "$iCompressLevel,\n" - "$iCompressLevelNetwork,\n" - "$strHost,\n" - "$strUser,\n" - "$iSshPort,\n" - "$iProtocolTimeout,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strCommandSSH'},\n" - "{name => 'strCommand'},\n" - "{name => 'iBufferMax'},\n" - "{name => 'iCompressLevel'},\n" - "{name => 'iCompressLevelNetwork'},\n" - "{name => 'strHost'},\n" - "{name => 'strUser'},\n" - "{name => 'iSshPort', required => false},\n" - "{name => 'iProtocolTimeout'},\n" - ");\n" - "\n" - "my $strCommandSshPort = defined($iSshPort) ? '-p ' . $iSshPort . ' ' : '';\n" - "\n\n" - "$strCommand =\n" - "\"${strCommandSSH} -o LogLevel=error -o Compression=no -o PasswordAuthentication=no $strCommandSshPort\" .\n" - "\"${strUser}\\@${strHost} '${strCommand}'\";\n" - "\n\n" - "my $self = $class->SUPER::new(\n" - "'remote', \"remote process on '$strHost'\", $strCommand, $iBufferMax, $iCompressLevel, $iCompressLevelNetwork,\n" - "$iProtocolTimeout);\n" - "bless $self, $class;\n" - "\n\n" - "$self->{strHost} = $strHost;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Remote/Minion.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Remote::Minion;\n" - "use parent 'pgBackRest::Protocol::Command::Minion';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use File::Basename qw(dirname);\n" - "\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Common::Io::Buffered;\n" - "use pgBackRest::Common::Wait;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Db;\n" - "use pgBackRest::Protocol::Command::Minion;\n" - "use pgBackRest::Protocol::Helper;\n" - "use pgBackRest::Protocol::Storage::Helper;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$iBufferMax,\n" - "$iProtocolTimeout\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'iBufferMax'},\n" - "{name => 'iProtocolTimeout'}\n" - ");\n" - "\n\n" - "my $self = $class->SUPER::new(cfgCommandName(CFGCMD_REMOTE), $iBufferMax, $iProtocolTimeout);\n" - "bless $self, $class;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub init\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->init');\n" - "\n\n" - "my $oStorage = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? storageDb() : storageRepo();\n" - "\n" - "my $oDb = cfgOptionTest(CFGOPT_TYPE, CFGOPTVAL_REMOTE_TYPE_DB) ? new pgBackRest::Db() : undef;\n" - "\n\n" - "my $hCommandMap =\n" - "{\n" - "\n" - "&OP_DB_CONNECT => sub {$oDb->connect()},\n" - "&OP_DB_EXECUTE_SQL => sub {$oDb->executeSql(@{shift()})},\n" - "&OP_DB_INFO => sub {$oDb->info(@{shift()})},\n" - "\n\n" - "&OP_STORAGE_OPEN_READ => sub\n" - "{\n" - "my $oSourceFileIo = $oStorage->openRead(@{shift()});\n" - "\n\n" - "if (defined($oSourceFileIo) && (!defined($oSourceFileIo->{oStorageCRead}) || $oSourceFileIo->open()))\n" - "{\n" - "$self->outputWrite(true);\n" - "\n" - "$oStorage->copy(\n" - "$oSourceFileIo, new pgBackRest::Protocol::Storage::File($self, $oSourceFileIo), {bSourceOpen => true});\n" - "\n" - "return true;\n" - "}\n" - "\n" - "return false;\n" - "},\n" - "&OP_STORAGE_OPEN_WRITE => sub\n" - "{\n" - "my $oDestinationFileIo = $oStorage->openWrite(@{shift()});\n" - "$oStorage->copy(new pgBackRest::Protocol::Storage::File($self, $oDestinationFileIo), $oDestinationFileIo);\n" - "},\n" - "\n" - "&OP_STORAGE_CIPHER_PASS_USER => sub {$oStorage->cipherPassUser()},\n" - "&OP_STORAGE_EXISTS => sub {$oStorage->exists(@{shift()})},\n" - "&OP_STORAGE_LIST => sub {$oStorage->list(@{shift()})},\n" - "&OP_STORAGE_MANIFEST => sub {$oStorage->manifestJson(@{shift()})},\n" - "&OP_STORAGE_MOVE => sub {$oStorage->move(@{shift()})},\n" - "&OP_STORAGE_PATH_GET => sub {$oStorage->pathGet(@{shift()})},\n" - "&OP_STORAGE_HASH_SIZE => sub {$oStorage->hashSize(@{shift()})},\n" - "\n\n" - "&OP_WAIT => sub {waitRemainder(@{shift()})},\n" - "};\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'hCommandMap', value => $hCommandMap}\n" - ");\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Storage/File.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Storage::File;\n" - "use parent 'pgBackRest::Common::Io::Base';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$oProtocol,\n" - "$oFileIo,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'oProtocol', trace => true},\n" - "{name => 'oFileIo', required => false, trace => true},\n" - ");\n" - "\n\n" - "my $self = $class->SUPER::new($oProtocol->io()->id() . ' file');\n" - "bless $self, $class;\n" - "\n\n" - "$self->{oProtocol} = $oProtocol;\n" - "$self->{oFileIo} = $oFileIo;\n" - "\n\n" - "$self->{bWrite} = false;\n" - "\n\n" - "$self->eofSet(false);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub eof\n" - "{\n" - "return shift->{bEOF};\n" - "}\n" - "\n\n\n\n" - "sub eofSet\n" - "{\n" - "my $self = shift;\n" - "my $bEOF = shift;\n" - "\n" - "$self->{bEOF} = $bEOF;\n" - "}\n" - "\n\n\n\n" - "sub read\n" - "{\n" - "my $self = shift;\n" - "my $rtBuffer = shift;\n" - "\n\n" - "return 0 if $self->eof();\n" - "\n" - "my $lBlockSize;\n" - "\n\n" - "my $strBlockHeader = $self->{oProtocol}->io()->readLine();\n" - "\n" - "if ($strBlockHeader !~ /^BRBLOCK[0-9]+$/)\n" - "{\n" - "confess &log(ERROR, \"invalid block header '${strBlockHeader}'\", ERROR_FILE_READ);\n" - "}\n" - "\n\n" - "$lBlockSize = substr($strBlockHeader, 7);\n" - "\n\n" - "if ($lBlockSize > 0)\n" - "{\n" - "$self->{oProtocol}->io()->read($rtBuffer, $lBlockSize, true);\n" - "}\n" - "else\n" - "{\n" - "$self->eofSet(true);\n" - "}\n" - "\n\n" - "return $lBlockSize;\n" - "}\n" - "\n\n\n\n" - "sub write\n" - "{\n" - "my $self = shift;\n" - "my $rtBuffer = shift;\n" - "\n\n" - "$self->{bWrite} = true;\n" - "\n\n" - "my $lBlockSize = defined($rtBuffer) ? length($$rtBuffer) : 0;\n" - "\n\n" - "if ($lBlockSize > 0)\n" - "{\n" - "\n" - "$self->{oProtocol}->io()->writeLine(\"BRBLOCK${lBlockSize}\");\n" - "\n\n" - "$self->{oProtocol}->io()->write($rtBuffer);\n" - "}\n" - "\n" - "return length($$rtBuffer);\n" - "}\n" - "\n\n\n\n" - "sub close\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "if (defined($self->{oProtocol}))\n" - "{\n" - "\n" - "if ($self->{bWrite})\n" - "{\n" - "$self->{oProtocol}->io()->writeLine(\"BRBLOCK0\");\n" - "}\n" - "\n\n" - "if ($self->{oProtocol}->master())\n" - "{\n" - "($self->{rhResult}) = $self->{oProtocol}->outputRead();\n" - "\n\n" - "$self->{oProtocol}->outputRead();\n" - "}\n" - "\n" - "else\n" - "{\n" - "$self->{oProtocol}->outputWrite($self->{oFileIo}->resultAll());\n" - "}\n" - "\n\n" - "delete($self->{oProtocol});\n" - "}\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Storage/Helper.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Storage::Helper;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename qw(basename);\n" - "\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::LibC qw(:storage);\n" - "use pgBackRest::Protocol::Helper;\n" - "use pgBackRest::Protocol::Storage::Remote;\n" - "use pgBackRest::Storage::Helper;\n" - "\n\n\n\n" - "use constant STORAGE_DB => '';\n" - "push @EXPORT, qw(STORAGE_DB);\n" - "\n" - "use constant STORAGE_REPO => '';\n" - "push @EXPORT, qw(STORAGE_REPO);\n" - "use constant STORAGE_REPO_ARCHIVE => '';\n" - "push @EXPORT, qw(STORAGE_REPO_ARCHIVE);\n" - "use constant STORAGE_REPO_BACKUP => '';\n" - "push @EXPORT, qw(STORAGE_REPO_BACKUP);\n" - "\n\n\n\n" - "my $hStorage;\n" - "\n\n\n\n" - "sub storageDb\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$iRemoteIdx,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::storageDb', \\@_,\n" - "{name => 'iRemoteIdx', optional => true, default => cfgOptionValid(CFGOPT_HOST_ID) ? cfgOption(CFGOPT_HOST_ID) : 1,\n" - "trace => true},\n" - ");\n" - "\n\n" - "if (!defined($hStorage->{&STORAGE_DB}{$iRemoteIdx}))\n" - "{\n" - "if (isDbLocal({iRemoteIdx => $iRemoteIdx}))\n" - "{\n" - "$hStorage->{&STORAGE_DB}{$iRemoteIdx} = new pgBackRest::Storage::Storage(\n" - "STORAGE_DB, {lBufferMax => cfgOption(CFGOPT_BUFFER_SIZE)});\n" - "}\n" - "else\n" - "{\n" - "$hStorage->{&STORAGE_DB}{$iRemoteIdx} = new pgBackRest::Protocol::Storage::Remote(\n" - "protocolGet(CFGOPTVAL_REMOTE_TYPE_DB, $iRemoteIdx));\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oStorageDb', value => $hStorage->{&STORAGE_DB}{$iRemoteIdx}, trace => true},\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(storageDb);\n" - "\n\n\n\n" - "sub storageRepo\n" - "{\n" - "\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strStanza,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::storageRepo', \\@_,\n" - "{name => 'strStanza', optional => true, trace => true},\n" - ");\n" - "\n\n" - "if (!defined($hStorage->{&STORAGE_REPO}))\n" - "{\n" - "if (isRepoLocal())\n" - "{\n" - "$hStorage->{&STORAGE_REPO} = new pgBackRest::Storage::Storage(\n" - "STORAGE_REPO, {lBufferMax => cfgOption(CFGOPT_BUFFER_SIZE)});\n" - "}\n" - "else\n" - "{\n" - "\n" - "$hStorage->{&STORAGE_REPO} = new pgBackRest::Protocol::Storage::Remote(\n" - "protocolGet(CFGOPTVAL_REMOTE_TYPE_BACKUP));\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oStorageRepo', value => $hStorage->{&STORAGE_REPO}, trace => true},\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(storageRepo);\n" - "\n\n\n\n" - "sub storageRepoCacheClear\n" - "{\n" - "\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '::storageRepoCacheClear');\n" - "\n" - "delete($hStorage->{&STORAGE_REPO});\n" - "\n" - "storageRepoFree();\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n" - "push @EXPORT, qw(storageRepoCacheClear);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Protocol/Storage/Remote.pm", - .data = - "\n\n\n" - "package pgBackRest::Protocol::Storage::Remote;\n" - "use parent 'pgBackRest::Storage::Base';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use JSON::PP;\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Protocol::Helper;\n" - "use pgBackRest::Protocol::Storage::File;\n" - "use pgBackRest::Storage::Base;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$oProtocol,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'oProtocol'},\n" - ");\n" - "\n\n" - "my $self = $class->SUPER::new({lBufferMax => $oProtocol->io()->bufferMax()});\n" - "bless $self, $class;\n" - "\n\n" - "$self->{oProtocol} = $oProtocol;\n" - "\n\n" - "$self->{oJSON} = JSON::PP->new()->allow_nonref();\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub exists\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->exists', \\@_,\n" - "{name => 'strPathExp'},\n" - ");\n" - "\n" - "my $bExists = $self->{oProtocol}->cmdExecute(OP_STORAGE_EXISTS, [$strPathExp]);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bExists', value => $bExists}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub hashSize\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - "$rhParam,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->hashSize', \\@_,\n" - "{name => 'strPathExp'},\n" - "{name => 'rhParam', required => false},\n" - ");\n" - "\n" - "my ($strHash, $lSize) = $self->{oProtocol}->cmdExecute(OP_STORAGE_HASH_SIZE, [$strPathExp, $rhParam]);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strHash', value => $strHash},\n" - "{name => 'lSize', value => $lSize}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub list\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - "$rhParam,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->list', \\@_,\n" - "{name => 'strPathExp'},\n" - "{name => 'rhParam', required => false},\n" - ");\n" - "\n" - "my @stryFileList = $self->{oProtocol}->cmdExecute(OP_STORAGE_LIST, [$strPathExp, $rhParam]);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'stryFileList', value => \\@stryFileList}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub manifest\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - "$rhParam,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->manifest', \\@_,\n" - "{name => 'strPathExp'},\n" - "{name => 'rhParam', required => false},\n" - ");\n" - "\n" - "my $hManifest = $self->{oJSON}->decode($self->{oProtocol}->cmdExecute(OP_STORAGE_MANIFEST, [$strPathExp, $rhParam]));\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'hManifest', value => $hManifest, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub openRead\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strFileExp,\n" - "$rhParam,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->openRead', \\@_,\n" - "{name => 'strFileExp'},\n" - "{name => 'rhParam', required => false},\n" - ");\n" - "\n" - "my $oSourceFileIo =\n" - "$self->{oProtocol}->cmdExecute(OP_STORAGE_OPEN_READ, [$strFileExp, $rhParam]) ?\n" - "new pgBackRest::Protocol::Storage::File($self->{oProtocol}) : undef;\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oFileIo', value => $oSourceFileIo, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub openWrite\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strFileExp,\n" - "$rhParam,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->openWrite', \\@_,\n" - "{name => 'strFileExp'},\n" - "{name => 'rhParam', required => false},\n" - ");\n" - "\n\n" - "$self->{oProtocol}->cmdWrite(OP_STORAGE_OPEN_WRITE, [$strFileExp, $rhParam]);\n" - "my $oDestinationFileIo = new pgBackRest::Protocol::Storage::File($self->{oProtocol});\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oFileIo', value => $oDestinationFileIo, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub pathGet\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - "$rhParam,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->pathGet', \\@_,\n" - "{name => 'strPathExp', required => false},\n" - "{name => 'rhParam', required => false},\n" - ");\n" - "\n" - "my $strPath = $self->{oProtocol}->cmdExecute(OP_STORAGE_PATH_GET, [$strPathExp, $rhParam]);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strPath', value => $strPath}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub move\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strSourcePathExp,\n" - "$strDestinationPathExp,\n" - "$rhParam,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->move', \\@_,\n" - "{name => 'strSourcePathExp'},\n" - "{name => 'strDestinationPathExp'},\n" - "{name => 'rhParam', required => false},\n" - ");\n" - "\n" - "$self->{oProtocol}->cmdExecute(OP_STORAGE_MOVE, [$strSourcePathExp, $strDestinationPathExp, $rhParam], false);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub cipherPassUser\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->cipherPassUser', \\@_,\n" - ");\n" - "\n" - "my $strCipherPassUser = $self->{oProtocol}->cmdExecute(OP_STORAGE_CIPHER_PASS_USER);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strCipherPassUser', value => $strCipherPassUser, redact => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub protocol {shift->{oProtocol}};\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Storage/Base.pm", - .data = - "\n\n\n" - "package pgBackRest::Storage::Base;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename qw(dirname);\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Io::Base;\n" - "use pgBackRest::Common::Log;\n" - "\n\n\n\n" - "use constant STORAGE_LOCAL => '';\n" - "push @EXPORT, qw(STORAGE_LOCAL);\n" - "\n" - "use constant STORAGE_S3 => 's3';\n" - "push @EXPORT, qw(STORAGE_S3);\n" - "use constant STORAGE_POSIX => 'posix';\n" - "push @EXPORT, qw(STORAGE_POSIX);\n" - "\n\n\n\n" - "use constant STORAGE_COMPRESS => 'compress';\n" - "push @EXPORT, qw(STORAGE_COMPRESS);\n" - "use constant STORAGE_DECOMPRESS => 'decompress';\n" - "push @EXPORT, qw(STORAGE_DECOMPRESS);\n" - "\n\n\n\n" - "use constant STORAGE_ENCRYPT => 'encrypt';\n" - "push @EXPORT, qw(STORAGE_ENCRYPT);\n" - "use constant STORAGE_DECRYPT => 'decrypt';\n" - "push @EXPORT, qw(STORAGE_DECRYPT);\n" - "use constant CIPHER_MAGIC => 'Salted__';\n" - "push @EXPORT, qw(CIPHER_MAGIC);\n" - "\n\n\n\n" - "use constant STORAGE_FILTER_CIPHER_BLOCK => 'pgBackRest::Storage::Filter::CipherBlock';\n" - "push @EXPORT, qw(STORAGE_FILTER_CIPHER_BLOCK);\n" - "use constant STORAGE_FILTER_GZIP => 'pgBackRest::Storage::Filter::Gzip';\n" - "push @EXPORT, qw(STORAGE_FILTER_GZIP);\n" - "use constant STORAGE_FILTER_SHA => 'pgBackRest::Storage::Filter::Sha';\n" - "push @EXPORT, qw(STORAGE_FILTER_SHA);\n" - "\n\n\n\n\n\n\n" - "use constant STORAGE_CAPABILITY_SIZE_DIFF => 'size-diff';\n" - "push @EXPORT, qw(STORAGE_CAPABILITY_SIZE_DIFF);\n" - "\n" - "use constant STORAGE_CAPABILITY_LINK => 'link';\n" - "push @EXPORT, qw(STORAGE_CAPABILITY_LINK);\n" - "use constant STORAGE_CAPABILITY_PATH_SYNC => 'path-sync';\n" - "push @EXPORT, qw(STORAGE_CAPABILITY_PATH_SYNC);\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{lBufferMax},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'lBufferMax', optional => true, default => COMMON_IO_BUFFER_MAX, trace => true},\n" - ");\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n\n\n" - "sub copy\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$xSourceFile,\n" - "$xDestinationFile,\n" - "$bSourceOpen,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->copy', \\@_,\n" - "{name => 'xSourceFile', required => false},\n" - "{name => 'xDestinationFile'},\n" - "{name => 'bSourceOpen', optional => true, default => false},\n" - ");\n" - "\n\n" - "my $oSourceFileIo = defined($xSourceFile) ? (ref($xSourceFile) ? $xSourceFile : $self->openRead($xSourceFile)) : undef;\n" - "\n\n" - "my $bResult = false;\n" - "\n\n" - "if (defined($oSourceFileIo))\n" - "{\n" - "my $oDestinationFileIo = ref($xDestinationFile) ? $xDestinationFile : $self->openWrite($xDestinationFile);\n" - "\n\n" - "if (defined($oSourceFileIo->{oStorageCRead}) && defined($oDestinationFileIo->{oStorageCWrite}))\n" - "{\n" - "$bResult = $self->{oStorageC}->copy(\n" - "$oSourceFileIo->{oStorageCRead}, $oDestinationFileIo->{oStorageCWrite}) ? true : false;\n" - "}\n" - "else\n" - "{\n" - "\n" - "$bResult = defined($oSourceFileIo->{oStorageCRead}) ? ($bSourceOpen || $oSourceFileIo->open()) : true;\n" - "\n" - "if ($bResult)\n" - "{\n" - "\n" - "if (defined($oDestinationFileIo->{oStorageCWrite}))\n" - "{\n" - "$oDestinationFileIo->open();\n" - "}\n" - "\n\n" - "do\n" - "{\n" - "\n" - "my $tBuffer = '';\n" - "\n" - "$oSourceFileIo->read(\\$tBuffer, $self->{lBufferMax});\n" - "$oDestinationFileIo->write(\\$tBuffer);\n" - "}\n" - "while (!$oSourceFileIo->eof());\n" - "\n\n" - "$oSourceFileIo->close();\n" - "$oDestinationFileIo->close();\n" - "}\n" - "}\n" - "}\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bResult', value => $bResult, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub get\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$xFile,\n" - "$strCipherPass,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->get', \\@_,\n" - "{name => 'xFile', required => false, trace => true},\n" - "{name => 'strCipherPass', optional => true, redact => true},\n" - ");\n" - "\n\n\n" - "my $oFileIo = defined($xFile) ? (ref($xFile) ? $xFile : $self->openRead(\n" - "$xFile, {strCipherPass => defined($strCipherPass) ? $strCipherPass : $self->cipherPassUser()})) : undef;\n" - "\n\n" - "my $tContent;\n" - "my $lSize = 0;\n" - "\n" - "if (defined($oFileIo))\n" - "{\n" - "my $lSizeRead;\n" - "\n" - "do\n" - "{\n" - "$lSizeRead = $oFileIo->read(\\$tContent, $self->{lBufferMax});\n" - "$lSize += $lSizeRead;\n" - "}\n" - "while ($lSizeRead != 0);\n" - "\n\n" - "$oFileIo->close();\n" - "\n\n" - "if ($lSize == 0)\n" - "{\n" - "$tContent = undef;\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'rtContent', value => defined($oFileIo) ? \\$tContent : undef, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub pathAbsolute\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strBasePath,\n" - "$strPath\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '::pathAbsolute', \\@_,\n" - "{name => 'strBasePath', trace => true},\n" - "{name => 'strPath', trace => true}\n" - ");\n" - "\n\n" - "my $strAbsolutePath;\n" - "\n\n" - "if (index($strPath, '/') == 0)\n" - "{\n" - "$strAbsolutePath = $strPath;\n" - "}\n" - "\n" - "else\n" - "{\n" - "\n" - "if (index($strBasePath, '/') != 0 || index($strBasePath, '/..') != -1)\n" - "{\n" - "confess &log(ERROR, \"${strBasePath} is not an absolute path\", ERROR_PATH_TYPE);\n" - "}\n" - "\n" - "while (index($strPath, '..') == 0)\n" - "{\n" - "$strBasePath = dirname($strBasePath);\n" - "$strPath = substr($strPath, 2);\n" - "\n" - "if (index($strPath, '/') == 0)\n" - "{\n" - "$strPath = substr($strPath, 1);\n" - "}\n" - "}\n" - "\n" - "$strAbsolutePath = \"${strBasePath}/${strPath}\";\n" - "}\n" - "\n\n" - "if (index($strAbsolutePath, '/') != 0 || index($strAbsolutePath, '/..') != -1)\n" - "{\n" - "confess &log(ERROR, \"result ${strAbsolutePath} was not an absolute path\", ERROR_PATH_TYPE);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strAbsolutePath', value => $strAbsolutePath, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub put\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$xFile,\n" - "$xContent,\n" - "$strCipherPass,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->put', \\@_,\n" - "{name => 'xFile', trace => true},\n" - "{name => 'xContent', required => false, trace => true},\n" - "{name => 'strCipherPass', optional => true, trace => true, redact => true},\n" - ");\n" - "\n\n\n" - "my $oFileIo = ref($xFile) ? $xFile : $self->openWrite(\n" - "$xFile, {strCipherPass => defined($strCipherPass) ? $strCipherPass : $self->cipherPassUser()});\n" - "\n\n" - "my $lSize = defined($xContent) ? length(ref($xContent) ? $$xContent : $xContent) : 0;\n" - "\n\n" - "if ($lSize > 0)\n" - "{\n" - "$oFileIo->write(ref($xContent) ? $xContent : \\$xContent);\n" - "}\n" - "\n" - "else\n" - "{\n" - "$oFileIo->open();\n" - "}\n" - "\n\n" - "$oFileIo->close();\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'lSize', value => $lSize, trace => true},\n" - ");\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Storage/Helper.pm", - .data = - "\n\n\n" - "package pgBackRest::Storage::Helper;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "use File::Basename qw(basename);\n" - "\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Config::Config;\n" - "use pgBackRest::Storage::Base;\n" - "use pgBackRest::Storage::Storage;\n" - "use pgBackRest::Version;\n" - "\n\n\n\n" - "use constant COMPRESS_EXT => 'gz';\n" - "push @EXPORT, qw(COMPRESS_EXT);\n" - "\n\n\n\n" - "use constant STORAGE_TEMP_EXT => PROJECT_EXE . '.tmp';\n" - "push @EXPORT, qw(STORAGE_TEMP_EXT);\n" - "\n\n\n\n\n\n\n" - "sub storageLocal\n" - "{\n" - "\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '::storageLocal');\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oStorageLocal', value => new pgBackRest::Storage::Storage(STORAGE_LOCAL), trace => true},\n" - ");\n" - "}\n" - "\n" - "push @EXPORT, qw(storageLocal);\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Storage/Storage.pm", - .data = - "\n\n\n" - "package pgBackRest::Storage::Storage;\n" - "use parent 'pgBackRest::Storage::Base';\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use File::Basename qw(dirname);\n" - "use Fcntl qw(:mode);\n" - "use File::stat qw{lstat};\n" - "use JSON::PP;\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Io::Handle;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Storage::Base;\n" - "use pgBackRest::Storage::StorageRead;\n" - "use pgBackRest::Storage::StorageWrite;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{strType},\n" - "$self->{strPath},\n" - "$self->{lBufferMax},\n" - "$self->{strDefaultPathMode},\n" - "$self->{strDefaultFileMode},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'strType'},\n" - "{name => 'strPath', optional => true},\n" - "{name => 'lBufferMax', optional => true, default => 65536},\n" - "{name => 'strDefaultPathMode', optional => true, default => '0750'},\n" - "{name => 'strDefaultFileMode', optional => true, default => '0640'},\n" - ");\n" - "\n\n" - "$self->{oStorageC} = pgBackRest::LibC::Storage->new($self->{strType}, $self->{strPath});\n" - "\n\n" - "if ($self->{strType} eq '')\n" - "{\n" - "$self->{strCipherType} = $self->{oStorageC}->cipherType();\n" - "$self->{strCipherPass} = $self->{oStorageC}->cipherPass();\n" - "}\n" - "\n\n" - "$self->{oJSON} = JSON::PP->new()->allow_nonref();\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub exists\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strFileExp,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->exists', \\@_,\n" - "{name => 'strFileExp'},\n" - ");\n" - "\n\n" - "my $bExists = $self->{oStorageC}->exists($strFileExp);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bExists', value => $bExists ? true : false}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub get\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$xFile,\n" - "$strCipherPass,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->get', \\@_,\n" - "{name => 'xFile', required => false, trace => true},\n" - "{name => 'strCipherPass', optional => true, default => $self->cipherPassUser(), redact => true},\n" - ");\n" - "\n\n\n" - "my $oFileIo = defined($xFile) ? (ref($xFile) ? $xFile : $self->openRead($xFile, {strCipherPass => $strCipherPass})) : undef;\n" - "\n\n" - "my $bEmpty = false;\n" - "my $tContent = $self->{oStorageC}->get($oFileIo->{oStorageCRead});\n" - "\n" - "if (defined($tContent) && length($tContent) == 0)\n" - "{\n" - "$tContent = undef;\n" - "$bEmpty = true;\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'rtContent', value => defined($tContent) || $bEmpty ? \\$tContent : undef, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n\n" - "sub hashSize\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$xFileExp,\n" - "$bIgnoreMissing,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->hashSize', \\@_,\n" - "{name => 'xFileExp'},\n" - "{name => 'bIgnoreMissing', optional => true, default => false},\n" - ");\n" - "\n\n" - "my $strHash;\n" - "my $lSize;\n" - "\n\n" - "my $oFileIo = ref($xFileExp) ? $xFileExp : $self->openRead($xFileExp, {bIgnoreMissing => $bIgnoreMissing});\n" - "\n\n" - "$oFileIo->{oStorageCRead}->filterAdd(COMMON_IO_HANDLE, undef);\n" - "$oFileIo->{oStorageCRead}->filterAdd(STORAGE_FILTER_SHA, undef);\n" - "\n\n" - "if ($self->{oStorageC}->readDrain($oFileIo->{oStorageCRead}))\n" - "{\n" - "$strHash = $oFileIo->result(STORAGE_FILTER_SHA);\n" - "$lSize = $oFileIo->result(COMMON_IO_HANDLE);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strHash', value => $strHash},\n" - "{name => 'lSize', value => $lSize}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub info\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathFileExp,\n" - "$bIgnoreMissing,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->info', \\@_,\n" - "{name => 'strPathFileExp'},\n" - "{name => 'bIgnoreMissing', optional => true, default => false},\n" - ");\n" - "\n" - "my $rhInfo;\n" - "my $strJson = $self->{oStorageC}->info($strPathFileExp, $bIgnoreMissing);\n" - "\n" - "if (defined($strJson))\n" - "{\n" - "$rhInfo = $self->{oJSON}->decode($strJson);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'rhInfo', value => $rhInfo, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub linkCreate\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strSourcePathFileExp,\n" - "$strDestinationLinkExp,\n" - "$bHard,\n" - "$bRelative,\n" - "$bPathCreate,\n" - "$bIgnoreExists,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->linkCreate', \\@_,\n" - "{name => 'strSourcePathFileExp'},\n" - "{name => 'strDestinationLinkExp'},\n" - "{name => 'bHard', optional=> true, default => false},\n" - "{name => 'bRelative', optional=> true, default => false},\n" - "{name => 'bPathCreate', optional=> true, default => true},\n" - "{name => 'bIgnoreExists', optional => true, default => false},\n" - ");\n" - "\n\n" - "my $strSourcePathFile = $self->pathGet($strSourcePathFileExp);\n" - "my $strDestinationLink = $self->pathGet($strDestinationLinkExp);\n" - "\n\n" - "if ($bRelative)\n" - "{\n" - "\n" - "my @strySource = split('/', $strSourcePathFile);\n" - "my @stryDestination = split('/', $strDestinationLink);\n" - "\n" - "while (defined($strySource[0]) && defined($stryDestination[0]) && $strySource[0] eq $stryDestination[0])\n" - "{\n" - "shift(@strySource);\n" - "shift(@stryDestination);\n" - "}\n" - "\n\n" - "$strSourcePathFile = '';\n" - "\n" - "for (my $iIndex = 0; $iIndex < @stryDestination - 1; $iIndex++)\n" - "{\n" - "$strSourcePathFile .= '../';\n" - "}\n" - "\n\n" - "$strSourcePathFile .= join('/', @strySource);\n" - "\n" - "logDebugMisc\n" - "(\n" - "$strOperation, 'apply relative path',\n" - "{name => 'strSourcePathFile', value => $strSourcePathFile, trace => true}\n" - ");\n" - "}\n" - "\n" - "if (!($bHard ? link($strSourcePathFile, $strDestinationLink) : symlink($strSourcePathFile, $strDestinationLink)))\n" - "{\n" - "my $strMessage = \"unable to create link '${strDestinationLink}'\";\n" - "\n\n" - "if ($OS_ERROR{ENOENT})\n" - "{\n" - "\n" - "if (!$self->exists($strSourcePathFile))\n" - "{\n" - "confess &log(ERROR, \"${strMessage} because source '${strSourcePathFile}' does not exist\", ERROR_FILE_MISSING);\n" - "}\n" - "\n" - "if (!$bPathCreate)\n" - "{\n" - "confess &log(ERROR, \"${strMessage} because parent does not exist\", ERROR_PATH_MISSING);\n" - "}\n" - "\n\n" - "$self->pathCreate(dirname($strDestinationLink), {bIgnoreExists => true, bCreateParent => true});\n" - "\n\n" - "$self->linkCreate($strSourcePathFile, $strDestinationLink, {bHard => $bHard});\n" - "}\n" - "\n" - "elsif ($OS_ERROR{EEXIST})\n" - "{\n" - "if (!$bIgnoreExists)\n" - "{\n" - "confess &log(ERROR, \"${strMessage} because it already exists\", ERROR_PATH_EXISTS);\n" - "}\n" - "}\n" - "else\n" - "{\n" - "logErrorResult(ERROR_PATH_CREATE, ${strMessage}, $OS_ERROR);\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n" - "sub list\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - "$strExpression,\n" - "$strSortOrder,\n" - "$bIgnoreMissing,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->list', \\@_,\n" - "{name => 'strPathExp', required => false},\n" - "{name => 'strExpression', optional => true},\n" - "{name => 'strSortOrder', optional => true, default => 'forward'},\n" - "{name => 'bIgnoreMissing', optional => true, default => false},\n" - ");\n" - "\n\n" - "my $rstryFileList = [];\n" - "my $strFileList = $self->{oStorageC}->list($strPathExp, $bIgnoreMissing, $strSortOrder eq 'forward', $strExpression);\n" - "\n" - "if (defined($strFileList) && $strFileList ne '[]')\n" - "{\n" - "$rstryFileList = $self->{oJSON}->decode($strFileList);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'stryFileList', value => $rstryFileList}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub manifest\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - "$strFilter,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->manifest', \\@_,\n" - "{name => 'strPathExp'},\n" - "{name => 'strFilter', optional => true, trace => true},\n" - ");\n" - "\n" - "my $hManifest = $self->{oJSON}->decode($self->manifestJson($strPathExp, {strFilter => $strFilter}));\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'hManifest', value => $hManifest, trace => true}\n" - ");\n" - "}\n" - "\n" - "sub manifestJson\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - "$strFilter,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->manifestJson', \\@_,\n" - "{name => 'strPathExp'},\n" - "{name => 'strFilter', optional => true, trace => true},\n" - ");\n" - "\n" - "my $strManifestJson = $self->{oStorageC}->manifest($strPathExp, $strFilter);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strManifestJson', value => $strManifestJson, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub move\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strSourceFileExp,\n" - "$strDestinationFileExp,\n" - "$bPathCreate,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->move', \\@_,\n" - "{name => 'strSourceFileExp'},\n" - "{name => 'strDestinationFileExp'},\n" - ");\n" - "\n\n" - "my $strSourceFile = $self->pathGet($strSourceFileExp);\n" - "my $strDestinationFile = $self->pathGet($strDestinationFileExp);\n" - "\n\n" - "if (!rename($strSourceFile, $strDestinationFile))\n" - "{\n" - "logErrorResult(ERROR_FILE_MOVE, \"unable to move '${strSourceFile}' to '${strDestinationFile}'\", $OS_ERROR);\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n" - "sub openRead\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$xFileExp,\n" - "$bIgnoreMissing,\n" - "$rhyFilter,\n" - "$strCipherPass,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->openRead', \\@_,\n" - "{name => 'xFileExp'},\n" - "{name => 'bIgnoreMissing', optional => true, default => false},\n" - "{name => 'rhyFilter', optional => true},\n" - "{name => 'strCipherPass', optional => true, default => $self->cipherPassUser(), redact => true},\n" - ");\n" - "\n\n" - "my $oFileIo = pgBackRest::LibC::StorageRead->new($self->{oStorageC}, $xFileExp, $bIgnoreMissing);\n" - "\n\n" - "if (defined($self->cipherType()))\n" - "{\n" - "$oFileIo->filterAdd(STORAGE_FILTER_CIPHER_BLOCK, $self->{oJSON}->encode([false, $self->cipherType(), $strCipherPass]));\n" - "}\n" - "\n\n" - "if (defined($rhyFilter))\n" - "{\n" - "foreach my $rhFilter (@{$rhyFilter})\n" - "{\n" - "$oFileIo->filterAdd(\n" - "$rhFilter->{strClass}, defined($rhFilter->{rxyParam}) ? $self->{oJSON}->encode($rhFilter->{rxyParam}) : undef);\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oFileIo', value => new pgBackRest::Storage::StorageRead($self, $oFileIo), trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub openWrite\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$xFileExp,\n" - "$strMode,\n" - "$strUser,\n" - "$strGroup,\n" - "$lTimestamp,\n" - "$bAtomic,\n" - "$bPathCreate,\n" - "$rhyFilter,\n" - "$strCipherPass,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->openWrite', \\@_,\n" - "{name => 'xFileExp'},\n" - "{name => 'strMode', optional => true, default => $self->{strDefaultFileMode}},\n" - "{name => 'strUser', optional => true},\n" - "{name => 'strGroup', optional => true},\n" - "{name => 'lTimestamp', optional => true, default => '0'},\n" - "{name => 'bAtomic', optional => true, default => false},\n" - "{name => 'bPathCreate', optional => true, default => false},\n" - "{name => 'rhyFilter', optional => true},\n" - "{name => 'strCipherPass', optional => true, default => $self->cipherPassUser(), redact => true},\n" - ");\n" - "\n\n" - "my $oFileIo = pgBackRest::LibC::StorageWrite->new(\n" - "$self->{oStorageC}, $xFileExp, oct($strMode), $strUser, $strGroup, $lTimestamp, $bAtomic, $bPathCreate);\n" - "\n\n" - "if (defined($rhyFilter))\n" - "{\n" - "foreach my $rhFilter (@{$rhyFilter})\n" - "{\n" - "$oFileIo->filterAdd(\n" - "$rhFilter->{strClass}, defined($rhFilter->{rxyParam}) ? $self->{oJSON}->encode($rhFilter->{rxyParam}) : undef);\n" - "}\n" - "}\n" - "\n\n" - "if (defined($self->cipherType()))\n" - "{\n" - "$oFileIo->filterAdd(STORAGE_FILTER_CIPHER_BLOCK, $self->{oJSON}->encode([true, $self->cipherType(), $strCipherPass]));\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'oFileIo', value => new pgBackRest::Storage::StorageWrite($self, $oFileIo), trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub owner\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathFileExp,\n" - "$strUser,\n" - "$strGroup\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->owner', \\@_,\n" - "{name => 'strPathFileExp'},\n" - "{name => 'strUser', required => false},\n" - "{name => 'strGroup', required => false}\n" - ");\n" - "\n\n" - "if (defined($strUser) || defined($strGroup))\n" - "{\n" - "my $strPathFile = $self->pathGet($strPathFileExp);\n" - "my $strMessage = \"unable to set ownership for '${strPathFile}'\";\n" - "my $iUserId;\n" - "my $iGroupId;\n" - "\n\n\n" - "my $oStat = lstat($strPathFile);\n" - "\n" - "if (!defined($oStat))\n" - "{\n" - "confess &log(ERROR, \"unable to stat '${strPathFile}': No such file or directory\", ERROR_FILE_MISSING);\n" - "}\n" - "\n" - "if (!defined($strUser))\n" - "{\n" - "$iUserId = $oStat->uid;\n" - "}\n" - "\n" - "if (!defined($strGroup))\n" - "{\n" - "$iGroupId = $oStat->gid;\n" - "}\n" - "\n\n" - "if (defined($strUser))\n" - "{\n" - "$iUserId = getpwnam($strUser);\n" - "\n" - "if (!defined($iUserId))\n" - "{\n" - "logErrorResult(ERROR_FILE_OWNER, \"${strMessage} because user '${strUser}' does not exist\");\n" - "}\n" - "}\n" - "\n\n" - "if (defined($strGroup))\n" - "{\n" - "$iGroupId = getgrnam($strGroup);\n" - "\n" - "if (!defined($iGroupId))\n" - "{\n" - "logErrorResult(ERROR_FILE_OWNER, \"${strMessage} because group '${strGroup}' does not exist\");\n" - "}\n" - "}\n" - "\n\n" - "if ($iUserId != $oStat->uid || $iGroupId != $oStat->gid)\n" - "{\n" - "if (!chown($iUserId, $iGroupId, $strPathFile))\n" - "{\n" - "logErrorResult(ERROR_FILE_OWNER, \"${strMessage}\", $OS_ERROR);\n" - "}\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub pathAbsolute\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strBasePath,\n" - "$strPath\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->pathAbsolute', \\@_,\n" - "{name => 'strBasePath', trace => true},\n" - "{name => 'strPath', trace => true}\n" - ");\n" - "\n\n" - "my $strAbsolutePath;\n" - "\n\n" - "if (index($strPath, '/') == 0)\n" - "{\n" - "$strAbsolutePath = $strPath;\n" - "}\n" - "\n" - "else\n" - "{\n" - "\n" - "if (index($strBasePath, '/') != 0 || index($strBasePath, '/..') != -1)\n" - "{\n" - "confess &log(ERROR, \"${strBasePath} is not an absolute path\", ERROR_PATH_TYPE);\n" - "}\n" - "\n" - "while (index($strPath, '..') == 0)\n" - "{\n" - "$strBasePath = dirname($strBasePath);\n" - "$strPath = substr($strPath, 2);\n" - "\n" - "if (index($strPath, '/') == 0)\n" - "{\n" - "$strPath = substr($strPath, 1);\n" - "}\n" - "}\n" - "\n" - "$strAbsolutePath = \"${strBasePath}/${strPath}\";\n" - "}\n" - "\n\n" - "if (index($strAbsolutePath, '/') != 0 || index($strAbsolutePath, '/..') != -1)\n" - "{\n" - "confess &log(ERROR, \"result ${strAbsolutePath} was not an absolute path\", ERROR_PATH_TYPE);\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strAbsolutePath', value => $strAbsolutePath, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub pathCreate\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - "$strMode,\n" - "$bIgnoreExists,\n" - "$bCreateParent,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->pathCreate', \\@_,\n" - "{name => 'strPathExp'},\n" - "{name => 'strMode', optional => true},\n" - "{name => 'bIgnoreExists', optional => true, default => false},\n" - "{name => 'bCreateParent', optional => true, default => false},\n" - ");\n" - "\n\n" - "$self->{oStorageC}->pathCreate($strPathExp, $strMode, $bIgnoreExists, $bCreateParent);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub pathExists\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->pathExists', \\@_,\n" - "{name => 'strPathExp'},\n" - ");\n" - "\n\n" - "my $bExists = $self->{oStorageC}->pathExists($strPathExp);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bExists', value => $bExists ? true : false}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub pathGet\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->pathGet', \\@_,\n" - "{name => 'strPathExp'},\n" - ");\n" - "\n\n" - "my $strPath = $self->{oStorageC}->pathGet($strPathExp);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'strPath', value => $strPath, trace => true}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub pathRemove\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - "$bIgnoreMissing,\n" - "$bRecurse,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->pathRemove', \\@_,\n" - "{name => 'strPathExp'},\n" - "{name => 'bIgnoreMissing', optional => true, default => true},\n" - "{name => 'bRecurse', optional => true, default => false},\n" - ");\n" - "\n" - "$self->{oStorageC}->pathRemove($strPathExp, $bIgnoreMissing, $bRecurse);\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n" - "sub pathSync\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strPathExp,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->pathSync', \\@_,\n" - "{name => 'strPathExp'},\n" - ");\n" - "\n" - "$self->{oStorageC}->pathSync($strPathExp);\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n" - "sub put\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$xFile,\n" - "$xContent,\n" - "$strCipherPass,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->put', \\@_,\n" - "{name => 'xFile', trace => true},\n" - "{name => 'xContent', required => false, trace => true},\n" - "{name => 'strCipherPass', optional => true, default => $self->cipherPassUser(), trace => true, redact => true},\n" - ");\n" - "\n\n\n" - "my $oFileIo = ref($xFile) ? $xFile : $self->openWrite($xFile, {strCipherPass => $strCipherPass});\n" - "\n\n" - "my $lSize = $self->{oStorageC}->put($oFileIo->{oStorageCWrite}, ref($xContent) ? $$xContent : $xContent);\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'lSize', value => $lSize, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub remove\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$xFileExp,\n" - "$bIgnoreMissing,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->remove', \\@_,\n" - "{name => 'xFileExp'},\n" - "{name => 'bIgnoreMissing', optional => true, default => true},\n" - ");\n" - "\n" - "foreach my $strFileExp (ref($xFileExp) ? @{$xFileExp} : ($xFileExp))\n" - "{\n" - "$self->{oStorageC}->remove($strFileExp, $bIgnoreMissing);\n" - "}\n" - "\n\n" - "return logDebugReturn($strOperation);\n" - "}\n" - "\n\n\n\n" - "sub encrypted\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strFileExp,\n" - "$bIgnoreMissing,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->encrypted', \\@_,\n" - "{name => 'strFileExp'},\n" - "{name => 'bIgnoreMissing', optional => true, default => false},\n" - ");\n" - "\n" - "my $bEncrypted = false;\n" - "\n\n" - "my $oFileIo = new pgBackRest::Storage::StorageRead(\n" - "$self, pgBackRest::LibC::StorageRead->new($self->{oStorageC}, $strFileExp, $bIgnoreMissing));\n" - "\n\n\n" - "if (!$oFileIo->open())\n" - "{\n" - "if (defined($self->cipherType()))\n" - "{\n" - "$bEncrypted = true;\n" - "}\n" - "}\n" - "else\n" - "{\n" - "\n" - "my $tMagicSignature = '';\n" - "my $lSizeRead = $oFileIo->read(\\$tMagicSignature, length(CIPHER_MAGIC));\n" - "$oFileIo->close();\n" - "\n" - "if (substr($tMagicSignature, 0, length(CIPHER_MAGIC)) eq CIPHER_MAGIC)\n" - "{\n" - "$bEncrypted = true;\n" - "}\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bEncrypted', value => $bEncrypted}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub encryptionValid\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$bEncrypted,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->encryptionValid', \\@_,\n" - "{name => 'bEncrypted'},\n" - ");\n" - "\n" - "my $bValid = ($bEncrypted && defined($self->cipherType())) || (!$bEncrypted && !defined($self->cipherType()));\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bValid', value => $bValid ? true : false}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub capability {shift->type() eq STORAGE_POSIX}\n" - "sub type {shift->{oStorageC}->type()}\n" - "sub cipherType {shift->{strCipherType}}\n" - "sub cipherPassUser {shift->{strCipherPass}}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Storage/StorageRead.pm", - .data = - "\n\n\n" - "package pgBackRest::Storage::StorageRead;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use File::Basename qw(dirname);\n" - "use Fcntl qw(:mode);\n" - "use File::stat qw{lstat};\n" - "use JSON::PP;\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Storage::Base;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{oStorage},\n" - "$self->{oStorageCRead},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'oStorage'},\n" - "{name => 'oStorageCRead'},\n" - ");\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub open\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->open');\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bResult', value => $self->{oStorageCRead}->open() ? true : false, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub read\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my (\n" - "$strOperation,\n" - "$rtBuffer,\n" - "$iSize,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->read', \\@_,\n" - "{name => 'rtBuffer'},\n" - "{name => 'iSize'},\n" - ");\n" - "\n\n" - "my $iActualSize = 0;\n" - "\n" - "if (!$self->eof())\n" - "{\n" - "my $tBuffer = $self->{oStorageCRead}->read($iSize);\n" - "$iActualSize = length($tBuffer);\n" - "$$rtBuffer .= $tBuffer;\n" - "}\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'iActualSize', value => $iActualSize}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub eof\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->eof');\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bResult', value => $self->{oStorageCRead}->eof() ? true : false, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub close\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->close');\n" - "\n" - "$self->{oStorageCRead}->close();\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bResult', value => true, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub result\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strClass,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->result', \\@_,\n" - "{name => 'strClass'},\n" - ");\n" - "\n" - "my $xResult = $self->{oStorage}->{oJSON}->decode($self->{oStorageCRead}->result($strClass));\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'xResult', value => $xResult, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub resultAll\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->resultAll');\n" - "\n" - "my $xResult = $self->{oStorage}->{oJSON}->decode($self->{oStorageCRead}->resultAll());\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'xResultAll', value => $xResult, trace => true},\n" - ");\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Storage/StorageWrite.pm", - .data = - "\n\n\n" - "package pgBackRest::Storage::StorageWrite;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "use Carp qw(confess);\n" - "use English '-no_match_vars';\n" - "\n" - "use File::Basename qw(dirname);\n" - "use Fcntl qw(:mode);\n" - "use File::stat qw{lstat};\n" - "use JSON::PP;\n" - "\n" - "use pgBackRest::Common::Exception;\n" - "use pgBackRest::Common::Log;\n" - "use pgBackRest::Storage::Base;\n" - "\n\n\n\n" - "sub new\n" - "{\n" - "my $class = shift;\n" - "\n\n" - "my $self = {};\n" - "bless $self, $class;\n" - "\n\n" - "(\n" - "my $strOperation,\n" - "$self->{oStorage},\n" - "$self->{oStorageCWrite},\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->new', \\@_,\n" - "{name => 'oStorage'},\n" - "{name => 'oStorageCWrite'},\n" - ");\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'self', value => $self}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub open\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->open');\n" - "\n" - "$self->{oStorageCWrite}->open();\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bResult', value => true, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub write\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my (\n" - "$strOperation,\n" - "$rtBuffer,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->write', \\@_,\n" - "{name => 'rtBuffer'},\n" - ");\n" - "\n\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'iActualSize', value => $self->{oStorageCWrite}->write($$rtBuffer)}\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub close\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->close');\n" - "\n" - "$self->{oStorageCWrite}->close();\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'bResult', value => true, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub result\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my\n" - "(\n" - "$strOperation,\n" - "$strClass,\n" - ") =\n" - "logDebugParam\n" - "(\n" - "__PACKAGE__ . '->result', \\@_,\n" - "{name => 'strClass'},\n" - ");\n" - "\n" - "my $xResult = $self->{oStorage}->{oJSON}->decode($self->{oStorageCWrite}->result($strClass));\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'xResult', value => $xResult, trace => true},\n" - ");\n" - "}\n" - "\n\n\n\n" - "sub resultAll\n" - "{\n" - "my $self = shift;\n" - "\n\n" - "my ($strOperation) = logDebugParam(__PACKAGE__ . '->resultAll');\n" - "\n" - "my $xResult = $self->{oStorage}->{oJSON}->decode($self->{oStorageCWrite}->resultAll());\n" - "\n" - "return logDebugReturn\n" - "(\n" - "$strOperation,\n" - "{name => 'xResultAll', value => $xResult, trace => true},\n" - ");\n" - "}\n" - "\n" - "1;\n" - }, - { - .name = "pgBackRest/Version.pm", - .data = - "\n\n\n\n\n" - "package pgBackRest::Version;\n" - "\n" - "use strict;\n" - "use warnings FATAL => qw(all);\n" - "\n" - "use Cwd qw(abs_path);\n" - "use Exporter qw(import);\n" - "our @EXPORT = qw();\n" - "\n\n\n\n\n" - "use constant PROJECT_NAME => 'pgBackRest';\n" - "push @EXPORT, qw(PROJECT_NAME);\n" - "use constant PROJECT_EXE => lc(PROJECT_NAME);\n" - "push @EXPORT, qw(PROJECT_EXE);\n" - "use constant PROJECT_CONF => PROJECT_EXE . '.conf';\n" - "push @EXPORT, qw(PROJECT_CONF);\n" - "\n\n\n\n\n" - "my $strProjectBin;\n" - "\n" - "sub projectBin {return $strProjectBin};\n" - "sub projectBinSet {$strProjectBin = shift}\n" - "\n" - "push @EXPORT, qw(projectBin projectBinSet);\n" - "\n\n\n\n\n\n" - "use constant PROJECT_VERSION => '2.21dev';\n" - "push @EXPORT, qw(PROJECT_VERSION);\n" - "\n\n\n\n\n\n" - "use constant REPOSITORY_FORMAT => 5;\n" - "push @EXPORT, qw(REPOSITORY_FORMAT);\n" - "\n" - "1;\n" - }, -}; diff --git a/src/perl/exec.c b/src/perl/exec.c deleted file mode 100644 index b30185d08..000000000 --- a/src/perl/exec.c +++ /dev/null @@ -1,276 +0,0 @@ -/*********************************************************************************************************************************** -Execute Perl for Legacy Functionality -***********************************************************************************************************************************/ -#include "build.auto.h" - -#include -#include -#include -#include -#include - -#include "version.h" -#include "common/debug.h" -#include "common/error.h" -#include "common/memContext.h" -#include "config/config.h" -#include "perl/config.h" -#include "perl/exec.h" - -/*********************************************************************************************************************************** -Include LibC code - -This file is generated by the LibC xs build. Including it here allows the functions provided by the C library to be provided by the -pgBackRest binary instead which means the C library does not need to be deployed in production builds. -***********************************************************************************************************************************/ -#ifndef HAS_BOOL -# define HAS_BOOL 1 -#endif - -#include "perl/libc.auto.c" - -/*********************************************************************************************************************************** -Include embedded Perl modules -***********************************************************************************************************************************/ -typedef struct EmbeddedModule -{ - const char *name; - const char *data; -} EmbeddedModule; - -#include "perl/embed.auto.c" - -/*********************************************************************************************************************************** -Perl interpreter - -This is a silly name but Perl prefers it. -***********************************************************************************************************************************/ -static PerlInterpreter *my_perl = NULL; - -/*********************************************************************************************************************************** -Constants used to build perl options -***********************************************************************************************************************************/ -#define PGBACKREST_MODULE PROJECT_NAME "::Main" -#define PGBACKREST_MAIN PGBACKREST_MODULE "::main" - -/*********************************************************************************************************************************** -Build list of parameters to use for perl main -***********************************************************************************************************************************/ -String * -perlMain(void) -{ - FUNCTION_TEST_VOID(); - - // Add command arguments to pass to main - String *commandParam = strNew(""); - - for (unsigned int paramIdx = 0; paramIdx < strLstSize(cfgCommandParam()); paramIdx++) - strCatFmt(commandParam, ",'%s'", strPtr(strLstGet(cfgCommandParam(), paramIdx))); - - // Construct Perl main call - String *mainCall = strNewFmt( - "($iResult, $bErrorC, $strMessage) = " PGBACKREST_MAIN "('%s'%s)", cfgCommandName(cfgCommand()), strPtr(commandParam)); - - FUNCTION_TEST_RETURN(mainCall); -} - -/*********************************************************************************************************************************** -Dynamic module loader -***********************************************************************************************************************************/ -static const char * -embeddedModuleGetInternal(const char *moduleName) -{ - FUNCTION_TEST_BEGIN(); - FUNCTION_TEST_PARAM(STRINGZ, moduleName); - FUNCTION_TEST_END(); - - // Find module - const char *result = NULL; - - for (unsigned int moduleIdx = 0; moduleIdx < sizeof(embeddedModule) / sizeof(EmbeddedModule); moduleIdx++) - { - if (strcmp(embeddedModule[moduleIdx].name, moduleName) == 0) - { - result = embeddedModule[moduleIdx].data; - break; - } - } - - // Error if the module was not found - if (result == NULL) - THROW_FMT(AssertError, "unable to load embedded module '%s'", moduleName); - - FUNCTION_TEST_RETURN(result); -} - -XS_EUPXS(embeddedModuleGet); -XS_EUPXS(embeddedModuleGet) -{ - dVAR; dXSARGS; - (void)cv; - - // Get module name - CHECK(items == 1); - const char *moduleName = (const char *)SvPV_nolen(ST(0)); // {uncoverable_branch - Perl macro} - dXSTARG; // {uncoverable_branch - Perl macro} - - // Return module data - sv_setpv(TARG, embeddedModuleGetInternal(moduleName)); - XSprePUSH; - PUSHTARG; // {uncoverable_branch - Perl macro} - - XSRETURN(1); -} - -/*********************************************************************************************************************************** -Init the dynaloader so other C modules can be loaded - -There are no FUNCTION_TEST* calls because this is a callback from Perl and it doesn't seem wise to mix our stack stuff up in it. -***********************************************************************************************************************************/ -#define LOADER_SUB \ - "sub\n" \ - "{\n" \ - " if ($_[1] =~ /^pgBackRest/)\n" \ - " {\n" \ - " my $data = pgBackRest::LibC::embeddedModuleGet($_[1]);\n" \ - "\n" \ - " open my $fh, '<', \\$data;\n" \ - " return $fh;\n" \ - " }\n" \ - "}" - -EXTERN_C void boot_DynaLoader (pTHX_ CV* cv); - -static void xs_init(pTHX) -{ - dXSUB_SYS; - PERL_UNUSED_CONTEXT; - - // Register the LibC functions by registering the boot function and calling it - newXS("pgBackRest::LibC::boot", boot_pgBackRest__LibC, __FILE__); - eval_pv("pgBackRest::LibC::boot()", TRUE); - - // Register the embedded module getter - newXS("pgBackRest::LibC::embeddedModuleGet", embeddedModuleGet, __FILE__); - - // DynaLoader is a special case - newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); -} - -/*********************************************************************************************************************************** -Evaluate a perl statement -***********************************************************************************************************************************/ -static void -perlEval(const String *statement) -{ - FUNCTION_TEST_BEGIN(); - FUNCTION_TEST_PARAM(STRING, statement); - FUNCTION_TEST_END(); - - eval_pv(strPtr(statement), TRUE); - - FUNCTION_TEST_RETURN_VOID(); -} - -/*********************************************************************************************************************************** -Initialize Perl -***********************************************************************************************************************************/ -static void -perlInit(void) -{ - FUNCTION_TEST_VOID(); - - if (!my_perl) - { - // Initialize Perl with dummy args and environment - int argc = 1; - const char *argv[1] = {strPtr(cfgExe())}; - const char *env[1] = {NULL}; - PERL_SYS_INIT3(&argc, (char ***)&argv, (char ***)&env); - - // Create the interpreter - const char *embedding[] = {"", "-e", "0"}; - my_perl = perl_alloc(); - perl_construct(my_perl); - - // Don't let $0 assignment update the proctitle or embedding[0] - PL_origalen = 1; - - // Start the interpreter - perl_parse(my_perl, xs_init, 3, (char **)embedding, NULL); - PL_exit_flags |= PERL_EXIT_DESTRUCT_END; - perl_run(my_perl); - - // Use customer loader to get all embedded modules - eval_pv("splice(@INC, 0, 0, " LOADER_SUB ");", true); - - // Now that the custom loader is installed, load the main module; - eval_pv("use " PGBACKREST_MODULE ";", true); - - // Set config data -- this is done separately to avoid it being included in stack traces - perlEval(strNewFmt(PGBACKREST_MAIN "ConfigSet('%s', '%s')", strPtr(cfgExe()), strPtr(perlOptionJson()))); - } - - FUNCTION_TEST_RETURN_VOID(); -} - -/*********************************************************************************************************************************** -Execute main function in Perl -***********************************************************************************************************************************/ -static int perlExecResult(int code, bool errorC, const char *message) -{ - FUNCTION_TEST_BEGIN(); - FUNCTION_TEST_PARAM(INT, code); - FUNCTION_TEST_PARAM(BOOL, errorC); - FUNCTION_TEST_PARAM(STRINGZ, message); - FUNCTION_TEST_END(); - - int result = code; - - if (code >= errorTypeCode(&AssertError)) - { - if (errorC) - RETHROW(); - else - THROW_CODE(code, strlen(message) == 0 ? PERL_EMBED_ERROR : message); - } - - FUNCTION_TEST_RETURN(result); -} - -int -perlExec(void) -{ - FUNCTION_LOG_VOID(logLevelDebug); - - // Initialize Perl - perlInit(); - - // Run perl main function - perlEval(perlMain()); - - // Return result code - int code = (int)SvIV(get_sv("iResult", 0)); // {uncoverable_branch - Perl macro} - bool errorC = (int)SvIV(get_sv("bErrorC", 0)); // {uncoverable_branch - Perl macro} - char *message = SvPV_nolen(get_sv("strMessage", 0)); // {uncoverable_branch - Perl macro} - - FUNCTION_LOG_RETURN(INT, perlExecResult(code, errorC, message)); -} - -/*********************************************************************************************************************************** -Free Perl objects - -Don't bother freeing Perl itself since we are about to exit. -***********************************************************************************************************************************/ -void -perlFree(int result) -{ - FUNCTION_TEST_BEGIN(); - FUNCTION_TEST_PARAM(INT, result); - FUNCTION_TEST_END(); - - if (my_perl != NULL) - perlEval(strNewFmt(PGBACKREST_MAIN "Cleanup(%d)", result)); - - FUNCTION_TEST_RETURN_VOID(); -} diff --git a/src/perl/exec.h b/src/perl/exec.h deleted file mode 100644 index a2f74aa00..000000000 --- a/src/perl/exec.h +++ /dev/null @@ -1,18 +0,0 @@ -/*********************************************************************************************************************************** -Execute Perl for Legacy Functionality -***********************************************************************************************************************************/ -#ifndef PERL_EXEC_H -#define PERL_EXEC_H - -/*********************************************************************************************************************************** -Error message for errors thrown from embedded Perl -***********************************************************************************************************************************/ -#define PERL_EMBED_ERROR "===PERL-EMBED-ERROR===" - -/*********************************************************************************************************************************** -Functions -***********************************************************************************************************************************/ -int perlExec(void); -void perlFree(int result); - -#endif diff --git a/src/perl/libc.auto.c b/src/perl/libc.auto.c deleted file mode 100644 index dbb74de85..000000000 --- a/src/perl/libc.auto.c +++ /dev/null @@ -1,2337 +0,0 @@ -/* - * This file was generated automatically by ExtUtils::ParseXS version 3.34 from the - * contents of LibC.xs. Do not edit this file, edit LibC.xs instead. - * - * ANY CHANGES MADE HERE WILL BE LOST! - * - */ - -/*********************************************************************************************************************************** -C to Perl Interface - -The following C types are mapped by the current typemap: - -'AV *', 'Boolean', 'CV *', 'FILE *', 'FileHandle', 'HV *', 'I16', 'I32', 'I8', 'IV', 'InOutStream', 'InputStream', 'NV', -'OutputStream', 'PerlIO *', 'Result', 'STRLEN', 'SV *', 'SVREF', 'SysRet', 'SysRetLong', 'Time_t *', 'U16', 'U32', 'U8', 'UV', -'bool', 'bool_t', 'caddr_t', 'char', 'char *', 'char **', 'const char *', 'double', 'float', 'int', 'long', 'short', 'size_t', -'ssize_t', 'time_t', 'unsigned', 'unsigned char', 'unsigned char *', 'unsigned int', 'unsigned long', 'unsigned long *', -'unsigned short', 'void *', 'wchar_t', 'wchar_t *' -***********************************************************************************************************************************/ -#include "build.auto.h" - -#define PERL_NO_GET_CONTEXT - -/*********************************************************************************************************************************** -Perl includes - -Order is critical here so don't change it. -***********************************************************************************************************************************/ -#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 8 || (__GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ >= 0))) - #define WARNING_MAYBE_INITIALIZED 1 -#elif __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ >= 0))) - #define WARNING_INITIALIZED 1 -#endif - -#if WARNING_MAYBE_INITIALIZED - #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#elif WARNING_INITIALIZED - #pragma GCC diagnostic ignored "-Wuninitialized" -#endif - -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wconversion" - -#include -#include -#include - -#if WARNING_MAYBE_INITIALIZED - #pragma GCC diagnostic warning "-Wmaybe-uninitialized" -#elif WARNING_INITIALIZED - #pragma GCC diagnostic warning "-Wuninitialized" -#endif - -/*********************************************************************************************************************************** -C includes - -These includes are from the src directory. There is no Perl-specific code in them. -***********************************************************************************************************************************/ -#include "common/crypto/common.h" -#include "common/error.h" -#include "common/io/io.h" -#include "common/lock.h" -#include "config/config.h" -#include "config/define.h" -#include "config/load.h" -#include "config/parse.h" -#include "perl/config.h" -#include "postgres/pageChecksum.h" -#include "storage/posix/storage.h" - -/*********************************************************************************************************************************** -Helper macros -***********************************************************************************************************************************/ -#include "LibC.h" - -/*********************************************************************************************************************************** -XSH includes - -These includes define data structures that are required for the C to Perl interface but are not part of the regular C source. -***********************************************************************************************************************************/ -#include "xs/crypto/hash.xsh" -#include "xs/common/encode.xsh" -#include "xs/postgres/client.xsh" -#include "xs/storage/storage.xsh" -#include "xs/storage/storageRead.xsh" -#include "xs/storage/storageWrite.xsh" - -/*********************************************************************************************************************************** -Module definition -***********************************************************************************************************************************/ -#ifndef PERL_UNUSED_VAR -# define PERL_UNUSED_VAR(var) if (0) var = var -#endif - -#ifndef dVAR -# define dVAR dNOOP -#endif - - -/* This stuff is not part of the API! You have been warned. */ -#ifndef PERL_VERSION_DECIMAL -# define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s) -#endif -#ifndef PERL_DECIMAL_VERSION -# define PERL_DECIMAL_VERSION \ - PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION) -#endif -#ifndef PERL_VERSION_GE -# define PERL_VERSION_GE(r,v,s) \ - (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s)) -#endif -#ifndef PERL_VERSION_LE -# define PERL_VERSION_LE(r,v,s) \ - (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s)) -#endif - -/* XS_INTERNAL is the explicit static-linkage variant of the default - * XS macro. - * - * XS_EXTERNAL is the same as XS_INTERNAL except it does not include - * "STATIC", ie. it exports XSUB symbols. You probably don't want that - * for anything but the BOOT XSUB. - * - * See XSUB.h in core! - */ - - -/* TODO: This might be compatible further back than 5.10.0. */ -#if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1) -# undef XS_EXTERNAL -# undef XS_INTERNAL -# if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING) -# define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name) -# define XS_INTERNAL(name) STATIC XSPROTO(name) -# endif -# if defined(__SYMBIAN32__) -# define XS_EXTERNAL(name) EXPORT_C XSPROTO(name) -# define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name) -# endif -# ifndef XS_EXTERNAL -# if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus) -# define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__) -# define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__) -# else -# ifdef __cplusplus -# define XS_EXTERNAL(name) extern "C" XSPROTO(name) -# define XS_INTERNAL(name) static XSPROTO(name) -# else -# define XS_EXTERNAL(name) XSPROTO(name) -# define XS_INTERNAL(name) STATIC XSPROTO(name) -# endif -# endif -# endif -#endif - -/* perl >= 5.10.0 && perl <= 5.15.1 */ - - -/* The XS_EXTERNAL macro is used for functions that must not be static - * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL - * macro defined, the best we can do is assume XS is the same. - * Dito for XS_INTERNAL. - */ -#ifndef XS_EXTERNAL -# define XS_EXTERNAL(name) XS(name) -#endif -#ifndef XS_INTERNAL -# define XS_INTERNAL(name) XS(name) -#endif - -/* Now, finally, after all this mess, we want an ExtUtils::ParseXS - * internal macro that we're free to redefine for varying linkage due - * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use - * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to! - */ - -#undef XS_EUPXS -#if defined(PERL_EUPXS_ALWAYS_EXPORT) -# define XS_EUPXS(name) XS_EXTERNAL(name) -#else - /* default to internal */ -# define XS_EUPXS(name) XS_INTERNAL(name) -#endif - -#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE -#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params) - -/* prototype to pass -Wmissing-prototypes */ -STATIC void -S_croak_xs_usage(const CV *const cv, const char *const params); - -STATIC void -S_croak_xs_usage(const CV *const cv, const char *const params) -{ - const GV *const gv = CvGV(cv); - - PERL_ARGS_ASSERT_CROAK_XS_USAGE; - - if (gv) { - const char *const gvname = GvNAME(gv); - const HV *const stash = GvSTASH(gv); - const char *const hvname = stash ? HvNAME(stash) : NULL; - - if (hvname) - Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params); - else - Perl_croak_nocontext("Usage: %s(%s)", gvname, params); - } else { - /* Pants. I don't think that it should be possible to get here. */ - Perl_croak_nocontext("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params); - } -} -#undef PERL_ARGS_ASSERT_CROAK_XS_USAGE - -#define croak_xs_usage S_croak_xs_usage - -#endif - -/* NOTE: the prototype of newXSproto() is different in versions of perls, - * so we define a portable version of newXSproto() - */ -#ifdef newXS_flags -#define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0) -#else -#define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv) -#endif /* !defined(newXS_flags) */ - -#if PERL_VERSION_LE(5, 21, 5) -# define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file) -#else -# define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b) -#endif - - -XS_EUPXS(XS_pgBackRest__LibC_libcUvSize); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_libcUvSize) -{ - dVAR; dXSARGS; - if (items != 0) - croak_xs_usage(cv, ""); - { - I32 RETVAL; - dXSTARG; - RETVAL = UVSIZE; - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - - -/* INCLUDE: Including 'xs/common/encode.xs' from 'LibC.xs' */ - - -/* INCLUDE: Including 'xs/common/lock.xs' from 'xs/common/encode.xs' */ - - -/* INCLUDE: Including 'xs/config/config.xs' from 'xs/common/lock.xs' */ - - -/* INCLUDE: Including 'xs/config/configTest.xs' from 'xs/config/config.xs' */ - - -/* INCLUDE: Including 'xs/config/define.xs' from 'xs/config/configTest.xs' */ - - -/* INCLUDE: Including 'xs/crypto/hash.xs' from 'xs/config/define.xs' */ - - -/* INCLUDE: Including 'xs/crypto/random.xs' from 'xs/crypto/hash.xs' */ - - -/* INCLUDE: Including 'xs/postgres/client.xs' from 'xs/crypto/random.xs' */ - - -/* INCLUDE: Including 'xs/postgres/pageChecksum.xs' from 'xs/postgres/client.xs' */ - - -/* INCLUDE: Including 'xs/storage/storage.xs' from 'xs/postgres/pageChecksum.xs' */ - - -/* INCLUDE: Including 'xs/storage/storageRead.xs' from 'xs/storage/storage.xs' */ - - -/* INCLUDE: Including 'xs/storage/storageWrite.xs' from 'xs/storage/storageRead.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_new); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_new) -{ - dVAR; dXSARGS; - if (items != 9) - croak_xs_usage(cv, "class, storage, file, mode, user, group, timeModified, atomic, pathCreate"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - const String * class = STR_NEW_SV(ST(0)); - pgBackRest__LibC__Storage storage; - const String * file = STR_NEW_SV(ST(2)); - U32 mode = (unsigned long)SvUV(ST(3)) -; - const String * user = STR_NEW_SV(ST(4)); - const String * group = STR_NEW_SV(ST(5)); - IV timeModified = (IV)SvIV(ST(6)) -; - bool atomic = (bool)SvTRUE(ST(7)) -; - bool pathCreate = (bool)SvTRUE(ST(8)) -; - pgBackRest__LibC__StorageWrite RETVAL; - - if (SvROK(ST(1)) && sv_derived_from(ST(1), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - storage = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageWrite::new", - "storage", "pgBackRest::LibC::Storage") -; - CHECK(strEqZ(class, PACKAGE_NAME_LIBC "::StorageWrite")); - - RETVAL = storageWriteMove( - storageNewWriteP( - storage, file, .modeFile = mode, .user = user, .group = group, .timeModified = (time_t)timeModified, - .noCreatePath = storageFeature(storage, storageFeaturePath) ? !pathCreate : false, .noSyncPath = !atomic, - .noAtomic = !atomic), - MEM_CONTEXT_XS_OLD()); - { - SV * RETVALSV; - RETVALSV = sv_newmortal(); - sv_setref_pv(RETVALSV, "pgBackRest::LibC::StorageWrite", (void*)RETVAL); - ST(0) = RETVALSV; - } - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_filterAdd); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_filterAdd) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "self, filter, param"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageWrite self; - const String * filter = STR_NEW_SV(ST(1)); - const String * param = STR_NEW_SV(ST(2)); - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageWrite")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageWrite,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageWrite::filterAdd", - "self", "pgBackRest::LibC::StorageWrite") -; - IoFilterGroup *filterGroup = ioWriteFilterGroup(storageWriteIo(self)); - storageFilterXsAdd(filterGroup, filter, param); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_open); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_open) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageWrite self; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageWrite")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageWrite,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageWrite::open", - "self", "pgBackRest::LibC::StorageWrite") -; - ioWriteOpen(storageWriteIo(self)); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_write); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_write) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, buffer"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageWrite self; - const Buffer * buffer = BUF_CONST_SV(ST(1)); - UV RETVAL; - dXSTARG; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageWrite")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageWrite,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageWrite::write", - "self", "pgBackRest::LibC::StorageWrite") -; - ioWrite(storageWriteIo(self), buffer); - RETVAL = bufUsed(buffer); - XSprePUSH; PUSHu((UV)RETVAL); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_close); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_close) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageWrite self; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageWrite")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageWrite,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageWrite::close", - "self", "pgBackRest::LibC::StorageWrite") -; - ioWriteClose(storageWriteIo(self)); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_result); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_result) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, filter"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageWrite self; - const String * filter = STR_NEW_SV(ST(1)); - const char * RETVAL; - dXSTARG; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageWrite")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageWrite,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageWrite::result", - "self", "pgBackRest::LibC::StorageWrite") -; - RETVAL = strPtr(storageFilterXsResult(ioWriteFilterGroup(storageWriteIo(self)), filter)); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_resultAll); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_resultAll) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageWrite self; - const char * RETVAL; - dXSTARG; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageWrite")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageWrite,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageWrite::resultAll", - "self", "pgBackRest::LibC::StorageWrite") -; - RETVAL = strPtr(storageFilterXsResultAll(ioWriteFilterGroup(storageWriteIo(self)))); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_DESTROY); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageWrite_DESTROY) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageWrite self; - - if (SvROK(ST(0))) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageWrite,tmp); - } - else - Perl_croak_nocontext("%s: %s is not a reference", - "pgBackRest::LibC::StorageWrite::DESTROY", - "self") -; - storageWriteFree(self); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -/* INCLUDE: Returning to 'xs/storage/storageRead.xs' from 'xs/storage/storageWrite.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_new); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_new) -{ - dVAR; dXSARGS; - if (items != 4) - croak_xs_usage(cv, "class, storage, file, ignoreMissing"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - const String * class = STR_NEW_SV(ST(0)); - pgBackRest__LibC__Storage storage; - const String * file = STR_NEW_SV(ST(2)); - bool ignoreMissing = (bool)SvTRUE(ST(3)) -; - pgBackRest__LibC__StorageRead RETVAL; - - if (SvROK(ST(1)) && sv_derived_from(ST(1), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - storage = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageRead::new", - "storage", "pgBackRest::LibC::Storage") -; - CHECK(strEqZ(class, PACKAGE_NAME_LIBC "::StorageRead")); - - RETVAL = storageReadMove(storageNewReadP(storage, file, .ignoreMissing = ignoreMissing), MEM_CONTEXT_XS_OLD()); - { - SV * RETVALSV; - RETVALSV = sv_newmortal(); - sv_setref_pv(RETVALSV, "pgBackRest::LibC::StorageRead", (void*)RETVAL); - ST(0) = RETVALSV; - } - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_filterAdd); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_filterAdd) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "self, filter, param"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead self; - const String * filter = STR_NEW_SV(ST(1)); - const String * param = STR_NEW_SV(ST(2)); - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageRead::filterAdd", - "self", "pgBackRest::LibC::StorageRead") -; - IoFilterGroup *filterGroup = ioReadFilterGroup(storageReadIo(self)); - storageFilterXsAdd(filterGroup, filter, param); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_open); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_open) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead self; - bool RETVAL; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageRead::open", - "self", "pgBackRest::LibC::StorageRead") -; - RETVAL = ioReadOpen(storageReadIo(self)); - ST(0) = boolSV(RETVAL); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_read); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_read) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, bufferSize"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead self; - U32 bufferSize = (unsigned long)SvUV(ST(1)) -; - SV * RETVAL; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageRead::read", - "self", "pgBackRest::LibC::StorageRead") -; - RETVAL = NEWSV(0, bufferSize); - SvPOK_only(RETVAL); - - Buffer *bufferRead = bufNewUseC((unsigned char *)SvPV_nolen(RETVAL), bufferSize); - ioRead(storageReadIo(self), bufferRead); - - SvCUR_set(RETVAL, bufUsed(bufferRead)); - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_eof); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_eof) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead self; - bool RETVAL; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageRead::eof", - "self", "pgBackRest::LibC::StorageRead") -; - RETVAL = ioReadEof(storageReadIo(self)); - ST(0) = boolSV(RETVAL); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_close); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_close) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead self; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageRead::close", - "self", "pgBackRest::LibC::StorageRead") -; - ioReadClose(storageReadIo(self)); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_result); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_result) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, filter"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead self; - const String * filter = STR_NEW_SV(ST(1)); - const char * RETVAL; - dXSTARG; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageRead::result", - "self", "pgBackRest::LibC::StorageRead") -; - RETVAL = strPtr(storageFilterXsResult(ioReadFilterGroup(storageReadIo(self)), filter)); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_resultAll); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_resultAll) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead self; - const char * RETVAL; - dXSTARG; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::StorageRead::resultAll", - "self", "pgBackRest::LibC::StorageRead") -; - RETVAL = strPtr(storageFilterXsResultAll(ioReadFilterGroup(storageReadIo(self)))); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_DESTROY); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__StorageRead_DESTROY) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead self; - - if (SvROK(ST(0))) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not a reference", - "pgBackRest::LibC::StorageRead::DESTROY", - "self") -; - storageReadFree(self); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -/* INCLUDE: Returning to 'xs/storage/storage.xs' from 'xs/storage/storageRead.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_new); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_new) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "class, type, path"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - const String * class = STR_NEW_SV(ST(0)); - const String * type = STR_NEW_SV(ST(1)); - const String * path = STR_NEW_SV(ST(2)); - pgBackRest__LibC__Storage RETVAL; - CHECK(strEqZ(class, PACKAGE_NAME_LIBC "::Storage")); - - if (strEqZ(type, "")) - { - memContextSwitch(MEM_CONTEXT_XS_OLD()); - RETVAL = storagePosixNew( - path == NULL ? STRDEF("/") : path, STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL); - storagePathEnforceSet((Storage *)RETVAL, false); - memContextSwitch(MEM_CONTEXT_XS_TEMP()); - } - else if (strEqZ(type, "")) - { - CHECK(path == NULL); - RETVAL = (Storage *)storageRepoWrite(); - } - else if (strEqZ(type, "")) - { - CHECK(path == NULL); - - memContextSwitch(MEM_CONTEXT_XS_OLD()); - RETVAL = storagePosixNew(cfgOptionStr(cfgOptPgPath), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL); - storagePathEnforceSet((Storage *)RETVAL, false); - memContextSwitch(MEM_CONTEXT_XS_TEMP()); - } - else - THROW_FMT(AssertError, "unexpected storage type '%s'", strPtr(type)); - { - SV * RETVALSV; - RETVALSV = sv_newmortal(); - sv_setref_pv(RETVALSV, "pgBackRest::LibC::Storage", (void*)RETVAL); - ST(0) = RETVALSV; - } - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_bucketCreate); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_bucketCreate) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::bucketCreate", - "self", "pgBackRest::LibC::Storage") -; - if (strEq(storageType(self), STORAGE_S3_TYPE_STR)) - storageS3Request((StorageS3 *)storageDriver(self), HTTP_VERB_PUT_STR, FSLASH_STR, NULL, NULL, true, false); - else - THROW_FMT(AssertError, "unable to create bucket on '%s' storage", strPtr(storageType(self))); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_copy); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_copy) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "self, source, destination"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead source; - pgBackRest__LibC__StorageWrite destination; - bool RETVAL; - - if (SvROK(ST(1)) && sv_derived_from(ST(1), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - source = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::copy", - "source", "pgBackRest::LibC::StorageRead") -; - - if (SvROK(ST(2)) && sv_derived_from(ST(2), "pgBackRest::LibC::StorageWrite")) { - IV tmp = SvIV((SV*)SvRV(ST(2))); - destination = INT2PTR(pgBackRest__LibC__StorageWrite,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::copy", - "destination", "pgBackRest::LibC::StorageWrite") -; - RETVAL = storageCopyP(source, destination); - ST(0) = boolSV(RETVAL); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_exists); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_exists) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, fileExp"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * fileExp = STR_NEW_SV(ST(1)); - bool RETVAL; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::exists", - "self", "pgBackRest::LibC::Storage") -; - RETVAL = storageExistsP(self, fileExp); - ST(0) = boolSV(RETVAL); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_get); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_get) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, read"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead read; - SV * RETVAL; - - if (SvROK(ST(1)) && sv_derived_from(ST(1), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - read = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::get", - "read", "pgBackRest::LibC::StorageRead") -; - RETVAL = NULL; - Buffer *buffer = storageGetP(read); - - if (buffer != NULL) - { - if (bufUsed(buffer) == 0) - RETVAL = newSVpv("", 0); - else - RETVAL = newSVpv((char *)bufPtr(buffer), bufUsed(buffer)); - } - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_info); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_info) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "self, pathExp, ignoreMissing"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * pathExp = STR_NEW_SV(ST(1)); - bool ignoreMissing = (bool)SvTRUE(ST(2)) -; - SV * RETVAL; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::info", - "self", "pgBackRest::LibC::Storage") -; - RETVAL = NULL; - - StorageInfo info = storageInfoP(self, pathExp, .ignoreMissing = ignoreMissing); - - if (info.exists) - { - String *json = storageManifestXsInfo(NULL, &info); - RETVAL = newSVpv((char *)strPtr(json), strSize(json)); - } - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_list); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_list) -{ - dVAR; dXSARGS; - if (items != 5) - croak_xs_usage(cv, "self, pathExp, ignoreMissing, sortAsc, expression"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * pathExp = STR_NEW_SV(ST(1)); - bool ignoreMissing = (bool)SvTRUE(ST(2)) -; - bool sortAsc = (bool)SvTRUE(ST(3)) -; - const String * expression = STR_NEW_SV(ST(4)); - SV * RETVAL; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::list", - "self", "pgBackRest::LibC::Storage") -; - StringList *fileList = strLstSort( - storageListP(self, pathExp, .errorOnMissing = storageFeature(self, storageFeaturePath) ? !ignoreMissing : false, - .expression = expression), sortAsc ? sortOrderAsc : sortOrderDesc); - - const String *fileListJson = jsonFromVar(varNewVarLst(varLstNewStrLst(fileList))); - - RETVAL = newSVpv(strPtr(fileListJson), strSize(fileListJson)); - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_manifest); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_manifest) -{ - dVAR; dXSARGS; - if (items < 2 || items > 3) - croak_xs_usage(cv, "self, pathExp, filter=NULL"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * pathExp = STR_NEW_SV(ST(1)); - const String * filter = STR_NEW_SV(ST(2)); - SV * RETVAL; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::manifest", - "self", "pgBackRest::LibC::Storage") -; - StorageManifestXsCallbackData data = {.storage = self, .json = strNew("{"), .pathRoot = pathExp, .filter = filter}; - - // If a path is specified - StorageInfo info = storageInfoP(self, pathExp, .ignoreMissing = true); - - if (!info.exists || info.type == storageTypePath) - { - storageInfoListP( - self, data.pathRoot, storageManifestXsCallback, &data, - .errorOnMissing = storageFeature(self, storageFeaturePath) ? true : false); - } - // Else a file is specified - else - { - info.name = strBase(storagePathP(self, pathExp)); - strCat(data.json, strPtr(storageManifestXsInfo(NULL, &info))); - } - - strCat(data.json, "}"); - - RETVAL = newSVpv((char *)strPtr(data.json), strSize(data.json)); - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathCreate); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathCreate) -{ - dVAR; dXSARGS; - if (items != 5) - croak_xs_usage(cv, "self, pathExp, mode, ignoreExists, createParent"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * pathExp = STR_NEW_SV(ST(1)); - const String * mode = STR_NEW_SV(ST(2)); - bool ignoreExists = (bool)SvTRUE(ST(3)) -; - bool createParent = (bool)SvTRUE(ST(4)) -; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::pathCreate", - "self", "pgBackRest::LibC::Storage") -; - if (storageFeature(self, storageFeaturePath)) - storagePathCreateP( - self, pathExp, .mode = mode ? cvtZToMode(strPtr(mode)) : 0, .errorOnExists = !ignoreExists, - .noParentCreate = !createParent); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathExists); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathExists) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, pathExp"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * pathExp = STR_NEW_SV(ST(1)); - bool RETVAL; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::pathExists", - "self", "pgBackRest::LibC::Storage") -; - RETVAL = true; - - if (storageFeature(self, storageFeaturePath)) - RETVAL = storagePathExistsP(self, pathExp); - ST(0) = boolSV(RETVAL); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathGet); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathGet) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, pathExp"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * pathExp = STR_NEW_SV(ST(1)); - SV * RETVAL; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::pathGet", - "self", "pgBackRest::LibC::Storage") -; - String *path = storagePathP(self, pathExp); - RETVAL = newSVpv((char *)strPtr(path), strSize(path)); - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathRemove); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathRemove) -{ - dVAR; dXSARGS; - if (items != 4) - croak_xs_usage(cv, "self, pathExp, ignoreMissing, recurse"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * pathExp = STR_NEW_SV(ST(1)); - bool ignoreMissing = (bool)SvTRUE(ST(2)) -; - bool recurse = (bool)SvTRUE(ST(3)) -; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::pathRemove", - "self", "pgBackRest::LibC::Storage") -; - storagePathRemoveP( - self, pathExp, .errorOnMissing = storageFeature(self, storageFeaturePath) ? !ignoreMissing : false, .recurse = recurse); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathSync); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_pathSync) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, pathExp"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * pathExp = STR_NEW_SV(ST(1)); - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::pathSync", - "self", "pgBackRest::LibC::Storage") -; - storagePathSyncP(self, pathExp); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_put); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_put) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "self, write, buffer"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageWrite write; - const Buffer * buffer = BUF_CONST_SV(ST(2)); - UV RETVAL; - dXSTARG; - - if (SvROK(ST(1)) && sv_derived_from(ST(1), "pgBackRest::LibC::StorageWrite")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - write = INT2PTR(pgBackRest__LibC__StorageWrite,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::put", - "write", "pgBackRest::LibC::StorageWrite") -; - storagePutP(write, buffer); - RETVAL = buffer ? bufUsed(buffer) : 0; - XSprePUSH; PUSHu((UV)RETVAL); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_readDrain); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_readDrain) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, read"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__StorageRead read; - bool RETVAL; - - if (SvROK(ST(1)) && sv_derived_from(ST(1), "pgBackRest::LibC::StorageRead")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - read = INT2PTR(pgBackRest__LibC__StorageRead,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::readDrain", - "read", "pgBackRest::LibC::StorageRead") -; - RETVAL = false; - - // Read and discard all IO (this is useful for processing filters) - if (ioReadOpen(storageReadIo(read))) - { - Buffer *buffer = bufNew(ioBufferSize()); - - do - { - ioRead(storageReadIo(read), buffer); - bufUsedZero(buffer); - } - while (!ioReadEof(storageReadIo(read))); - - ioReadClose(storageReadIo(read)); - RETVAL = true; - } - ST(0) = boolSV(RETVAL); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_remove); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_remove) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "self, fileExp, ignoreMissing"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const String * fileExp = STR_NEW_SV(ST(1)); - bool ignoreMissing = (bool)SvTRUE(ST(2)) -; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::remove", - "self", "pgBackRest::LibC::Storage") -; - storageRemoveP(self, fileExp, .errorOnMissing = storageFeature(self, storageFeaturePath) ? !ignoreMissing : false); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_cipherType); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_cipherType) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - const char * RETVAL; - dXSTARG; - if (cfgOptionStr(cfgOptRepoCipherType) == NULL || cipherType(cfgOptionStr(cfgOptRepoCipherType)) == cipherTypeNone) - RETVAL = NULL; - else - RETVAL = strPtr(cfgOptionStr(cfgOptRepoCipherType)); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_cipherPass); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_cipherPass) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - const char * RETVAL; - dXSTARG; - RETVAL = strPtr(cfgOptionStr(cfgOptRepoCipherPass)); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__Storage_type); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__Storage_type) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__Storage self; - const char * RETVAL; - dXSTARG; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::Storage")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__Storage,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::Storage::type", - "self", "pgBackRest::LibC::Storage") -; - RETVAL = strPtr(storageType(self)); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_storageRepoFree); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_storageRepoFree) -{ - dVAR; dXSARGS; - if (items != 0) - croak_xs_usage(cv, ""); - { - storageHelperFree(); - } - XSRETURN_EMPTY; -} - - -/* INCLUDE: Returning to 'xs/postgres/pageChecksum.xs' from 'xs/storage/storage.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC_pageChecksum); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_pageChecksum) -{ - dVAR; dXSARGS; - if (items != 3) - croak_xs_usage(cv, "page, blockNo, pageSize"); - { - const char * page = (const char *)SvPV_nolen(ST(0)) -; - U32 blockNo = (unsigned long)SvUV(ST(1)) -; - U32 pageSize = (unsigned long)SvUV(ST(2)) -; - U16 RETVAL; - dXSTARG; - RETVAL = 0; - - ERROR_XS_BEGIN() - { - RETVAL = pageChecksum( - (const unsigned char *)page, blockNo, pageSize); - } - ERROR_XS_END(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - - -/* INCLUDE: Returning to 'xs/postgres/client.xs' from 'xs/postgres/pageChecksum.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC__PgClient_new); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__PgClient_new) -{ - dVAR; dXSARGS; - if (items != 5) - croak_xs_usage(cv, "class, host, port, database, queryTimeout"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - const String * class = STR_NEW_SV(ST(0)); - const String * host = STR_NEW_SV(ST(1)); - U32 port = (unsigned long)SvUV(ST(2)) -; - const String * database = STR_NEW_SV(ST(3)); - UV queryTimeout = (UV)SvUV(ST(4)) -; - pgBackRest__LibC__PgClient RETVAL; - CHECK(strEqZ(class, PACKAGE_NAME_LIBC "::PgClient")); - - memContextSwitch(MEM_CONTEXT_XS_OLD()); - RETVAL = pgClientNew(host, port, database, NULL, queryTimeout); - memContextSwitch(MEM_CONTEXT_XS_TEMP()); - { - SV * RETVALSV; - RETVALSV = sv_newmortal(); - sv_setref_pv(RETVALSV, "pgBackRest::LibC::PgClient", (void*)RETVAL); - ST(0) = RETVALSV; - } - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__PgClient_open); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__PgClient_open) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__PgClient self; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::PgClient")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__PgClient,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::PgClient::open", - "self", "pgBackRest::LibC::PgClient") -; - pgClientOpen(self); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__PgClient_query); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__PgClient_query) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "self, query"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__PgClient self; - const String * query = STR_NEW_SV(ST(1)); - const char * RETVAL; - dXSTARG; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::PgClient")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__PgClient,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::PgClient::query", - "self", "pgBackRest::LibC::PgClient") -; - VariantList *result = pgClientQuery(self, query); - RETVAL = result ? strPtr(jsonFromVar(varNewVarLst(result))) : NULL; - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC__PgClient_close); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__PgClient_close) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__PgClient self; - - if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::PgClient")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__PgClient,tmp); - } - else - Perl_croak_nocontext("%s: %s is not of type %s", - "pgBackRest::LibC::PgClient::close", - "self", "pgBackRest::LibC::PgClient") -; - pgClientClose(self); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -XS_EUPXS(XS_pgBackRest__LibC__PgClient_DESTROY); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC__PgClient_DESTROY) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "self"); - { - MEM_CONTEXT_XS_TEMP_BEGIN() - { - pgBackRest__LibC__PgClient self; - - if (SvROK(ST(0))) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - self = INT2PTR(pgBackRest__LibC__PgClient,tmp); - } - else - Perl_croak_nocontext("%s: %s is not a reference", - "pgBackRest::LibC::PgClient::DESTROY", - "self") -; - pgClientFree(self); - } - MEM_CONTEXT_XS_TEMP_END(); - } - XSRETURN_EMPTY; -} - - -/* INCLUDE: Returning to 'xs/crypto/random.xs' from 'xs/postgres/client.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC_cryptoRandomBytes); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cryptoRandomBytes) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "size"); - { - I32 size = (I32)SvIV(ST(0)) -; - SV * RETVAL; - RETVAL = newSV(size); - SvPOK_only(RETVAL); - - cryptoRandomBytes((unsigned char *)SvPV_nolen(RETVAL), size); - - SvCUR_set(RETVAL, size); - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - XSRETURN(1); -} - - -/* INCLUDE: Returning to 'xs/crypto/hash.xs' from 'xs/crypto/random.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC_cryptoHashOne); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cryptoHashOne) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "type, message"); - { - const char * type = (const char *)SvPV_nolen(ST(0)) -; - SV * message = ST(1) -; - SV * RETVAL; - RETVAL = NULL; - - MEM_CONTEXT_XS_TEMP_BEGIN() - { - STRLEN messageSize; - const void *messagePtr = SvPV(message, messageSize); - - String *hash = bufHex(cryptoHashOne(strNew(type), BUF(messagePtr, messageSize))); - - RETVAL = newSV(strSize(hash)); - SvPOK_only(RETVAL); - strcpy((char *)SvPV_nolen(RETVAL), strPtr(hash)); - SvCUR_set(RETVAL, strSize(hash)); - } - MEM_CONTEXT_XS_TEMP_END(); - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - XSRETURN(1); -} - - -/* INCLUDE: Returning to 'xs/config/define.xs' from 'xs/crypto/hash.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC_cfgCommandId); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgCommandId) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "commandName"); - { - const char * commandName = (const char *)SvPV_nolen(ST(0)) -; - I32 RETVAL; - dXSTARG; - RETVAL = 0; - - ERROR_XS_BEGIN() - { - RETVAL = cfgCommandId(commandName); - } - ERROR_XS_END(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionId); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionId) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "optionName"); - { - const char * optionName = (const char *)SvPV_nolen(ST(0)) -; - I32 RETVAL; - dXSTARG; - RETVAL = 0; - - ERROR_XS_BEGIN() - { - RETVAL = cfgOptionId(optionName); - } - ERROR_XS_END(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionDefault); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionDefault) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "commandId, optionId"); - { - U32 commandId = (unsigned long)SvUV(ST(0)) -; - U32 optionId = (unsigned long)SvUV(ST(1)) -; - const char * RETVAL; - dXSTARG; - RETVAL = NULL; - - ERROR_XS_BEGIN() - { - RETVAL = cfgDefOptionDefault(cfgCommandDefIdFromId(commandId), cfgOptionDefIdFromId(optionId)); - } - ERROR_XS_END(); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionPrefix); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionPrefix) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "optionId"); - { - U32 optionId = (unsigned long)SvUV(ST(0)) -; - const char * RETVAL; - dXSTARG; - RETVAL = NULL; - - ERROR_XS_BEGIN() - { - RETVAL = cfgDefOptionPrefix(cfgOptionDefIdFromId(optionId)); - } - ERROR_XS_END(); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionSecure); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionSecure) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "optionId"); - { - U32 optionId = (unsigned long)SvUV(ST(0)) -; - bool RETVAL; - RETVAL = false; - - ERROR_XS_BEGIN() - { - RETVAL = cfgDefOptionSecure(cfgOptionDefIdFromId(optionId)); - } - ERROR_XS_END(); - ST(0) = boolSV(RETVAL); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionType); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionType) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "optionId"); - { - U32 optionId = (unsigned long)SvUV(ST(0)) -; - I32 RETVAL; - dXSTARG; - RETVAL = 0; - - ERROR_XS_BEGIN() - { - RETVAL = cfgDefOptionType(cfgOptionDefIdFromId(optionId)); - } - ERROR_XS_END(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionValid); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgDefOptionValid) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "commandId, optionId"); - { - U32 commandId = (unsigned long)SvUV(ST(0)) -; - U32 optionId = (unsigned long)SvUV(ST(1)) -; - bool RETVAL; - RETVAL = false; - - ERROR_XS_BEGIN() - { - RETVAL = cfgDefOptionValid(cfgCommandDefIdFromId(commandId), cfgOptionDefIdFromId(optionId)); - } - ERROR_XS_END(); - ST(0) = boolSV(RETVAL); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionTotal); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionTotal) -{ - dVAR; dXSARGS; - if (items != 0) - croak_xs_usage(cv, ""); - { - U32 RETVAL; - dXSTARG; - RETVAL = CFG_OPTION_TOTAL; - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - - -/* INCLUDE: Returning to 'xs/config/configTest.xs' from 'xs/config/define.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC_cfgParseTest); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgParseTest) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "backrestBin, parseParam"); - { - const char * backrestBin = (const char *)SvPV_nolen(ST(0)) -; - const char * parseParam = (const char *)SvPV_nolen(ST(1)) -; - SV * RETVAL; - RETVAL = NULL; - - ERROR_XS_BEGIN() - { - // This should run in a temp context but for some reason getopt_long gets upset when if gets called again after the previous - // arg list being freed. So, this is a memory leak but it is only used for testing, not production. - StringList *paramList = strLstNewSplitZ(strCat(strNew("pgbackrest|"), parseParam), "|"); - - // Don't use cfgLoad() because it has a lot of side effects that we don't want - configParse(strLstSize(paramList), strLstPtr(paramList), false); - cfgExeSet(strNew(backrestBin)); - cfgLoadUpdateOption(); - - String *result = perlOptionJson(); - - RETVAL = newSV(strSize(result)); - SvPOK_only(RETVAL); - - strcpy(SvPV_nolen(RETVAL), strPtr(result)); - SvCUR_set(RETVAL, strSize(result)); - } - ERROR_XS_END() - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - XSRETURN(1); -} - - -/* INCLUDE: Returning to 'xs/config/config.xs' from 'xs/config/configTest.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC_cfgCommandName); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgCommandName) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "commandId"); - { - U32 commandId = (unsigned long)SvUV(ST(0)) -; - const char * RETVAL; - dXSTARG; - - RETVAL = cfgCommandName(commandId); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionIndex); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionIndex) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "optionId"); - { - U32 optionId = (unsigned long)SvUV(ST(0)) -; - I32 RETVAL; - dXSTARG; - - RETVAL = cfgOptionIndex(optionId); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionIndexTotal); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionIndexTotal) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "optionId"); - { - U32 optionId = (unsigned long)SvUV(ST(0)) -; - I32 RETVAL; - dXSTARG; - - RETVAL = cfgOptionIndexTotal(optionId); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionName); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_cfgOptionName) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "optionId"); - { - U32 optionId = (unsigned long)SvUV(ST(0)) -; - const char * RETVAL; - dXSTARG; - - RETVAL = cfgOptionName(optionId); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); -} - - -/* INCLUDE: Returning to 'xs/common/lock.xs' from 'xs/config/config.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC_lockAcquire); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_lockAcquire) -{ - dVAR; dXSARGS; - if (items != 5) - croak_xs_usage(cv, "lockPath, command, stanza, lockTimeout, failOnNoLock"); - { - const char * lockPath = (const char *)SvPV_nolen(ST(0)) -; - const char * command = (const char *)SvPV_nolen(ST(1)) -; - const char * stanza = (const char *)SvPV_nolen(ST(2)) -; - double lockTimeout = (double)SvNV(ST(3)) -; - bool failOnNoLock = (bool)SvTRUE(ST(4)) -; - bool RETVAL; - RETVAL = false; - - MEM_CONTEXT_XS_TEMP_BEGIN() - { - // Set the command so we can get the correct lock type to use - cfgCommandSet(cfgCommandId(command)); - - // Attempt to acquire the lock - if (cfgLockRequired()) - RETVAL = lockAcquire(strNew(lockPath), strNew(stanza), cfgLockType(), (TimeMSec)(lockTimeout * 1000), failOnNoLock); - } - MEM_CONTEXT_XS_TEMP_END(); - ST(0) = boolSV(RETVAL); - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_lockRelease); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_lockRelease) -{ - dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "failOnNoLock"); - { - bool failOnNoLock = (bool)SvTRUE(ST(0)) -; - bool RETVAL; - RETVAL = false; - - MEM_CONTEXT_XS_TEMP_BEGIN() - { - RETVAL = lockRelease(failOnNoLock); - } - MEM_CONTEXT_XS_TEMP_END(); - ST(0) = boolSV(RETVAL); - } - XSRETURN(1); -} - - -/* INCLUDE: Returning to 'xs/common/encode.xs' from 'xs/common/lock.xs' */ - - -XS_EUPXS(XS_pgBackRest__LibC_encodeToStr); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_encodeToStr) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "encodeType, source"); - { - int encodeType = (int)SvIV(ST(0)) -; - SV * source = ST(1) -; - SV * RETVAL; - RETVAL = NULL; - - STRLEN sourceSize; - unsigned char *sourcePtr = (unsigned char *)SvPV(source, sourceSize); - - ERROR_XS_BEGIN() - { - RETVAL = newSV(encodeToStrSize(encodeType, sourceSize)); - SvPOK_only(RETVAL); - - encodeToStr(encodeType, sourcePtr, sourceSize, (char *)SvPV_nolen(RETVAL)); - SvCUR_set(RETVAL, encodeToStrSize(encodeType, sourceSize)); - } - ERROR_XS_END(); - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - XSRETURN(1); -} - - -XS_EUPXS(XS_pgBackRest__LibC_decodeToBin); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_pgBackRest__LibC_decodeToBin) -{ - dVAR; dXSARGS; - if (items != 2) - croak_xs_usage(cv, "encodeType, source"); - { - int encodeType = (int)SvIV(ST(0)) -; - const char * source = (const char *)SvPV_nolen(ST(1)) -; - SV * RETVAL; - RETVAL = NULL; - - ERROR_XS_BEGIN() - { - RETVAL = newSV(decodeToBinSize(encodeType, source)); - SvPOK_only(RETVAL); - - decodeToBin(encodeType, source, (unsigned char *)SvPV_nolen(RETVAL)); - SvCUR_set(RETVAL, decodeToBinSize(encodeType, source)); - } - ERROR_XS_END(); - RETVAL = sv_2mortal(RETVAL); - ST(0) = RETVAL; - } - XSRETURN(1); -} - - -/* INCLUDE: Returning to 'LibC.xs' from 'xs/common/encode.xs' */ - -#ifdef __cplusplus -extern "C" -#endif -XS_EXTERNAL(boot_pgBackRest__LibC); /* prototype to pass -Wmissing-prototypes */ -XS_EXTERNAL(boot_pgBackRest__LibC) -{ -#if PERL_VERSION_LE(5, 21, 5) - dVAR; dXSARGS; -#else - dVAR; dXSBOOTARGSXSAPIVERCHK; -#endif -#if (PERL_REVISION == 5 && PERL_VERSION < 9) - char* file = __FILE__; -#else - const char* file = __FILE__; -#endif - - PERL_UNUSED_VAR(file); - - PERL_UNUSED_VAR(cv); /* -W */ - PERL_UNUSED_VAR(items); /* -W */ -#if PERL_VERSION_LE(5, 21, 5) - XS_VERSION_BOOTCHECK; -# ifdef XS_APIVERSION_BOOTCHECK - XS_APIVERSION_BOOTCHECK; -# endif -#endif - - newXS_deffile("pgBackRest::LibC::libcUvSize", XS_pgBackRest__LibC_libcUvSize); - newXS_deffile("pgBackRest::LibC::StorageWrite::new", XS_pgBackRest__LibC__StorageWrite_new); - newXS_deffile("pgBackRest::LibC::StorageWrite::filterAdd", XS_pgBackRest__LibC__StorageWrite_filterAdd); - newXS_deffile("pgBackRest::LibC::StorageWrite::open", XS_pgBackRest__LibC__StorageWrite_open); - newXS_deffile("pgBackRest::LibC::StorageWrite::write", XS_pgBackRest__LibC__StorageWrite_write); - newXS_deffile("pgBackRest::LibC::StorageWrite::close", XS_pgBackRest__LibC__StorageWrite_close); - newXS_deffile("pgBackRest::LibC::StorageWrite::result", XS_pgBackRest__LibC__StorageWrite_result); - newXS_deffile("pgBackRest::LibC::StorageWrite::resultAll", XS_pgBackRest__LibC__StorageWrite_resultAll); - newXS_deffile("pgBackRest::LibC::StorageWrite::DESTROY", XS_pgBackRest__LibC__StorageWrite_DESTROY); - newXS_deffile("pgBackRest::LibC::StorageRead::new", XS_pgBackRest__LibC__StorageRead_new); - newXS_deffile("pgBackRest::LibC::StorageRead::filterAdd", XS_pgBackRest__LibC__StorageRead_filterAdd); - newXS_deffile("pgBackRest::LibC::StorageRead::open", XS_pgBackRest__LibC__StorageRead_open); - newXS_deffile("pgBackRest::LibC::StorageRead::read", XS_pgBackRest__LibC__StorageRead_read); - newXS_deffile("pgBackRest::LibC::StorageRead::eof", XS_pgBackRest__LibC__StorageRead_eof); - newXS_deffile("pgBackRest::LibC::StorageRead::close", XS_pgBackRest__LibC__StorageRead_close); - newXS_deffile("pgBackRest::LibC::StorageRead::result", XS_pgBackRest__LibC__StorageRead_result); - newXS_deffile("pgBackRest::LibC::StorageRead::resultAll", XS_pgBackRest__LibC__StorageRead_resultAll); - newXS_deffile("pgBackRest::LibC::StorageRead::DESTROY", XS_pgBackRest__LibC__StorageRead_DESTROY); - newXS_deffile("pgBackRest::LibC::Storage::new", XS_pgBackRest__LibC__Storage_new); - newXS_deffile("pgBackRest::LibC::Storage::bucketCreate", XS_pgBackRest__LibC__Storage_bucketCreate); - newXS_deffile("pgBackRest::LibC::Storage::copy", XS_pgBackRest__LibC__Storage_copy); - newXS_deffile("pgBackRest::LibC::Storage::exists", XS_pgBackRest__LibC__Storage_exists); - newXS_deffile("pgBackRest::LibC::Storage::get", XS_pgBackRest__LibC__Storage_get); - newXS_deffile("pgBackRest::LibC::Storage::info", XS_pgBackRest__LibC__Storage_info); - newXS_deffile("pgBackRest::LibC::Storage::list", XS_pgBackRest__LibC__Storage_list); - newXS_deffile("pgBackRest::LibC::Storage::manifest", XS_pgBackRest__LibC__Storage_manifest); - newXS_deffile("pgBackRest::LibC::Storage::pathCreate", XS_pgBackRest__LibC__Storage_pathCreate); - newXS_deffile("pgBackRest::LibC::Storage::pathExists", XS_pgBackRest__LibC__Storage_pathExists); - newXS_deffile("pgBackRest::LibC::Storage::pathGet", XS_pgBackRest__LibC__Storage_pathGet); - newXS_deffile("pgBackRest::LibC::Storage::pathRemove", XS_pgBackRest__LibC__Storage_pathRemove); - newXS_deffile("pgBackRest::LibC::Storage::pathSync", XS_pgBackRest__LibC__Storage_pathSync); - newXS_deffile("pgBackRest::LibC::Storage::put", XS_pgBackRest__LibC__Storage_put); - newXS_deffile("pgBackRest::LibC::Storage::readDrain", XS_pgBackRest__LibC__Storage_readDrain); - newXS_deffile("pgBackRest::LibC::Storage::remove", XS_pgBackRest__LibC__Storage_remove); - newXS_deffile("pgBackRest::LibC::Storage::cipherType", XS_pgBackRest__LibC__Storage_cipherType); - newXS_deffile("pgBackRest::LibC::Storage::cipherPass", XS_pgBackRest__LibC__Storage_cipherPass); - newXS_deffile("pgBackRest::LibC::Storage::type", XS_pgBackRest__LibC__Storage_type); - newXS_deffile("pgBackRest::LibC::storageRepoFree", XS_pgBackRest__LibC_storageRepoFree); - newXS_deffile("pgBackRest::LibC::pageChecksum", XS_pgBackRest__LibC_pageChecksum); - newXS_deffile("pgBackRest::LibC::PgClient::new", XS_pgBackRest__LibC__PgClient_new); - newXS_deffile("pgBackRest::LibC::PgClient::open", XS_pgBackRest__LibC__PgClient_open); - newXS_deffile("pgBackRest::LibC::PgClient::query", XS_pgBackRest__LibC__PgClient_query); - newXS_deffile("pgBackRest::LibC::PgClient::close", XS_pgBackRest__LibC__PgClient_close); - newXS_deffile("pgBackRest::LibC::PgClient::DESTROY", XS_pgBackRest__LibC__PgClient_DESTROY); - newXS_deffile("pgBackRest::LibC::cryptoRandomBytes", XS_pgBackRest__LibC_cryptoRandomBytes); - newXS_deffile("pgBackRest::LibC::cryptoHashOne", XS_pgBackRest__LibC_cryptoHashOne); - newXS_deffile("pgBackRest::LibC::cfgCommandId", XS_pgBackRest__LibC_cfgCommandId); - newXS_deffile("pgBackRest::LibC::cfgOptionId", XS_pgBackRest__LibC_cfgOptionId); - newXS_deffile("pgBackRest::LibC::cfgDefOptionDefault", XS_pgBackRest__LibC_cfgDefOptionDefault); - newXS_deffile("pgBackRest::LibC::cfgDefOptionPrefix", XS_pgBackRest__LibC_cfgDefOptionPrefix); - newXS_deffile("pgBackRest::LibC::cfgDefOptionSecure", XS_pgBackRest__LibC_cfgDefOptionSecure); - newXS_deffile("pgBackRest::LibC::cfgDefOptionType", XS_pgBackRest__LibC_cfgDefOptionType); - newXS_deffile("pgBackRest::LibC::cfgDefOptionValid", XS_pgBackRest__LibC_cfgDefOptionValid); - newXS_deffile("pgBackRest::LibC::cfgOptionTotal", XS_pgBackRest__LibC_cfgOptionTotal); - newXS_deffile("pgBackRest::LibC::cfgParseTest", XS_pgBackRest__LibC_cfgParseTest); - newXS_deffile("pgBackRest::LibC::cfgCommandName", XS_pgBackRest__LibC_cfgCommandName); - newXS_deffile("pgBackRest::LibC::cfgOptionIndex", XS_pgBackRest__LibC_cfgOptionIndex); - newXS_deffile("pgBackRest::LibC::cfgOptionIndexTotal", XS_pgBackRest__LibC_cfgOptionIndexTotal); - newXS_deffile("pgBackRest::LibC::cfgOptionName", XS_pgBackRest__LibC_cfgOptionName); - newXS_deffile("pgBackRest::LibC::lockAcquire", XS_pgBackRest__LibC_lockAcquire); - newXS_deffile("pgBackRest::LibC::lockRelease", XS_pgBackRest__LibC_lockRelease); - newXS_deffile("pgBackRest::LibC::encodeToStr", XS_pgBackRest__LibC_encodeToStr); - newXS_deffile("pgBackRest::LibC::decodeToBin", XS_pgBackRest__LibC_decodeToBin); -#if PERL_VERSION_LE(5, 21, 5) -# if PERL_VERSION_GE(5, 9, 0) - if (PL_unitcheckav) - call_list(PL_scopestack_ix, PL_unitcheckav); -# endif - XSRETURN_YES; -#else - Perl_xs_boot_epilog(aTHX_ ax); -#endif -} diff --git a/src/protocol/helper.c b/src/protocol/helper.c index e1b04a82a..1c2c323d8 100644 --- a/src/protocol/helper.c +++ b/src/protocol/helper.c @@ -265,9 +265,6 @@ protocolRemoteParam(ProtocolStorageType protocolStorageType, unsigned int protoc optionReplace, VARSTR(CFGOPT_CONFIG_PATH_STR), cfgOptionSource(optConfigPath) != cfgSourceDefault ? cfgOption(optConfigPath) : NULL); - // Use a C remote - kvPut(optionReplace, VARSTR(CFGOPT_C_STR), VARBOOL(true)); - // Copy pg options to index 0 since that's what the remote will be expecting if (hostIdx != 0) { diff --git a/src/storage/storage.c b/src/storage/storage.c index a4a80e937..4a4627185 100644 --- a/src/storage/storage.c +++ b/src/storage/storage.c @@ -30,7 +30,6 @@ struct Storage mode_t modeFile; mode_t modePath; bool write; - bool pathEnforce; StoragePathExpressionCallback *pathExpressionFunction; }; @@ -75,7 +74,6 @@ storageNew( this->path = strDup(path); this->modeFile = modeFile; this->modePath = modePath; - this->pathEnforce = true; this->write = write; this->pathExpressionFunction = pathExpressionFunction; @@ -681,7 +679,7 @@ storagePath(const Storage *this, const String *pathExp, StoragePathParam param) // Make sure the base storage path is contained within the path expression if (!strEqZ(this->path, "/")) { - if (this->pathEnforce && !param.noEnforce && (!strBeginsWith(pathExp, this->path) || + if (!param.noEnforce && (!strBeginsWith(pathExp, this->path) || !(strSize(pathExp) == strSize(this->path) || *(strPtr(pathExp) + strSize(this->path)) == '/'))) { THROW_FMT(AssertError, "absolute path '%s' is not in base path '%s'", strPtr(pathExp), strPtr(this->path)); @@ -966,22 +964,6 @@ storageInterface(const Storage *this) FUNCTION_TEST_RETURN(this->interface); } -/*********************************************************************************************************************************** -Set whether absolute paths are required to be in the base path -***********************************************************************************************************************************/ -void -storagePathEnforceSet(Storage *this, bool enforce) -{ - FUNCTION_TEST_BEGIN(); - FUNCTION_TEST_PARAM(STORAGE, this); - FUNCTION_TEST_PARAM(BOOL, enforce); - FUNCTION_TEST_END(); - - this->pathEnforce = enforce; - - FUNCTION_TEST_RETURN_VOID(); -} - /*********************************************************************************************************************************** Get the storage type (posix, cifs, etc.) ***********************************************************************************************************************************/ diff --git a/src/storage/storage.intern.h b/src/storage/storage.intern.h index 7203f9a71..7d805a75a 100644 --- a/src/storage/storage.intern.h +++ b/src/storage/storage.intern.h @@ -302,10 +302,6 @@ Getters/Setters void *storageDriver(const Storage *this); StorageInterface storageInterface(const Storage *this); -// The option is intended to be used only with the Perl interface since Perl is not tidy about where it reads. It should be -// removed when the Perl interface is removed. -void storagePathEnforceSet(Storage *this, bool enforce); - /*********************************************************************************************************************************** Macros for function logging ***********************************************************************************************************************************/ diff --git a/test/define.yaml b/test/define.yaml index de98607d8..0c195fe6f 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -16,7 +16,7 @@ # * define - defines for C code (will also be applied to the test harness) # * define-test - defines for the test harness # * debugUnitSuppress - don't define DEBUG_UNIT for unit tests -- this is used to test unit test debugging macros -# * perlReq - is Perl required for this C test? +# * binReq - is the pgbackrest binary required for this test? # * containerReq - is this test required to run in a container? # # Some options are unique to tests: @@ -28,8 +28,6 @@ # ********************************************************************************************************************************** # Unit tests -# -# Unit tests are assumed to be C tests unless they end in "-perl". # ********************************************************************************************************************************** unit: @@ -291,10 +289,6 @@ unit: common/encode: full common/encode/base64: full - # ---------------------------------------------------------------------------------------------------------------------------- - - name: encode-perl - total: 1 - # ---------------------------------------------------------------------------------------------------------------------------- - name: reg-exp total: 3 @@ -309,26 +303,6 @@ unit: coverage: common/ini: full - # ---------------------------------------------------------------------------------------------------------------------------- - - name: ini-perl - total: 10 - - # ---------------------------------------------------------------------------------------------------------------------------- - - name: io-handle-perl - total: 6 - - # ---------------------------------------------------------------------------------------------------------------------------- - - name: io-buffered-perl - total: 3 - - # ---------------------------------------------------------------------------------------------------------------------------- - - name: io-process-perl - total: 3 - - # ---------------------------------------------------------------------------------------------------------------------------- - - name: log-perl - total: 1 - # ******************************************************************************************************************************** - name: postgres @@ -354,26 +328,6 @@ unit: coverage: postgres/pageChecksum: full - # ******************************************************************************************************************************** - - name: perl - - test: - # ---------------------------------------------------------------------------------------------------------------------------- - - name: config - total: 1 - - coverage: - perl/config: full - - # ---------------------------------------------------------------------------------------------------------------------------- - - name: exec - total: 4 - containerReq: true - perlReq: true - - coverage: - perl/exec: full - # ******************************************************************************************************************************** - name: config @@ -427,17 +381,6 @@ unit: - name: storage test: - # ---------------------------------------------------------------------------------------------------------------------------- - - name: perl - total: 13 - - coverage: - Storage/Storage: partial - - # ---------------------------------------------------------------------------------------------------------------------------- - - name: helper-perl - total: 3 - # ---------------------------------------------------------------------------------------------------------------------------- - name: cifs total: 1 @@ -468,7 +411,7 @@ unit: - name: remote total: 12 containerReq: true - perlReq: true + binReq: true coverage: storage/remote/read: full @@ -497,19 +440,11 @@ unit: - name: protocol test: - # ---------------------------------------------------------------------------------------------------------------------------- - - name: common-minion-perl - total: 1 - - # ---------------------------------------------------------------------------------------------------------------------------- - - name: helper-perl - total: 2 - # ---------------------------------------------------------------------------------------------------------------------------- - name: protocol total: 9 containerReq: true - perlReq: true + binReq: true coverage: protocol/client: full @@ -544,10 +479,6 @@ unit: coverage: info/infoArchive: full - # ---------------------------------------------------------------------------------------------------------------------------- - - name: info-archive-perl - total: 4 - # ---------------------------------------------------------------------------------------------------------------------------- - name: info-backup total: 2 @@ -562,10 +493,6 @@ unit: coverage: info/manifest: full - # ---------------------------------------------------------------------------------------------------------------------------- - - name: info-backup-perl - total: 3 - # ******************************************************************************************************************************** - name: db @@ -574,7 +501,7 @@ unit: - name: db total: 3 containerReq: true - perlReq: true + binReq: true coverage: db/db: full @@ -595,7 +522,7 @@ unit: # ---------------------------------------------------------------------------------------------------------------------------- - name: archive-get total: 5 - perlReq: true + binReq: true coverage: command/archive/get/file: full @@ -605,7 +532,7 @@ unit: # ---------------------------------------------------------------------------------------------------------------------------- - name: archive-push total: 4 - perlReq: true + binReq: true coverage: command/archive/push/file: full @@ -623,7 +550,7 @@ unit: # ---------------------------------------------------------------------------------------------------------------------------- - name: backup total: 10 - perlReq: true + binReq: true coverage: command/backup/backup: full @@ -698,7 +625,7 @@ unit: - name: restore total: 11 containerReq: true - perlReq: true + binReq: true coverage: command/restore/file: full @@ -727,14 +654,6 @@ unit: coverage: command/storage/list: full - # ******************************************************************************************************************************** - - name: manifest - - test: - # ---------------------------------------------------------------------------------------------------------------------------- - - name: all-perl - total: 11 - # ********************************************************************************************************************************** # Integration tests # diff --git a/test/lib/pgBackRestTest/Common/DefineTest.pm b/test/lib/pgBackRestTest/Common/DefineTest.pm index b7c7c0a44..f5db56dd4 100644 --- a/test/lib/pgBackRestTest/Common/DefineTest.pm +++ b/test/lib/pgBackRestTest/Common/DefineTest.pm @@ -63,8 +63,8 @@ use constant TESTDEF_TOTAL => 'total'; push @EXPORT, qw(TESTDEF_TOTAL); use constant TESTDEF_TYPE => 'type'; push @EXPORT, qw(TESTDEF_TYPE); -use constant TESTDEF_PERL_REQ => 'perlReq'; - push @EXPORT, qw(TESTDEF_PERL_REQ); +use constant TESTDEF_BIN_REQ => 'binReq'; + push @EXPORT, qw(TESTDEF_BIN_REQ); use constant TESTDEF_VM => 'vm'; push @EXPORT, qw(TESTDEF_VM); @@ -128,7 +128,7 @@ sub testDefLoad # Resolve variables that can be set in the module or the test foreach my $strVar ( - TESTDEF_DEFINE, TESTDEF_DEFINE_TEST, TESTDEF_DEBUG_UNIT_SUPPRESS, TESTDEF_DB, TESTDEF_PERL_REQ, TESTDEF_VM, + TESTDEF_DEFINE, TESTDEF_DEFINE_TEST, TESTDEF_DEBUG_UNIT_SUPPRESS, TESTDEF_DB, TESTDEF_BIN_REQ, TESTDEF_VM, TESTDEF_CONTAINER_REQUIRED) { $hTestDefHash->{$strModule}{$strTest}{$strVar} = coalesce( diff --git a/test/lib/pgBackRestTest/Common/JobTest.pm b/test/lib/pgBackRestTest/Common/JobTest.pm index e8140ecea..d61e83af2 100644 --- a/test/lib/pgBackRestTest/Common/JobTest.pm +++ b/test/lib/pgBackRestTest/Common/JobTest.pm @@ -233,8 +233,8 @@ sub run $rhBuildInit->{$self->{oTest}->{&TEST_VM}}{$self->{iVmIdx}} = true; } - # If testing Perl code (or C code that calls Perl code) install bin and Perl C Library - if ($self->{oTest}->{&TEST_VM} ne VM_NONE && (!$self->{oTest}->{&TEST_C} || $self->{oTest}->{&TEST_PERL_REQ})) + # If testing Perl code (or C code that calls the binary) install binary + if ($self->{oTest}->{&TEST_VM} ne VM_NONE && (!$self->{oTest}->{&TEST_C} || $self->{oTest}->{&TEST_BIN_REQ})) { jobInstallC($self->{strBackRestBase}, $self->{oTest}->{&TEST_VM}, $strImage); } @@ -433,8 +433,7 @@ sub run buildPutDiffers($self->{oStorageTest}, "$self->{strGCovPath}/test.c", $strTestC); # Create build.auto.h - my $strBuildAutoH = - "#define HAVE_LIBPERL\n"; + my $strBuildAutoH = ""; buildPutDiffers($self->{oStorageTest}, "$self->{strGCovPath}/" . BUILD_AUTO_H, $strBuildAutoH); @@ -451,8 +450,7 @@ sub run # Flags that are common to all builds my $strCommonFlags = - '-I. -Itest -std=c99 -fPIC -g -Wno-clobbered -D_POSIX_C_SOURCE=200112L' . - ' `perl -MExtUtils::Embed -e ccopts`' . + '-I. -Itest -std=c99 -fPIC -g -Wno-clobbered -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64' . ' `xml2-config --cflags`' . ($self->{bProfile} ? " -pg" : '') . ' -I`pg_config --includedir`' . ($self->{oTest}->{&TEST_DEBUG_UNIT_SUPPRESS} ? '' : " -DDEBUG_UNIT") . @@ -504,7 +502,6 @@ sub run "LDFLAGS=-lcrypto -lssl -lxml2 -lz" . (vmCoverageC($self->{oTest}->{&TEST_VM}) && $self->{bCoverageUnit} ? " -lgcov" : '') . (vmWithBackTrace($self->{oTest}->{&TEST_VM}) && $self->{bBackTrace} ? ' -lbacktrace' : '') . - " `perl -MExtUtils::Embed -e ldopts`\n" . "\n" . "SRCS=" . join(' ', @stryCFile) . "\n" . "OBJS=\$(SRCS:.c=.o)\n" . @@ -783,7 +780,7 @@ sub end } #################################################################################################################################### -# Install C binary and library +# Install C binary #################################################################################################################################### sub jobInstallC { @@ -791,7 +788,6 @@ sub jobInstallC my $strVm = shift; my $strImage = shift; - # Install Perl C Library my $oVm = vmGet(); my $strBuildPath = "${strBasePath}/test/.vagrant/bin/${strVm}"; my $strBuildLibCPath = "${strBuildPath}/libc"; diff --git a/test/lib/pgBackRestTest/Common/ListTest.pm b/test/lib/pgBackRestTest/Common/ListTest.pm index 0b5a84c03..1c37b2e6d 100644 --- a/test/lib/pgBackRestTest/Common/ListTest.pm +++ b/test/lib/pgBackRestTest/Common/ListTest.pm @@ -38,8 +38,8 @@ use constant TEST_MODULE => 'module'; push @EXPORT, qw(TEST_MODULE); use constant TEST_NAME => 'test'; push @EXPORT, qw(TEST_NAME); -use constant TEST_PERL_REQ => 'perl-req'; - push @EXPORT, qw(TEST_PERL_REQ); +use constant TEST_BIN_REQ => 'bin-req'; + push @EXPORT, qw(TEST_BIN_REQ); use constant TEST_PGSQL_BIN => 'pgsql-bin'; push @EXPORT, qw(TEST_PGSQL_BIN); use constant TEST_INTEGRATION => 'integration'; @@ -172,7 +172,7 @@ sub testListGet &TEST_CONTAINER => defined($hTest->{&TESTDEF_CONTAINER}) ? $hTest->{&TESTDEF_CONTAINER} : $hModule->{&TESTDEF_CONTAINER}, &TEST_PGSQL_BIN => $strPgSqlBin, - &TEST_PERL_REQ => $hTest->{&TESTDEF_PERL_REQ}, + &TEST_BIN_REQ => $hTest->{&TESTDEF_BIN_REQ}, &TEST_INTEGRATION => $hTest->{&TESTDEF_INTEGRATION}, &TEST_MODULE => $strModule, &TEST_NAME => $strModuleTest, diff --git a/test/lib/pgBackRestTest/Module/Common/CommonEncodePerlTest.pm b/test/lib/pgBackRestTest/Module/Common/CommonEncodePerlTest.pm deleted file mode 100644 index 77e12eb3c..000000000 --- a/test/lib/pgBackRestTest/Module/Common/CommonEncodePerlTest.pm +++ /dev/null @@ -1,62 +0,0 @@ -#################################################################################################################################### -# Test Binary to String Encode/Decode -#################################################################################################################################### -package pgBackRestTest::Module::Common::CommonEncodePerlTest; -use parent 'pgBackRestTest::Common::RunTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Ini; -use pgBackRest::Common::Log; -use pgBackRest::LibC qw(:encode); -use pgBackRest::Version; - -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - ################################################################################################################################ - if ($self->begin("encodeToStrBase64() and decodeToBinBase64()")) - { - my $strData = 'string_to_encode'; - my $strEncodedData = 'c3RyaW5nX3RvX2VuY29kZQ=='; - - $self->testResult(sub {encodeToStr(ENCODE_TYPE_BASE64, $strData)}, $strEncodedData, 'encode string'); - $self->testResult(sub {decodeToBin(ENCODE_TYPE_BASE64, $strEncodedData)}, $strData, 'decode string'); - - #--------------------------------------------------------------------------------------------------------------------------- - my $tData = - pack('C', 1) . pack('C', 2) . pack('C', 3) . pack('C', 4) . pack('C', 5) . pack('C', 4) . pack('C', 3) . pack('C', 2); - my $tEncodedData = 'AQIDBAUEAwI='; - - $self->testResult(sub {encodeToStr(ENCODE_TYPE_BASE64, $tData)}, $tEncodedData, 'encode binary'); - $self->testResult(sub {decodeToBin(ENCODE_TYPE_BASE64, $tEncodedData)}, $tData, 'decode binary'); - - #--------------------------------------------------------------------------------------------------------------------------- - $tData .= pack('C', 1); - $tEncodedData = 'AQIDBAUEAwIB'; - - $self->testResult(sub {encodeToStr(ENCODE_TYPE_BASE64, $tData)}, $tEncodedData, 'encode binary'); - $self->testResult(sub {decodeToBin(ENCODE_TYPE_BASE64, $tEncodedData)}, $tData, 'decode binary'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {encodeToStr(99999, '')}, ERROR_ASSERT, 'invalid encode type 99999'); - $self->testException( - sub {decodeToBin(ENCODE_TYPE_BASE64, "XX")}, ERROR_FORMAT, 'base64 size 2 is not evenly divisible by 4'); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Common/CommonIniPerlTest.pm b/test/lib/pgBackRestTest/Module/Common/CommonIniPerlTest.pm deleted file mode 100644 index c2e1e1b68..000000000 --- a/test/lib/pgBackRestTest/Module/Common/CommonIniPerlTest.pm +++ /dev/null @@ -1,533 +0,0 @@ -#################################################################################################################################### -# Unit tests for Ini module -#################################################################################################################################### -package pgBackRestTest::Module::Common::CommonIniPerlTest; -use parent 'pgBackRestTest::Common::RunTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Ini; -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::Storage::Base; -use pgBackRest::Version; - -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# iniHeader -#################################################################################################################################### -sub iniHeader -{ - my $self = shift; - my $oIni = shift; - my $iFormat = shift; - my $iVersion = shift; - my $strChecksum = shift; - - return - "[backrest]\n" . - "backrest-format=" . (defined($iFormat) ? $iFormat : $oIni->get(INI_SECTION_BACKREST, INI_KEY_FORMAT)) . "\n" . - "backrest-version=\"" . (defined($iVersion) ? $iVersion : $oIni->get(INI_SECTION_BACKREST, INI_KEY_VERSION)) . "\"\n" . - "\n" . - "[backrest]\n" . - "backrest-checksum=\"" . - (defined($strChecksum) ? $strChecksum : $oIni->get(INI_SECTION_BACKREST, INI_KEY_CHECKSUM)) . "\"\n"; -} - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - # Test ini file - my $strTestFile = $self->testPath() . '/test.ini'; - my $strTestFileCopy = "${strTestFile}.copy"; - - # Test keys, values - my $strSection = 'test-section'; - my $strKey = 'test-key'; - my $strSubKey = 'test-subkey'; - my $strValue = 'test-value'; - - ################################################################################################################################ - if ($self->begin("iniRender()")) - { - #--------------------------------------------------------------------------------------------------------------------------- - my $oIni = {section1 => {key => 'value'}, section2 => {key => ['value1', 'value2']}}; - - $self->testResult( - sub {iniRender($oIni, true)}, "[section1]\nkey=value\n\n[section2]\nkey=value1\nkey=value2\n", - 'relaxed formatting'); - $self->testResult( - sub {iniRender($oIni, false)}, "[section1]\nkey=\"value\"\n\n[section2]\nkey=[\"value1\",\"value2\"]\n", - 'strict formatting'); - } - - ################################################################################################################################ - if ($self->begin("iniParse()")) - { - #--------------------------------------------------------------------------------------------------------------------------- - my $strIni = "[section]\nkey"; - - $self->testException(sub {iniParse($strIni)}, ERROR_CONFIG, "unable to find '=' in 'key'"); - - #--------------------------------------------------------------------------------------------------------------------------- - $strIni = "[section]\n# comment\n\nkey=\"value\""; - - $self->testResult(sub {iniParse($strIni)}, '{section => {key => value}}', 'ignore blank lines and comments'); - - #--------------------------------------------------------------------------------------------------------------------------- - $strIni = "[section]\nkey=value"; - - $self->testResult(sub {iniParse($strIni, {bRelaxed => true})}, '{section => {key => value}}', 'relaxed value read'); - - #--------------------------------------------------------------------------------------------------------------------------- - $strIni = "[section]\nkey=value1\nkey=value2\nkey=value3"; - - $self->testResult( - sub {iniParse($strIni, {bRelaxed => true})}, '{section => {key => (value1, value2, value3)}}', 'relaxed array read'); - } - - ################################################################################################################################ - if ($self->begin("Ini->new()")) - { - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {(new pgBackRest::Common::Ini($strTestFile, {bIgnoreMissing => true}))->exists()}, false, 'ignore missing'); - - #--------------------------------------------------------------------------------------------------------------------------- - my $oIni = new pgBackRest::Common::Ini( - $strTestFile, {bLoad => false, iInitFormat => 4, strInitVersion => '1.01'}); - - $self->testResult($oIni->exists(), false, 'file does not exist'); - - $oIni->saveCopy(); - - $self->testResult($oIni->exists(), false, 'file does not exist after saveCopy()'); - - $self->testResult( - sub {${storageTest()->get($strTestFile . INI_COPY_EXT)}}, - $self->iniHeader(undef, 4, '1.01', '488e5ca1a018cd7cd6d4e15150548f39f493dacd'), - 'empty with synthetic format and version'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - $oIni->saveCopy(); - - $self->testResult( - sub {${storageTest()->get($strTestFile . INI_COPY_EXT)}}, - $self->iniHeader(undef, REPOSITORY_FORMAT, PROJECT_VERSION, $oIni->hash()), - 'empty with default format and version'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {storageTest()->list($self->testPath())}, - 'test.ini.copy', - 'only copy is saved'); - - $oIni->save(); - - $self->testResult( - sub {storageTest()->list($self->testPath())}, - '(test.ini, test.ini.copy)', - 'both versions are saved'); - - $self->testException( - sub {$oIni->saveCopy()}, ERROR_ASSERT, - "cannot save copy only when '${strTestFile}' exists"); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'normal load'); - - #--------------------------------------------------------------------------------------------------------------------------- - my $hIni = iniParse(${storageTest()->get($strTestFile)}); - $hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = BOGUS; - storageTest()->put($strTestFile, iniRender($hIni)); - storageTest()->put($strTestFileCopy, iniRender($hIni)); - - $self->testException( - sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING, - "unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT); - # "invalid checksum in '${strTestFile}', expected '" . - # $oIni->get(INI_SECTION_BACKREST, INI_KEY_CHECKSUM) . "' but found 'bogus'"); - - $hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = $oIni->hash(); - storageTest()->put($strTestFile, iniRender($hIni)); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni->numericSet(INI_SECTION_BACKREST, INI_KEY_FORMAT, undef, REPOSITORY_FORMAT - 1); - $oIni->save(); - - $self->testException( - sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING, - "unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT); - # "invalid format in '${strTestFile}', expected " . REPOSITORY_FORMAT . ' but found ' . (REPOSITORY_FORMAT - 1)); - - $oIni->numericSet(INI_SECTION_BACKREST, INI_KEY_FORMAT, undef, REPOSITORY_FORMAT); - $oIni->save(); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni->set(INI_SECTION_BACKREST, INI_KEY_VERSION, undef, '1.01'); - $oIni->save(); - - $self->testResult( - sub {${storageTest()->get($strTestFile . INI_COPY_EXT)}}, - $self->iniHeader($oIni, undef, '1.01'), - 'verify old version was written'); - - $oIni = new pgBackRest::Common::Ini($strTestFile); - - $self->testResult(sub {$oIni->get(INI_SECTION_BACKREST, INI_KEY_VERSION)}, PROJECT_VERSION, 'version is updated on load'); - $oIni->save(); - - $self->testResult( - sub {${storageTest()->get($strTestFile . INI_COPY_EXT)}}, - $self->iniHeader($oIni, undef, PROJECT_VERSION), - 'verify version is updated on load'); - - $self->testResult(sub {$oIni->save()}, false, 'save again with no changes'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {new pgBackRest::Common::Ini($strTestFile, {bLoad => false, strContent => ${storageTest()->get($strTestFile)}})}, - '[object]', 'new() passing content as a string'); - - #--------------------------------------------------------------------------------------------------------------------------- - executeTest("rm -rf ${strTestFile}*"); - - $self->testException( - sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING, - "unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT); - - #--------------------------------------------------------------------------------------------------------------------------- - storageTest()->put($strTestFileCopy, BOGUS); - - $self->testException( - sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING, - "unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT); - # "key/value pair 'bogus' found outside of a section"); - - #--------------------------------------------------------------------------------------------------------------------------- - my $oIniSource = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - - storageTest()->put($strTestFileCopy, iniRender($oIniSource->{oContent})); - - $self->testException( - sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING, - "unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT); - # "invalid checksum in '${strTestFileCopy}', expected '" . - # $oIniSource->hash() . "' but found [undef]"); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIniSource = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - $oIniSource->save(); - - storageTest()->put($strTestFile, BOGUS); - - # main invalid, copy ok - $self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'invalid main - load copy'); - - #--------------------------------------------------------------------------------------------------------------------------- - storageTest()->remove($strTestFileCopy); - - storageTest()->put($strTestFile, "[section]\n" . BOGUS); - - # main invalid, copy missing - $self->testException - (sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING, - "unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT); - #"unable to find '=' in 'bogus'"); - - #--------------------------------------------------------------------------------------------------------------------------- - storageTest()->put($strTestFile, iniRender($oIniSource->{oContent})); - - $self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'main ok, copy missing'); - - #--------------------------------------------------------------------------------------------------------------------------- - storageTest()->put($strTestFileCopy, BOGUS); - - # main ok, copy invalid - $self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'main ok, copy invalid'); - - #--------------------------------------------------------------------------------------------------------------------------- - storageTest()->put($strTestFile, BOGUS); - - # main invalid, copy invalid - $self->testException( - sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_FILE_MISSING, - "unable to open ${strTestFile} or ${strTestFile}" . INI_COPY_EXT); - # "key/value pair 'bogus' found outside of a section"); - - #--------------------------------------------------------------------------------------------------------------------------- - storageTest()->put($strTestFile, iniRender($hIni)); - $hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = BOGUS; - storageTest()->put($strTestFileCopy, iniRender($hIni)); - - $self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'invalid copy header - load main'); - - #--------------------------------------------------------------------------------------------------------------------------- - $hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = $oIni->hash(); - storageTest()->put($strTestFileCopy, iniRender($hIni)); - $hIni->{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = BOGUS; - storageTest()->put($strTestFile, iniRender($hIni)); - - $self->testResult(sub {new pgBackRest::Common::Ini($strTestFile)}, '[object]', 'invalid main header - load copy'); - - #--------------------------------------------------------------------------------------------------------------------------- - # Prepend encryption Magic signature to copy (main invalid) to simulate encryption - executeTest('echo "' . CIPHER_MAGIC . '$(cat ' . $strTestFileCopy . ')" > ' . $strTestFileCopy); - - $self->testException(sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_CRYPTO, - "unable to parse '$strTestFileCopy'" . - "\nHINT: is or was the repo encrypted?"); - - # Prepend encryption Magic signature to main to simulate encryption - executeTest('echo "' . CIPHER_MAGIC . '$(cat ' . $strTestFile . ')" > ' . $strTestFile); - - $self->testException(sub {new pgBackRest::Common::Ini($strTestFile)}, ERROR_CRYPTO, - "unable to parse '$strTestFile'" . - "\nHINT: is or was the repo encrypted?"); - } - - ################################################################################################################################ - if ($self->begin("Ini->set()")) - { - my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oIni->set()}, ERROR_ASSERT, 'strSection and strKey are required'); - $self->testException(sub {$oIni->set($strSection)}, ERROR_ASSERT, 'strSection and strKey are required'); - $self->testException(sub {$oIni->set(undef, $strKey)}, ERROR_ASSERT, 'strSection and strKey are required'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni->{bModified} = false; - $self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'set key value'); - $self->testResult($oIni->modified(), true, ' check changed flag = true'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni->{bModified} = false; - $self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, false, 'set same key value'); - $self->testResult($oIni->modified(), false, ' check changed flag remains false'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni->{bModified} = false; - $self->testResult(sub {$oIni->set($strSection, $strKey, undef, "${strValue}2")}, true, 'set different key value'); - $self->testResult($oIni->modified(), true, ' check changed flag = true'); - - $self->testResult(sub {$oIni->get($strSection, $strKey)}, "${strValue}2", 'get last key value'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni->{bModified} = false; - $self->testResult(sub {$oIni->set($strSection, $strKey, undef, undef)}, true, 'set undef key value'); - $self->testResult($oIni->modified(), true, ' check changed flag = true'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->set($strSection, "${strKey}2", $strSubKey, $strValue)}, true, 'set subkey value'); - } - - ################################################################################################################################ - if ($self->begin("Ini->get()")) - { - my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oIni->get()}, ERROR_ASSERT, 'strSection is required'); - - $self->testException(sub {$oIni->get($strSection)}, ERROR_ASSERT, "strSection '${strSection}' is required but not defined"); - - $self->testException( - sub {$oIni->get($strSection, $strKey, undef)}, ERROR_ASSERT, - "strSection '${strSection}', strKey '${strKey}' is required but not defined"); - - $self->testException( - sub {$oIni->get($strSection, undef, $strSubKey)}, ERROR_ASSERT, - "strKey is required when strSubKey '${strSubKey}' is requested"); - - $self->testException( - sub {$oIni->get($strSection, $strKey, $strSubKey, true)}, ERROR_ASSERT, - "strSection '${strSection}', strKey '${strKey}', strSubKey '${strSubKey}' is required but not defined"); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->get($strSection, undef, undef, false)}, '[undef]', 'section value is not required'); - - $self->testResult(sub {$oIni->get($strSection, undef, undef, false, $strValue)}, $strValue, 'section value is defaulted'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni->set($strSection, $strKey, $strSubKey, $strValue); - - $self->testResult(sub {$oIni->get($strSection, "${strKey}2", "${strSubKey}2", false)}, undef, 'missing key value'); - - $self->testResult(sub {$oIni->get($strSection, $strKey, "${strSubKey}2", false)}, undef, 'missing subkey value'); - - $self->testResult(sub {$oIni->get($strSection, $strKey, $strSubKey)}, $strValue, 'get subkey value'); - - $self->testResult(sub {$oIni->get($strSection, $strKey)}, "{${strSubKey} => ${strValue}}", 'get key value'); - - $self->testResult(sub {$oIni->get($strSection)}, "{${strKey} => {${strSubKey} => ${strValue}}}", 'get section value'); - } - - ################################################################################################################################ - if ($self->begin("Ini->remove()")) - { - my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oIni->remove()}, ERROR_ASSERT, 'strSection is required'); - - $self->testException( - sub {$oIni->remove($strSection, undef, $strSubKey)}, ERROR_ASSERT, - "strKey is required when strSubKey '${strSubKey}' is requested"); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni->{bModified} = false; - $self->testResult(sub {$oIni->remove($strSection)}, false, 'undefined section is not removed'); - $self->testResult($oIni->modified(), '0', ' check changed flag remains false'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'set key'); - - $oIni->{bModified} = false; - $self->testResult(sub {$oIni->remove($strSection, $strKey)}, true, ' remove key'); - $self->testResult($oIni->modified(), '1', ' check changed flag = true'); - $self->testResult(sub {$oIni->test($strSection, $strKey)}, false, ' test key'); - $self->testResult(sub {$oIni->test($strSection)}, false, ' test section'); - - $self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'set key 1'); - $self->testResult(sub {$oIni->set($strSection, "${strKey}2", undef, $strValue)}, true, ' set key 2'); - $self->testResult(sub {$oIni->remove($strSection, $strKey)}, true, ' remove key 1'); - $self->testResult(sub {$oIni->test($strSection, $strKey)}, false, ' test key'); - $self->testResult(sub {$oIni->test($strSection)}, true, ' test section'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'set key'); - - $self->testResult(sub {$oIni->remove($strSection)}, true, ' remove section'); - $self->testResult(sub {$oIni->test($strSection)}, false, ' test section'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->set($strSection, $strKey, $strSubKey, $strValue)}, true, 'set subkey'); - - $self->testResult(sub {$oIni->remove($strSection, $strKey, $strSubKey)}, true, ' remove subkey'); - $self->testResult(sub {$oIni->test($strSection, $strKey, $strSubKey)}, false, ' test subkey'); - $self->testResult(sub {$oIni->test($strSection, $strKey)}, true, ' test key'); - $self->testResult(sub {$oIni->test($strSection)}, true, ' test section'); - - $self->testResult(sub {$oIni->set($strSection, $strKey, $strSubKey, $strValue)}, true, 'set subkey 1'); - $self->testResult(sub {$oIni->set($strSection, $strKey, "${strSubKey}2", $strValue)}, true, 'set subkey 2'); - - $self->testResult(sub {$oIni->remove($strSection, $strKey, $strSubKey)}, true, ' remove subkey'); - $self->testResult(sub {$oIni->test($strSection, $strKey, $strSubKey)}, false, ' test subkey'); - $self->testResult(sub {$oIni->test($strSection, $strKey)}, true, ' test key'); - $self->testResult(sub {$oIni->test($strSection)}, true, ' test section'); - } - - ################################################################################################################################ - if ($self->begin("Ini->test()")) - { - my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->test($strSection, $strKey)}, false, 'test undefined key'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->set($strSection, $strKey, undef, $strValue)}, true, 'define key'); - - $self->testResult(sub {$oIni->test($strSection, $strKey)}, true, 'test key exists'); - - $self->testResult(sub {$oIni->test($strSection, $strKey, undef, $strValue)}, true, 'test key value'); - - $self->testResult(sub {$oIni->test($strSection, $strKey, undef, BOGUS)}, false, 'test key invalid value'); - } - - ################################################################################################################################ - if ($self->begin("Ini->boolSet() & Ini->boolGet() & Ini->boolTest()")) - { - my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->boolTest($strSection, $strKey)}, false, 'test bool on undefined key'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->boolGet($strSection, $strKey, undef, false, false)}, false, 'get bool default false value'); - $self->testResult(sub {$oIni->boolGet($strSection, $strKey, undef, false, true)}, true, 'get bool default true value'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->boolSet($strSection, $strKey, undef, undef)}, true, 'set bool false (undef) value'); - $self->testResult(sub {$oIni->boolGet($strSection, $strKey)}, false, ' check bool false value'); - - $self->testResult(sub {$oIni->boolTest($strSection, $strKey, undef, false)}, true, 'test bool on false key'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->boolSet($strSection, $strKey, undef, false)}, false, 'set bool false value'); - $self->testResult(sub {$oIni->boolGet($strSection, $strKey)}, false, ' check value'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->boolSet($strSection, $strKey, undef, true)}, true, 'set bool false value'); - $self->testResult(sub {$oIni->boolGet($strSection, $strKey)}, true, ' check value'); - - $self->testResult(sub {$oIni->boolTest($strSection, $strKey, undef, true)}, true, 'test bool on true key'); - } - - ################################################################################################################################ - if ($self->begin("Ini->numericSet() & Ini->numericGet() & Ini->numericTest()")) - { - my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->numericSet($strSection, $strKey)}, true, 'set numeric undef value'); - $self->testResult(sub {$oIni->test($strSection, $strKey)}, false, 'test numeric undef value'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->numericGet($strSection, $strKey, undef, false, 1000)}, 1000, 'get numeric default value'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->numericSet($strSection, $strKey, undef, 0)}, true, 'set numeric 0 value'); - $self->testResult(sub {$oIni->numericGet($strSection, $strKey)}, 0, ' check value'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->numericSet($strSection, $strKey, undef, 0)}, false, 'set numeric 0 value again'); - $self->testResult(sub {$oIni->numericGet($strSection, $strKey)}, 0, ' check value'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->numericSet($strSection, $strKey, undef, -100)}, true, 'set numeric -100 value'); - $self->testResult(sub {$oIni->numericGet($strSection, $strKey)}, -100, ' check value'); - } - - ################################################################################################################################ - if ($self->begin("Ini->keys()")) - { - my $oIni = new pgBackRest::Common::Ini($strTestFile, {bLoad => false}); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->keys($strSection)}, '[undef]', 'section undefined'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIni->set($strSection, 'a', undef, $strValue); - $oIni->set($strSection, 'c', undef, $strValue); - $oIni->set($strSection, 'b', undef, $strValue); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIni->keys($strSection)}, '(a, b, c)', 'sort forward (default)'); - - $self->testResult(sub {$oIni->keys($strSection, INI_SORT_FORWARD)}, '(a, b, c)', 'sort forward'); - - $self->testResult(sub {$oIni->keys($strSection, INI_SORT_REVERSE)}, '(c, b, a)', 'sort reverse'); - - $self->testResult(sub {sort($oIni->keys($strSection, INI_SORT_NONE))}, '(a, b, c)', 'sort none'); - - $self->testException(sub {sort($oIni->keys($strSection, BOGUS))}, ERROR_ASSERT, "invalid strSortOrder '" . BOGUS . "'"); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Common/CommonIoBufferedPerlTest.pm b/test/lib/pgBackRestTest/Module/Common/CommonIoBufferedPerlTest.pm deleted file mode 100644 index 91b1eeae5..000000000 --- a/test/lib/pgBackRestTest/Module/Common/CommonIoBufferedPerlTest.pm +++ /dev/null @@ -1,259 +0,0 @@ -#################################################################################################################################### -# Tests for Common::Io::Buffered module -#################################################################################################################################### -package pgBackRestTest::Module::Common::CommonIoBufferedPerlTest; -use parent 'pgBackRestTest::Common::RunTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use IO::Socket::UNIX; -use Time::HiRes qw(usleep); - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Io::Buffered; -use pgBackRest::Common::Log; -use pgBackRest::Common::Wait; - -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# socketServer -#################################################################################################################################### -sub socketServer -{ - my $self = shift; - my $strSocketFile = shift; - my $fnServer = shift; - - # Fork off the server - if (fork() == 0) - { - # Open the domain socket - my $oSocketServer = IO::Socket::UNIX->new(Type => SOCK_STREAM(), Local => $strSocketFile, Listen => 1); - &log(INFO, " * socket server open"); - - # Wait for a connection and create IO object - my $oConnection = $oSocketServer->accept(); - my $oIoHandle = new pgBackRest::Common::Io::Handle('socket server', $oConnection, $oConnection); - &log(INFO, " * socket server connected"); - - # Run server function - $fnServer->($oIoHandle); - - # Shutdown server - $oSocketServer->close(); - &log(INFO, " * socket server closed"); - unlink($strSocketFile); - exit 0; - } - - # Wait for client socket - my $oWait = waitInit(5); - while (!-e $strSocketFile && waitMore($oWait)) {}; - - # Open the client socket - my $oClient = IO::Socket::UNIX->new(Type => SOCK_STREAM(), Peer => $strSocketFile); - - if (!defined($oClient)) - { - logErrorResult(ERROR_FILE_OPEN, 'unable to open client socket', $OS_ERROR); - } - - &log(INFO, " * socket client connected"); - - return $oClient; -} - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - # Test data - my $strSocketFile = $self->testPath() . qw{/} . 'domain.socket'; - - ################################################################################################################################ - if ($self->begin('new() & timeout() & bufferMax()')) - { - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoBuffered = $self->testResult( - sub {new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle('test'), 10, 2048)}, '[object]', 'new - no handles'); - - $self->testResult(sub {$oIoBuffered->timeout()}, 10, ' check timeout'); - $self->testResult(sub {$oIoBuffered->bufferMax()}, 2048, ' check buffer max'); - } - - ################################################################################################################################ - if ($self->begin('readLine() & writeLine()')) - { - my $oClient = $self->socketServer($strSocketFile, sub - { - my $oIoHandle = shift; - - my $tResponse = ''; - my $tData; - - # Ack after timeout - while (length($tResponse) != 1) {$oIoHandle->read(\$tResponse, 1)}; - - # Write 8 char line - $tResponse = ''; - $tData = "12345678\n"; - $oIoHandle->write(\$tData); - while (length($tResponse) != 1) {$oIoHandle->read(\$tResponse, 1)}; - - # Write 3 lines - $tResponse = ''; - $tData = "1\n2\n345678\n"; - $oIoHandle->write(\$tData); - while (length($tResponse) != 1) {$oIoHandle->read(\$tResponse, 1)}; - - # Write blank line - $tResponse = ''; - $tData = "\n"; - $oIoHandle->write(\$tData); - while (length($tResponse) != 1) {$oIoHandle->read(\$tResponse, 1)}; - - # Write char with no linefeed - $tResponse = ''; - $tData = "A"; - $oIoHandle->write(\$tData); - while (length($tResponse) != 1) {$oIoHandle->read(\$tResponse, 1)}; - - # Write linefeed - $tResponse = ''; - $tData = "\n"; - $oIoHandle->write(\$tData); - while (length($tResponse) != 1) {$oIoHandle->read(\$tResponse, 1)}; - }); - - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoBuffered = $self->testResult( - sub {new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle('socket client', $oClient, $oClient), 1, 4)}, '[object]', 'open'); - - $self->testException( - sub {$oIoBuffered->readLine()}, ERROR_FILE_READ, 'unable to read line after 1 second(s) from socket client'); - - $oIoBuffered->writeLine(); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIoBuffered->readLine()}, '12345678', 'read 8 char line'); - $oIoBuffered->writeLine(); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIoBuffered->readLine()}, '1', 'read 1 char line'); - $self->testResult(sub {$oIoBuffered->readLine()}, '2', 'read 1 char line'); - $self->testResult(sub {$oIoBuffered->readLine()}, '345678', 'read 6 char line'); - $oIoBuffered->writeLine(); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIoBuffered->readLine()}, '', 'read blank line'); - $oIoBuffered->writeLine(); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIoBuffered->readLine(undef, false)}, undef, 'read ignoring error'); - - $self->testException( - sub {$oIoBuffered->readLine(undef, true)}, ERROR_FILE_READ, - 'unable to read line after 1 second(s) from socket client'); - - # Clear buffer so EOF tests pass - $oIoBuffered->writeLine(); - $oIoBuffered->readLine(); - $oIoBuffered->writeLine(); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oIoBuffered->readLine()}, ERROR_FILE_READ, 'unexpected EOF reading line from socket client'); - - $self->testException( - sub {$oIoBuffered->readLine(false)}, ERROR_FILE_READ, 'unexpected EOF reading line from socket client'); - - $self->testResult(sub {$oIoBuffered->readLine(true)}, undef, 'ignore EOF'); - } - - ################################################################################################################################ - if ($self->begin('read')) - { - my $tBuffer; - - my $oClient = $self->socketServer($strSocketFile, sub - { - my $oIoHandle = shift; - - my $tResponse = ''; - my $tData; - - # Ack after timeout - while (length($tResponse) != 1) {$oIoHandle->read(\$tResponse, 1)}; - - # Write mixed buffer - $tResponse = ''; - $tData = "123\n123\n1"; - $oIoHandle->write(\$tData); - while (length($tResponse) != 1) {$oIoHandle->read(\$tResponse, 1)}; - - # Write buffer - $tResponse = ''; - $tData = "23456789"; - $oIoHandle->write(\$tData); - - # Wait before writing the rest to force client to loop - usleep(500); - $tData = "0"; - $oIoHandle->write(\$tData); - while (length($tResponse) != 1) {$oIoHandle->read(\$tResponse, 1)}; - }); - - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoBuffered = $self->testResult( - sub {new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle('socket client', $oClient, $oClient), 1, 8)}, '[object]', 'open'); - - $self->testException( - sub {$oIoBuffered->read(\$tBuffer, 1, true)}, ERROR_FILE_READ, - 'unable to read 1 byte(s) after 1 second(s) from socket client'); - - $self->testResult(sub {$oIoBuffered->read(\$tBuffer, 1)}, 0, ' read 0 char buffer'); - - $oIoBuffered->writeLine(); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIoBuffered->readLine()}, '123', ' read 3 char line'); - - undef($tBuffer); - $self->testResult(sub {$oIoBuffered->read(\$tBuffer, 1)}, 1, ' read 1 char buffer'); - $self->testResult(sub {$tBuffer}, '1', ' check 1 char buffer'); - - $self->testResult(sub {$oIoBuffered->read(\$tBuffer, 3)}, 3, ' read 3 char buffer'); - $self->testResult(sub {$tBuffer}, "123\n", ' check 3 char buffer'); - - $oIoBuffered->writeLine(); - - #--------------------------------------------------------------------------------------------------------------------------- - undef($tBuffer); - $self->testResult(sub {$oIoBuffered->read(\$tBuffer, 10)}, 10, ' read 10 char buffer'); - $self->testResult(sub {$tBuffer}, '1234567890', ' check 10 char buffer'); - - $oIoBuffered->writeLine(); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIoBuffered->read(\$tBuffer, 5)}, 0, ' expect EOF'); - - $self->testException( - sub {$oIoBuffered->read(\$tBuffer, 5, true)}, ERROR_FILE_READ, - 'unable to read 5 byte(s) due to EOF from socket client'); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Common/CommonIoHandlePerlTest.pm b/test/lib/pgBackRestTest/Module/Common/CommonIoHandlePerlTest.pm deleted file mode 100644 index 17e1f89b7..000000000 --- a/test/lib/pgBackRestTest/Module/Common/CommonIoHandlePerlTest.pm +++ /dev/null @@ -1,209 +0,0 @@ -#################################################################################################################################### -# Tests for Common::Io::Handle module -#################################################################################################################################### -package pgBackRestTest::Module::Common::CommonIoHandlePerlTest; -use parent 'pgBackRestTest::Common::RunTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use Fcntl qw(O_RDONLY O_WRONLY O_CREAT O_TRUNC O_NONBLOCK); - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Io::Base; -use pgBackRest::Common::Io::Handle; -use pgBackRest::Common::Log; - -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - # Test data - my $strFile = $self->testPath() . qw{/} . 'file.txt'; - my $strFileContent = 'TESTDATA'; - my $iFileLength = length($strFileContent); - my $iFileLengthHalf = int($iFileLength / 2); - - ################################################################################################################################ - if ($self->begin('new() & handleRead() & handleReadSet() & handleWrite() & handleWriteSet()')) - { - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoHandle = $self->testResult( - sub {new pgBackRest::Common::Io::Handle('test', undef, undef)}, '[object]', 'new - no handles'); - - $self->testResult(sub {$oIoHandle->id()}, 'test', ' check error msg'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$oIoHandle->handleReadSet(1)}, 1, ' set read handle'); - $self->testResult(sub {$oIoHandle->handleRead()}, 1, ' check read handle'); - $self->testResult(sub {$oIoHandle->handleWrite()}, undef, ' check write handle'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$oIoHandle->handleWriteSet(2)}, 2, ' set write handle'); - $self->testResult(sub {$oIoHandle->handleRead()}, 1, ' check read handle'); - $self->testResult(sub {$oIoHandle->handleWrite()}, 2, ' check write handle'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIoHandle = $self->testResult( - sub {new pgBackRest::Common::Io::Handle('test', 1, undef)}, '[object]', 'new - read handle'); - - $self->testResult(sub {$oIoHandle->handleRead()}, 1, ' check read handle'); - $self->testResult(sub {$oIoHandle->handleWrite()}, undef, ' check write handle'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIoHandle = $self->testResult( - sub {new pgBackRest::Common::Io::Handle('test', undef, 2)}, '[object]', 'new - write handle'); - - $self->testResult(sub {$oIoHandle->handleRead()}, undef, ' check read handle'); - $self->testResult(sub {$oIoHandle->handleWrite()}, 2, ' check write handle'); - - #--------------------------------------------------------------------------------------------------------------------------- - $oIoHandle = $self->testResult( - sub {new pgBackRest::Common::Io::Handle('test', 1, 2)}, '[object]', 'new - read/write handle'); - - $self->testResult(sub {$oIoHandle->handleRead()}, 1, ' check read handle'); - $self->testResult(sub {$oIoHandle->handleWrite()}, 2, ' check write handle'); - } - - ################################################################################################################################ - if ($self->begin('read()')) - { - my $tContent; - my $fhRead; - - #--------------------------------------------------------------------------------------------------------------------------- - executeTest("echo -n '${strFileContent}' | tee ${strFile}"); - - sysopen($fhRead, $strFile, O_RDONLY) - or confess &log(ERROR, "unable to open '${strFile}'"); - - my $oIoHandle = $self->testResult(sub {new pgBackRest::Common::Io::Handle("'$strFile'", $fhRead)}, '[object]', 'open'); - $self->testException( - sub {$oIoHandle->read(\$tContent, -1)}, ERROR_FILE_READ, "unable to read from '${strFile}': Negative length"); - - #--------------------------------------------------------------------------------------------------------------------------- - $tContent = undef; - - sysopen($fhRead, $strFile, O_RDONLY) - or confess &log(ERROR, "unable to open '${strFile}'"); - - $oIoHandle = $self->testResult(sub {new pgBackRest::Common::Io::Handle("'$strFile'", $fhRead)}, '[object]', 'open'); - - $self->testResult(sub {$oIoHandle->read(\$tContent, $iFileLengthHalf)}, $iFileLengthHalf, ' read part 1'); - $self->testResult($tContent, substr($strFileContent, 0, $iFileLengthHalf), ' check read'); - - $self->testResult(sub {$oIoHandle->eof()}, false, ' not eof'); - - $self->testResult( - sub {$oIoHandle->read( - \$tContent, $iFileLength - $iFileLengthHalf)}, $iFileLength - $iFileLengthHalf, ' read part 2'); - $self->testResult($tContent, $strFileContent, ' check read'); - - $self->testResult(sub {$oIoHandle->read(\$tContent, 1)}, 0, ' zero read'); - $self->testResult(sub {$oIoHandle->eof()}, true, ' eof'); - } - - ################################################################################################################################ - if ($self->begin('write()')) - { - my $tContent; - my $fhRead; - my $fhWrite; - - #--------------------------------------------------------------------------------------------------------------------------- - sysopen($fhWrite, $strFile, O_WRONLY | O_CREAT | O_TRUNC) - or confess &log(ERROR, "unable to open '${strFile}'"); - - my $oIoHandle = $self->testResult( - sub {new pgBackRest::Common::Io::Handle("'$strFile'", undef, $fhWrite)}, '[object]', 'open write'); - - $self->testException( - sub {$oIoHandle->write(undef)}, ERROR_FILE_WRITE, - "unable to write to '${strFile}': Can't use an undefined value as a SCALAR reference"); - - #--------------------------------------------------------------------------------------------------------------------------- - $tContent = substr($strFileContent, 0, $iFileLengthHalf); - $self->testResult(sub {$oIoHandle->write(\$tContent)}, $iFileLengthHalf, ' write part 1'); - $self->testResult(sub {$oIoHandle->size()}, $iFileLengthHalf, ' check part 1 size'); - - $tContent = substr($strFileContent, $iFileLengthHalf); - $self->testResult(sub {$oIoHandle->write(\$tContent)}, $iFileLength - $iFileLengthHalf, ' write part 2'); - $self->testResult(sub {$oIoHandle->size()}, $iFileLength, ' check part 2 size'); - $self->testResult(sub {$oIoHandle->close()}, true, ' close'); - - sysopen($fhRead, $strFile, O_RDONLY) - or confess &log(ERROR, "unable to open '${strFile}'"); - - $oIoHandle = $self->testResult(sub {new pgBackRest::Common::Io::Handle("'$strFile'", $fhRead)}, '[object]', 'open read'); - - $tContent = undef; - $self->testResult(sub {$oIoHandle->read(\$tContent, $iFileLength)}, $iFileLength, ' read'); - $self->testResult($tContent, $strFileContent, ' check write content'); - } - - ################################################################################################################################ - if ($self->begin('result() & resultSet()')) - { - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoHandle = $self->testResult( - sub {new pgBackRest::Common::Io::Handle('test', undef, undef)}, '[object]', 'new - no handles'); - - $self->testResult(sub {$oIoHandle->resultSet('Module::1', 1)}, 1, ' set int result'); - $self->testResult(sub {$oIoHandle->resultSet('Module::2', {value => 2})}, '{value => 2}', ' set hash result'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIoHandle->result('Module::1')}, 1, ' check int result'); - $self->testResult(sub {$oIoHandle->result('Module::2')}, '{value => 2}', ' check hash result'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oIoHandle->{rhResult}}, '{Module::1 => 1, Module::2 => {value => 2}}', ' check all results'); - } - - ################################################################################################################################ - if ($self->begin('className()')) - { - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoHandle = $self->testResult( - sub {new pgBackRest::Common::Io::Handle('test', undef, undef)}, '[object]', 'new - no handles'); - - $self->testResult(sub {$oIoHandle->className()}, COMMON_IO_HANDLE, ' check class name'); - } - - ################################################################################################################################ - if ($self->begin('close()')) - { - my $tContent; - my $fhRead; - - #--------------------------------------------------------------------------------------------------------------------------- - executeTest("echo -n '${strFileContent}' | tee ${strFile}"); - - sysopen($fhRead, $strFile, O_RDONLY) - or confess &log(ERROR, "unable to open '${strFile}'"); - - my $oIoHandle = $self->testResult(sub {new pgBackRest::Common::Io::Handle("'$strFile'", $fhRead)}, '[object]', 'open read'); - $self->testResult(sub {$oIoHandle->read(\$tContent, $iFileLengthHalf)}, $iFileLengthHalf, ' read'); - $self->testResult(sub {$oIoHandle->close()}, true, ' close'); - $self->testResult(sub {$oIoHandle->close()}, true, ' close again'); - - $self->testResult(sub {$oIoHandle->result(COMMON_IO_HANDLE)}, $iFileLengthHalf, ' check result'); - - # Destroy and to make sure close runs again - undef($oIoHandle); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Common/CommonIoProcessPerlTest.pm b/test/lib/pgBackRestTest/Module/Common/CommonIoProcessPerlTest.pm deleted file mode 100644 index 25cd8d7d5..000000000 --- a/test/lib/pgBackRestTest/Module/Common/CommonIoProcessPerlTest.pm +++ /dev/null @@ -1,72 +0,0 @@ -#################################################################################################################################### -# Tests for Common::Io::Process module -#################################################################################################################################### -package pgBackRestTest::Module::Common::CommonIoProcessPerlTest; -use parent 'pgBackRestTest::Common::RunTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Io::Buffered; -use pgBackRest::Common::Io::Process; -use pgBackRest::Common::Log; - -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - # Test data - my $strFile = $self->testPath() . qw{/} . 'file.txt'; - my $strFileContent = 'TESTDATA'; - - ################################################################################################################################ - if ($self->begin('new() & processId()')) - { - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoProcess = $self->testResult(sub { - new pgBackRest::Common::Io::Process( - new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle('test'), 1, 32), "echo '${strFileContent}'")}, '[object]', 'new - echo'); - $self->testResult(sub {defined($oIoProcess->processId())}, true, ' process id defined'); - } - - ################################################################################################################################ - if ($self->begin('close() and error when stderr has data')) - { - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoProcess = - new pgBackRest::Common::Io::Process( - new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle('test'), 1, 32), "echo '${strFileContent}' 1>&2"); - - $self->testException( - sub {$oIoProcess->close()}, ERROR_FILE_READ, 'test terminated unexpectedly [000]: TESTDATA'); - } - - ################################################################################################################################ - if ($self->begin('close() & error()')) - { - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoProcess = - new pgBackRest::Common::Io::Process( - new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle('test'), 1, 32), "echo '${strFileContent}'"); - $oIoProcess->close(); - $self->testException( - sub {$oIoProcess->error()}, ERROR_ASSERT, 'cannot call error() after process has been closed'); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Common/CommonLogPerlTest.pm b/test/lib/pgBackRestTest/Module/Common/CommonLogPerlTest.pm deleted file mode 100644 index 1bbeaa4d1..000000000 --- a/test/lib/pgBackRestTest/Module/Common/CommonLogPerlTest.pm +++ /dev/null @@ -1,46 +0,0 @@ -#################################################################################################################################### -# CommonLogTest.pm - Unit tests for Log module -#################################################################################################################################### -package pgBackRestTest::Module::Common::CommonLogPerlTest; -use parent 'pgBackRestTest::Common::RunTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Ini; -use pgBackRest::Common::Log; -use pgBackRest::Version; - -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - ################################################################################################################################ - if ($self->begin("log()")) - { - logWarnOnErrorEnable(); - $self->testResult(sub {&log(ERROR, "my test log", 27)}, "[object]", 'log error as warning', - {strLogExpect => "WARN: [027]: my test log"}); - - $self->testResult(sub {&log(INFO, "my test log")}, "my test log", 'log info as info', - {strLogLevel => INFO, strLogExpect => "INFO: my test log"}); - - logWarnOnErrorDisable(); - $self->testResult(sub {&log(ERROR, "my test log", 27)}, "[object]", 'log error', - {strLogExpect => "ERROR: [027]: my test log"}); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Info/InfoInfoArchivePerlTest.pm b/test/lib/pgBackRestTest/Module/Info/InfoInfoArchivePerlTest.pm deleted file mode 100644 index 1a2daefec..000000000 --- a/test/lib/pgBackRestTest/Module/Info/InfoInfoArchivePerlTest.pm +++ /dev/null @@ -1,249 +0,0 @@ -#################################################################################################################################### -# Unit tests for ArchiveInfo -#################################################################################################################################### -package pgBackRestTest::Module::Info::InfoInfoArchivePerlTest; -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::Archive::Info; -use pgBackRest::Backup::Info; -use pgBackRest::Common::Cipher; -use pgBackRest::Common::Exception; -use pgBackRest::Common::Ini; -use pgBackRest::Common::Lock; -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::DbVersion; -use pgBackRest::InfoCommon; -use pgBackRest::Manifest; -use pgBackRest::Protocol::Storage::Helper; -use pgBackRest::Storage::Base; - -use pgBackRestTest::Env::HostEnvTest; -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# initModule -#################################################################################################################################### -sub initModule -{ - my $self = shift; - - $self->{strRepoPath} = $self->testPath() . '/repo'; -} - -#################################################################################################################################### -# initTest -#################################################################################################################################### -sub initTest -{ - my $self = shift; - - # Clear cache from the previous test - storageRepoCacheClear(); - - # Load options - $self->configTestClear(); - $self->optionTestSet(CFGOPT_STANZA, $self->stanza()); - $self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo'); - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - # Create backup info path - storageRepo()->pathCreate(STORAGE_REPO_BACKUP, {bCreateParent => true}); - - # Create archive info path - storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE, {bCreateParent => true}); -} - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - my $strArchiveTestFile = $self->dataPath() . '/backup.wal1_'; - - ################################################################################################################################ - if ($self->begin("Archive::Info::new()")) - { - $self->testException(sub {new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, ERROR_FILE_MISSING, - ARCHIVE_INFO_FILE . " does not exist but is required to push/get WAL segments\n" . - "HINT: is archive_command configured in postgresql.conf?\n" . - "HINT: has a stanza-create been performed?\n" . - "HINT: use --no-archive-check to disable archive checks during backup if you have an alternate archiving scheme."); - } - - ################################################################################################################################ - if ($self->begin("Archive::Info::reconstruct()")) - { - my $tWalContent = $self->walGenerateContent(PG_VERSION_94); - my $strWalChecksum = $self->walGenerateContentChecksum(PG_VERSION_94); - - my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false, - {bLoad => false, bIgnoreMissing => true}); - - storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1/0000000100000001", {bCreateParent => true}); - my $strArchiveFile = storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1/0000000100000001/") . - "000000010000000100000001-${strWalChecksum}"; - storageTest()->put($strArchiveFile, $tWalContent); - - $self->testResult(sub {$oArchiveInfo->reconstruct(PG_VERSION_94, $self->dbSysId(PG_VERSION_94))}, "[undef]", 'reconstruct'); - $self->testResult(sub {$oArchiveInfo->check(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), false)}, PG_VERSION_94 . "-1", - ' check reconstruct'); - - # Attempt to reconstruct from an encypted archived WAL for an unencrypted repo - #--------------------------------------------------------------------------------------------------------------------------- - # Prepend encryption Magic signature to simulate encryption - executeTest('echo "' . CIPHER_MAGIC . '" > ' . $strArchiveFile); - - $self->testException(sub {$oArchiveInfo->reconstruct(PG_VERSION_94, $self->dbSysId(PG_VERSION_94))}, ERROR_CRYPTO, - "encryption incompatible for '$strArchiveFile'" . - "\nHINT: is or was the repo encrypted?"); - - executeTest('rm ' . $strArchiveFile); - - # Attempt to reconstruct from an encypted archived WAL with an encrypted repo - #--------------------------------------------------------------------------------------------------------------------------- - storageRepoCacheClear(); - $self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC); - $self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x'); - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - # Instantiate an archive.info object with a sub passphrase for the archived WAL - my $strCipherPassSub = 'y'; - $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false, - {bLoad => false, bIgnoreMissing => true, strCipherPassSub => $strCipherPassSub}); - - # Create an encrypted archived WAL - storageRepo()->put($strArchiveFile, $tWalContent, {strCipherPass => $strCipherPassSub}); - - $self->testResult(sub {$oArchiveInfo->reconstruct(PG_VERSION_94, $self->dbSysId(PG_VERSION_94))}, "[undef]", 'reconstruct'); - $self->testResult(sub {$oArchiveInfo->check(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), false)}, PG_VERSION_94 . "-1", - ' check reconstruction from encrypted archive'); - - $oArchiveInfo->save(); - - # Confirm encrypted - $self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/' - . ARCHIVE_INFO_FILE) && ($oArchiveInfo->cipherPassSub() eq $strCipherPassSub)}, true, - ' new archive info encrypted'); - } - - ################################################################################################################################ - if ($self->begin("Archive::Info::archiveIdList(), check(), archiveId()")) - { - my @stryArchiveId; - my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false, - {bLoad => false, bIgnoreMissing => true}); - - $oArchiveInfo->create(PG_VERSION_92, $self->dbSysId(PG_VERSION_92), false); - $oArchiveInfo->dbSectionSet(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $oArchiveInfo->dbHistoryIdGet(false) + 1); - $oArchiveInfo->dbSectionSet(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), $oArchiveInfo->dbHistoryIdGet(false) + 10); - $oArchiveInfo->dbSectionSet(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $oArchiveInfo->dbHistoryIdGet(false) + 1); - $oArchiveInfo->save(); - - # Check gets only the latest DB and returns only that archiveId - push(@stryArchiveId, $oArchiveInfo->check(PG_VERSION_93, $self->dbSysId(PG_VERSION_93))); - $self->testResult(sub {(@stryArchiveId == 1) && ($stryArchiveId[0] eq PG_VERSION_93 . "-13")}, true, - 'check - return only newest archiveId'); - - $self->testResult(sub {$oArchiveInfo->archiveId( - {strDbVersion => PG_VERSION_93, ullDbSysId => $self->dbSysId(PG_VERSION_93)})}, - PG_VERSION_93 . "-13", 'archiveId - return only newest archiveId for multiple histories'); - - $self->testException( - sub {$oArchiveInfo->archiveId({strDbVersion => PG_VERSION_94, ullDbSysId => BOGUS})}, ERROR_ARCHIVE_MISMATCH, - "unable to retrieve the archive id for database version '" . PG_VERSION_94 . "' and system-id '" . BOGUS . "'"); - - $self->testException(sub {$oArchiveInfo->check(PG_VERSION_94, $self->dbSysId(PG_VERSION_94))}, ERROR_ARCHIVE_MISMATCH, - "WAL segment version " . PG_VERSION_94 . " does not match archive version " . PG_VERSION_93 . - "\nWAL segment system-id " . $self->dbSysId(PG_VERSION_94) . " does not match archive system-id " . - $self->dbSysId(PG_VERSION_93) . "\nHINT: are you archiving to the correct stanza?"); - - @stryArchiveId = $oArchiveInfo->archiveIdList(PG_VERSION_93, $self->dbSysId(PG_VERSION_93)); - $self->testResult(sub {(@stryArchiveId == 2) && ($stryArchiveId[0] eq PG_VERSION_93 . "-13") && - ($stryArchiveId[1] eq PG_VERSION_93 . "-2")}, true, 'archiveIdList - returns multiple archiveId - newest first'); - - @stryArchiveId = $oArchiveInfo->archiveIdList(PG_VERSION_94, $self->dbSysId(PG_VERSION_94)); - $self->testResult(sub {(@stryArchiveId == 1) && ($stryArchiveId[0] eq PG_VERSION_94 . "-12")}, true, - 'archiveIdList - returns older archiveId'); - - $self->testException( - sub {$oArchiveInfo->archiveIdList(PG_VERSION_95, $self->dbSysId(PG_VERSION_94))}, ERROR_ARCHIVE_MISMATCH, - "unable to retrieve the archive id for database version '" . PG_VERSION_95 . "' and system-id '" . - $self->dbSysId(PG_VERSION_94) . "'"); - } - - ################################################################################################################################ - if ($self->begin("encryption")) - { - # Create an unencrypted archive.info file - #--------------------------------------------------------------------------------------------------------------------------- - my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false, - {bLoad => false, bIgnoreMissing => true}); - $oArchiveInfo->create(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), true); - - # Confirm unencrypted - $self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/' - . ARCHIVE_INFO_FILE)}, false, ' new archive info unencrypted'); - - my $strFile = $oArchiveInfo->{strFileName}; - - # Prepend encryption Magic signature to simulate encryption - executeTest('echo "' . CIPHER_MAGIC . '$(cat ' . $strFile . ')" > ' . $strFile); - - $self->testException(sub {new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, ERROR_CRYPTO, - "unable to parse '$strFile'" . - "\nHINT: is or was the repo encrypted?"); - - # Remove the archive info files - executeTest('rm ' . $oArchiveInfo->{strFileName} . '*'); - - # Create an encrypted storage and archive.info file - #--------------------------------------------------------------------------------------------------------------------------- - my $strCipherPass = 'x'; - $self->configTestClear(); - $self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC); - $self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, $strCipherPass); - $self->optionTestSet(CFGOPT_STANZA, $self->stanza()); - $self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo'); - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - # Clear the storage repo settings - storageRepoCacheClear(); - - # Create an encrypted storage and generate an encryption sub passphrase to store in the file - my $strCipherPassSub = cipherPassGen(); - - # Error on encrypted repo but no passphrase passed to store in the file - $self->testException(sub {new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false, - {bLoad => false, bIgnoreMissing => true})}, ERROR_ASSERT, - 'a user passphrase and sub passphrase are both required when encrypting'); - - # Create an encrypted archiveInfo file - $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false, - {bLoad => false, bIgnoreMissing => true, strCipherPassSub => $strCipherPassSub}); - $oArchiveInfo->create(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), true); - - # Confirm encrypted - $self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/' - . ARCHIVE_INFO_FILE)}, true, ' new archive info encrypted'); - - $self->testResult(sub {$oArchiveInfo->test(INI_SECTION_CIPHER, INI_KEY_CIPHER_PASS, undef, $strCipherPassSub)}, - true, ' generated passphrase stored'); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Info/InfoInfoBackupPerlTest.pm b/test/lib/pgBackRestTest/Module/Info/InfoInfoBackupPerlTest.pm deleted file mode 100644 index f7da5ec61..000000000 --- a/test/lib/pgBackRestTest/Module/Info/InfoInfoBackupPerlTest.pm +++ /dev/null @@ -1,262 +0,0 @@ -#################################################################################################################################### -# Unit tests for BackupInfo -#################################################################################################################################### -package pgBackRestTest::Module::Info::InfoInfoBackupPerlTest; -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::Archive::Info; -use pgBackRest::Backup::Info; -use pgBackRest::Common::Cipher; -use pgBackRest::Common::Exception; -use pgBackRest::Common::Lock; -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::DbVersion; -use pgBackRest::InfoCommon; -use pgBackRest::Manifest; -use pgBackRest::Protocol::Storage::Helper; -use pgBackRest::Storage::Base; - -use pgBackRestTest::Env::HostEnvTest; -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# initModule -#################################################################################################################################### -sub initModule -{ - my $self = shift; - - $self->{strRepoPath} = $self->testPath() . '/repo'; -} - -#################################################################################################################################### -# initTest -#################################################################################################################################### -sub initTest -{ - my $self = shift; - - # Load options - $self->configTestClear(); - $self->optionTestSet(CFGOPT_STANZA, $self->stanza()); - $self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo'); - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - # Create backup info path - storageRepo()->pathCreate(STORAGE_REPO_BACKUP, {bCreateParent => true}); - - # Create archive info path - storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE, {bCreateParent => true}); -} - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - my $i93ControlVersion = 937; - my $i93CatalogVersion = 201306121; - my $i94ControlVersion = 942; - my $i94CatalogVersion = 201409291; - - ################################################################################################################################ - if ($self->begin("BackupInfo::check() && BackupInfo::confirmDb()")) - { - my $oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false, - {bIgnoreMissing => true}); - $oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $i93ControlVersion, $i93CatalogVersion, true); - - # All DB section matches - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oBackupInfo->check( - PG_VERSION_93, $i93ControlVersion, $i93CatalogVersion, $self->dbSysId(PG_VERSION_93), false)}, 1, 'db section matches'); - - # DB section version mismatch - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oBackupInfo->check(PG_VERSION_94, $i93ControlVersion, $i93CatalogVersion, - $self->dbSysId(PG_VERSION_93))}, ERROR_BACKUP_MISMATCH, - "database version = " . &PG_VERSION_94 . ", system-id " . $self->dbSysId(PG_VERSION_93) . - " does not match backup version = " . &PG_VERSION_93 . ", " . "system-id = " . $self->dbSysId(PG_VERSION_93) . - "\nHINT: is this the correct stanza?"); - - # DB section system-id mismatch - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException( - sub {$oBackupInfo->check(PG_VERSION_93, $i93ControlVersion, $i93CatalogVersion, $self->dbSysId(PG_VERSION_94))}, - ERROR_BACKUP_MISMATCH, - "database version = " . &PG_VERSION_93 . ", system-id " . $self->dbSysId(PG_VERSION_94) . - " does not match backup version = " . &PG_VERSION_93 . ", " . "system-id = " . $self->dbSysId(PG_VERSION_93) . - "\nHINT: is this the correct stanza?"); - - # DB section control version mismatch - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oBackupInfo->check(PG_VERSION_93, 123, $i93CatalogVersion, $self->dbSysId(PG_VERSION_93))}, - ERROR_BACKUP_MISMATCH, "database control-version = 123, catalog-version $i93CatalogVersion " . - "does not match backup control-version = $i93ControlVersion, catalog-version = $i93CatalogVersion" . - "\nHINT: this may be a symptom of database or repository corruption!"); - - # DB section catalog version mismatch - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oBackupInfo->check(PG_VERSION_93, $i93ControlVersion, 123456789, $self->dbSysId(PG_VERSION_93))}, - ERROR_BACKUP_MISMATCH, "database control-version = $i93ControlVersion, catalog-version 123456789 " . - "does not match backup control-version = $i93ControlVersion, catalog-version = $i93CatalogVersion" . - "\nHINT: this may be a symptom of database or repository corruption!"); - - my $strBackupLabel = "20170403-175647F"; - - $oBackupInfo->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_HISTORY_ID, - $oBackupInfo->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_HISTORY_ID)); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oBackupInfo->confirmDb($strBackupLabel, PG_VERSION_93, $self->dbSysId(PG_VERSION_93))}, true, - 'backup db matches'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oBackupInfo->confirmDb($strBackupLabel, PG_VERSION_94, $self->dbSysId(PG_VERSION_93))}, false, - 'backup db wrong version'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oBackupInfo->confirmDb($strBackupLabel, PG_VERSION_93, $self->dbSysId(PG_VERSION_94))}, false, - 'backup db wrong system-id'); - } - - ################################################################################################################################ - if ($self->begin("BackupInfo::backupArchiveDbHistoryId()")) - { - my $oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false, - {bIgnoreMissing => true}); - $oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $i93ControlVersion, $i93CatalogVersion, true); - - my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false, - {bLoad => false, bIgnoreMissing => true}); - $oArchiveInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), true); - - # Map archiveId to Backup history id - #--------------------------------------------------------------------------------------------------------------------------- - my $strArchiveId = $oArchiveInfo->archiveId({strDbVersion => PG_VERSION_93, ullDbSysId => $self->dbSysId(PG_VERSION_93)}); - $self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId, - storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, 1, 'backupArchiveDbHistoryId found'); - - # Unable to map archiveId to Backup history id - #--------------------------------------------------------------------------------------------------------------------------- - $strArchiveId = &PG_VERSION_94 . "-2"; - $self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId, - storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, "[undef]", 'backupArchiveDbHistoryId not found'); - - # Same version but different ullsystemid so continue looking until find match - #--------------------------------------------------------------------------------------------------------------------------- - # Update db section and db history sections - my $iHistoryId = $oBackupInfo->dbHistoryIdGet(true)+1; - $oBackupInfo->dbSectionSet( - PG_VERSION_94, $i94ControlVersion, $i94CatalogVersion, $self->dbSysId(PG_VERSION_93), $iHistoryId); - $oArchiveInfo->dbSectionSet(PG_VERSION_94, $self->dbSysId(PG_VERSION_93), $iHistoryId); - - $oBackupInfo->save(); - $oArchiveInfo->save(); - - $strArchiveId = &PG_VERSION_94 . "-" . $iHistoryId; - $self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId, - storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, $iHistoryId, 'same db version but different system-id'); - - # Different version but same ullsystemid - #--------------------------------------------------------------------------------------------------------------------------- - $iHistoryId = $oBackupInfo->dbHistoryIdGet(false)+1; - $oBackupInfo->dbSectionSet( - PG_VERSION_94, $i93ControlVersion, $i93CatalogVersion, $self->dbSysId(PG_VERSION_94), $iHistoryId); - $oArchiveInfo->dbSectionSet(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), $iHistoryId); - - $oBackupInfo->save(); - $oArchiveInfo->save(); - - $strArchiveId = &PG_VERSION_93 . "-" . $iHistoryId; - $self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId, - storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, "[undef]", 'same db system-id but different version'); - - # First and last version and ullsystemid same in backup.info but only 1st in archive info - return last - #--------------------------------------------------------------------------------------------------------------------------- - $iHistoryId = $oBackupInfo->dbHistoryIdGet(true)+1; - $oBackupInfo->dbSectionSet( - PG_VERSION_93, $i93ControlVersion, $i93CatalogVersion, $self->dbSysId(PG_VERSION_93), $iHistoryId); - - $oBackupInfo->save(); - - $strArchiveId = &PG_VERSION_93 . "-1"; - $self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId, - storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, $iHistoryId, 'duplicate 1st and last version/sysid - last chosen'); - } - - ################################################################################################################################ - if ($self->begin("encryption")) - { - # Create a backupInfo file - my $oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false, - {bIgnoreMissing => true}); - $oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $i93ControlVersion, $i93CatalogVersion, true); - - my $strFile = $oBackupInfo->{strFileName}; - - # Prepend encryption Magic signature to simulate encryption - executeTest('echo "' . CIPHER_MAGIC . '$(cat ' . $strFile . ')" > ' . $strFile); - - $self->testException(sub {new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP))}, ERROR_CRYPTO, - "unable to parse '$strFile'" . - "\nHINT: is or was the repo encrypted?"); - - # Create encrypted files, change the passphrase and attempt to load - ensure flush error returned as parse error - #--------------------------------------------------------------------------------------------------------------------------- - # Remove the backup info files - executeTest('rm ' . $oBackupInfo->{strFileName} . '*'); - - # Clear the storage repo settings and change the passphrase - storageRepoCacheClear(); - - my $strCipherPass = 'x'; - $self->configTestClear(); - $self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC); - $self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, $strCipherPass); - $self->optionTestSet(CFGOPT_STANZA, $self->stanza()); - $self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo'); - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - # Confirm exception when not passing a sub passphrase - $self->testException(sub {new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false, - {bIgnoreMissing => true})}, ERROR_ASSERT, - 'a user passphrase and sub passphrase are both required when encrypting'); - - my $strCipherPassSub = cipherPassGen(); - - # Create encrypted files - $oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false, - {bIgnoreMissing => true, strCipherPassSub => $strCipherPassSub}); - $oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $i93ControlVersion, $i93CatalogVersion, true); - - # Clear the storage repo settings and change the passphrase - storageRepoCacheClear(); - $self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC); - $self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, BOGUS); - $self->optionTestSet(CFGOPT_STANZA, $self->stanza()); - $self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo'); - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - $self->testException(sub {new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP))}, ERROR_CRYPTO, - "unable to parse '" . $oBackupInfo->{strFileName} . "'" . - "\nHINT: is or was the repo encrypted?"); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Manifest/ManifestAllPerlTest.pm b/test/lib/pgBackRestTest/Module/Manifest/ManifestAllPerlTest.pm deleted file mode 100644 index 595f92d41..000000000 --- a/test/lib/pgBackRestTest/Module/Manifest/ManifestAllPerlTest.pm +++ /dev/null @@ -1,1733 +0,0 @@ -#################################################################################################################################### -# Unit tests for Manifest module -#################################################################################################################################### -package pgBackRestTest::Module::Manifest::ManifestAllPerlTest; -use parent 'pgBackRestTest::Env::HostEnvTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); - -use File::Basename qw(dirname); -use Storable qw(dclone); - -use pgBackRest::Backup::Common; -use pgBackRest::Common::Exception; -use pgBackRest::Common::Ini; -use pgBackRest::Common::Log; -use pgBackRest::Common::String; -use pgBackRest::Common::Wait; -use pgBackRest::Config::Config; -use pgBackRest::DbVersion; -use pgBackRest::Manifest; -use pgBackRest::Protocol::Helper; -use pgBackRest::Protocol::Storage::Helper; -use pgBackRest::Storage::Helper; -use pgBackRest::Version; - -use pgBackRestTest::Common::ContainerTest; -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::FileTest; -use pgBackRestTest::Common::RunTest; -use pgBackRestTest::Env::Host::HostBackupTest; - -#################################################################################################################################### -# Issues / Improvements -# -# While working on the unit tests a number of possible issues/improvements have come up. Issues are documented in the tests where -# they are relevant with an INVESTIGATE tag. General improvements are listed here to be addressed later: -# -# 1. Assignment of required values to the manifest is haphazard. Db version is in the constructor but the rest is assigned in -# Backup.pm. These should probably all be passed in the constructor. It may be like it is now in part because of test needs -# but that should be changed if so. -# -# 2. Improve validate function to check that all values that are collected actually got set. Some things are being checked now, -# but others like backup-lsn-start, backup-wal-start, etc. are not. Include all options like option-compress, etc. and db info -# like db-id, system-id, etc. Basically, validate should check everything in the manifest before it is saved (for the last time -# since intermediate saves may be missing data) and make sure nothing is missing or extraneous. Also check the contents of -# values, i.e. make sure that checksum is really a 40-character hex string. -# -# 3. In fileAdd() the mode should be based on a mask (remove execute bit) of the dir mode, rather than a constant. i.e. dir mode -# 0700 should become 0600, dir mode 0750 should become 0640, etc. -#################################################################################################################################### - -#################################################################################################################################### -# Constants -#################################################################################################################################### -use constant MODE_0750 => '0750'; -use constant MODE_0700 => '0700'; -use constant MODE_0644 => '0644'; -use constant MODE_0600 => '0600'; -use constant PGCONTROL_SIZE => 8192; - -#################################################################################################################################### -# initModule -#################################################################################################################################### -sub initModule -{ - my $self = shift; - - $self->{strDbPath} = $self->testPath() . "/db"; - $self->{strRepoPath} = $self->testPath() . "/repo"; - $self->{strArchivePath} = "$self->{strRepoPath}/archive/" . $self->stanza(); - $self->{strBackupPath} = "$self->{strRepoPath}/backup/" . $self->stanza(); - $self->{strSpoolPath} = "$self->{strArchivePath}/out"; - $self->{strExpectedManifest} = $self->testPath() . "/expected.manifest"; - $self->{strActualManifest} = $self->testPath() . "/actual.manifest"; -} - -#################################################################################################################################### -# initTest -#################################################################################################################################### -sub initTest -{ - my $self = shift; - - # Create archive info path - storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true}); - - # Create backup info path - storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true}); - - # Create pg_control global path - storageTest()->pathCreate($self->{strDbPath} . '/' . DB_PATH_GLOBAL, {bCreateParent => true}); -} - -#################################################################################################################################### -# manifestCompare -#################################################################################################################################### -sub manifestCompare -{ - my $self = shift; - my $oManifestExpected = shift; - my $oManifestActual = shift; - - # Remove manifest files if exist - storageTest()->remove($self->{strExpectedManifest}, {bIgnoreMissing => true}); - storageTest()->remove($self->{strActualManifest}, {bIgnoreMissing => true}); - - # Section backup. Confirm the copy-start timestamp is set for the actual manifest then copy it to the expected so files can - # be compared - if ($oManifestActual->test(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_COPY_START)) - { - $oManifestExpected->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_COPY_START, undef, - $oManifestActual->get(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_COPY_START)); - } - else - { - return MANIFEST_KEY_TIMESTAMP_COPY_START . " not set in actual manifest"; - } - - storageTest()->put($self->{strActualManifest}, iniRender($oManifestActual->{oContent})); - storageTest()->put($self->{strExpectedManifest}, iniRender($oManifestExpected->{oContent})); - - return executeTest("diff " . $self->{strExpectedManifest} . " " . $self->{strActualManifest}); -} - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - $self->optionTestSet(CFGOPT_STANZA, $self->stanza()); - $self->optionTestSet(CFGOPT_REPO_PATH, $self->{strRepoPath}); - $self->optionTestSet(CFGOPT_PG_PATH, $self->{strDbPath}); - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - my $strBackupLabel = backupLabelFormat(CFGOPTVAL_BACKUP_TYPE_FULL, undef, 1482000000); - my $strBackupPath = storageRepo->pathGet(STORAGE_REPO_BACKUP . "/${strBackupLabel}"); - my $strBackupManifestFile = "$strBackupPath/" . FILE_MANIFEST; - - my $lTime = time() - 10000; - my $strTest = 'test'; - - my $oManifestBase = new pgBackRest::Common::Ini($self->{strExpectedManifest}, {bLoad => false}); - - # Section: backup:db - $oManifestBase->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_94); - $oManifestBase->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, $self->dbCatalogVersion(PG_VERSION_94)); - # Section: target:path - my $hDefault = {}; - $oManifestBase->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA, undef, $hDefault); - $oManifestBase->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_GLOBAL, undef, $hDefault); - # Section: target:path:default - $oManifestBase->set(MANIFEST_SECTION_TARGET_PATH . ":default", MANIFEST_SUBKEY_MODE, undef, MODE_0750); - $oManifestBase->set(MANIFEST_SECTION_TARGET_PATH . ":default", MANIFEST_SUBKEY_GROUP, undef, TEST_GROUP); - $oManifestBase->set(MANIFEST_SECTION_TARGET_PATH . ":default", MANIFEST_SUBKEY_USER, undef, TEST_USER); - # Section backup:target - $oManifestBase->set(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_TYPE, MANIFEST_VALUE_PATH); - $oManifestBase->set(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_PATH, $self->{strDbPath}); - - ################################################################################################################################ - if ($self->begin('new()')) - { - # Missing DB and DB Catalog version - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {(new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false}))}, ERROR_ASSERT, - 'strDbVersion and iDbCatalogVersion must be provided with bLoad = false'); - - # Missing DB version - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {(new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}))}, ERROR_ASSERT, - 'strDbVersion and iDbCatalogVersion must be provided with bLoad = false'); - - # Missing DB Catalog version - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {(new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, - strDbVersion => PG_VERSION_94}))}, ERROR_ASSERT, - 'strDbVersion and iDbCatalogVersion must be provided with bLoad = false'); - - # Successfully instantiate - #--------------------------------------------------------------------------------------------------------------------------- - my $oManifest = $self->testResult(sub {(new pgBackRest::Manifest($strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}))}, - "[object]", 'manifest instantiated'); - - # Initialize - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->test(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_94) && - $oManifest->test(INI_SECTION_BACKREST, INI_KEY_FORMAT, undef, $oManifest->{iInitFormat}) && - $oManifest->test(INI_SECTION_BACKREST, INI_KEY_VERSION, undef, $oManifest->{strInitVersion})}, true, - ' manifest initialized'); - - # Attempt to save without proper path - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oManifest->save()}, ERROR_FILE_MISSING, - "unable to open file '${strBackupManifestFile}' for write in missing path"); - - # Create path and save - #--------------------------------------------------------------------------------------------------------------------------- - storageRepo()->pathCreate($strBackupPath); - $self->testResult(sub {$oManifest->save()}, "[undef]", 'manifest saved'); - - # Load and check the saved file - #--------------------------------------------------------------------------------------------------------------------------- - my $oBackupManifest = $self->testResult(sub {(new pgBackRest::Manifest($strBackupManifestFile))}, "[object]", - ' saved manifest loaded'); - $self->testResult(sub {($oManifest->numericGet(INI_SECTION_BACKREST, INI_KEY_FORMAT) == - $oBackupManifest->numericGet(INI_SECTION_BACKREST, INI_KEY_FORMAT)) && - ($oManifest->get(INI_SECTION_BACKREST, INI_KEY_CHECKSUM) eq - $oBackupManifest->get(INI_SECTION_BACKREST, INI_KEY_CHECKSUM))}, true, - ' saved manifest equals initial manifest'); - } - - ################################################################################################################################ - if ($self->begin('build()')) - { - my $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - # Build error if offline = true and no tablespace path - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false)}, ERROR_PATH_MISSING, - "unable to list file info for missing path '" . $self->{strDbPath} . "/" . MANIFEST_TARGET_PGTBLSPC . "'"); - - # bOnline = true tests - #--------------------------------------------------------------------------------------------------------------------------- - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - # Create expected manifest from base - my $oStorageTemp = $oManifestBase->{oStorage}; - $oManifestBase->{oStorage} = undef; - my $oManifestExpected = dclone($oManifestBase); - $oManifestBase->{oStorage} = $oStorageTemp; - $oManifestExpected->{oStorage} = $oStorageTemp; - - # Add global/pg_control file and PG_VERSION file and create a directory with a different modes than default - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_FILE_PGCONTROL, - {strMode => MODE_0644, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), - $self->controlGenerateContent(PG_VERSION_94)); - - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_FILE_PGVERSION, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), PG_VERSION_94); - - # Create base path with different mode than default - storageDb()->pathCreate(DB_PATH_BASE, {strMode => MODE_0700}); - - # Update expected manifest - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MODE, undef, MODE_0600); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_GROUP, undef, TEST_GROUP); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_USER, undef, TEST_USER); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, true); - - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL, MANIFEST_SUBKEY_SIZE, PGCONTROL_SIZE); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL, MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL, MANIFEST_SUBKEY_MODE, MODE_0644); - - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' .DB_FILE_PGVERSION, - MANIFEST_SUBKEY_SIZE, length(&PG_VERSION_94)); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' .DB_FILE_PGVERSION, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_BASE, MANIFEST_SUBKEY_MODE, MODE_0700); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'paths/files and different modes'); - - $self->testException( - sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_ASSERT, - 'manifest has already been built'); - - # Master = false (what can be copied from a standby vs the master) - #--------------------------------------------------------------------------------------------------------------------------- - my $strOidFile = '11111'; - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_PATH_BASE . '/' . $strOidFile, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), $strOidFile); - - # Update expected manifest - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE . '/' . $strOidFile, - MANIFEST_SUBKEY_MASTER, undef, false); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE . '/' . $strOidFile, - MANIFEST_SUBKEY_SIZE, length($strOidFile)); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE . '/' . $strOidFile, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'master false'); - - # Create pg_config path and postgresql.conf file - my $strConfFile = '/postgresql.conf'; - my $strConfContent = "listen_addresses = *\n"; - storageTest()->pathCreate('pg_config'); - storageTest()->put(storageTest()->openWrite($self->testPath() . '/pg_config' . $strConfFile, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), $strConfContent); - - # link db/postgresql.conf -> pg_config/postgresql.conf - testLinkCreate($self->{strDbPath} . $strConfFile, $self->testPath() . '/pg_config' . $strConfFile); - - # INVESTIGATE: on the command line, these links appear to be fine but in the code, a debug line prior to the recursive call to build() produces: - # STRPATH BEFORE BUILD: /home/ubuntu/test/test-0/db/base, STRLEVEL PASSED: $VAR1 = 'pg_data/base/pg_config_bad'; - # STRFILTER: $VAR1 = undef; - # STRPATH BEFORE BUILD: /home/ubuntu/test/test-0/db/pg_config, STRLEVEL PASSED: $VAR1 = 'pg_data/base/pg_config_bad/postgresql.conf.link'; - # STRFILTER: $VAR1 = undef; - # STRPATH BEFORE BUILD: /home/ubuntu/test/test-0/db/base/base, STRLEVEL PASSED: $VAR1 = 'pg_data/base/postgresql.conf'; - # STRFILTER: $VAR1 = undef; - # - # and right here throws: 'unable to stat '/home/ubuntu/test/test-0/db/base/pg_config/postgresql.conf': No such file or directory' - # -- note the extra "base" here - it should just be /home/ubuntu/test/test-0/db/pg_config/postgresql.conf - # # link db/base/pg_config_bad -> ../../db/pg_config - # testLinkCreate($self->{strDbPath} . '/'. DB_PATH_BASE . '/pg_config_bad', '../../db/pg_config'); - # # link db/base/postgresql.conf -> ../pg_config/postgresql.conf - # testLinkCreate($self->{strDbPath} . '/'. DB_PATH_BASE . '/postgresql.conf', '..' . $strConfFile); - # $self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_LINK_DESTINATION, - # 'TEST THIS'); - - # INVESTIGATE: Even though the below code creates a duplicate link, this error occurs (note the pg_config/pg_config): - # 'unable to stat '/home/ubuntu/test/test-0/db/pg_config/pg_config/./postgresql.conf': No such file or directory' - # ubuntu@pgbackrest-test:~$ ls -l /home/ubuntu/test/test-0/db/pg_config/ - # total 4 - # -rw------- 1 ubuntu ubuntu 21 Nov 9 17:07 postgresql.conf - # lrwxrwxrwx 1 ubuntu ubuntu 17 Nov 9 19:53 postgresql.conf.bad.link -> ./postgresql.conf - # lrwxrwxrwx 1 ubuntu ubuntu 17 Nov 9 19:53 postgresql.conf.link -> ./postgresql.conf - # # This link will cause errors because it points to the same location as above - # testLinkCreate($self->{strDbPath} . $strConfFile . '.bad.link', './postgresql.conf'); - # - # $self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true)}, ERROR_LINK_DESTINATION, - # 'TEST ERROR'); - # testFileRemove($self->{strDbPath} . $strConfFile . '.link.bad'); - - # Update expected manifest - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_BASE, MANIFEST_SUBKEY_MODE, MODE_0700); - - # Section backup:target - $oManifestExpected->set( - MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA . $strConfFile, MANIFEST_SUBKEY_FILE, 'postgresql.conf'); - $oManifestExpected->set( - MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA . $strConfFile, MANIFEST_SUBKEY_PATH, - $self->testPath() . '/pg_config'); - $oManifestExpected->set( - MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA . $strConfFile, MANIFEST_SUBKEY_TYPE, MANIFEST_VALUE_LINK); - # Section target:file - $oManifestExpected->set( - MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strConfFile, MANIFEST_SUBKEY_SIZE, - length($strConfContent)); - $oManifestExpected->set( - MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/postgresql.conf', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - # Section target:link - $oManifestExpected->set(MANIFEST_SECTION_TARGET_LINK, MANIFEST_TARGET_PGDATA . '/postgresql.conf', - MANIFEST_SUBKEY_DESTINATION, $self->testPath() . '/pg_config' . $strConfFile); - # Section target:link:default - $oManifestExpected->set(MANIFEST_SECTION_TARGET_LINK . ":default", MANIFEST_SUBKEY_GROUP, undef, TEST_GROUP); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_LINK . ":default", MANIFEST_SUBKEY_USER, undef, TEST_USER); - - # Create an unreadable file and path in pg_config to test that we are only reading the files we need to - executeTest( - "sudo touch " . $self->testPath() . "/pg_config/do_not_read.txt" . - " && sudo mkdir -m 700 " . $self->testPath() . "/pg_config/do_not_read"); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'link'); - - # Create a link loop and expect an error - #--------------------------------------------------------------------------------------------------------------------------- - testLinkCreate($self->{strDbPath} . '/pgdata', $self->{strDbPath}); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testException( - sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_FORMAT, - 'recursion in manifest build exceeds depth of 16: pg_data/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/' . - "pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata/pgdata\n" . - 'HINT: is there a link loop in $PGDATA?'); - - testFileRemove($self->{strDbPath} . '/pgdata'); - - # Test skip files/directories - #--------------------------------------------------------------------------------------------------------------------------- - # Create files to skip - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_FILE_POSTGRESQLAUTOCONFTMP ), ''); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_FILE_BACKUPLABELOLD), ''); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_FILE_POSTMASTEROPTS), ''); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_FILE_POSTMASTERPID), ''); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_FILE_RECOVERYCONF), ''); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_FILE_RECOVERYDONE), ''); - - # Create temp table files in a data directory - these will be skipped - my $strDbDataDirBasePath = "/" . DB_PATH_BASE . "/12134"; - my $strDbDataDir = $self->{strDbPath} . $strDbDataDirBasePath; - storageDb()->pathCreate($strDbDataDir); - - my $strTempFileOid = '/t123_456'; - storageDb()->put(storageDb()->openWrite($strDbDataDir . $strTempFileOid, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->put(storageDb()->openWrite($strDbDataDir . $strTempFileOid . '.1', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->put(storageDb()->openWrite($strDbDataDir . $strTempFileOid . '_fsm', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->put(storageDb()->openWrite($strDbDataDir . $strTempFileOid . '_vm.12', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - - # Create unlogged files to skip - my $strUnlogFileOid = '/12345'; - my $strUnlogFile = $strDbDataDir . $strUnlogFileOid; - storageDb()->put(storageDb()->openWrite($strUnlogFile . '_init', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); # will not be skipped - storageDb()->put(storageDb()->openWrite($strUnlogFile . '_init.1', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); # will not be skipped - storageDb()->put(storageDb()->openWrite($strUnlogFile . '_vm.1_vm', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); # will not be skipped - storageDb()->put(storageDb()->openWrite($strUnlogFile, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->put(storageDb()->openWrite($strUnlogFile . '.11', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->put(storageDb()->openWrite($strUnlogFile . '_fsm.1', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->put(storageDb()->openWrite($strUnlogFile . '_vm', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - - # Create an OID file and instead of OID_init file create a directory - the OID file and directory will NOT be skipped - my $strNotUnlogFileOid = '/54321'; - my $strNotUnlogFile = $strDbDataDir . $strNotUnlogFileOid; - storageDb()->put(storageDb()->openWrite($strNotUnlogFile, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->pathCreate($strNotUnlogFile . '_init'); - - # Create a temp-looking file not in the database directory - this will not be skipped - my $strTempNoSkip = '/' . DB_PATH_BASE . '/t111_111'; - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . $strTempNoSkip, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - - # Create directories to skip. Add a bogus file to them for test coverage. - storageDb()->pathCreate(DB_FILE_PREFIX_TMP); - storageDb()->pathCreate('pg_xlog'); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/pg_xlog/' . BOGUS, - {strMode => MODE_0644, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->pathCreate(DB_PATH_PGDYNSHMEM); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_PATH_PGDYNSHMEM . '/' . BOGUS, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->pathCreate(DB_PATH_PGNOTIFY); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_PATH_PGNOTIFY . '/' . BOGUS, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->pathCreate(DB_PATH_PGREPLSLOT); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_PATH_PGREPLSLOT . '/' . BOGUS, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->pathCreate(DB_PATH_PGSERIAL); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_PATH_PGSERIAL . '/' . BOGUS, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->pathCreate(DB_PATH_PGSNAPSHOTS); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_PATH_PGSNAPSHOTS . '/' . BOGUS, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->pathCreate(DB_PATH_PGSTATTMP); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_PATH_PGSTATTMP . '/' . BOGUS, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->pathCreate(DB_PATH_PGSUBTRANS); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . DB_PATH_PGSUBTRANS . '/' . BOGUS, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->pathCreate(DB_FILE_PGINTERNALINIT); - - # Update expected manifest with files and paths that will not be skipped - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA . '/pg_xlog', undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_PGDYNSHMEM, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_PGNOTIFY, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_PGREPLSLOT, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_PGSERIAL, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_PGSNAPSHOTS, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_PGSTATTMP, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_PGSUBTRANS, undef, $hDefault); - - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strTempNoSkip, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strTempNoSkip, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . $strUnlogFileOid . - '_init', MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . $strUnlogFileOid . - '_init', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . $strUnlogFileOid . - '_init.1', MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . $strUnlogFileOid . - '_init.1', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . $strUnlogFileOid . - '_vm.1_vm', MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . $strUnlogFileOid . - '_vm.1_vm', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . $strNotUnlogFileOid, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . $strNotUnlogFileOid, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . $strNotUnlogFileOid . - '_init', undef, $hDefault); - - # The number of files that can be retrieved from the standby has increased so default for [target:file:default] "master" - # setting is now expected to be false and the files that must be copied from the master will individually change to true - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, false); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . "/" . DB_PATH_BASE . "/" . $strOidFile, - MANIFEST_SUBKEY_MASTER); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . DB_FILE_PGVERSION, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strConfFile, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL, MANIFEST_SUBKEY_MASTER, true); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'skip directories/files'); - - # Unskip code path coverage - #--------------------------------------------------------------------------------------------------------------------------- - $oStorageTemp = $oManifestExpected->{oStorage}; - $oManifestExpected->{oStorage} = undef; - my $oManifestExpectedUnskip = dclone($oManifestExpected); - $oManifestExpected->{oStorage} = $oStorageTemp; - $oManifestExpectedUnskip->{oStorage} = $oStorageTemp; - - # Change DB version to 93 - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_93, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_93)}); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_93); - $oManifestExpectedUnskip->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, - $self->dbCatalogVersion(PG_VERSION_93)); - - # Update expected manifest - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGDYNSHMEM . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGDYNSHMEM . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGDYNSHMEM . '/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGREPLSLOT . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGREPLSLOT . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGREPLSLOT . '/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_93, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_93)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 94 directories'); - - # Change DB version to 91 - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_91, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_91)}); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_91 . ''); - $oManifestExpectedUnskip->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, - $self->dbCatalogVersion(PG_VERSION_91)); - - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSNAPSHOTS . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSNAPSHOTS . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSNAPSHOTS . '/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_91, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_91)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 92 directories'); - - # Change DB version to 90 - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_90, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_90)}); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_90); - $oManifestExpectedUnskip->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, - $self->dbCatalogVersion(PG_VERSION_90)); - - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSERIAL . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSERIAL . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - - # Any file that has a pattern for unlogged tables will not be skipped. - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid, MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid, MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '.11', MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '.11', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_fsm.1', MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_fsm.1', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_vm', MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_vm', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - - # The number of files that can be retrieved from the standby has increased so default for [target:file:default] "master" - # setting is now expected to be false and the files that must be copied from the master will individually change to true - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, false); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . "/" . DB_FILE_PGVERSION, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL, MANIFEST_SUBKEY_MASTER, true); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strConfFile, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGDYNSHMEM . '/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGREPLSLOT . '/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSNAPSHOTS . '/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSERIAL . '/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpectedUnskip->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE . '/' . - $strOidFile, MANIFEST_SUBKEY_MASTER); - $oManifestExpectedUnskip->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_init', MANIFEST_SUBKEY_MASTER); - $oManifestExpectedUnskip->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_init.1', MANIFEST_SUBKEY_MASTER); - $oManifestExpectedUnskip->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_vm.1_vm', MANIFEST_SUBKEY_MASTER); - $oManifestExpectedUnskip->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strTempNoSkip, - MANIFEST_SUBKEY_MASTER); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_90, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_90)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 91 directories'); - - # Change DB version to 84 - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_84, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_84)}); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_84 . ''); - $oManifestExpectedUnskip->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, - $self->dbCatalogVersion(PG_VERSION_84)); - - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGNOTIFY . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGNOTIFY . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGNOTIFY . '/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - - # Files that look like "temp" object files will no longer be skipped - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strTempFileOid, MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strTempFileOid, MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strTempFileOid . '.1', MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strTempFileOid . '.1', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strTempFileOid . '_fsm', MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strTempFileOid . '_fsm', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strTempFileOid . '_vm.12', MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strTempFileOid . '_vm.12', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_84, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_84)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 90 directories'); - - # Change DB version to 83 - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_83, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_83)}); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_83); - $oManifestExpectedUnskip->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, - $self->dbCatalogVersion(PG_VERSION_83)); - - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSTATTMP . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpectedUnskip->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSTATTMP . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpectedUnskip->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSTATTMP . '/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_83, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_83)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpectedUnskip, $oManifest)}, "", 'unskip 84 directories'); - - # Reset Manifest for next tests - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - # Remove files and expect manifest entries not necessary for the rest of the tests - testPathRemove($strDbDataDir); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_init.1'); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_init'); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strUnlogFileOid . '_vm.1_vm'); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, true); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE . '/' . $strOidFile, - MANIFEST_SUBKEY_MASTER, false); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strTempNoSkip, - MANIFEST_SUBKEY_MASTER, false); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . "/" . DB_FILE_PGVERSION, - MANIFEST_SUBKEY_MASTER); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strConfFile, - MANIFEST_SUBKEY_MASTER); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL, MANIFEST_SUBKEY_MASTER); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strNotUnlogFileOid); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA . $strDbDataDirBasePath . - $strNotUnlogFileOid . '_init'); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'manifest reset'); - - # Tablespaces - #--------------------------------------------------------------------------------------------------------------------------- - # Create pg_tblspc path - my $strTblSpcPath = $self->{strDbPath} . '/' . DB_PATH_PGTBLSPC; - storageDb()->pathCreate($strTblSpcPath, {bCreateParent => true}); - - # Create a directory in pg_tblspc - storageDb()->pathCreate("$strTblSpcPath/" . BOGUS, {strMode => '0700'}); - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_LINK_EXPECTED, - MANIFEST_TARGET_PGTBLSPC . "/" . BOGUS . " is not a symlink - " . DB_PATH_PGTBLSPC . " should contain only symlinks"); - - testPathRemove("${strTblSpcPath}/" . BOGUS); - - my $strTblspcId = '99999'; - - # Invalid relative tablespace is ../ - testLinkCreate("${strTblSpcPath}/${strTblspcId}", '../'); - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_LINK_DESTINATION, - 'tablespace symlink ../ destination must not be in $PGDATA'); - testFileRemove("${strTblSpcPath}/${strTblspcId}"); - - # Invalid relative tablespace is .. - testLinkCreate("${strTblSpcPath}/${strTblspcId}", '..'); - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_LINK_DESTINATION, - 'tablespace symlink .. destination must not be in $PGDATA'); - testFileRemove("${strTblSpcPath}/${strTblspcId}"); - - # Invalid relative tablespace is ../base - a subdirectory of $PGDATA - testLinkCreate("${strTblSpcPath}/${strTblspcId}", '../base'); - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_LINK_DESTINATION, - 'tablespace symlink ../base destination must not be in $PGDATA'); - testFileRemove("${strTblSpcPath}/${strTblspcId}"); - - # Invalid absolute tablespace is $self->{strDbPath} . /base - testLinkCreate("${strTblSpcPath}/${strTblspcId}", $self->{strDbPath} . '/base'); - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testException( - sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_LINK_DESTINATION, - "tablespace symlink $self->{strDbPath}/base destination must not be in \$PGDATA"); - testFileRemove("${strTblSpcPath}/${strTblspcId}"); - - # Invalid relative tablespace is ../../BOGUS - which is not in $PGDATA and does not exist - testLinkCreate("${strTblSpcPath}/${strTblspcId}", '../../' . BOGUS); - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, ERROR_ASSERT, - "tablespace with oid ${strTblspcId} not found in tablespace map\n" . - "HINT: was a tablespace created or dropped during the backup?"); - testFileRemove("${strTblSpcPath}/${strTblspcId}"); - - # Create tablespace directory outside PGDATA - my $strTablespace = 'tablespace'; - storageTest()->pathCreate($strTablespace); - - my $strIntermediateLink = $self->testPath() . "/intermediate_link"; - - # Create a link to a link - testLinkCreate($strIntermediateLink, $self->testPath() . '/' . $strTablespace); - testLinkCreate("${strTblSpcPath}/${strTblspcId}", $strIntermediateLink); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testException(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false)}, ERROR_LINK_DESTINATION, - "link '${strTblSpcPath}/${strTblspcId}' -> '$strIntermediateLink' cannot reference another link"); - - testFileRemove($strIntermediateLink); - testFileRemove("${strTblSpcPath}/${strTblspcId}"); - - # Reload the manifest otherwise it will contain invalid data from the above exception tests - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - # Create a valid symlink pg_tblspc/1 to tablespace/ts1/1 directory - my $strTablespaceOid = '1'; - my $strTablespaceName = "ts${strTablespaceOid}"; - storageTest()->pathCreate("${strTablespace}/${strTablespaceName}/${strTablespaceOid}", {bCreateParent => true}); - my $strTablespacePath = storageTest()->pathGet("${strTablespace}/${strTablespaceName}/${strTablespaceOid}"); - testLinkCreate("${strTblSpcPath}/${strTablespaceOid}", $strTablespacePath); - - # Create the directory PG would create when the sql CREATE TABLESPACE is run - my $strTblspcVersion = 'PG_9.4_201409291'; - my $strTblspcDir = $strTblspcVersion . '/11'; - storageTest()->pathCreate("$strTablespacePath/$strTblspcDir", {bCreateParent => true}); - - # Create a file and path that will error if read - executeTest("sudo touch ${strTablespacePath}/do_not_read.txt && sudo mkdir -m 700 ${strTablespacePath}/do_not_read"); - - # Create unlogged and temp files - storageDb()->put(storageDb()->openWrite($strTablespacePath . '/' . $strTblspcDir . $strUnlogFileOid . '_init', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->put(storageDb()->openWrite($strTablespacePath . '/' . $strTblspcDir . $strUnlogFileOid, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->put(storageDb()->openWrite($strTablespacePath . '/' . $strTblspcDir . $strTempFileOid, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - storageDb()->put(storageDb()->openWrite($strTablespacePath . '/' . $strTblspcDir . '/' . $strOidFile, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - - # The number of files that can be retrieved from the standby has increased so default for [target:file:default] "master" - # setting is now expected to be false and the files that must be copied from the master will individually change to true - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, false); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . DB_FILE_PGVERSION, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strConfFile, - MANIFEST_SUBKEY_MASTER, true); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL, MANIFEST_SUBKEY_MASTER, true); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . "/" . DB_PATH_BASE . "/" . $strOidFile, - MANIFEST_SUBKEY_MASTER); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strTempNoSkip, - MANIFEST_SUBKEY_MASTER); - - # Create the tablespace info in expected manifest - my $strMfTs = MANIFEST_TARGET_PGTBLSPC . "/" . $strTablespaceOid; - $oManifestExpected->set(MANIFEST_SECTION_BACKUP_TARGET, $strMfTs, MANIFEST_SUBKEY_PATH, $strTablespacePath); - $oManifestExpected->set(MANIFEST_SECTION_BACKUP_TARGET, $strMfTs, MANIFEST_SUBKEY_TABLESPACE_ID, $strTablespaceOid); - $oManifestExpected->set(MANIFEST_SECTION_BACKUP_TARGET, $strMfTs, MANIFEST_SUBKEY_TABLESPACE_NAME, $strTablespaceName); - $oManifestExpected->set(MANIFEST_SECTION_BACKUP_TARGET, $strMfTs, MANIFEST_SUBKEY_TYPE, MANIFEST_VALUE_LINK); - - $oManifestExpected->set(MANIFEST_SECTION_TARGET_LINK, MANIFEST_TARGET_PGDATA . "/${strMfTs}", MANIFEST_SUBKEY_DESTINATION, - $strTablespacePath); - - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGTBLSPC, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_PATH_PGTBLSPC, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, $strMfTs, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, $strMfTs . '/' . $strTblspcVersion, undef, $hDefault); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, $strMfTs . '/' . $strTblspcDir, undef, $hDefault); - - # Don't skip unlog init file or normal oid files - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strUnlogFileOid . '_init', - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strUnlogFileOid . '_init', - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . '/' . $strOidFile, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . '/' . $strOidFile, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - - # In offline mode, do not skip the db WAL path - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL, MANIFEST_SUBKEY_MODE, MODE_0644); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/pg_xlog/' . BOGUS, - MANIFEST_SUBKEY_MODE, MODE_0644); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/pg_xlog/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/pg_xlog/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/pg_xlog/' . BOGUS, - MANIFEST_SUBKEY_MASTER, true); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'offline with valid tablespace - do not skip database WAL directory and only copy unlogged init file'); - - # Create tablespace and database maps - my $hTablespaceMap = {}; - $hTablespaceMap->{$strTablespaceOid} = $strTablespaceName; - - my $hDatabaseMap = {}; - $hDatabaseMap->{&BOGUS}{&MANIFEST_KEY_DB_ID} = 12345; - $hDatabaseMap->{&BOGUS}{&MANIFEST_KEY_DB_LAST_SYSTEM_ID} = 67890; - - $oManifestExpected->numericSet(MANIFEST_SECTION_DB, BOGUS, MANIFEST_KEY_DB_ID, $hDatabaseMap->{&BOGUS}{&MANIFEST_KEY_DB_ID}); - $oManifestExpected->numericSet(MANIFEST_SECTION_DB, BOGUS, MANIFEST_KEY_DB_LAST_SYSTEM_ID, - $hDatabaseMap->{&BOGUS}{&MANIFEST_KEY_DB_LAST_SYSTEM_ID}); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false, $hTablespaceMap, $hDatabaseMap); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'offline passing tablespace map and database map'); - - # Remove the unreadable file and path because they will not work with tests for PG < 9.0 - executeTest("sudo rm ${strTablespacePath}/do_not_read.txt && sudo rmdir ${strTablespacePath}/do_not_read"); - - # Exclusions - #--------------------------------------------------------------------------------------------------------------------------- - # Excluded links - storageDb()->linkCreate('/dev/null', 'postgresql.auto.conf'); - storageDb()->linkCreate('/etc/hosts', 'hosts'); - - # Exclude log files but not directory - storageDb()->pathCreate('pg_log'); - storageDb()->put(storageDb()->openWrite('pg_log/logfile'), 'EXCLUDE'); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA . '/pg_log', undef, $hDefault); - - # Exclude directory and all contents - storageDb()->pathCreate('global/exclude'); - storageDb()->put(storageDb()->openWrite('global/exclude/exclude.txt'), 'EXCLUDE'); - - # Test exclusions against the ideal manifest - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build( - storageDb(), $self->{strDbPath}, undef, false, false, $hTablespaceMap, $hDatabaseMap, - {'postgresql.auto.conf' => true, 'hosts' => true, 'pg_log/' => true, 'global/exclude' => true}); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'check exclusions'); - - # Remove excluded files so we don't have to pass exclusions to the rest of the tests - storageDb()->remove('postgresql.auto.conf'); - storageDb()->remove('hosts'); - storageDb()->remove('pg_log/logfile'); - storageDb()->pathRemove('global/exclude', {bRecurse => true}); - - # Reload the manifest with version < 9.0 - #--------------------------------------------------------------------------------------------------------------------------- - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_84, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_84)}); - - # Catalog not stored in < 9.0 - $oManifestExpected->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_84 . ''); - $oManifestExpected->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, - $self->dbCatalogVersion(PG_VERSION_84)); - - # The number of files that can be retrieved from the standby has been superseded so [target:file:default] "master" - # setting is now expected to be true and the files that must be copied from the master will individually change to false - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, true); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . "/" . DB_FILE_PGVERSION, - MANIFEST_SUBKEY_MASTER); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strConfFile, - MANIFEST_SUBKEY_MASTER); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_FILE_PGCONTROL, MANIFEST_SUBKEY_MASTER); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/pg_xlog/' . BOGUS, - MANIFEST_SUBKEY_MASTER); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE . '/' . - $strOidFile, MANIFEST_SUBKEY_MASTER, false); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . $strTempNoSkip, - MANIFEST_SUBKEY_MASTER, false); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strUnlogFileOid . '_init', - MANIFEST_SUBKEY_MASTER, false); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . '/' . $strOidFile, - MANIFEST_SUBKEY_MASTER, false); - - # Add unskip directories - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGDYNSHMEM . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGDYNSHMEM . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGREPLSLOT . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGREPLSLOT . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSNAPSHOTS . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSNAPSHOTS . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSERIAL . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGSERIAL . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGNOTIFY . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_PATH_PGNOTIFY . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - - # Add unskip of temp and unlog file patterns - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strUnlogFileOid, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strUnlogFileOid, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strUnlogFileOid, - MANIFEST_SUBKEY_MASTER, false); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strTempFileOid, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strTempFileOid, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, $strMfTs . '/' . $strTblspcDir . $strTempFileOid, - MANIFEST_SUBKEY_MASTER, false); - - $oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false, $hTablespaceMap, $hDatabaseMap); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'tablespace with version < 9.0'); - - $oManifestExpected->remove(MANIFEST_SECTION_DB); - - # Undefined user/group - #--------------------------------------------------------------------------------------------------------------------------- - executeTest("sudo chgrp 777 " . $self->{strDbPath} . '/pg_xlog/' . BOGUS); - executeTest("sudo chown 777 " . $self->{strDbPath} . '/pg_xlog/' . BOGUS); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/pg_xlog/' . BOGUS, - MANIFEST_SUBKEY_GROUP, false); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/pg_xlog/' . BOGUS, - MANIFEST_SUBKEY_USER, false); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_84, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_84)}); - $oManifest->build(storageDb(), $self->{strDbPath}, undef, false, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'undefined user/group'); - - # Reset the group / owner - executeTest("sudo chgrp " . TEST_GROUP . " " . $self->{strDbPath} . '/pg_xlog/' . BOGUS); - executeTest("sudo chown " . TEST_USER . " " . $self->{strDbPath} . '/pg_xlog/' . BOGUS); - } - - ################################################################################################################################ - if ($self->begin('get/set')) - { - my $oManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - # SubKey required but has not been set - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oManifest->boolGet(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_CHECKSUM_PAGE)}, - ERROR_ASSERT, "strSection '" . MANIFEST_SECTION_TARGET_FILE . "', strKey '" . BOGUS . "', strSubKey '" . - MANIFEST_SUBKEY_CHECKSUM_PAGE . "' is required but not defined"); - - # SubKey not required and not set - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->boolGet(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_CHECKSUM_PAGE, false)}, - false, 'boolGet() - false'); - - # Set and get a boolean value - #--------------------------------------------------------------------------------------------------------------------------- - $oManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_CHECKSUM_PAGE, true); - $self->testResult(sub {$oManifest->boolGet(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_CHECKSUM_PAGE)}, true, - 'boolGet() - true'); - - # Get default boolean value - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_COMPRESS, undef, false, true)}, - true, 'boolGet() - default true'); - - # Get but don't return a default boolean value even if there is supposed to be one - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->boolGet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_COMPRESS, undef, false, false)}, - false, 'boolGet() - default false'); - - # Get default numeric value - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->numericGet(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_SIZE, false, 0)}, - 0, 'numericGet() - default 0'); - - # Coverage for $self->SUPER::get("${strSection}:default" - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->get(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_USER, false)}, - "[undef]", 'get() - default section'); - - # Get the correct path for the control file in the DB - #--------------------------------------------------------------------------------------------------------------------------- - $oManifest->set(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_PATH, $self->{strDbPath}); - $self->testResult(sub {$oManifest->dbPathGet($oManifest->get(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, - MANIFEST_SUBKEY_PATH), MANIFEST_FILE_PGCONTROL)}, - $self->{strDbPath} . "/" . DB_FILE_PGCONTROL, 'dbPathGet() - control file'); - - # Get filename - no path passed - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->dbPathGet(undef, BOGUS)}, BOGUS, 'dbPathGet() - filename'); - - # repoPathGet - no tablespace - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->repoPathGet(MANIFEST_TARGET_PGDATA, DB_FILE_PGCONTROL)}, - MANIFEST_TARGET_PGDATA . "/" . DB_FILE_PGCONTROL, 'repoPathGet() - pg_control'); - - # repoPathGet - tablespace - no subpath - #--------------------------------------------------------------------------------------------------------------------------- - my $strTablespaceId = "1"; - my $strTablespace = MANIFEST_TARGET_PGTBLSPC . "/" . $strTablespaceId; - my $strTablespaceName = "ts" . $strTablespaceId; - - $oManifest->set(MANIFEST_SECTION_BACKUP_TARGET, $strTablespace, MANIFEST_SUBKEY_PATH, $self->{strDbPath} . - "/tablespace/" . $strTablespaceName); - $self->testResult(sub {$oManifest->repoPathGet($strTablespace)}, $strTablespace, - 'repoPathGet() - tablespace - no tablespace-id nor subpath'); - - # repoPathGet - fully qualified tablespace target - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->tablespacePathGet()}, "PG_" . PG_VERSION_94 . "_" . - $self->dbCatalogVersion(PG_VERSION_94), 'tablespacePathGet()'); - - $oManifest->set(MANIFEST_SECTION_BACKUP_TARGET, $strTablespace, MANIFEST_SUBKEY_TABLESPACE_ID, $strTablespaceId); - $oManifest->set(MANIFEST_SECTION_BACKUP_TARGET, $strTablespace, MANIFEST_SUBKEY_TABLESPACE_NAME, $strTablespaceName); - $oManifest->set(MANIFEST_SECTION_BACKUP_TARGET, $strTablespace, MANIFEST_SUBKEY_TYPE, MANIFEST_VALUE_LINK); - - $self->testResult(sub {$oManifest->repoPathGet($strTablespace, BOGUS)}, $strTablespace . "/PG_" . PG_VERSION_94 . "_" . - $self->dbCatalogVersion(PG_VERSION_94) . "/" . BOGUS, 'repoPathGet() - tablespace valid with subpath'); - - # Set the DB version to < 9.0 - there is no special subdirectory in earlier PG versions - $oManifest->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_84); - $self->testResult(sub {$oManifest->repoPathGet($strTablespace, BOGUS)}, $strTablespace . "/" . BOGUS, - 'repoPathGet() - tablespace in 8.4 valid with subpath'); - $oManifest->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_94); - - # isTargetLink - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->isTargetLink(MANIFEST_TARGET_PGDATA)}, false, "isTargetLink - false"); - $self->testResult(sub {$oManifest->isTargetLink($strTablespace)}, true, "isTargetLink - true"); - - # isTargetLink - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult(sub {$oManifest->isTargetFile(MANIFEST_TARGET_PGDATA)}, false, "isTargetFile - false"); - - $oManifest->set(MANIFEST_SECTION_BACKUP_TARGET, MANIFEST_TARGET_PGDATA, MANIFEST_SUBKEY_FILE, BOGUS); - $self->testResult(sub {$oManifest->isTargetFile(MANIFEST_TARGET_PGDATA)}, true, "isTargetFile - true"); - } - - ################################################################################################################################ - if ($self->begin('isTarget - exceptions')) - { - my $oManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - # Target not defined - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oManifest->isTargetValid()}, ERROR_ASSERT, 'target is not defined'); - $self->testException(sub {$oManifest->isTargetFile()}, ERROR_ASSERT, 'target is not defined'); - $self->testException(sub {$oManifest->isTargetLink()}, ERROR_ASSERT, 'target is not defined'); - $self->testException(sub {$oManifest->isTargetTablespace()}, ERROR_ASSERT, 'target is not defined'); - - # Target not valid - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException(sub {$oManifest->isTargetValid(BOGUS, true)}, ERROR_ASSERT, BOGUS . ' is not a valid target'); - $self->testResult(sub {$oManifest->isTargetValid(BOGUS, false)}, false, 'isTargetValid - bError = false, return false'); - $self->testResult(sub {$oManifest->isTargetValid(BOGUS)}, false, 'isTargetValid - bError = undef, false'); - } - - ################################################################################################################################ - if ($self->begin('dbVerion(), xactPath(), walPath()')) - { - # dbVersion, xactPath and walPath - PG < 10 - #--------------------------------------------------------------------------------------------------------------------------- - my $oManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - $self->testResult(sub {$oManifest->dbVersion()}, PG_VERSION_94, 'dbVersion < 10'); - $self->testResult(sub {$oManifest->xactPath()}, 'pg_clog', ' xactPath - pg_clog'); - $self->testResult(sub {$oManifest->walPath()}, 'pg_xlog', ' walPath - pg_xlog'); - - # dbVersion, xactPath and walPath - PG >= 10 - #--------------------------------------------------------------------------------------------------------------------------- - $oManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_10, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_10)}); - - $self->testResult(sub {$oManifest->dbVersion()}, PG_VERSION_10, 'dbVersion >= 10'); - $self->testResult(sub {$oManifest->xactPath()}, 'pg_xact', ' xactPath - pg_xact'); - $self->testResult(sub {$oManifest->walPath()}, 'pg_wal', ' walPath - pg_wal'); - } - - ################################################################################################################################ - if ($self->begin('validate()')) - { - my $oManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - # Set a target:file with only a timestamp - fail size not set - #--------------------------------------------------------------------------------------------------------------------------- - $oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_TIMESTAMP, 1509384645); - $self->testException(sub {$oManifest->validate()}, ERROR_ASSERT, - "manifest subvalue 'size' not set for file '" . BOGUS . "'"); - - # Set target:file size - fail checksum not set - #--------------------------------------------------------------------------------------------------------------------------- - $oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_SIZE, 1); - $self->testException(sub {$oManifest->validate()}, ERROR_ASSERT, - "manifest subvalue 'checksum' not set for file '" . BOGUS . "'"); - - # Set target:file checksum - validate passes when size > 0 and checksum set - #--------------------------------------------------------------------------------------------------------------------------- - $oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_CHECKSUM, 0); - $self->testResult(sub {$oManifest->validate()}, "[undef]", 'manifest validated - size 1, checksum 0'); - - # Set target:file size to 0 - validate passes when size 0 - #--------------------------------------------------------------------------------------------------------------------------- - $oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, BOGUS, MANIFEST_SUBKEY_SIZE, 0); - $self->testResult(sub {$oManifest->validate()}, "[undef]", 'manifest validated - size 0'); - } - - ################################################################################################################################ - if ($self->begin('future file and last manifest')) - { - my $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - # Create expected manifest from base - my $oStorageTemp = $oManifestBase->{oStorage}; - $oManifestBase->{oStorage} = undef; - my $oManifestExpected = dclone($oManifestBase); - $oManifestBase->{oStorage} = $oStorageTemp; - $oManifestExpected->{oStorage} = $oStorageTemp; - - # Future timestamp on file - #--------------------------------------------------------------------------------------------------------------------------- - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strTest, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime + 20000}), $strTest); - - # Update expected manifest - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MODE, undef, MODE_0600); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_GROUP, undef, TEST_GROUP); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_USER, undef, TEST_USER); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, true); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_SIZE, - length($strTest)); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_TIMESTAMP, - $lTime + 20000); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_FUTURE, 'y'); - - $self->testResult(sub {$oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false)}, true, - 'future timestamp warning, enable delta checksum', {strLogExpect => - "WARN: file " . MANIFEST_TARGET_PGDATA . "/$strTest has timestamp in the future, enabling delta checksum\n" . - "WARN: some files have timestamps in the future - they will be copied to prevent possible race conditions"}); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", ' manifest future subkey=y'); - - # Future timestamp in last manifest - #--------------------------------------------------------------------------------------------------------------------------- - $oStorageTemp = $oManifestExpected->{oStorage}; - $oManifestExpected->{oStorage} = undef; - my $oLastManifest = dclone($oManifestExpected); - $oManifestExpected->{oStorage} = $oStorageTemp; - $oLastManifest->{oStorage} = $oStorageTemp; - - # Set a backup label - $oLastManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL, undef, BOGUS); - $oManifestExpected->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_PRIOR, undef, BOGUS); - - # Remove the file and recreate it without it being in the future - storageTest()->remove($self->{strDbPath} . '/' . $strTest); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strTest, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), $strTest); - - # Remove the future subkey from the expected manifest and reset the timestamp - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_FUTURE); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_TIMESTAMP, - $lTime); - - # Create a new manifest - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - # Last manifest is passed with online option=false, but passing true as current online status to invoke warning delta - # being enabled - $oLastManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef, false); - $self->testResult(sub {$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false)}, true, - 'last manifest future timestamp warning - delta enabled for online mismatch', {strLogExpect => - "WARN: the online option has changed since the last backup, enabling delta checksum\n" . - "WARN: some files have timestamps in the future - they will be copied to prevent possible race conditions"}); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - ' last manifest future subkey=y, new manifest future subkey removed'); - - # Set online in last manifest to avoid delta warning being displayed in the rest of the tests - $oLastManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef, true); - - # File info in last manifest same as current - #--------------------------------------------------------------------------------------------------------------------------- - $oLastManifest->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_FUTURE); - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_TIMESTAMP, - $lTime); - $oLastManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef, true); - - # Update reference in expected manifest - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_REFERENCE, - BOGUS); - - # Check reference - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - $self->testResult(sub {$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false)}, false, - 'delta is not enabled'); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - ' reference set to prior backup label'); - - # Zero-sized file and size of file changed but timestamp did not - #--------------------------------------------------------------------------------------------------------------------------- - # Create a new file reference and a zero-sized file reference - my $strTestNew = $strTest . 'new'; - my $strZeroFile = 'zero-file'; - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strTestNew, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), $strTestNew); - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strZeroFile, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - # Change the size on a file - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strTest, - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), $strTest . 'more'); - - # Set a reference, checksum, repo size, master and page checksum in the last manifest - my $strCheckSum = '1234567890'; - my $lRepoSize = 10000; - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_SIZE, length($strTestNew)); - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_REFERENCE, BOGUS . BOGUS); - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_CHECKSUM, $strCheckSum); - $oLastManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_REPO_SIZE, $lRepoSize); - $oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_MASTER, false); - $oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_CHECKSUM_PAGE, true); - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_SIZE, 0); - $oLastManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_REPO_SIZE, $lRepoSize); - $oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_MASTER, false); - $oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_CHECKSUM_PAGE, true); - - # Update expected manifest - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_SIZE, length($strTestNew)); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_REFERENCE, BOGUS . BOGUS); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_CHECKSUM, $strCheckSum); - $oManifestExpected->numericSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_REPO_SIZE, $lRepoSize); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_CHECKSUM_PAGE, true); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_REFERENCE, BOGUS); - $oManifestExpected->numericSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_REPO_SIZE, $lRepoSize); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_CHECKSUM_PAGE, true); - # Remove the reference for strTest since the size has changed - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, - MANIFEST_SUBKEY_REFERENCE); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, - MANIFEST_SUBKEY_SIZE, length($strTest . 'more')); - - # Default "master" is flipping because it's not something we read from disk - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, false); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, - MANIFEST_SUBKEY_MASTER, true); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testResult(sub {$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false)}, true, - 'timestamp same, contents different, delta is enabled', {strLogExpect => - "WARN: file " . MANIFEST_TARGET_PGDATA . - "/$strTest timestamp in the past or size changed but timestamp did not, enabling delta checksum"}); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", ' updates from last manifest'); - - # new timestamp less than last manifest timestamp for referenced file - #--------------------------------------------------------------------------------------------------------------------------- - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, - MANIFEST_SUBKEY_TIMESTAMP, $lTime + 100); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, - MANIFEST_SUBKEY_REFERENCE); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $self->testResult(sub {$oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false)}, true, - 'time in past, delta enabled', {strLogExpect => - "WARN: file " . MANIFEST_TARGET_PGDATA . - "/$strTest timestamp in the past or size changed but timestamp did not, enabling delta checksum"}); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - ' manifest compare'); - - # Reset the timestamp - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, - MANIFEST_SUBKEY_TIMESTAMP, $lTime + 0); - - # Timestamp in the lastManifest is different than built manifest (size and content the same) - #--------------------------------------------------------------------------------------------------------------------------- - # pass delta=true - expected manifest will use the timestamp set for the file on disk ($lTime) - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_TIMESTAMP, $lTime - 10); - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_TIMESTAMP, $lTime - 10); - - # Add a file not in the last manifest - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strTest . '2', - {strMode => MODE_0600, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), $strTest); - - # Update expected manifest - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest . '2', - MANIFEST_SUBKEY_SIZE, length($strTest)); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest . '2', - MANIFEST_SUBKEY_TIMESTAMP, $lTime + 0); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest . '2', - MANIFEST_SUBKEY_MASTER, true); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, true); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'delta true, size same, timestamp different'); - - # With different timestamp in last manifest pass delta=false - the references to the prior backup will be removed for the - # non-zero file but the zero file will still have a reference - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_REFERENCE); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_CHECKSUM); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_REPO_SIZE); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTestNew, - MANIFEST_SUBKEY_CHECKSUM_PAGE); - - # Update the size in the last manifest to match the current and add the reference to the expected manifest - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, - MANIFEST_SUBKEY_SIZE, length($strTest . 'more')); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, - MANIFEST_SUBKEY_REFERENCE, BOGUS); - - # Default "master" is flipping because it's not something we read from disk - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, true); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest, MANIFEST_SUBKEY_MASTER); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strTest . '2', - MANIFEST_SUBKEY_MASTER); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_MASTER, false); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'delta false, size same, timestamp different'); - - # MANIFEST_SUBKEY_CHECKSUM_PAGE = false and MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR set/not set from last manifest - #--------------------------------------------------------------------------------------------------------------------------- - $oLastManifest->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_CHECKSUM_PAGE, false); - - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_CHECKSUM_PAGE, false); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'checksum-page false, checksum-page-error not set'); - - my @iyChecksumPageError = (1); - $oLastManifest->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR, \@iyChecksumPageError); - - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . $strZeroFile, - MANIFEST_SUBKEY_CHECKSUM_PAGE_ERROR, \@iyChecksumPageError); - - $oManifest = new pgBackRest::Manifest( - $strBackupManifestFile, - {bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->build(storageDb(), $self->{strDbPath}, $oLastManifest, true, false); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'checksum-page false, checksum-page-error set'); - } - - ################################################################################################################################ - if ($self->begin('fileAdd()')) - { - my $oManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - my $oStorageTemp = $oManifestBase->{oStorage}; - $oManifestBase->{oStorage} = undef; - my $oManifestExpected = dclone($oManifestBase); - $oManifestBase->{oStorage} = $oStorageTemp; - $oManifestExpected->{oStorage} = $oStorageTemp; - - # Add a bogus file - all traces to be removed after the manifest has been built to simulate an initial manifest and avoid - # missing files error - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . BOGUS, - {strMode => MODE_0750, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTime}), ''); - - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MODE, undef, MODE_0750); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_GROUP, undef, TEST_GROUP); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_USER, undef, TEST_USER); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MASTER, undef, true); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . BOGUS, - MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, MANIFEST_TARGET_PGDATA . '/' . BOGUS, - MANIFEST_SUBKEY_TIMESTAMP, $lTime); - - $oManifest->build(storageDb(), $self->{strDbPath}, undef, true, false); - - # Remove the initial file and reset the manifest portions relating to the file for the following tests - storageDb()->remove($self->{strDbPath} . '/' . BOGUS); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE . ":default"); - $oManifest->remove(MANIFEST_SECTION_TARGET_FILE); - $oManifest->remove(MANIFEST_SECTION_TARGET_FILE . ":default"); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'build initial manifest'); - - # Add a file after building manifest - my $lTimeTest = $lTime + 10; - storageDb()->put(storageDb()->openWrite($self->{strDbPath} . '/' . $strTest, - {strMode => MODE_0644, strUser => TEST_USER, strGroup => TEST_GROUP, lTimestamp => $lTimeTest}), $strTest); - - $oManifest->fileAdd($strTest, $lTimeTest, 0, 0, true); - - # Update expected manifest - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_MODE, MODE_0600); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_USER, TEST_USER); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_GROUP, TEST_GROUP); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_TIMESTAMP, $lTimeTest); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_SIZE, 0); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_CHECKSUM, 0); - $oManifestExpected->boolSet(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_MASTER, true); - - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", 'file added to manifest'); - - # Remove the file user, mode and group from the actual and expected manifest - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_MODE); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_USER); - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_GROUP); - - $oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_MODE); - $oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_USER); - $oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_GROUP); - - # Add a target:file:default section to the manifests with a mode other than 0600 - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MODE, undef, MODE_0750); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_GROUP, undef, TEST_GROUP); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_USER, undef, TEST_USER); - - $oManifest->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MODE, undef, MODE_0750); - $oManifest->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_GROUP, undef, TEST_GROUP); - $oManifest->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_USER, undef, TEST_USER); - - # Set the expected mode to 0600 - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_MODE, MODE_0600); - - $oManifest->fileAdd($strTest, $lTimeTest, 0, 0, true); - - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'file added to manifest - file:default values set'); - - # Remove the file mode from the manifests and change the default so it need not be set for the file - $oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_MODE); - $oManifest->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MODE, undef, MODE_0600); - - $oManifestExpected->remove(MANIFEST_SECTION_TARGET_FILE, $strTest, MANIFEST_SUBKEY_MODE); - $oManifestExpected->set(MANIFEST_SECTION_TARGET_FILE . ":default", MANIFEST_SUBKEY_MODE, undef, MODE_0600); - - $oManifest->fileAdd($strTest, $lTimeTest, 0, 0, true); - $self->testResult(sub {$self->manifestCompare($oManifestExpected, $oManifest)}, "", - 'file added to manifest - default mode set 0600'); - } - - ################################################################################################################################ - if ($self->begin('isChecksumPage()')) - { - my $strFile = BOGUS; - - $self->testResult(sub {isChecksumPage($strFile)}, false, "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE . '/' . DB_FILE_PGVERSION; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE . '/' . DB_FILE_PGINTERNALINIT; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE. '/' . DB_FILE_PGFILENODEMAP; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGTBLSPC . '/' . DB_FILE_PGFILENODEMAP; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGTBLSPC . '/' . DB_FILE_PGINTERNALINIT; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGTBLSPC . '/' . DB_FILE_PGVERSION; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_PATH_GLOBAL. '/' . DB_FILE_PGFILENODEMAP; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_PATH_GLOBAL. '/' . DB_FILE_PGINTERNALINIT; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_PATH_GLOBAL. '/' . DB_FILE_PGVERSION; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_PATH_GLOBAL. '/' . DB_FILE_PGCONTROL; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_FILE_PGCONTROL; - $self->testResult(sub {isChecksumPage($strFile)}, false, - "file '${strFile}' isChecksumPage=false"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_PATH_BASE . '/123/' . BOGUS; - $self->testResult(sub {isChecksumPage($strFile)}, true, - "file '${strFile}' isChecksumPage=true"); - - $strFile = MANIFEST_TARGET_PGDATA . '/' . DB_PATH_GLOBAL . '/' . BOGUS; - $self->testResult(sub {isChecksumPage($strFile)}, true, - "file '${strFile}' isChecksumPage=true"); - } - - ################################################################################################################################ - if ($self->begin('checkDelta()')) - { - my $oManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - - $self->testResult(sub {$oManifest->checkDelta('test', false, "000000010000000000000000", "000000020000000000000000")}, true, - "timeline switch, delta enabled", - {strLogExpect => "WARN: a timeline switch has occurred since the test backup, enabling delta checksum"}); - - $self->testResult(sub {$oManifest->checkDelta('last', false, "000000010000000000000000", "000000010000000000000000")}, true, - "online option changed, delta enabled", - {strLogExpect => "WARN: the online option has changed since the last backup, enabling delta checksum"}); - - $self->testResult(sub {$oManifest->checkDelta('test', true, "000000010000000000000000", undef)}, false, - "no last timeline, online same, delta not enabled"); - - $self->testResult(sub {$oManifest->checkDelta('test', false, undef, "000000010000000000000000")}, true, - "no current timeline, online not same, delta enabled"); - - $self->testResult(sub {$oManifest->checkDelta('test', true, undef, undef)}, false, - "no timelines, online same, delta not enabled"); - } - - ################################################################################################################################ - if ($self->begin('checkDeltaFile()')) - { - # Additional tests to cover checkDeltaFile not covered by build tests - my $oManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - my $strFile = MANIFEST_TARGET_PGDATA . '/' . BOGUS; - my @stryFileList = ($strFile . '1'); - push(@stryFileList, $strFile); - - $self->testResult(sub {$oManifest->checkDeltaFile(\@stryFileList, undef, undef)}, false, - "no prior manifest, no time begin, delta not enabled"); - - my $oManifestPrior = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94, - iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)}); - $oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile . '1', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile . '1', MANIFEST_SUBKEY_SIZE, 0); - $oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE, 0); - $oManifestPrior->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile . '1', MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestPrior->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile . '1', MANIFEST_SUBKEY_SIZE, 0); - $oManifestPrior->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_TIMESTAMP, $lTime); - $oManifestPrior->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE, 0); - $oManifestPrior->set(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_FUTURE, 'y'); - - $self->testResult(sub {$oManifest->checkDeltaFile(\@stryFileList, $oManifestPrior, $lTime)}, true, - "prior manifest, time begin same, prior future is set, delta enabled", {strLogExpect => - "WARN: file $strFile has timestamp in the future, enabling delta checksum"}); - - $oManifestPrior->remove(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_FUTURE); - - $self->testResult(sub {$oManifest->checkDeltaFile(\@stryFileList, $oManifestPrior)}, false, - "simulate aborted manifest, delta not enabled"); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm b/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm index 6abcc83db..39d8d2498 100644 --- a/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm +++ b/test/lib/pgBackRestTest/Module/Mock/MockAllTest.pm @@ -26,6 +26,7 @@ use pgBackRest::InfoCommon; use pgBackRest::LibC qw(:checksum); use pgBackRest::Manifest; use pgBackRest::Protocol::Storage::Helper; +use pgBackRest::Storage::Helper; use pgBackRest::Version; use pgBackRestTest::Common::ContainerTest; @@ -142,7 +143,7 @@ sub run '184473f470864e067ee3a22e64b47b0a1c356f29', $lTime, undef, true); # Load sample page - my $tBasePage = ${storageTest()->get($self->dataPath() . '/page.bin')}; + my $tBasePage = ${storageLocal()->get($self->dataPath() . '/page.bin')}; my $iBasePageChecksum = 0x1B99; # Create base path diff --git a/test/lib/pgBackRestTest/Module/Protocol/ProtocolCommonMinionPerlTest.pm b/test/lib/pgBackRestTest/Module/Protocol/ProtocolCommonMinionPerlTest.pm deleted file mode 100644 index 1620f30cf..000000000 --- a/test/lib/pgBackRestTest/Module/Protocol/ProtocolCommonMinionPerlTest.pm +++ /dev/null @@ -1,135 +0,0 @@ -#################################################################################################################################### -# Tests for Protocol::Common::Minion module -#################################################################################################################################### -package pgBackRestTest::Module::Protocol::ProtocolCommonMinionPerlTest; -use parent 'pgBackRestTest::Common::RunTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use IO::Socket::UNIX; -use Time::HiRes qw(usleep); - -use pgBackRest::Common::Exception; -use pgBackRest::Common::Io::Buffered; -use pgBackRest::Common::Log; -use pgBackRest::Common::Wait; -use pgBackRest::LibC qw(:config); -use pgBackRest::Protocol::Base::Minion; -use pgBackRest::Version; - -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# socketServer -#################################################################################################################################### -sub socketServer -{ - my $self = shift; - my $strSocketFile = shift; - my $fnServer = shift; - - # Fork off the server - if (fork() == 0) - { - # Open the domain socket - my $oSocketServer = IO::Socket::UNIX->new(Type => SOCK_STREAM(), Local => $strSocketFile, Listen => 1); - &log(INFO, " * socket server open"); - - # Wait for a connection and create IO object - my $oConnection = $oSocketServer->accept(); - my $oIoHandle = new pgBackRest::Common::Io::Handle('socket server', $oConnection, $oConnection); - &log(INFO, " * socket server connected"); - - # Run server function - $fnServer->($oIoHandle); - - # Shutdown server - $oSocketServer->close(); - &log(INFO, " * socket server closed"); - unlink($strSocketFile); - exit 0; - } - - # Wait for client socket - my $oWait = waitInit(5); - while (!-e $strSocketFile && waitMore($oWait)) {}; - - # Open the client socket - my $oClient = IO::Socket::UNIX->new(Type => SOCK_STREAM(), Peer => $strSocketFile); - - if (!defined($oClient)) - { - logErrorResult(ERROR_FILE_OPEN, 'unable to open client socket', $OS_ERROR); - } - - &log(INFO, " * socket client connected"); - - return $oClient; -} - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - # Test data - my $strSocketFile = $self->testPath() . qw{/} . 'domain.socket'; - - ################################################################################################################################ - # if ($self->begin('new() & timeout() & bufferMax()')) - # { - # #--------------------------------------------------------------------------------------------------------------------------- - # my $oIoBuffered = $self->testResult( - # sub {new pgBackRest::Common::Io::Buffered( - # new pgBackRest::Common::Io::Handle('test'), 10, 2048)}, '[object]', 'new - no handles'); - # - # $self->testResult(sub {$oIoBuffered->timeout()}, 10, ' check timeout'); - # $self->testResult(sub {$oIoBuffered->bufferMax()}, 2048, ' check buffer max'); - # } - - ################################################################################################################################ - if ($self->begin('process()')) - { - my $oClient = $self->socketServer($strSocketFile, sub - { - my $oIoHandle = shift; - - my $oMinion = new pgBackRest::Protocol::Base::Minion('test', new pgBackRest::Common::Io::Buffered($oIoHandle, 5, 4096)); - - # Use bogus lock path to ensure a lock is not taken for the archive-get command - $oMinion->process($self->testPath(), cfgCommandName(CFGCMD_ARCHIVE_GET), "test", 0); - }); - - #--------------------------------------------------------------------------------------------------------------------------- - my $oIoBuffered = $self->testResult( - sub {new pgBackRest::Common::Io::Buffered( - new pgBackRest::Common::Io::Handle('socket client', $oClient, $oClient), 5, 4096)}, '[object]', 'open'); - - $self->testResult( - sub {$oIoBuffered->readLine()}, - '{"name":"' . PROJECT_NAME . '","service":"test","version":"' . PROJECT_VERSION . '"}', 'read greeting'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$oIoBuffered->writeLine('{"cmd":"noop"}')}, 15, 'write noop'); - $self->testResult( - sub {$oIoBuffered->readLine()}, '{"out":[]}', 'read output'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$oIoBuffered->writeLine('{"cmd":"exit"}')}, 15, 'write exit'); - $self->testResult( - sub {$oIoBuffered->readLine(true)}, undef, 'read EOF'); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Protocol/ProtocolHelperPerlTest.pm b/test/lib/pgBackRestTest/Module/Protocol/ProtocolHelperPerlTest.pm deleted file mode 100644 index 72e819257..000000000 --- a/test/lib/pgBackRestTest/Module/Protocol/ProtocolHelperPerlTest.pm +++ /dev/null @@ -1,155 +0,0 @@ -#################################################################################################################################### -# Protocol Helper Tests -#################################################################################################################################### -package pgBackRestTest::Module::Protocol::ProtocolHelperPerlTest; -use parent 'pgBackRestTest::Env::ConfigEnvTest'; - -#################################################################################################################################### -# 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::Archive::Common; -use pgBackRest::Common::Exception; -use pgBackRest::Common::Log; -use pgBackRest::Config::Config; -use pgBackRest::Protocol::Helper; -use pgBackRest::Protocol::Storage::Helper; -use pgBackRest::Storage::Helper; -use pgBackRest::Version; - -use pgBackRestTest::Env::HostEnvTest; -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Env::Host::HostBackupTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# initModule -#################################################################################################################################### -sub initModule -{ - my $self = shift; - - $self->{strDbPath} = $self->testPath() . '/db'; - $self->{strRepoPath} = $self->testPath() . '/repo'; - $self->{strArchivePath} = "$self->{strRepoPath}/archive/" . $self->stanza(); -} - -#################################################################################################################################### -# initTest -#################################################################################################################################### -sub initTest -{ - my $self = shift; - - # Create archive info - storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true}); -} - -#################################################################################################################################### -# initOption -#################################################################################################################################### -sub initOption -{ - my $self = shift; - - $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_COMPRESS, false); - - $self->optionTestSet(CFGOPT_DB_TIMEOUT, 5); - $self->optionTestSet(CFGOPT_PROTOCOL_TIMEOUT, 6); - $self->optionTestSet(CFGOPT_ARCHIVE_TIMEOUT, 3); -} - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - ################################################################################################################################ - if ($self->begin('protocolParam()')) - { - $self->optionTestSet(CFGOPT_STANZA, $self->stanza()); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST, 1), 'pg-host-1'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_PATH, 1), '/db1'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_PORT, 1), '1111'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST_CMD, 1), 'pgbackrest1'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST, 2), 'pg-host-2'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_PATH, 2), '/db2'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_PORT, 2), '2222'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST_CMD, 2), 'pgbackrest2'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG, 2), '/config2'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH, 2), '/config-include2'); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_PATH, 2), '/config-path2'); - $self->configTestLoad(CFGCMD_BACKUP); - - $self->testResult( - sub {pgBackRest::Protocol::Helper::protocolParam(cfgCommandName(CFGCMD_BACKUP), CFGOPTVAL_REMOTE_TYPE_DB, 2)}, - '(pg-host-2, postgres, [undef], pgbackrest2 --buffer-size=4194304 --command=backup --compress-level=6' . - ' --compress-level-network=3 --config=/config2 --config-include-path=/config-include2 --config-path=/config-path2' . - ' --log-level-file=off --pg1-path=/db2 --pg1-port=2222 --process=0 --protocol-timeout=1830 --stanza=db --type=db' . - ' remote)', - 'more than one backup db host'); - - # -------------------------------------------------------------------------------------------------------------------------- - $self->configTestClear(); - $self->optionTestSet(CFGOPT_STANZA, $self->stanza()); - $self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_PATH, 1), '/db1'); - $self->optionTestSet(CFGOPT_REPO_HOST, 'repo-host'); - $self->optionTestSet(CFGOPT_REPO_PATH, '/repo'); - $self->optionTestSet(CFGOPT_REPO_HOST_CMD, 'pgbackrest-repo'); - $self->optionTestSet(CFGOPT_REPO_HOST_CONFIG, '/config-repo'); - $self->optionTestSet(CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH, '/config-include-repo'); - $self->optionTestSet(CFGOPT_REPO_HOST_CONFIG_PATH, '/config-path-repo'); - $self->configTestLoad(CFGCMD_RESTORE); - - $self->testResult( - sub {pgBackRest::Protocol::Helper::protocolParam(cfgCommandName(CFGCMD_RESTORE), CFGOPTVAL_REMOTE_TYPE_BACKUP)}, - '(repo-host, pgbackrest, [undef], pgbackrest-repo --buffer-size=4194304 --command=restore --compress-level=6' . - ' --compress-level-network=3 --config=/config-repo --config-include-path=/config-include-repo' . - ' --config-path=/config-path-repo --log-level-file=off --pg1-path=/db1 --process=0 --protocol-timeout=1830' . - ' --repo1-path=/repo --stanza=db --type=backup remote)', - 'config params to repo host'); - } - - ################################################################################################################################ - if ($self->begin("Protocol::Helper")) - { - $self->initOption(); - $self->optionTestSet(CFGOPT_REPO_HOST, 'localhost'); - $self->optionTestSet(CFGOPT_REPO_HOST_USER, $self->pgUser()); - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - $self->testResult( - sub {protocolGet(CFGOPTVAL_REMOTE_TYPE_BACKUP, undef, {strBackRestBin => $self->backrestExe()})}, "[object]", - 'ssh default port'); - - # Destroy protocol object - protocolDestroy(); - - $self->optionTestSet(CFGOPT_REPO_HOST_PORT, 25); - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - $self->testException( - sub {protocolGet(CFGOPTVAL_REMOTE_TYPE_BACKUP, undef, {strBackRestBin => $self->backrestExe()})}, ERROR_FILE_READ, - "remote process on 'localhost' terminated unexpectedly: ssh: connect to host localhost port 25:"); - - # Destroy protocol object - protocolDestroy(); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm b/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm index bdc2744db..0b6f3f621 100644 --- a/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm +++ b/test/lib/pgBackRestTest/Module/Real/RealAllTest.pm @@ -25,6 +25,7 @@ use pgBackRest::Config::Config; use pgBackRest::InfoCommon; use pgBackRest::Manifest; use pgBackRest::Protocol::Storage::Helper; +use pgBackRest::Storage::Helper; use pgBackRest::Version; use pgBackRestTest::Common::ContainerTest; @@ -319,7 +320,7 @@ sub run 'fail on backup info file missing from non-empty dir', {iExpectedExitStatus => ERROR_PATH_NOT_EMPTY}); # Change the database version by copying a new pg_control file to a new pg-path to use for db mismatch test - storageDb()->pathCreate( + storageLocal()->pathCreate( $oHostDbMaster->dbPath() . '/testbase/' . DB_PATH_GLOBAL, {strMode => '0700', bIgnoreExists => true, bCreateParent => true}); $self->controlGenerate( @@ -769,7 +770,7 @@ sub run # Version <= 8.4 always places a PG_VERSION file in the tablespace if ($oHostDbMaster->pgVersion() <= PG_VERSION_84) { - if (!storageDb()->exists("${strTablespacePath}/" . DB_FILE_PGVERSION)) + if (!storageLocal()->exists("${strTablespacePath}/" . DB_FILE_PGVERSION)) { confess &log(ASSERT, "unable to find '" . DB_FILE_PGVERSION . "' in tablespace path '${strTablespacePath}'"); } @@ -787,14 +788,14 @@ sub run '/PG_' . $oHostDbMaster->pgVersion() . qw{_} . $oBackupInfo->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_CATALOG); # Check that path exists - if (!storageDb()->pathExists($strTablespacePath)) + if (!storageLocal()->pathExists($strTablespacePath)) { confess &log(ASSERT, "unable to find tablespace path '${strTablespacePath}'"); } } # Make sure there are some files in the tablespace path (exclude PG_VERSION if <= 8.4 since that was tested above) - if (grep(!/^PG\_VERSION$/i, storageDb()->list($strTablespacePath)) == 0) + if (grep(!/^PG\_VERSION$/i, storageLocal()->list($strTablespacePath)) == 0) { confess &log(ASSERT, "no files found in tablespace path '${strTablespacePath}'"); } @@ -864,7 +865,7 @@ sub run # Save recovery file to test so we can use it in the next test $strRecoveryFile = $oHostDbMaster->pgVersion() >= PG_VERSION_12 ? 'postgresql.auto.conf' : DB_FILE_RECOVERYCONF; - storageDb()->copy( + storageLocal()->copy( $oHostDbMaster->dbBasePath() . qw{/} . $strRecoveryFile, $self->testPath() . qw{/} . $strRecoveryFile); $oHostDbMaster->clusterStart(); @@ -886,7 +887,7 @@ sub run executeTest('rm -rf ' . $oHostDbMaster->tablespacePath(1) . "/*"); # Restore recovery file that was saved in last test - storageDb()->move($self->testPath . "/${strRecoveryFile}", $oHostDbMaster->dbBasePath() . "/${strRecoveryFile}"); + storageLocal()->move($self->testPath . "/${strRecoveryFile}", $oHostDbMaster->dbBasePath() . "/${strRecoveryFile}"); # Also touch recovery.signal when required if ($oHostDbMaster->pgVersion() >= PG_VERSION_12) diff --git a/test/lib/pgBackRestTest/Module/Storage/StorageHelperPerlTest.pm b/test/lib/pgBackRestTest/Module/Storage/StorageHelperPerlTest.pm deleted file mode 100644 index d3e43cdb8..000000000 --- a/test/lib/pgBackRestTest/Module/Storage/StorageHelperPerlTest.pm +++ /dev/null @@ -1,116 +0,0 @@ -#################################################################################################################################### -# StorageHelperTest.pm - Tests for Storage::Helper module. -#################################################################################################################################### -package pgBackRestTest::Module::Storage::StorageHelperPerlTest; -use parent 'pgBackRestTest::Env::ConfigEnvTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use Storable qw(dclone); - -use pgBackRest::Config::Config; -use pgBackRest::Common::Exception; -use pgBackRest::Common::Log; -use pgBackRest::Protocol::Storage::Helper; -use pgBackRest::Storage::Helper; - -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Env::Host::HostBackupTest; -use pgBackRestTest::Common::RunTest; - -#################################################################################################################################### -# initTest - initialization before each test -#################################################################################################################################### -sub initTest -{ - my $self = shift; - - storageTest()->pathCreate('db'); - storageTest()->pathCreate('repo'); - storageTest()->pathCreate('spool'); -} - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - # Define test file - my $strFile = 'file.txt'; - my $strFileCopy = 'file.txt.copy'; - my $strFileContent = 'TESTDATA'; - my $iFileSize = length($strFileContent); - - # Setup parameters - $self->optionTestSet(CFGOPT_PG_PATH, $self->testPath() . '/db'); - $self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo'); - $self->optionTestSet(CFGOPT_SPOOL_PATH, $self->testPath() . '/spool'); - $self->optionTestSet(CFGOPT_STANZA, $self->stanza()); - $self->optionTestSetBool(CFGOPT_ARCHIVE_ASYNC, true); - - $self->configTestLoad(CFGCMD_ARCHIVE_PUSH); - - #------------------------------------------------------------------------------------------------------------------------------- - if ($self->begin("storageLocal()")) - { - $self->testResult(sub {storageLocal($self->testPath())->put("/tmp/${strFile}", $strFileContent)}, $iFileSize, 'put'); - $self->testResult(sub {${storageTest()->get("/tmp/${strFile}")}}, $strFileContent, ' check put'); - - $self->testResult( - sub {storageLocal($self->testPath())->put("/tmp/${strFile}", $strFileContent)}, $iFileSize, 'put cache storage'); - $self->testResult(sub {${storageTest()->get("/tmp/${strFile}")}}, $strFileContent, ' check put'); - } - - #------------------------------------------------------------------------------------------------------------------------------- - if ($self->begin("storageDb()")) - { - $self->testResult(sub {storageDb()->put($strFile, $strFileContent)}, $iFileSize, 'put'); - $self->testResult(sub {${storageTest()->get("db/${strFile}")}}, $strFileContent, ' check put'); - - $self->testResult(sub {storageDb()->put($strFileCopy, $strFileContent)}, $iFileSize, 'put cached storage'); - $self->testResult(sub {${storageTest()->get("db/${strFileCopy}")}}, $strFileContent, ' check put'); - } - - #------------------------------------------------------------------------------------------------------------------------------- - if ($self->begin("storageRepo()")) - { - $self->testResult(sub {storageRepo()->put($strFile, $strFileContent)}, $iFileSize, 'put'); - $self->testResult(sub {${storageTest()->get("repo/${strFile}")}}, $strFileContent, ' check put'); - - $self->testResult(sub {storageRepo()->put($strFileCopy, $strFileContent)}, $iFileSize, 'put cached storage'); - $self->testResult(sub {${storageTest()->get("repo/${strFileCopy}")}}, $strFileContent, ' check put'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {storageRepo()->pathGet(STORAGE_REPO_ARCHIVE)}, $self->testPath() . '/repo/archive/db', 'check archive path'); - $self->testResult( - sub {storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . '/9.3-1/000000010000000100000001')}, - $self->testPath() . '/repo/archive/db/9.3-1/0000000100000001/000000010000000100000001', 'check repo WAL file'); - $self->testResult( - sub {storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . '/9.3-1/0000000100000001')}, - $self->testPath() . '/repo/archive/db/9.3-1/0000000100000001', 'check repo WAL path'); - $self->testResult( - sub {storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . '/9.3-1/0000000100000001')}, - $self->testPath() . '/repo/archive/db/9.3-1/0000000100000001', 'check repo WAL major path'); - $self->testResult( - sub {storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . '/9.3-1')}, - $self->testPath() . '/repo/archive/db/9.3-1', 'check repo archive id path'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {storageRepo()->pathGet(STORAGE_REPO_BACKUP)}, $self->testPath() . '/repo/backup/db', 'check backup path'); - $self->testResult( - sub {storageRepo()->pathGet(STORAGE_REPO_BACKUP . '/file')}, $self->testPath() . '/repo/backup/db/file', - 'check backup file'); - } -} - -1; diff --git a/test/lib/pgBackRestTest/Module/Storage/StoragePerlTest.pm b/test/lib/pgBackRestTest/Module/Storage/StoragePerlTest.pm deleted file mode 100644 index 9afd9bab2..000000000 --- a/test/lib/pgBackRestTest/Module/Storage/StoragePerlTest.pm +++ /dev/null @@ -1,351 +0,0 @@ -#################################################################################################################################### -# Tests for Storage::Local module -#################################################################################################################################### -package pgBackRestTest::Module::Storage::StoragePerlTest; -use parent 'pgBackRestTest::Common::RunTest'; - -#################################################################################################################################### -# Perl includes -#################################################################################################################################### -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use pgBackRest::Config::Config; -use pgBackRest::Common::Exception; -use pgBackRest::Common::Log; -use pgBackRest::LibC qw(:crypto); -use pgBackRest::Storage::Base; - -use pgBackRestTest::Common::ContainerTest; -use pgBackRestTest::Common::ExecuteTest; -use pgBackRestTest::Common::RunTest; -use pgBackRestTest::Env::Host::HostBackupTest; - -#################################################################################################################################### -# run -#################################################################################################################################### -sub run -{ - my $self = shift; - - # Define test file - my $strFile = $self->testPath() . '/file.txt'; - my $strFileCopy = $self->testPath() . '/file.txt.copy'; - my $strFileHash = 'bbbcf2c59433f68f22376cd2439d6cd309378df6'; - my $strFileContent = 'TESTDATA'; - my $iFileSize = length($strFileContent); - - # Create local storage - $self->{oStorageLocal} = new pgBackRest::Storage::Storage(''); - - ################################################################################################################################ - if ($self->begin("pathGet()")) - { - $self->testResult(sub {$self->storageLocal()->pathGet('file')}, '/file', 'relative path'); - $self->testResult(sub {$self->storageLocal()->pathGet('/file2')}, '/file2', 'absolute path'); - } - - ################################################################################################################################ - if ($self->begin('put()')) - { - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$self->storageLocal()->put($self->storageLocal()->openWrite($strFile))}, 0, 'put empty'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$self->storageLocal()->put($strFile)}, 0, 'put empty (all defaults)'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$self->storageLocal()->put($self->storageLocal()->openWrite($strFile), $strFileContent)}, $iFileSize, 'put'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$self->storageLocal()->put($self->storageLocal()->openWrite($strFile), \$strFileContent)}, $iFileSize, - 'put reference'); - } - - ################################################################################################################################ - if ($self->begin('get()')) - { - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$self->storageLocal()->get($self->storageLocal()->openRead($strFile, {bIgnoreMissing => true}))}, undef, - 'get missing'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->storageLocal()->put($strFile); - $self->testResult(sub {${$self->storageLocal()->get($strFile)}}, undef, 'get empty'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->storageLocal()->put($strFile, $strFileContent); - $self->testResult(sub {${$self->storageLocal()->get($strFile)}}, $strFileContent, 'get'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {${$self->storageLocal()->get($self->storageLocal()->openRead($strFile))}}, $strFileContent, 'get from io'); - } - - ################################################################################################################################ - if ($self->begin('hashSize()')) - { - $self->testResult( - sub {$self->storageLocal()->put($strFile, $strFileContent)}, 8, 'put'); - - $self->testResult( - sub {$self->storageLocal()->hashSize($strFile)}, - qw{(} . cryptoHashOne('sha1', $strFileContent) . ', ' . $iFileSize . qw{)}, ' check hash/size'); - $self->testResult( - sub {$self->storageLocal()->hashSize(BOGUS, {bIgnoreMissing => true})}, "([undef], [undef])", - ' check missing hash/size'); - } - - ################################################################################################################################ - if ($self->begin('copy()')) - { - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException( - sub {$self->storageLocal()->copy($self->storageLocal()->openRead($strFile), $strFileCopy)}, ERROR_FILE_MISSING, - "unable to open missing file '${strFile}' for read"); - $self->testResult( - sub {$self->storageLocal()->exists($strFileCopy)}, false, ' destination does not exist'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {$self->storageLocal()->copy( - $self->storageLocal()->openRead($strFile, {bIgnoreMissing => true}), - $self->storageLocal()->openWrite($strFileCopy))}, - false, 'missing source io'); - $self->testResult( - sub {$self->storageLocal()->exists($strFileCopy)}, false, ' destination does not exist'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException( - sub {$self->storageLocal()->copy($self->storageLocal()->openRead($strFile), $strFileCopy)}, ERROR_FILE_MISSING, - "unable to open missing file '${strFile}' for read"); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->storageLocal()->put($strFile, $strFileContent); - - $self->testResult(sub {$self->storageLocal()->copy($strFile, $strFileCopy)}, true, 'copy filename->filename'); - $self->testResult(sub {${$self->storageLocal()->get($strFileCopy)}}, $strFileContent, ' check copy'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->storageLocal()->remove($strFileCopy); - - $self->testResult( - sub {$self->storageLocal()->copy($self->storageLocal()->openRead($strFile), $strFileCopy)}, true, 'copy io->filename'); - $self->testResult(sub {${$self->storageLocal()->get($strFileCopy)}}, $strFileContent, ' check copy'); - - #--------------------------------------------------------------------------------------------------------------------------- - $self->storageLocal()->remove($strFileCopy); - - $self->testResult( - sub {$self->storageLocal()->copy( - $self->storageLocal()->openRead($strFile), $self->storageLocal()->openWrite($strFileCopy))}, - true, 'copy io->io'); - $self->testResult(sub {${$self->storageLocal()->get($strFileCopy)}}, $strFileContent, ' check copy'); - } - - ################################################################################################################################ - if ($self->begin('exists()')) - { - $self->storageLocal()->put($self->testPath() . "/test.file"); - - $self->testResult(sub {$self->storageLocal()->exists($self->testPath() . "/test.file")}, true, 'existing file'); - $self->testResult(sub {$self->storageLocal()->exists($self->testPath() . "/test.missing")}, false, 'missing file'); - $self->testResult(sub {$self->storageLocal()->exists($self->testPath())}, false, 'path'); - } - - ################################################################################################################################ - if ($self->begin('info()')) - { - $self->testResult( - sub {$self->storageLocal()->info($self->testPath())}, - "{group => " . $self->group() . ", mode => 0770, type => d, user => " . $self->pgUser() . "}", - 'stat dir successfully'); - - $self->testException(sub {$self->storageLocal()->info(BOGUS)}, ERROR_FILE_OPEN, - "unable to get info for missing path/file '/bogus'"); - } - - ################################################################################################################################ - if ($self->begin("manifest() and list()")) - { - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException( - sub {$self->storageLocal()->manifest($self->testPath() . '/missing')}, - ERROR_PATH_MISSING, "unable to list file info for missing path '" . $self->testPath() . "/missing'"); - - #--------------------------------------------------------------------------------------------------------------------------- - # Setup test data - executeTest('mkdir -m 750 ' . $self->testPath() . '/sub1'); - executeTest('mkdir -m 750 ' . $self->testPath() . '/sub1/sub2'); - executeTest('mkdir -m 750 ' . $self->testPath() . '/sub2'); - - executeTest("echo 'TESTDATA' > " . $self->testPath() . '/test.txt'); - utime(1111111111, 1111111111, $self->testPath() . '/test.txt'); - executeTest('chmod 1640 ' . $self->testPath() . '/test.txt'); - - executeTest("echo 'TESTDATA_' > ". $self->testPath() . '/sub1/test-sub1.txt'); - utime(1111111112, 1111111112, $self->testPath() . '/sub1/test-sub1.txt'); - executeTest('chmod 0640 ' . $self->testPath() . '/sub1/test-sub1.txt'); - - executeTest("echo 'TESTDATA_' > ". $self->testPath() . '/sub1/.test-sub1.txt'); - utime(1111111112, 1111111112, $self->testPath() . '/sub1/.test-sub1.txt'); - executeTest('chmod 0640 ' . $self->testPath() . '/sub1/.test-sub1.txt'); - - executeTest("echo 'TESTDATA__' > " . $self->testPath() . '/sub1/sub2/test-sub2.txt'); - utime(1111111113, 1111111113, $self->testPath() . '/sub1/sub2/test-sub2.txt'); - executeTest('chmod 0646 ' . $self->testPath() . '/sub1/sub2/test-sub2.txt'); - - executeTest('mkfifo -m 606 ' . $self->testPath() . '/sub1/apipe'); - - executeTest('ln ' . $self->testPath() . '/test.txt ' . $self->testPath() . '/sub1/test-hardlink.txt'); - executeTest('ln ' . $self->testPath() . '/test.txt ' . $self->testPath() . '/sub1/sub2/test-hardlink.txt'); - - executeTest('ln -s .. ' . $self->testPath() . '/sub1/test'); - executeTest('chmod 0700 ' . $self->testPath() . '/sub1/test'); - executeTest('ln -s ../.. ' . $self->testPath() . '/sub1/sub2/test'); - executeTest('chmod 0750 ' . $self->testPath() . '/sub1/sub2/test'); - - executeTest('chmod 0770 ' . $self->testPath()); - - $self->testResult( - sub {$self->storageLocal()->manifest($self->testPath())}, - '{. => {group => ' . $self->group() . ', mode => 0770, type => d, user => ' . $self->pgUser() . '}, ' . - 'sub1 => {group => ' . $self->group() . ', mode => 0750, type => d, user => ' . $self->pgUser() . '}, ' . - 'sub1/.test-sub1.txt => ' . - '{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111112, size => 10, type => f, user => ' . - $self->pgUser() . '}, ' . - 'sub1/apipe => {group => ' . $self->group() . ', mode => 0606, type => s, user => ' . $self->pgUser() . '}, ' . - 'sub1/sub2 => {group => ' . $self->group() . ', mode => 0750, type => d, user => ' . $self->pgUser() . '}, ' . - 'sub1/sub2/test => {group => ' . $self->group() . ', link_destination => ../.., type => l, user => ' . - $self->pgUser() . '}, ' . - 'sub1/sub2/test-hardlink.txt => ' . - '{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111111, size => 9, type => f, user => ' . - $self->pgUser() . '}, ' . - 'sub1/sub2/test-sub2.txt => ' . - '{group => ' . $self->group() . ', mode => 0646, modification_time => 1111111113, size => 11, type => f, user => ' . - $self->pgUser() . '}, ' . - 'sub1/test => {group => ' . $self->group() . ', link_destination => .., type => l, user => ' . $self->pgUser() . '}, ' . - 'sub1/test-hardlink.txt => ' . - '{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111111, size => 9, type => f, user => ' . - $self->pgUser() . '}, ' . - 'sub1/test-sub1.txt => ' . - '{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111112, size => 10, type => f, user => ' . - $self->pgUser() . '}, ' . - 'sub2 => {group => ' . $self->group() . ', mode => 0750, type => d, user => ' . $self->pgUser() . '}, ' . - 'test.txt => ' . - '{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111111, size => 9, type => f, user => ' . - $self->pgUser() . '}}', - 'complete manifest'); - - $self->testResult(sub {$self->storageLocal()->list($self->testPath())}, "(sub1, sub2, test.txt)", "list"); - $self->testResult(sub {$self->storageLocal()->list($self->testPath(), {strExpression => "2\$"})}, "sub2", "list"); - $self->testResult( - sub {$self->storageLocal()->list($self->testPath(), {strSortOrder => 'reverse'})}, "(test.txt, sub2, sub1)", - "list reverse"); - $self->testResult(sub {$self->storageLocal()->list($self->testPath() . "/sub2")}, "[undef]", "list empty"); - $self->testResult( - sub {$self->storageLocal()->list($self->testPath() . "/sub99", {bIgnoreMissing => true})}, "[undef]", "list missing"); - $self->testException( - sub {$self->storageLocal()->list($self->testPath() . "/sub99")}, ERROR_PATH_MISSING, - "unable to list files for missing path '" . $self->testPath() . "/sub99'"); - } - - ################################################################################################################################ - if ($self->begin('move()')) - { - my $strFileCopy = "${strFile}.copy"; - my $strFileSub = $self->testPath() . '/sub/file.txt'; - - #--------------------------------------------------------------------------------------------------------------------------- - $self->testException( - sub {$self->storageLocal()->move($strFile, $strFileCopy)}, ERROR_FILE_MOVE, - "unable to move '${strFile}' to '${strFile}.copy': No such file or directory"); - } - - ################################################################################################################################ - if ($self->begin('owner()')) - { - my $strFile = $self->testPath() . "/test.txt"; - - $self->testException( - sub {$self->storageLocal()->owner($strFile, 'root')}, ERROR_FILE_MISSING, - "unable to stat '${strFile}': No such file or directory"); - - executeTest("touch ${strFile}"); - - $self->testException( - sub {$self->storageLocal()->owner($strFile, BOGUS)}, ERROR_FILE_OWNER, - "unable to set ownership for '${strFile}' because user 'bogus' does not exist"); - $self->testException( - sub {$self->storageLocal()->owner($strFile, undef, BOGUS)}, ERROR_FILE_OWNER, - "unable to set ownership for '${strFile}' because group 'bogus' does not exist"); - - $self->testResult(sub {$self->storageLocal()->owner($strFile)}, undef, "no ownership changes"); - $self->testResult(sub {$self->storageLocal()->owner($strFile, TEST_USER)}, undef, "same user"); - $self->testResult(sub {$self->storageLocal()->owner($strFile, undef, TEST_GROUP)}, undef, "same group"); - $self->testResult( - sub {$self->storageLocal()->owner($strFile, TEST_USER, TEST_GROUP)}, undef, - "same user, group"); - - $self->testException( - sub {$self->storageLocal()->owner($strFile, 'root', undef)}, ERROR_FILE_OWNER, - "unable to set ownership for '${strFile}': Operation not permitted"); - $self->testException( - sub {$self->storageLocal()->owner($strFile, undef, 'root')}, ERROR_FILE_OWNER, - "unable to set ownership for '${strFile}': Operation not permitted"); - - executeTest("sudo chown :root ${strFile}"); - $self->testResult( - sub {$self->storageLocal()->owner($strFile, undef, TEST_GROUP)}, undef, "change group back from root"); - } - - ################################################################################################################################ - if ($self->begin('pathCreate()')) - { - my $strTestPath = $self->testPath() . "/" . BOGUS; - - $self->testResult(sub {$self->storageLocal()->pathCreate($strTestPath)}, "[undef]", - "test creation of path " . $strTestPath); - - $self->testException(sub {$self->storageLocal()->pathCreate($strTestPath)}, ERROR_PATH_CREATE, - "unable to create path '". $strTestPath. "'"); - - $self->testResult(sub {$self->storageLocal()->pathCreate($strTestPath, {bIgnoreExists => true})}, "[undef]", - "ignore path exists"); - } - - ################################################################################################################################ - if ($self->begin('pathExists()')) - { - $self->storageLocal()->put($self->testPath() . "/test.file"); - - $self->testResult(sub {$self->storageLocal()->pathExists($self->testPath() . "/test.file")}, false, 'existing file'); - $self->testResult(sub {$self->storageLocal()->pathExists($self->testPath() . "/test.missing")}, false, 'missing file'); - $self->testResult(sub {$self->storageLocal()->pathExists($self->testPath())}, true, 'path'); - } - - ################################################################################################################################ - if ($self->begin('pathSync()')) - { - $self->testResult(sub {$self->storageLocal()->pathSync($self->testPath())}, "[undef]", "test path sync"); - } -} - -#################################################################################################################################### -# Getters -#################################################################################################################################### -# sub host {return '127.0.0.1'} -# sub pathLocal {return shift->{strPathLocal}}; -# sub pathRemote {return shift->{strPathRemote}}; -sub storageLocal {return shift->{oStorageLocal}}; -# sub storageEncrypt {return shift->{oStorageEncrypt}}; -# sub storageRemote {return shift->{oStorageRemote}}; - -1; diff --git a/test/patch/debian-package.patch b/test/patch/debian-package.patch new file mode 100644 index 000000000..0424c9687 --- /dev/null +++ b/test/patch/debian-package.patch @@ -0,0 +1,36 @@ +--- control ++++ control +@@ -4,7 +4,7 @@ + Maintainer: Debian PostgreSQL Maintainers + Uploaders: Adrian Vondendriesch + Build-Depends: debhelper (>= 9), +- libperl-dev, ++ perl, + libpq-dev, + libssl-dev, + libxml-checker-perl, +@@ -18,10 +18,8 @@ + + Package: pgbackrest + Architecture: any +-Depends: perl, +- postgresql-common, ++Depends: postgresql-common, + ${misc:Depends}, +- ${perl:Depends}, + ${shlibs:Depends} + Suggests: pgbackrest-doc + Description: Reliable PostgreSQL Backup & Restore +--- copyright ++++ copyright +@@ -3,8 +3,8 @@ + Source: https://github.com/pgbackrest/pgbackrest + + Files: * +-Copyright: 2015-2016 The PostgreSQL Global Development Group +- 2013-2016 David Steele ++Copyright: 2015-2020 The PostgreSQL Global Development Group ++ 2013-2020 David Steele + License: MIT + + Files: debian/* diff --git a/test/patch/rhel-package.patch b/test/patch/rhel-package.patch new file mode 100644 index 000000000..d8c5a7731 --- /dev/null +++ b/test/patch/rhel-package.patch @@ -0,0 +1,20 @@ +--- pgbackrest.spec ++++ pgbackrest.spec +@@ -8,16 +8,7 @@ + Url: http://www.pgbackrest.org/ + Source0: https://github.com/pgbackrest/pgbackrest/archive/release/%{version}.tar.gz + Source1: pgbackrest-conf.patch +-Requires: perl-XML-LibXML perl-IO-Socket-SSL +-%if 0%{?rhel} && 0%{?rhel} <= 6 +-Requires: perl-parent perl-JSON perl-Time-HiRes +-%else +-Requires: perl-JSON-PP +-%endif +-Requires: perl-Digest-SHA perl-DBD-Pg perl-Time-HiRes zlib +-Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) +-BuildRequires: openssl-devel zlib-devel perl-ExtUtils-Embed +-BuildRequires: postgresql%{pgmajorversion}-devel ++BuildRequires: openssl-devel zlib-devel postgresql%{pgmajorversion}-devel + Requires: postgresql-libs + + diff --git a/test/src/module/common/exitTest.c b/test/src/module/common/exitTest.c index beafb20af..419ba9faf 100644 --- a/test/src/module/common/exitTest.c +++ b/test/src/module/common/exitTest.c @@ -107,19 +107,6 @@ testRun(void) } TRY_END(); - // ------------------------------------------------------------------------------------------------------------------------- - TRY_BEGIN() - { - THROW(RuntimeError, PERL_EMBED_ERROR); - } - CATCH_ANY() - { - exitSafe(0, true, signalTypeNone); - harnessLogResult( - "P00 INFO: archive-push command end: aborted with exception [122]"); - } - TRY_END(); - // ------------------------------------------------------------------------------------------------------------------------- TEST_RESULT_INT( exitSafe(errorTypeCode(&TermError), false, signalTypeNone), errorTypeCode(&TermError), "exit on term with no signal"); diff --git a/test/src/module/perl/configTest.c b/test/src/module/perl/configTest.c deleted file mode 100644 index 3b572a4b9..000000000 --- a/test/src/module/perl/configTest.c +++ /dev/null @@ -1,112 +0,0 @@ -/*********************************************************************************************************************************** -Test Perl Exec -***********************************************************************************************************************************/ -#include "config/config.h" - -/*********************************************************************************************************************************** -Test Run -***********************************************************************************************************************************/ -void -testRun(void) -{ - FUNCTION_HARNESS_VOID(); - - // ***************************************************************************************************************************** - if (testBegin("perlOptionJson()")) - { - cfgInit(); - TEST_RESULT_STR(strPtr(perlOptionJson()), "{}", "no options"); - - // ------------------------------------------------------------------------------------------------------------------------- - cfgInit(); - - cfgOptionValidSet(cfgOptCompress, true); - cfgOptionSet(cfgOptCompress, cfgSourceParam, varNewBool(true)); - - cfgOptionValidSet(cfgOptConfig, true); - cfgOptionNegateSet(cfgOptConfig, true); - cfgOptionSet(cfgOptConfig, cfgSourceParam, NULL); - - cfgOptionValidSet(cfgOptOnline, true); - cfgOptionNegateSet(cfgOptOnline, true); - cfgOptionSet(cfgOptOnline, cfgSourceParam, varNewBool(false)); - - cfgOptionValidSet(cfgOptPgHost, true); - cfgOptionResetSet(cfgOptPgHost, true); - - cfgOptionValidSet(cfgOptPgPath, true); - cfgOptionSet(cfgOptPgPath, cfgSourceConfig, varNewStr(strNew("/path/db/pg"))); - - cfgOptionValidSet(cfgOptBackupStandby, true); - cfgOptionResetSet(cfgOptBackupStandby, true); - cfgOptionSet(cfgOptBackupStandby, cfgSourceParam, varNewBool(false)); - - cfgOptionValidSet(cfgOptProtocolTimeout, true); - cfgOptionSet(cfgOptProtocolTimeout, cfgSourceParam, varNewDbl(1.1)); - - cfgOptionValidSet(cfgOptArchivePushQueueMax, true); - cfgOptionSet(cfgOptArchivePushQueueMax, cfgSourceParam, varNewInt64(999999999999)); - - cfgOptionValidSet(cfgOptRepoCipherPass, true); - cfgOptionSet(cfgOptRepoCipherPass, cfgSourceConfig, varNewStr(strNew("part1\npart2"))); - - cfgOptionValidSet(cfgOptCompressLevel, true); - cfgOptionSet(cfgOptCompressLevel, cfgSourceConfig, varNewInt(3)); - - cfgOptionValidSet(cfgOptStanza, true); - cfgOptionSet(cfgOptStanza, cfgSourceDefault, varNewStr(strNew("db"))); - - TEST_RESULT_STR( - strPtr(perlOptionJson()), - "{" - "\"archive-push-queue-max\":" - "{\"negate\":false,\"reset\":false,\"source\":\"param\",\"valid\":true,\"value\":999999999999}," - "\"backup-standby\":{\"negate\":false,\"reset\":true,\"source\":\"param\",\"valid\":true,\"value\":false}," - "\"compress\":{\"negate\":false,\"reset\":false,\"source\":\"param\",\"valid\":true,\"value\":true}," - "\"compress-level\":{\"negate\":false,\"reset\":false,\"source\":\"config\",\"valid\":true,\"value\":3}," - "\"config\":{\"negate\":true,\"reset\":false,\"source\":\"param\",\"valid\":true}," - "\"online\":{\"negate\":true,\"reset\":false,\"source\":\"param\",\"valid\":true,\"value\":false}," - "\"pg1-host\":{\"negate\":false,\"reset\":true,\"source\":\"default\",\"valid\":true}," - "\"pg1-path\":{\"negate\":false,\"reset\":false,\"source\":\"config\",\"valid\":true,\"value\":\"/path/db/pg\"}," - "\"protocol-timeout\":{\"negate\":false,\"reset\":false,\"source\":\"param\",\"valid\":true,\"value\":1.1}," - "\"repo1-cipher-pass\":{\"negate\":false,\"reset\":false,\"source\":\"config\",\"valid\":true," - "\"value\":\"part1\\npart2\"}," - "\"stanza\":{\"negate\":false,\"reset\":false,\"source\":\"default\",\"valid\":true,\"value\":\"db\"}" - "}", - "simple options"); - - // ------------------------------------------------------------------------------------------------------------------------- - cfgInit(); - - cfgOptionValidSet(cfgOptDbInclude, true); - StringList *includeList = strLstNew(); - strLstAdd(includeList, strNew("db1")); - strLstAdd(includeList, strNew("db2")); - cfgOptionSet(cfgOptDbInclude, cfgSourceParam, varNewVarLst(varLstNewStrLst(includeList))); - - cfgOptionValidSet(cfgOptRecoveryOption, true); - - Variant *recoveryVar = varNewKv(kvNew()); - KeyValue *recoveryKv = varKv(recoveryVar); - kvPut(recoveryKv, varNewStr(strNew("standby_mode")), varNewStr(strNew("on"))); - kvPut(recoveryKv, varNewStr(strNew("primary_conn_info")), varNewStr(strNew("blah"))); - cfgOptionSet(cfgOptRecoveryOption, cfgSourceParam, recoveryVar); - - StringList *commandParamList = strLstNew(); - strLstAdd(commandParamList, strNew("param1")); - strLstAdd(commandParamList, strNew("param2")); - cfgCommandParamSet(commandParamList); - - TEST_RESULT_STR( - strPtr(perlOptionJson()), - "{" - "\"db-include\":{\"negate\":false,\"reset\":false,\"source\":\"param\",\"valid\":true," - "\"value\":{\"db1\":true,\"db2\":true}}," - "\"recovery-option\":{\"negate\":false,\"reset\":false,\"source\":\"param\",\"valid\":true," - "\"value\":{\"primary_conn_info\":\"blah\",\"standby_mode\":\"on\"}}" - "}", - "complex options"); - } - - FUNCTION_HARNESS_RESULT_VOID(); -} diff --git a/test/src/module/perl/execTest.c b/test/src/module/perl/execTest.c deleted file mode 100644 index 165a93db4..000000000 --- a/test/src/module/perl/execTest.c +++ /dev/null @@ -1,82 +0,0 @@ -/*********************************************************************************************************************************** -Test Perl Exec -***********************************************************************************************************************************/ -#include "config/config.h" -#include "config/load.h" - -/*********************************************************************************************************************************** -Test Run -***********************************************************************************************************************************/ -void -testRun(void) -{ - FUNCTION_HARNESS_VOID(); - - // ***************************************************************************************************************************** - if (testBegin("perlMain()")) - { - // ------------------------------------------------------------------------------------------------------------------------- - cfgInit(); - cfgCommandSet(cfgCmdInfo); - cfgExeSet(strNew("/path/to/pgbackrest")); - - TEST_RESULT_STR( - strPtr(perlMain()), "($iResult, $bErrorC, $strMessage) = pgBackRest::Main::main('info')", "command with no options"); - - // ------------------------------------------------------------------------------------------------------------------------- - cfgOptionValidSet(cfgOptCompress, true); - cfgOptionSet(cfgOptCompress, cfgSourceParam, varNewBool(true)); - - StringList *commandParamList = strLstNew(); - strLstAdd(commandParamList, strNew("A")); - strLstAdd(commandParamList, strNew("B")); - cfgCommandParamSet(commandParamList); - - TEST_RESULT_STR( - strPtr(perlMain()), "($iResult, $bErrorC, $strMessage) = pgBackRest::Main::main('info','A','B')", - "command with one option and params"); - } - - // ***************************************************************************************************************************** - if (testBegin("embeddedModuleGetInternal()")) - { - TEST_ERROR(embeddedModuleGetInternal(BOGUS_STR), AssertError, "unable to load embedded module 'BOGUS'"); - } - - // ***************************************************************************************************************************** - if (testBegin("perlExecResult()")) - { - TRY_BEGIN() - { - THROW(PathMissingError, "test message"); - } - CATCH_ANY() - { - TEST_ERROR(perlExecResult(errorTypeCode(&PathMissingError), true, NULL), PathMissingError, "test message"); - } - TRY_END(); - - TEST_RESULT_INT(perlExecResult(0, false, NULL), 0, "test success"); - } - - // ***************************************************************************************************************************** - if (testBegin("perlInit(), perlExec(), and perlFree()")) - { - StringList *argList = strLstNew(); - strLstAdd(argList, strNew("pgbackrest")); - strLstAdd(argList, strNew("--stanza=db")); - strLstAdd(argList, strNew("--log-level-console=off")); - strLstAdd(argList, strNew("--log-level-stderr=off")); - strLstAdd(argList, strNew("--log-level-file=off")); - strLstAdd(argList, strNew("archive-push")); - - TEST_RESULT_VOID(cfgLoad(strLstSize(argList), strLstPtr(argList)), "load archive-push config"); - - TEST_RESULT_VOID(perlFree(0), "free Perl before it is init'd"); - TEST_RESULT_VOID(perlInit(), "init Perl"); - TEST_ERROR(perlExec(), PathMissingError, PERL_EMBED_ERROR); - TEST_RESULT_VOID(perlFree(0), "free Perl"); - } - - FUNCTION_HARNESS_RESULT_VOID(); -} diff --git a/test/src/module/protocol/protocolTest.c b/test/src/module/protocol/protocolTest.c index f8049325d..a5ffd43ff 100644 --- a/test/src/module/protocol/protocolTest.c +++ b/test/src/module/protocol/protocolTest.c @@ -220,7 +220,7 @@ testRun(void) strPtr( strNew( "-o|LogLevel=error|-o|Compression=no|-o|PasswordAuthentication=no|repo-host-user@repo-host" - "|pgbackrest --c --command=archive-get --log-level-file=off --log-level-stderr=error --process=0" + "|pgbackrest --command=archive-get --log-level-file=off --log-level-stderr=error --process=0" " --stanza=test1 --type=backup remote")), "remote protocol params"); @@ -243,7 +243,7 @@ testRun(void) strPtr( strNew( "-o|LogLevel=error|-o|Compression=no|-o|PasswordAuthentication=no|-p|444|repo-host-user@repo-host" - "|pgbackrest --c --command=archive-get --config=/path/pgbackrest.conf --config-include-path=/path/include" + "|pgbackrest --command=archive-get --config=/path/pgbackrest.conf --config-include-path=/path/include" " --config-path=/path/config --log-level-file=info --log-level-stderr=error --log-subprocess --process=1" " --stanza=test1 --type=backup remote")), "remote protocol params with replacements"); @@ -265,7 +265,7 @@ testRun(void) strPtr( strNew( "-o|LogLevel=error|-o|Compression=no|-o|PasswordAuthentication=no|pgbackrest@repo-host" - "|pgbackrest --c --command=archive-get --log-level-file=off --log-level-stderr=error --process=3" + "|pgbackrest --command=archive-get --log-level-file=off --log-level-stderr=error --process=3" " --stanza=test1 --type=backup remote")), "remote protocol params for backup local"); @@ -284,7 +284,7 @@ testRun(void) strPtr( strNew( "-o|LogLevel=error|-o|Compression=no|-o|PasswordAuthentication=no|postgres@pg1-host" - "|pgbackrest --c --command=backup --log-level-file=off --log-level-stderr=error --pg1-path=/path/to/1" + "|pgbackrest --command=backup --log-level-file=off --log-level-stderr=error --pg1-path=/path/to/1" " --process=1 --stanza=test1 --type=db remote")), "remote protocol params for db backup"); @@ -309,7 +309,7 @@ testRun(void) strPtr( strNew( "-o|LogLevel=error|-o|Compression=no|-o|PasswordAuthentication=no|postgres@pg2-host" - "|pgbackrest --c --command=backup --log-level-file=off --log-level-stderr=error --pg1-path=/path/to/2" + "|pgbackrest --command=backup --log-level-file=off --log-level-stderr=error --pg1-path=/path/to/2" " --process=4 --stanza=test1 --type=db remote")), "remote protocol params for db local"); @@ -334,7 +334,7 @@ testRun(void) strPtr( strNew( "-o|LogLevel=error|-o|Compression=no|-o|PasswordAuthentication=no|postgres@pg3-host" - "|pgbackrest --c --command=backup --log-level-file=off --log-level-stderr=error --pg1-path=/path/to/3" + "|pgbackrest --command=backup --log-level-file=off --log-level-stderr=error --pg1-path=/path/to/3" " --pg1-port=3333 --pg1-socket-path=/socket3 --process=4 --stanza=test1 --type=db remote")), "remote protocol params for db local"); } diff --git a/test/src/module/storage/posixTest.c b/test/src/module/storage/posixTest.c index ad7217353..17cbef06b 100644 --- a/test/src/module/storage/posixTest.c +++ b/test/src/module/storage/posixTest.c @@ -544,11 +544,6 @@ testRun(void) storagePathP(storageTest, strNew("/path/toot")), AssertError, "absolute path '/path/toot' is not in base path '/path/to'"); - // Path enforcement disabled globally - storagePathEnforceSet(storageTest, false); - TEST_RESULT_STR(strPtr(storagePathP(storageTest, strNew("/bogus"))), "/bogus", "path enforce disabled globally"); - storagePathEnforceSet(storageTest, true); - // Path enforcement disabled for a single call TEST_RESULT_STR(strPtr(storagePathP(storageTest, strNew("/bogus"), .noEnforce = true)), "/bogus", "path enforce disabled"); diff --git a/test/test.pl b/test/test.pl index 65bc99bbb..ae5bce33c 100755 --- a/test/test.pl +++ b/test/test.pl @@ -38,7 +38,6 @@ use pgBackRestBuild::Build::Common; use pgBackRestBuild::Config::Build; use pgBackRestBuild::Config::BuildDefine; use pgBackRestBuild::Config::BuildParse; -use pgBackRestBuild::Embed::Build; use pgBackRestBuild::Error::Build; use pgBackRestBuild::Error::Data; @@ -567,59 +566,6 @@ eval } } - # Auto-generate C library code to embed in the binary - #----------------------------------------------------------------------------------------------------------------------- - if ($bGenLibC && (!$bSmart || grep(/^libc\//, @stryModifiedList))) - { - my $strLibC = executeTest( - "cd ${strBackRestBase}/libc && " . - "perl /usr/share/perl/5.26/ExtUtils/xsubpp -typemap /usr/share/perl/5.26/ExtUtils/typemap" . - " -typemap typemap LibC.xs"); - - # Trim off any trailing LFs - $strLibC = trim($strLibC) . "\n"; - - # Strip out line numbers. These are useful for the LibC build but only cause churn in the binary - # build. - $strLibC =~ s/^\#line .*\n//mg; - - # Save into the bin src dir - my @stryBuilt; - my $strBuilt = 'src/perl/libc.auto.c'; - - if (buildPutDiffers($oStorageBackRest, "${strBackRestBase}/${strBuilt}", $strLibC)) - { - push(@stryBuilt, $strBuilt); - push(@stryBuiltAll, @stryBuilt); - push(@stryModifiedList, @stryBuilt); - } - - &log(INFO, " autogenerated embedded C code: " . (@stryBuilt ? join(', ', @stryBuilt) : 'no changes')); - } - - # Auto-generate embedded Perl code - #----------------------------------------------------------------------------------------------------------------------- - if (!$bSmart || grep(/^lib\//, @stryModifiedList)) - { - my $rhBuild = - { - 'embed' => - { - &BLD_DATA => buildEmbed($oStorageBackRest), - &BLD_PATH => 'perl', - }, - }; - - my @stryBuilt = buildAll("${strBackRestBase}/src", $rhBuild); - &log(INFO, " autogenerated embedded Perl code: " . (@stryBuilt ? join(', ', @stryBuilt) : 'no changes')); - - if (@stryBuilt) - { - push(@stryBuiltAll, @stryBuilt); - push(@stryModifiedList, @stryBuilt); - } - } - # Auto-generate C Makefile #----------------------------------------------------------------------------------------------------------------------- if (!$bSmart || grep(/^(src|libc)\//, @stryModifiedList)) @@ -778,7 +724,7 @@ eval foreach my $hTest (@{$oyTestRun}) { # Bin build required for all Perl tests or if a C unit test calls Perl - if (!$hTest->{&TEST_C} || $hTest->{&TEST_PERL_REQ}) + if (!$hTest->{&TEST_C} || $hTest->{&TEST_BIN_REQ}) { $bBinRequired = true; }