mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-16 10:20:02 +02:00
731b862e6f
This is consistent with the way BackRest and BackRest test were renamed way back in 18fd2523
.
More modules will be moving to pgBackRestDoc soon so renaming now reduces churn later.
210 lines
6.8 KiB
Perl
210 lines
6.8 KiB
Perl
####################################################################################################################################
|
|
# Posix File Write
|
|
####################################################################################################################################
|
|
package pgBackRestTest::Common::StoragePosixWrite;
|
|
use parent 'pgBackRestTest::Common::Io::Handle';
|
|
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
use English '-no_match_vars';
|
|
|
|
use Fcntl qw(O_RDONLY O_WRONLY O_CREAT O_TRUNC);
|
|
use File::Basename qw(dirname);
|
|
|
|
use pgBackRestDoc::Common::Exception;
|
|
use pgBackRestDoc::Common::Log;
|
|
|
|
use pgBackRestTest::Common::Io::Handle;
|
|
use pgBackRestTest::Common::StorageBase;
|
|
|
|
####################################################################################################################################
|
|
# CONSTRUCTOR
|
|
####################################################################################################################################
|
|
sub new
|
|
{
|
|
my $class = shift;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$oDriver,
|
|
$strName,
|
|
$strMode,
|
|
$strUser,
|
|
$strGroup,
|
|
$lTimestamp,
|
|
$bPathCreate,
|
|
$bAtomic,
|
|
$bSync,
|
|
) =
|
|
logDebugParam
|
|
(
|
|
__PACKAGE__ . '->new', \@_,
|
|
{name => 'oDriver', trace => true},
|
|
{name => 'strName', trace => true},
|
|
{name => 'strMode', optional => true, trace => true},
|
|
{name => 'strUser', optional => true, trace => true},
|
|
{name => 'strGroup', optional => true, trace => true},
|
|
{name => 'lTimestamp', optional => true, trace => true},
|
|
{name => 'bPathCreate', optional => true, default => false, trace => true},
|
|
{name => 'bAtomic', optional => true, default => false, trace => true},
|
|
{name => 'bSync', optional => true, default => true, trace => true},
|
|
);
|
|
|
|
# Create the class hash
|
|
my $self = $class->SUPER::new("'${strName}'");
|
|
bless $self, $class;
|
|
|
|
# Set variables
|
|
$self->{oDriver} = $oDriver;
|
|
$self->{strName} = $strName;
|
|
$self->{strMode} = $strMode;
|
|
$self->{strUser} = $strUser;
|
|
$self->{strGroup} = $strGroup;
|
|
$self->{lTimestamp} = $lTimestamp;
|
|
$self->{bPathCreate} = $bPathCreate;
|
|
$self->{bAtomic} = $bAtomic;
|
|
$self->{bSync} = $bSync;
|
|
|
|
# If atomic create temp filename
|
|
if ($self->{bAtomic})
|
|
{
|
|
# Create temp file name
|
|
$self->{strNameTmp} = "$self->{strName}." . $self->{oDriver}->tempExtension();
|
|
}
|
|
|
|
# Open file on first write to avoid creating extraneous files on error
|
|
$self->{bOpened} = false;
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'self', value => $self, trace => true}
|
|
);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# open - open the file
|
|
####################################################################################################################################
|
|
sub open
|
|
{
|
|
my $self = shift;
|
|
|
|
# Get the file name
|
|
my $strFile = $self->{bAtomic} ? $self->{strNameTmp} : $self->{strName};
|
|
|
|
# Open the file
|
|
if (!sysopen(
|
|
$self->{fhFile}, $strFile, O_WRONLY | O_CREAT | O_TRUNC, oct(defined($self->{strMode}) ? $self->{strMode} : '0666')))
|
|
{
|
|
# If the path does not exist create it if requested
|
|
if ($OS_ERROR{ENOENT} && $self->{bPathCreate})
|
|
{
|
|
$self->{oDriver}->pathCreate(dirname($strFile), {bIgnoreExists => true, bCreateParent => true});
|
|
$self->{bPathCreate} = false;
|
|
return $self->open();
|
|
}
|
|
|
|
logErrorResult($OS_ERROR{ENOENT} ? ERROR_PATH_MISSING : ERROR_FILE_OPEN, "unable to open '${strFile}'", $OS_ERROR);
|
|
}
|
|
|
|
# Set file mode to binary
|
|
binmode($self->{fhFile});
|
|
|
|
# Set the owner
|
|
$self->{oDriver}->owner($strFile, {strUser => $self->{strUser}, strGroup => $self->{strGroup}});
|
|
|
|
# Set handle
|
|
$self->handleWriteSet($self->{fhFile});
|
|
|
|
# Mark file as opened
|
|
$self->{bOpened} = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# write - write data to a file
|
|
####################################################################################################################################
|
|
sub write
|
|
{
|
|
my $self = shift;
|
|
my $rtBuffer = shift;
|
|
|
|
# Open file if it is not open already
|
|
$self->open() if !$self->opened();
|
|
|
|
return $self->SUPER::write($rtBuffer);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# close - close the file
|
|
####################################################################################################################################
|
|
sub close
|
|
{
|
|
my $self = shift;
|
|
|
|
if (defined($self->handle()))
|
|
{
|
|
# Sync the file
|
|
if ($self->{bSync})
|
|
{
|
|
$self->handle()->sync();
|
|
}
|
|
|
|
# Close the file
|
|
close($self->handle());
|
|
undef($self->{fhFile});
|
|
|
|
# Get current filename
|
|
my $strCurrentName = $self->{bAtomic} ? $self->{strNameTmp} : $self->{strName};
|
|
|
|
# Set the modification time
|
|
if (defined($self->{lTimestamp}))
|
|
{
|
|
utime(time(), $self->{lTimestamp}, $strCurrentName)
|
|
or logErrorResult(ERROR_FILE_WRITE, "unable to set time for '${strCurrentName}'", $OS_ERROR);
|
|
}
|
|
|
|
# Move the file from temp to final if atomic
|
|
if ($self->{bAtomic})
|
|
{
|
|
$self->{oDriver}->move($strCurrentName, $self->{strName});
|
|
}
|
|
|
|
# Set result
|
|
$self->resultSet(COMMON_IO_HANDLE, $self->{lSize});
|
|
|
|
# Close parent
|
|
$self->SUPER::close();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# Close the handle if it is open (in case close() was never called)
|
|
####################################################################################################################################
|
|
sub DESTROY
|
|
{
|
|
my $self = shift;
|
|
|
|
if (defined($self->handle()))
|
|
{
|
|
CORE::close($self->handle());
|
|
undef($self->{fhFile});
|
|
}
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# Getters
|
|
####################################################################################################################################
|
|
sub handle {shift->{fhFile}}
|
|
sub opened {shift->{bOpened}}
|
|
sub name {shift->{strName}}
|
|
|
|
1;
|