mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-16 10:20:02 +02:00
195 lines
6.8 KiB
Perl
195 lines
6.8 KiB
Perl
####################################################################################################################################
|
|
# ARCHIVE PUSH FILE MODULE
|
|
####################################################################################################################################
|
|
package pgBackRest::Archive::ArchivePushFile;
|
|
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
use English '-no_match_vars';
|
|
|
|
use Exporter qw(import);
|
|
our @EXPORT = qw();
|
|
use File::Basename qw(basename);
|
|
|
|
use pgBackRest::Archive::ArchiveCommon;
|
|
use pgBackRest::Archive::ArchiveInfo;
|
|
use pgBackRest::Common::Exception;
|
|
use pgBackRest::Common::Log;
|
|
use pgBackRest::Config::Config;
|
|
use pgBackRest::File;
|
|
use pgBackRest::Protocol::Common;
|
|
|
|
####################################################################################################################################
|
|
# archivePushCheck
|
|
#
|
|
# Check that a WAL segment does not already exist in the archive be pushing. Files that are not segments (e.g. .history, .backup)
|
|
# will always be reported as not present and will be overwritten by archivePushFile().
|
|
####################################################################################################################################
|
|
sub archivePushCheck
|
|
{
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$oFile,
|
|
$strArchiveFile,
|
|
$strDbVersion,
|
|
$ullDbSysId,
|
|
$strWalFile,
|
|
) =
|
|
logDebugParam
|
|
(
|
|
__PACKAGE__ . '::archivePushCheck', \@_,
|
|
{name => 'oFile'},
|
|
{name => 'strArchiveFile'},
|
|
{name => 'strDbVersion', required => false},
|
|
{name => 'ullDbSysId', required => false},
|
|
{name => 'strWalFile', required => false},
|
|
);
|
|
|
|
# Set operation and debug strings
|
|
my $strArchiveId;
|
|
my $strChecksum;
|
|
|
|
# WAL file is segment?
|
|
my $bWalSegment = walIsSegment($strArchiveFile);
|
|
|
|
if ($oFile->isRemote(PATH_BACKUP_ARCHIVE))
|
|
{
|
|
# Execute the command
|
|
($strArchiveId, $strChecksum) = $oFile->{oProtocol}->cmdExecute(
|
|
OP_ARCHIVE_PUSH_CHECK, [$strArchiveFile, $strDbVersion, $ullDbSysId], true);
|
|
}
|
|
else
|
|
{
|
|
# If a segment check db version and system-id
|
|
if ($bWalSegment)
|
|
{
|
|
# If the info file exists check db version and system-id else error
|
|
$strArchiveId = (new pgBackRest::Archive::ArchiveInfo($oFile->pathGet(PATH_BACKUP_ARCHIVE)))->check(
|
|
$strDbVersion, $ullDbSysId);
|
|
|
|
# Check if the WAL segment already exists in the archive
|
|
my $strFoundFile = walSegmentFind($oFile, $strArchiveId, $strArchiveFile);
|
|
|
|
if (defined($strFoundFile))
|
|
{
|
|
$strChecksum = substr($strFoundFile, length($strArchiveFile) + 1, 40);
|
|
}
|
|
}
|
|
# Else just get the archive id
|
|
else
|
|
{
|
|
$strArchiveId = (new pgBackRest::Archive::ArchiveInfo($oFile->pathGet(PATH_BACKUP_ARCHIVE)))->archiveId();
|
|
}
|
|
}
|
|
|
|
my $strWarning;
|
|
|
|
if (defined($strChecksum) && !commandTest(CMD_REMOTE))
|
|
{
|
|
my $strChecksumNew = $oFile->hash(PATH_DB_ABSOLUTE, $strWalFile);
|
|
|
|
if ($strChecksumNew ne $strChecksum)
|
|
{
|
|
confess &log(ERROR, "WAL segment " . basename($strWalFile) . " already exists in the archive", ERROR_ARCHIVE_DUPLICATE);
|
|
}
|
|
|
|
$strWarning =
|
|
"WAL segment " . basename($strWalFile) . " already exists in the archive with the same checksum\n" .
|
|
"HINT: this is valid in some recovery scenarios but may also indicate a problem.";
|
|
|
|
&log(WARN, $strWarning);
|
|
}
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'strArchiveId', value => $strArchiveId},
|
|
{name => 'strChecksum', value => $strChecksum},
|
|
{name => 'strWarning', value => $strWarning}
|
|
);
|
|
}
|
|
|
|
push @EXPORT, qw(archivePushCheck);
|
|
|
|
####################################################################################################################################
|
|
# archivePushFile
|
|
#
|
|
# Copy a file from the WAL directory to the archive.
|
|
####################################################################################################################################
|
|
sub archivePushFile
|
|
{
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$oFile,
|
|
$strWalPath,
|
|
$strWalFile,
|
|
$bCompress,
|
|
$bRepoSync,
|
|
) =
|
|
logDebugParam
|
|
(
|
|
__PACKAGE__ . '::archivePushFile', \@_,
|
|
{name => 'oFile'},
|
|
{name => 'strWalPath'},
|
|
{name => 'strWalFile'},
|
|
{name => 'bCompress'},
|
|
{name => 'bRepoSync'},
|
|
);
|
|
|
|
# Get cluster info from the WAL
|
|
my $strDbVersion;
|
|
my $ullDbSysId;
|
|
|
|
if (walIsSegment($strWalFile))
|
|
{
|
|
($strDbVersion, $ullDbSysId) = walInfo("${strWalPath}/${strWalFile}");
|
|
}
|
|
|
|
# Check if the WAL already exists in the repo
|
|
my ($strArchiveId, $strChecksum, $strWarning) = archivePushCheck(
|
|
$oFile, $strWalFile, $strDbVersion, $ullDbSysId, walIsSegment($strWalFile) ? "${strWalPath}/${strWalFile}" : undef);
|
|
|
|
# Only copy the WAL segment if checksum is not defined. If checksum is defined it means that the WAL segment already exists
|
|
# in the repository with the same checksum (else there would have been an error on checksum mismatch).
|
|
if (!defined($strChecksum))
|
|
{
|
|
my $strArchiveFile = "${strArchiveId}/${strWalFile}";
|
|
|
|
# Append compression extension
|
|
if (walIsSegment($strWalFile) && $bCompress)
|
|
{
|
|
$strArchiveFile .= '.' . $oFile->{strCompressExtension};
|
|
}
|
|
|
|
# Copy the WAL segment
|
|
$oFile->copy(
|
|
PATH_DB_ABSOLUTE, "${strWalPath}/${strWalFile}", # Source type/file
|
|
PATH_BACKUP_ARCHIVE, $strArchiveFile, # Destination type/file
|
|
false, # Source is not compressed
|
|
walIsSegment($strWalFile) && $bCompress, # Destination compress is configurable
|
|
undef, undef, undef, # Unused params
|
|
true, # Create path if it does not exist
|
|
undef, undef, # Default User and group
|
|
walIsSegment($strWalFile), # Append checksum if WAL segment
|
|
$bRepoSync); # Sync repo directories?
|
|
}
|
|
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'strWarning', value => $strWarning}
|
|
);
|
|
}
|
|
|
|
push @EXPORT, qw(archivePushFile);
|
|
|
|
1;
|