1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/lib/pgBackRest/Protocol/Storage/File.pm
David Steele de7fc37f88 Storage and IO layer refactor:
Refactor storage layer to allow for new repository filesystems using drivers. (Reviewed by Cynthia Shang.)
Refactor IO layer to allow for new compression formats, checksum types, and other capabilities using filters. (Reviewed by Cynthia Shang.)
2017-06-09 17:51:41 -04:00

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;