You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-09-16 09:06:18 +02:00
Improved the code and tests for fileManifest().
Done to prevent a possible race condition when files are removed by the database while the manifest is being built.
This commit is contained in:
@@ -154,6 +154,14 @@
|
||||
|
||||
<release-list>
|
||||
<release date="XXXX-XX-XX" version="1.16dev" title="UNDER DEVELOPMENT">
|
||||
<release-core-list>
|
||||
<release-refactor-list>
|
||||
<release-item>
|
||||
<p>Improved the code and tests for <code>fileManifest()</code> to prevent a possible race condition when files are removed by the database while the manifest is being built.</p>
|
||||
</release-item>
|
||||
</release-refactor-list>
|
||||
</release-core-list>
|
||||
|
||||
<release-doc-list>
|
||||
<release-refactor-list>
|
||||
<release-item>
|
||||
|
@@ -392,9 +392,10 @@ sub fileManifestRecurse
|
||||
# Get a list of all files in the path (including .)
|
||||
my @stryFileList = fileList($strPathRead, undef, undef, $iDepth != 0);
|
||||
unshift(@stryFileList, '.');
|
||||
my $hFileStat = fileManifestList($strPathRead, \@stryFileList);
|
||||
|
||||
# Loop through all subpaths/files in the path
|
||||
foreach my $strFile (@stryFileList)
|
||||
foreach my $strFile (keys(%{$hFileStat}))
|
||||
{
|
||||
# Skip this file if it does not match the filter
|
||||
if (defined($strFilter) && $strFile ne $strFilter)
|
||||
@@ -402,29 +403,13 @@ sub fileManifestRecurse
|
||||
next;
|
||||
}
|
||||
|
||||
my $strPathFile = "${strPathRead}/$strFile";
|
||||
my $bCurrentDir = $strFile eq '.';
|
||||
|
||||
# Create the file and path names
|
||||
if ($iDepth != 0)
|
||||
{
|
||||
if ($bCurrentDir)
|
||||
{
|
||||
$strFile = $strSubPath;
|
||||
$strPathFile = $strPathRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
$strFile = "${strSubPath}/${strFile}";
|
||||
}
|
||||
}
|
||||
|
||||
$hManifest->{$strFile} = fileManifestStat($strPathFile);
|
||||
my $strManifestFile = $iDepth == 0 ? $strFile : ($strSubPath . ($strFile eq qw(.) ? '' : "/${strFile}"));
|
||||
$hManifest->{$strManifestFile} = $hFileStat->{$strFile};
|
||||
|
||||
# Recurse into directories
|
||||
if ($hManifest->{$strFile}{type} eq 'd' && !$bCurrentDir)
|
||||
if ($hManifest->{$strManifestFile}{type} eq 'd' && $strFile ne qw(.))
|
||||
{
|
||||
fileManifestRecurse($strPath, $strFile, $iDepth + 1, $hManifest);
|
||||
fileManifestRecurse($strPath, $strManifestFile, $iDepth + 1, $hManifest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,6 +417,42 @@ sub fileManifestRecurse
|
||||
return logDebugReturn($strOperation);
|
||||
}
|
||||
|
||||
sub fileManifestList
|
||||
{
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
my
|
||||
(
|
||||
$strOperation,
|
||||
$strPath,
|
||||
$stryFile,
|
||||
) =
|
||||
logDebugParam
|
||||
(
|
||||
__PACKAGE__ . '::fileManifestList', \@_,
|
||||
{name => 'strPath', trace => true},
|
||||
{name => 'stryFile', trace => true},
|
||||
);
|
||||
|
||||
my $hFileStat = {};
|
||||
|
||||
foreach my $strFile (@{$stryFile})
|
||||
{
|
||||
$hFileStat->{$strFile} = fileManifestStat("${strPath}" . ($strFile eq qw(.) ? '' : "/${strFile}"));
|
||||
|
||||
if (!defined($hFileStat->{$strFile}))
|
||||
{
|
||||
delete($hFileStat->{$strFile});
|
||||
}
|
||||
}
|
||||
|
||||
# Return from function and log return values if any
|
||||
return logDebugReturn
|
||||
(
|
||||
$strOperation,
|
||||
{name => 'hFileStat', value => $hFileStat, trace => true}
|
||||
);
|
||||
}
|
||||
|
||||
sub fileManifestStat
|
||||
{
|
||||
# Assign function parameters, defaults, and log debug info
|
||||
|
@@ -35,7 +35,7 @@ use constant BACKREST_BIN => abs_path(
|
||||
# Defines the current version of the BackRest executable. The version number is used to track features but does not affect what
|
||||
# repositories or manifests can be read - that's the job of the format number.
|
||||
#-----------------------------------------------------------------------------------------------------------------------------------
|
||||
use constant BACKREST_VERSION => '1.15';
|
||||
use constant BACKREST_VERSION => '1.16dev';
|
||||
push @EXPORT, qw(BACKREST_VERSION);
|
||||
|
||||
# Format Format Number
|
||||
|
@@ -11,7 +11,7 @@ use AutoLoader;
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
# Library version (add .999 during development)
|
||||
our $VERSION = '1.15';
|
||||
our $VERSION = '1.16.999';
|
||||
|
||||
sub libCVersion {return $VERSION};
|
||||
|
||||
|
@@ -164,7 +164,7 @@ my $oTestDef =
|
||||
},
|
||||
{
|
||||
&TESTDEF_TEST_NAME => 'manifest',
|
||||
&TESTDEF_TEST_TOTAL => 4,
|
||||
&TESTDEF_TEST_TOTAL => 5,
|
||||
&TESTDEF_TEST_INDIVIDUAL => false,
|
||||
},
|
||||
{
|
||||
|
@@ -83,6 +83,18 @@ sub run
|
||||
'stat link');
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("FileCommon::fileManifestList()"))
|
||||
{
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
my @stryFile = ('.', 'test.txt');
|
||||
|
||||
$self->testResult(
|
||||
sub {pgBackRest::FileCommon::fileManifestList($self->testPath(), \@stryFile)},
|
||||
'{. => {group => ' . $self->group() . ', mode => 0770, type => d, user => ' . $self->pgUser() . '}}',
|
||||
'skip missing file');
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("FileCommon::fileManifestRecurse()"))
|
||||
{
|
||||
|
Reference in New Issue
Block a user