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.
135 lines
4.7 KiB
Perl
135 lines
4.7 KiB
Perl
####################################################################################################################################
|
|
# LOCK MODULE
|
|
####################################################################################################################################
|
|
package BackRest::Lock;
|
|
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
|
|
use Exporter qw(import);
|
|
use Fcntl qw(:DEFAULT :flock);
|
|
use File::Basename qw(dirname);
|
|
|
|
use lib dirname($0) . '/../lib';
|
|
use BackRest::Config;
|
|
use BackRest::Exception;
|
|
use BackRest::Utility;
|
|
|
|
####################################################################################################################################
|
|
# Exported Functions
|
|
####################################################################################################################################
|
|
our @EXPORT = qw(lockAcquire lockRelease);
|
|
|
|
####################################################################################################################################
|
|
# Global lock type and handle
|
|
####################################################################################################################################
|
|
my $strCurrentLockType;
|
|
my $strCurrentLockFile;
|
|
my $hCurrentLockHandle;
|
|
|
|
####################################################################################################################################
|
|
# lockPathName
|
|
#
|
|
# Get the base path where the lock file will be stored.
|
|
####################################################################################################################################
|
|
sub lockPathName
|
|
{
|
|
my $strRepoPath = shift;
|
|
|
|
return "${strRepoPath}/lock";
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# lockFileName
|
|
#
|
|
# Get the lock file name.
|
|
####################################################################################################################################
|
|
sub lockFileName
|
|
{
|
|
my $strLockType = shift;
|
|
my $strStanza = shift;
|
|
my $strRepoPath = shift;
|
|
|
|
return lockPathName($strRepoPath) . "/${strStanza}-${strLockType}.lock";
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# lockAcquire
|
|
#
|
|
# Attempt to acquire the specified lock. If the lock is taken by another process return false, else take the lock and return true.
|
|
####################################################################################################################################
|
|
sub lockAcquire
|
|
{
|
|
my $strLockType = shift;
|
|
my $bFailOnNoLock = shift;
|
|
|
|
# Cannot proceed if a lock is currently held
|
|
if (defined($strCurrentLockType))
|
|
{
|
|
confess &lock(ASSERT, "${strCurrentLockType} lock is already held");
|
|
}
|
|
|
|
# Create the lock path if it does not exist
|
|
if (! -e lockPathName(optionGet(OPTION_REPO_PATH)))
|
|
{
|
|
mkdir lockPathName(optionGet(OPTION_REPO_PATH))
|
|
or confess(ERROR, 'unable to create lock path ' . lockPathName(optionGet(OPTION_REPO_PATH)), ERROR_PATH_CREATE);
|
|
}
|
|
|
|
# Attempt to open the lock file
|
|
$strCurrentLockFile = lockFileName($strLockType, optionGet(OPTION_STANZA), optionGet(OPTION_REPO_PATH));
|
|
|
|
sysopen($hCurrentLockHandle, $strCurrentLockFile, O_WRONLY | O_CREAT)
|
|
or confess &log(ERROR, "unable to open lock file ${strCurrentLockFile}", ERROR_FILE_OPEN);
|
|
|
|
# Attempt to lock the lock file
|
|
if (!flock($hCurrentLockHandle, LOCK_EX | LOCK_NB))
|
|
{
|
|
close($hCurrentLockHandle);
|
|
|
|
if (!defined($bFailOnNoLock) || $bFailOnNoLock)
|
|
{
|
|
confess &log(ERROR, "unable to acquire ${strLockType} lock", ERROR_LOCK_ACQUIRE);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
# Set current lock type so we know we have a lock
|
|
$strCurrentLockType = $strLockType;
|
|
|
|
# Lock was successful
|
|
return true;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# lockRelease
|
|
####################################################################################################################################
|
|
sub lockRelease
|
|
{
|
|
my $strLockType = shift;
|
|
|
|
# Fail if there is no lock
|
|
if (!defined($strCurrentLockType))
|
|
{
|
|
confess &log(ASSERT, 'no lock is currently held');
|
|
}
|
|
|
|
# # Fail if the lock being released is not the one held
|
|
# if ($strLockType ne $strCurrentLockType)
|
|
# {
|
|
# confess &log(ASSERT, "cannot remove lock ${strLockType} since ${strCurrentLockType} is currently held");
|
|
# }
|
|
|
|
# Remove the file
|
|
unlink($strCurrentLockFile);
|
|
close($hCurrentLockHandle);
|
|
|
|
# Undef lock variables
|
|
undef($strCurrentLockType);
|
|
undef($hCurrentLockHandle);
|
|
}
|
|
|
|
1;
|