mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-14 10:13:05 +02:00
1afbab010f
* IMPORTANT NOTE: This flag day release breaks compatibility with older versions of PgBackRest. The manifest format, on-disk structure, and the binary names have all changed. You must create a new repository to hold backups for this version of PgBackRest and keep your older repository for a time in case you need to do a restore. The `pg_backrest.conf` file has not changed but you'll need to change any references to `pg_backrest.pl` in cron (or elsewhere) to `pg_backrest` (without the `.pl` extension). * Add info command. * More efficient file ordering for backup. Files are copied in descending size order so a single thread does not end up copying a large file at the end. This had already been implemented for restore. * Logging now uses unbuffered output. This should make log files that are being written by multiple threads less chaotic. Suggested by Michael Renner. * Experimental support for PostgreSQL 9.5. This may break when the control version or WAL magic changes but will be updated in each release.
141 lines
5.4 KiB
Perl
141 lines
5.4 KiB
Perl
####################################################################################################################################
|
|
# BACKUP FILE MODULE
|
|
####################################################################################################################################
|
|
package BackRest::BackupFile;
|
|
|
|
use threads;
|
|
use Thread::Queue;
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
|
|
use Exporter qw(import);
|
|
use File::Basename qw(dirname);
|
|
|
|
use lib dirname($0);
|
|
use BackRest::Exception;
|
|
use BackRest::File;
|
|
use BackRest::Manifest;
|
|
use BackRest::Utility;
|
|
|
|
####################################################################################################################################
|
|
# backupFile
|
|
####################################################################################################################################
|
|
sub backupFile
|
|
{
|
|
my $oFile = shift; # File object
|
|
my $strSourceFile = shift; # Source file to backup
|
|
my $strDestinationFile = shift; # Destination backup file
|
|
my $bDestinationCompress = shift; # Compress destination file
|
|
my $strChecksum = shift; # File checksum to be checked
|
|
my $lModificationTime = shift; # File modification time
|
|
my $lSizeFile = shift; # File size
|
|
my $lSizeTotal = shift; # Total size of the files to be copied
|
|
my $lSizeCurrent = shift; # Size of files copied so far
|
|
|
|
my $bCopyResult; # Copy result
|
|
my $strCopyChecksum; # Copy checksum
|
|
my $lCopySize; # Copy Size
|
|
|
|
# Add the size of the current file to keep track of percent complete
|
|
$lSizeCurrent += $lSizeFile;
|
|
|
|
# If checksum is defined then the file already exists but needs to be checked
|
|
my $bCopy = true;
|
|
|
|
if (defined($strChecksum))
|
|
{
|
|
($strCopyChecksum, $lCopySize) = $oFile->hash_size(PATH_BACKUP_TMP, $strDestinationFile);
|
|
|
|
$bCopy = !($strCopyChecksum eq $strChecksum && $lCopySize == $lSizeFile);
|
|
|
|
if ($bCopy)
|
|
{
|
|
&log(WARN, "resumed backup file ${strDestinationFile} should have checksum ${strChecksum} but " .
|
|
"actually has checksum ${strCopyChecksum}. The file will be recopied and backup will " .
|
|
"continue but this may be an issue unless the backup temp path is known to be corrupted.");
|
|
}
|
|
}
|
|
|
|
if ($bCopy)
|
|
{
|
|
# Copy the file from the database to the backup (will return false if the source file is missing)
|
|
($bCopyResult, $strCopyChecksum, $lCopySize) =
|
|
$oFile->copy(PATH_DB_ABSOLUTE, $strSourceFile,
|
|
PATH_BACKUP_TMP, $strDestinationFile .
|
|
($bDestinationCompress ? '.' . $oFile->{strCompressExtension} : ''),
|
|
false, # Source is not compressed since it is the db directory
|
|
$bDestinationCompress, # Destination should be compressed based on backup settings
|
|
true, # Ignore missing files
|
|
$lModificationTime, # Set modification time - this is required for resume
|
|
undef, # Do not set original mode
|
|
true); # Create the destination directory if it does not exist
|
|
|
|
if (!$bCopyResult)
|
|
{
|
|
# If file is missing assume the database removed it (else corruption and nothing we can do!)
|
|
&log(INFO, "skip file removed by database: " . $strSourceFile);
|
|
|
|
return false, $lSizeCurrent, undef, undef;
|
|
}
|
|
}
|
|
|
|
# Ouput log
|
|
&log(INFO, (defined($strChecksum) && !$bCopy ? 'checksum resumed file' : 'backup file') .
|
|
" $strSourceFile (" . file_size_format($lCopySize) .
|
|
($lSizeTotal > 0 ? ', ' . int($lSizeCurrent * 100 / $lSizeTotal) . '%' : '') . ')' .
|
|
($lCopySize != 0 ? " checksum ${strCopyChecksum}" : ''));
|
|
|
|
return true, $lSizeCurrent, $lCopySize, $strCopyChecksum;
|
|
}
|
|
|
|
our @EXPORT = qw(backupFile);
|
|
|
|
####################################################################################################################################
|
|
# backupManifestUpdate
|
|
####################################################################################################################################
|
|
sub backupManifestUpdate
|
|
{
|
|
my $oManifest = shift;
|
|
my $strSection = shift;
|
|
my $strFile = shift;
|
|
my $bCopied = shift;
|
|
my $lSize = shift;
|
|
my $strChecksum = shift;
|
|
my $lManifestSaveSize = shift;
|
|
my $lManifestSaveCurrent = shift;
|
|
|
|
# If copy was successful store the checksum and size
|
|
if ($bCopied)
|
|
{
|
|
$oManifest->set($strSection, $strFile, MANIFEST_SUBKEY_SIZE, $lSize + 0);
|
|
|
|
if ($lSize > 0)
|
|
{
|
|
$oManifest->set($strSection, $strFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksum);
|
|
}
|
|
|
|
# Determine whether to save the manifest
|
|
$lManifestSaveCurrent += $lSize;
|
|
|
|
if ($lManifestSaveCurrent >= $lManifestSaveSize)
|
|
{
|
|
$oManifest->save();
|
|
&log(DEBUG, 'manifest saved');
|
|
|
|
$lManifestSaveCurrent = 0;
|
|
}
|
|
}
|
|
# Else the file was removed during backup so remove from manifest
|
|
else
|
|
{
|
|
$oManifest->remove($strSection, $strFile);
|
|
}
|
|
|
|
return $lManifestSaveCurrent;
|
|
}
|
|
|
|
push @EXPORT, qw(backupManifestUpdate);
|
|
|
|
1;
|