1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-16 10:20:02 +02:00
pgbackrest/lib/pgBackRest/Protocol/Storage/File.pm

152 lines
4.7 KiB
Perl
Raw Normal View History

####################################################################################################################################
# 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;