mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-16 10:20:02 +02:00
152 lines
4.7 KiB
Perl
152 lines
4.7 KiB
Perl
|
####################################################################################################################################
|
||
|
# Protocol File
|
||
|
####################################################################################################################################
|
||
|
package pgBackRest::Protocol::Storage::File;
|
||
|
use parent 'pgBackRest::Common::Io::Base';
|
||
|
|
||
|
use strict;
|
||
|
use warnings FATAL => qw(all);
|
||
|
use Carp qw(confess);
|
||
|
use English '-no_match_vars';
|
||
|
|
||
|
use Exporter qw(import);
|
||
|
our @EXPORT = qw();
|
||
|
|
||
|
use pgBackRest::Common::Exception;
|
||
|
use pgBackRest::Common::Log;
|
||
|
|
||
|
####################################################################################################################################
|
||
|
# CONSTRUCTOR
|
||
|
####################################################################################################################################
|
||
|
sub new
|
||
|
{
|
||
|
my $class = shift;
|
||
|
|
||
|
# Assign function parameters, defaults, and log debug info
|
||
|
my
|
||
|
(
|
||
|
$strOperation,
|
||
|
$oProtocol, # Master or minion protocol
|
||
|
$oFileIo, # File whose results will be returned via protocol
|
||
|
) =
|
||
|
logDebugParam
|
||
|
(
|
||
|
__PACKAGE__ . '->new', \@_,
|
||
|
{name => 'oProtocol', trace => true},
|
||
|
{name => 'oFileIo', required => false, trace => true},
|
||
|
);
|
||
|
|
||
|
# Create class
|
||
|
my $self = $class->SUPER::new($oProtocol->io()->id() . ' file');
|
||
|
bless $self, $class;
|
||
|
|
||
|
# Set variables
|
||
|
$self->{oProtocol} = $oProtocol;
|
||
|
$self->{oFileIo} = $oFileIo;
|
||
|
|
||
|
# Set read/write
|
||
|
$self->{bWrite} = false;
|
||
|
|
||
|
# Return from function and log return values if any
|
||
|
return logDebugReturn
|
||
|
(
|
||
|
$strOperation,
|
||
|
{name => 'self', value => $self}
|
||
|
);
|
||
|
}
|
||
|
|
||
|
####################################################################################################################################
|
||
|
# read - read block from protocol
|
||
|
####################################################################################################################################
|
||
|
sub read
|
||
|
{
|
||
|
my $self = shift;
|
||
|
my $rtBuffer = shift;
|
||
|
|
||
|
my $lBlockSize;
|
||
|
|
||
|
# Read the block header and make sure it's valid
|
||
|
my $strBlockHeader = $self->{oProtocol}->io()->readLine();
|
||
|
|
||
|
if ($strBlockHeader !~ /^BRBLOCK[0-9]+$/)
|
||
|
{
|
||
|
confess &log(ERROR, "invalid block header '${strBlockHeader}'", ERROR_FILE_READ);
|
||
|
}
|
||
|
|
||
|
# Get block size from the header
|
||
|
$lBlockSize = substr($strBlockHeader, 7);
|
||
|
|
||
|
# Read block if size > 0
|
||
|
if ($lBlockSize > 0)
|
||
|
{
|
||
|
$self->{oProtocol}->io()->read($rtBuffer, $lBlockSize, true);
|
||
|
}
|
||
|
|
||
|
# Return the block size
|
||
|
return $lBlockSize;
|
||
|
}
|
||
|
|
||
|
####################################################################################################################################
|
||
|
# write - write block to protocol
|
||
|
####################################################################################################################################
|
||
|
sub write
|
||
|
{
|
||
|
my $self = shift;
|
||
|
my $rtBuffer = shift;
|
||
|
|
||
|
# Set write
|
||
|
$self->{bWrite} = true;
|
||
|
|
||
|
# Get the buffer size
|
||
|
my $lBlockSize = defined($rtBuffer) ? length($$rtBuffer) : 0;
|
||
|
|
||
|
# Write if size > 0 (0 ends the copy stream so it should only be done in close())
|
||
|
if ($lBlockSize > 0)
|
||
|
{
|
||
|
# Write block header to the protocol stream
|
||
|
$self->{oProtocol}->io()->writeLine("BRBLOCK${lBlockSize}");
|
||
|
|
||
|
# Write block if size
|
||
|
$self->{oProtocol}->io()->write($rtBuffer);
|
||
|
}
|
||
|
|
||
|
return length($$rtBuffer);
|
||
|
}
|
||
|
|
||
|
####################################################################################################################################
|
||
|
# close - set the result hash
|
||
|
####################################################################################################################################
|
||
|
sub close
|
||
|
{
|
||
|
my $self = shift;
|
||
|
|
||
|
# Close if protocol is defined (to prevent this from running more than once)
|
||
|
if (defined($self->{oProtocol}))
|
||
|
{
|
||
|
# If writing output terminator
|
||
|
if ($self->{bWrite})
|
||
|
{
|
||
|
$self->{oProtocol}->io()->writeLine("BRBLOCK0");
|
||
|
}
|
||
|
|
||
|
# On master read the results
|
||
|
if ($self->{oProtocol}->master())
|
||
|
{
|
||
|
($self->{rhResult}) = $self->{oProtocol}->outputRead();
|
||
|
|
||
|
# Minion will send one more output message after file is closed which can be ignored
|
||
|
$self->{oProtocol}->outputRead();
|
||
|
}
|
||
|
# On minion write the results
|
||
|
else
|
||
|
{
|
||
|
$self->{oProtocol}->outputWrite($self->{oFileIo}->{rhResult});
|
||
|
}
|
||
|
|
||
|
# Delete protocol to prevent close from running again
|
||
|
delete($self->{oProtocol});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
1;
|