1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/lib/pgBackRest/BackupFile.pm

227 lines
9.1 KiB
Perl
Raw Normal View History

####################################################################################################################################
# BACKUP FILE MODULE
####################################################################################################################################
New simpler configuration and consistent project/exe/path naming. * The repo-path option now always refers to the repository where backups and archive are stored, whether local or remote, so the repo-remote-path option has been removed. The new spool-path option can be used to define a location for queueing WAL segments when archiving asynchronously. Otherwise, a local repository is no longer required. * Implemented a new config format which should be far simpler to use. See the User Guide and Configuration Reference for details but for a simple configuration all options can now be placed in the stanza section. Options that are shared between stanzas can be placed in the [global] section. More complex configurations can still make use of command sections though this should be a rare use case. * The default configuration filename is now pgbackrest.conf instead of pg_backrest.conf. This was done for consistency with other naming changes but also to prevent old config files from being loaded accidentally. * The default repository name was changed from /var/lib/backup to /var/lib/pgbackrest. * Lock files are now stored in /tmp/pgbackrest by default. These days /run/pgbackrest would be the preferred location but that would require init scripts which are not part of this release. The lock-path option can be used to configure the lock directory. * Log files are now stored in /var/log/pgbackrest by default and no longer have the date appended so they can be managed with logrotate. The log-path option can be used to configure the lock directory. * Executable filename changed from pg_backrest to pgbackrest.
2016-04-14 15:30:54 +02:00
package pgBackRest::BackupFile;
use threads;
use Thread::Queue;
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use lib dirname($0);
New simpler configuration and consistent project/exe/path naming. * The repo-path option now always refers to the repository where backups and archive are stored, whether local or remote, so the repo-remote-path option has been removed. The new spool-path option can be used to define a location for queueing WAL segments when archiving asynchronously. Otherwise, a local repository is no longer required. * Implemented a new config format which should be far simpler to use. See the User Guide and Configuration Reference for details but for a simple configuration all options can now be placed in the stanza section. Options that are shared between stanzas can be placed in the [global] section. More complex configurations can still make use of command sections though this should be a rare use case. * The default configuration filename is now pgbackrest.conf instead of pg_backrest.conf. This was done for consistency with other naming changes but also to prevent old config files from being loaded accidentally. * The default repository name was changed from /var/lib/backup to /var/lib/pgbackrest. * Lock files are now stored in /tmp/pgbackrest by default. These days /run/pgbackrest would be the preferred location but that would require init scripts which are not part of this release. The lock-path option can be used to configure the lock directory. * Log files are now stored in /var/log/pgbackrest by default and no longer have the date appended so they can be managed with logrotate. The log-path option can be used to configure the lock directory. * Executable filename changed from pg_backrest to pgbackrest.
2016-04-14 15:30:54 +02:00
use pgBackRest::Common::Exception;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::File;
use pgBackRest::FileCommon;
New simpler configuration and consistent project/exe/path naming. * The repo-path option now always refers to the repository where backups and archive are stored, whether local or remote, so the repo-remote-path option has been removed. The new spool-path option can be used to define a location for queueing WAL segments when archiving asynchronously. Otherwise, a local repository is no longer required. * Implemented a new config format which should be far simpler to use. See the User Guide and Configuration Reference for details but for a simple configuration all options can now be placed in the stanza section. Options that are shared between stanzas can be placed in the [global] section. More complex configurations can still make use of command sections though this should be a rare use case. * The default configuration filename is now pgbackrest.conf instead of pg_backrest.conf. This was done for consistency with other naming changes but also to prevent old config files from being loaded accidentally. * The default repository name was changed from /var/lib/backup to /var/lib/pgbackrest. * Lock files are now stored in /tmp/pgbackrest by default. These days /run/pgbackrest would be the preferred location but that would require init scripts which are not part of this release. The lock-path option can be used to configure the lock directory. * Log files are now stored in /var/log/pgbackrest by default and no longer have the date appended so they can be managed with logrotate. The log-path option can be used to configure the lock directory. * Executable filename changed from pg_backrest to pgbackrest.
2016-04-14 15:30:54 +02:00
use pgBackRest::Manifest;
####################################################################################################################################
# Operation constants
####################################################################################################################################
use constant OP_BACKUP_FILE => 'BackupFile';
use constant OP_BACKUP_FILE_BACKUP_FILE => OP_BACKUP_FILE . '::backupFile';
use constant OP_BACKUP_FILE_BACKUP_MANIFEST_UPDATE => OP_BACKUP_FILE . '::backupManifestUpdate';
####################################################################################################################################
# backupFile
####################################################################################################################################
sub backupFile
{
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oFile, # File object
$strDbFile, # Database file to backup
$strRepoFile, # Location in the repository to copy to
$bDestinationCompress, # Compress destination file
$strChecksum, # File checksum to be checked
$lModificationTime, # File modification time
$lSizeFile, # File size
$lSizeTotal, # Total size of the files to be copied
$lSizeCurrent, # Size of files copied so far
) =
logDebugParam
(
OP_BACKUP_FILE_BACKUP_FILE, \@_,
{name => 'oFile', trace => true},
{name => 'strDbFile', trace => true},
{name => 'strRepoFile', trace => true},
{name => 'bDestinationCompress', trace => true},
{name => 'strChecksum', required => false, trace => true},
{name => 'lModificationTime', trace => true},
{name => 'lSizeFile', trace => true},
{name => 'lSizeTotal', default => 0, trace => true},
{name => 'lSizeCurrent', required => false, trace => true}
);
my $bCopyResult = true; # Copy result
my $strCopyChecksum; # Copy checksum
my $lCopySize; # Copy Size
my $lRepoSize; # Repo 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;
# Add compression suffix if needed
my $strFileOp = $strRepoFile . ($bDestinationCompress ? '.' . $oFile->{strCompressExtension} : '');
if (defined($strChecksum))
{
($strCopyChecksum, $lCopySize) =
$oFile->hashSize(PATH_BACKUP_TMP, $strFileOp, $bDestinationCompress);
$bCopy = !($strCopyChecksum eq $strChecksum && $lCopySize == $lSizeFile);
if ($bCopy)
{
&log(WARN, "resumed backup file ${strRepoFile} 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, $strDbFile,
PATH_BACKUP_TMP, $strFileOp,
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 source file is missing then assume the database removed it (else corruption and nothing we can do!)
if (!$bCopyResult)
{
&log(DETAIL, "skip file removed by database: " . $strDbFile);
}
}
# If file was copied or checksum'd then get size in repo. This has to be checked after the file is at rest because filesystem
# compression may affect the actual repo size and this cannot be calculated in stream.
if ($bCopyResult)
{
$lRepoSize = (fileStat($oFile->pathGet(PATH_BACKUP_TMP, $strFileOp)))->size;
}
# Ouput log
if ($bCopyResult)
{
&log($bCopy ? INFO : DETAIL,
(defined($strChecksum) && !$bCopy ? 'checksum resumed file' : 'backup file') .
" ${strDbFile} (" . fileSizeFormat($lCopySize) .
($lSizeTotal > 0 ? ', ' . int($lSizeCurrent * 100 / $lSizeTotal) . '%' : '') . ')' .
($lCopySize != 0 ? " checksum ${strCopyChecksum}" : ''));
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'bCopyResult', value => $bCopyResult, trace => true},
{name => 'lSizeCurrent', value => $lSizeCurrent, trace => true},
{name => 'lCopySize', value => $lCopySize, trace => true},
{name => 'lRepoSize', value => $lRepoSize, trace => true},
{name => 'strCopyChecksum', value => $strCopyChecksum, trace => true}
);
}
push @EXPORT, qw(backupFile);
####################################################################################################################################
# backupManifestUpdate
####################################################################################################################################
sub backupManifestUpdate
{
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oManifest,
$strFile,
$bCopied,
$lSize,
$lRepoSize,
$strChecksum,
$lManifestSaveSize,
$lManifestSaveCurrent
) =
logDebugParam
(
OP_BACKUP_FILE_BACKUP_MANIFEST_UPDATE, \@_,
{name => 'oManifest', trace => true},
{name => 'strFile', trace => true},
{name => 'bCopied', trace => true},
{name => 'lSize', required => false, trace => true},
{name => 'lRepoSize', required => false, trace => true},
{name => 'strChecksum', required => false, trace => true},
{name => 'lManifestSaveSize', required => false, trace => true},
{name => 'lManifestSaveCurrent', required => false, trace => true}
);
# If copy was successful store the checksum and size
if ($bCopied)
{
$oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_SIZE, $lSize);
if ($lRepoSize != $lSize)
{
$oManifest->numericSet(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_REPO_SIZE, $lRepoSize);
}
if ($lSize > 0)
{
$oManifest->set(MANIFEST_SECTION_TARGET_FILE, $strFile, MANIFEST_SUBKEY_CHECKSUM, $strChecksum);
}
# Determine whether to save the manifest
if (defined($lManifestSaveSize))
{
$lManifestSaveCurrent += $lSize;
if ($lManifestSaveCurrent >= $lManifestSaveSize)
{
$oManifest->save();
logDebugMisc
(
$strOperation, 'save manifest',
{name => 'lManifestSaveSize', value => $lManifestSaveSize},
{name => 'lManifestSaveCurrent', value => $lManifestSaveCurrent}
);
$lManifestSaveCurrent = 0;
}
}
}
# Else the file was removed during backup so remove from manifest
else
{
$oManifest->remove(MANIFEST_SECTION_TARGET_FILE, $strFile);
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'lManifestSaveCurrent', value => $lManifestSaveCurrent, trace => true}
);
}
push @EXPORT, qw(backupManifestUpdate);
1;