1
0
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:
David Steele
2017-02-21 11:56:55 -05:00
parent 01312f6260
commit 14ca4dac6f
6 changed files with 65 additions and 24 deletions

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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};

View File

@@ -164,7 +164,7 @@ my $oTestDef =
},
{
&TESTDEF_TEST_NAME => 'manifest',
&TESTDEF_TEST_TOTAL => 4,
&TESTDEF_TEST_TOTAL => 5,
&TESTDEF_TEST_INDIVIDUAL => false,
},
{

View File

@@ -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()"))
{