1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-05 00:28:52 +02:00

In-stream compression now working in copy.

This commit is contained in:
David Steele
2014-06-15 15:56:45 -04:00
parent f51c06119c
commit adf654edb3
4 changed files with 317 additions and 156 deletions

View File

@ -121,7 +121,7 @@ while ($strCommand ne OP_EXIT)
} }
} }
}; };
if ($@) if ($@)
{ {
$oRemote->error_write($@); $oRemote->error_write($@);

View File

@ -27,12 +27,12 @@ use BackRest::Remote;
use Exporter qw(import); use Exporter qw(import);
our @EXPORT = qw(PATH_ABSOLUTE PATH_DB PATH_DB_ABSOLUTE PATH_BACKUP PATH_BACKUP_ABSOLUTE our @EXPORT = qw(PATH_ABSOLUTE PATH_DB PATH_DB_ABSOLUTE PATH_BACKUP PATH_BACKUP_ABSOLUTE
PATH_BACKUP_CLUSTERPATH_BACKUP_TMP PATH_BACKUP_ARCHIVE PATH_BACKUP_CLUSTERPATH_BACKUP_TMP PATH_BACKUP_ARCHIVE
COMMAND_ERR_FILE_MISSING COMMAND_ERR_FILE_READ COMMAND_ERR_FILE_MOVE COMMAND_ERR_FILE_TYPE COMMAND_ERR_FILE_MISSING COMMAND_ERR_FILE_READ COMMAND_ERR_FILE_MOVE COMMAND_ERR_FILE_TYPE
COMMAND_ERR_LINK_READ COMMAND_ERR_PATH_MISSING COMMAND_ERR_PATH_CREATE COMMAND_ERR_PARAM COMMAND_ERR_LINK_READ COMMAND_ERR_PATH_MISSING COMMAND_ERR_PATH_CREATE COMMAND_ERR_PARAM
PIPE_STDIN PIPE_STDOUT PIPE_STDERR PIPE_STDIN PIPE_STDOUT PIPE_STDERR
OP_FILE_LIST OP_FILE_EXISTS OP_FILE_HASH OP_FILE_REMOVE OP_FILE_MANIFEST OP_FILE_COMPRESS OP_FILE_LIST OP_FILE_EXISTS OP_FILE_HASH OP_FILE_REMOVE OP_FILE_MANIFEST OP_FILE_COMPRESS
OP_FILE_MOVE OP_FILE_COPY_OUT OP_FILE_COPY_IN OP_FILE_PATH_CREATE); OP_FILE_MOVE OP_FILE_COPY_OUT OP_FILE_COPY_IN OP_FILE_PATH_CREATE);
@ -603,11 +603,11 @@ sub move
# { # {
# my $self = shift; # my $self = shift;
# my $hOut = shift; # my $hOut = shift;
# #
# my $strBuffer; # my $strBuffer;
# my $hString = IO::String->new($strBuffer); # my $hString = IO::String->new($strBuffer);
# $self->pipe($hOut, $hString); # $self->pipe($hOut, $hString);
# #
# return $strBuffer; # return $strBuffer;
# } # }
@ -623,7 +623,7 @@ sub move
# my $hOut = shift; # my $hOut = shift;
# my $bCompress = shift; # my $bCompress = shift;
# my $bUncompress = shift; # my $bUncompress = shift;
# #
# # If compression is requested and the file is not already compressed # # If compression is requested and the file is not already compressed
# if (defined($bCompress) && $bCompress) # if (defined($bCompress) && $bCompress)
# { # {
@ -646,7 +646,7 @@ sub move
# my $strBuffer; # my $strBuffer;
# my $iResultRead; # my $iResultRead;
# my $iResultWrite; # my $iResultWrite;
# #
# # Read from the input handle # # Read from the input handle
# while (($iResultRead = sysread($hIn, $strBuffer, BLOCK_SIZE)) != 0) # while (($iResultRead = sysread($hIn, $strBuffer, BLOCK_SIZE)) != 0)
# { # {
@ -659,7 +659,7 @@ sub move
# { # {
# # Write to the output handle # # Write to the output handle
# $iResultWrite = syswrite($hOut, $strBuffer, $iResultRead); # $iResultWrite = syswrite($hOut, $strBuffer, $iResultRead);
# #
# if (!defined($iResultWrite) || $iResultWrite != $iResultRead) # if (!defined($iResultWrite) || $iResultWrite != $iResultRead)
# { # {
# confess $!; # confess $!;
@ -681,17 +681,17 @@ sub move
# my $hIn = shift; # my $hIn = shift;
# my $hOut = shift; # my $hOut = shift;
# my $hErr = shift; # my $hErr = shift;
# #
# # Close hIn # # Close hIn
# close($hIn); # close($hIn);
# #
# # Read STDERR into a string # # Read STDERR into a string
# my $strError = defined($hErr) ? $self->pipe_to_string($hErr) : "[unknown]"; # my $strError = defined($hErr) ? $self->pipe_to_string($hErr) : "[unknown]";
# #
# # Wait for the process to finish and report any errors # # Wait for the process to finish and report any errors
# waitpid($pId, 0); # waitpid($pId, 0);
# my $iExitStatus = ${^CHILD_ERROR_NATIVE} >> 8; # my $iExitStatus = ${^CHILD_ERROR_NATIVE} >> 8;
# #
# if ($iExitStatus != 0) # if ($iExitStatus != 0)
# { # {
# confess &log(ERROR, "command '${strCommand}' returned " . $iExitStatus . ": " . # confess &log(ERROR, "command '${strCommand}' returned " . $iExitStatus . ": " .
@ -699,6 +699,72 @@ sub move
# } # }
# } # }
####################################################################################################################################
# EXISTS - Checks for the existence of a file, but does not imply that the file is readable/writeable.
#
# Return: true if file exists, false otherwise
####################################################################################################################################
sub exists
{
my $self = shift;
my $strPathType = shift;
my $strPath = shift;
# Set operation variables
my $strPathOp = $self->path_get($strPathType, $strPath);
# Set operation and debug strings
my $strOperation = OP_FILE_EXISTS;
my $strDebug = "${strPathType}:${strPathOp}";
# Run remotely
if ($self->is_remote($strPathType))
{
# Build param hash
my %oParamHash;
$oParamHash{path} = ${strPathOp};
# Build debug string
$strDebug = "${strOperation}: remote (" . $self->{oRemote}->command_param_string(\%oParamHash) . "): " . $strDebug;
&log(DEBUG, $strDebug);
# Execute the command
return $self->{oRemote}->command_execute($strOperation, \%oParamHash, true, $strDebug) eq "Y";
}
# Run locally
else
{
# Build debug string
$strDebug = "${strOperation}: local: " . $strDebug;
&log(DEBUG, ${strDebug});
# Stat the file/path to determine if it exists
my $oStat = lstat($strPathOp);
# Evaluate error
if (!defined($oStat))
{
# If the error is not entry missing, then throw error
if (!$!{ENOENT})
{
if ($strPathType eq PATH_ABSOLUTE)
{
confess &log(ERROR, $!, COMMAND_ERR_FILE_READ);
}
else
{
confess &log(ERROR, "${strDebug}: " . $!, COMMAND_ERR_FILE_READ);
}
}
return false;
}
}
return true;
}
#################################################################################################################################### ####################################################################################################################################
# COPY # COPY
# #
@ -724,12 +790,12 @@ sub copy
my $strPermission = shift; my $strPermission = shift;
# Set defaults # Set defaults
my $bIsCompressed = false;
$bCompress = defined($bCompress) ? $bCompress : defined($self->{bCompress}) ? $self->{bCompress} : true; $bCompress = defined($bCompress) ? $bCompress : defined($self->{bCompress}) ? $self->{bCompress} : true;
$bIgnoreMissingSource = defined($bIgnoreMissingSource) ? $bIgnoreMissingSource : false; $bIgnoreMissingSource = defined($bIgnoreMissingSource) ? $bIgnoreMissingSource : false;
$bPathCreate = defined($bPathCreate) ? $bPathCreate : false; $bPathCreate = defined($bPathCreate) ? $bPathCreate : false;
# Set working variables # Set working variables
my $strErrorPrefix = "File->copy";
my $bSourceRemote = $self->is_remote($strSourcePathType) || $strSourcePathType eq PIPE_STDIN; my $bSourceRemote = $self->is_remote($strSourcePathType) || $strSourcePathType eq PIPE_STDIN;
my $bDestinationRemote = $self->is_remote($strDestinationPathType) || $strDestinationPathType eq PIPE_STDOUT; my $bDestinationRemote = $self->is_remote($strDestinationPathType) || $strDestinationPathType eq PIPE_STDOUT;
my $strSourceOp = $strSourcePathType eq PIPE_STDIN ? my $strSourceOp = $strSourcePathType eq PIPE_STDIN ?
@ -739,22 +805,22 @@ sub copy
my $strDestinationTmpOp = $strDestinationPathType eq PIPE_STDOUT ? my $strDestinationTmpOp = $strDestinationPathType eq PIPE_STDOUT ?
undef : $self->path_get($strDestinationPathType, $strDestinationFile, true); undef : $self->path_get($strDestinationPathType, $strDestinationFile, true);
# Determine if the file needs compression extension # Set operation and debug string
if ($bCompress && $strDestinationOp !~ "^.*\.$self->{strCompressExtension}\$") my $strOperation = "File->unknown";
{ my $strDebug = ($bSourceRemote ? " remote" : " local") . " ${strSourcePathType}" .
$strDestinationOp .= "." . $self->{strCompressExtension}; (defined($strSourceFile) ? ":${strSourceFile}" : "") .
} " to" . ($bDestinationRemote ? " remote" : " local") . " ${strDestinationPathType}" .
(defined($strDestinationFile) ? ":${strDestinationFile}" : "") .
# Output trace info ", compress = " . ($bCompress ? "true" : "false");
# &log(TRACE, "${strErrorPrefix}:" . ($bSourceRemote ? " remote" : " local") . " ${strSourcePathType}:${strSourceFile}" .
# " to" . ($bDestinationRemote ? " remote" : " local") . " ${strDestinationPathType}:${strDestinationFile}" .
# ", compress = " . ($bCompress ? "true" : "false"));
# Open the source file # Open the source file
my $hSourceFile; my $hSourceFile;
if (!$bSourceRemote) if (!$bSourceRemote)
{ {
# Determine if the file is compressed
$bIsCompressed = $strSourceOp !~ "^.*\.$self->{strCompressExtension}\$";
open($hSourceFile, "<", $strSourceOp) open($hSourceFile, "<", $strSourceOp)
or confess &log(ERROR, "cannot open ${strSourceOp}: " . $!); or confess &log(ERROR, "cannot open ${strSourceOp}: " . $!);
} }
@ -764,17 +830,21 @@ sub copy
if (!$bDestinationRemote) if (!$bDestinationRemote)
{ {
# Determine if the file needs compression extension
if ($bCompress && $strDestinationOp !~ "^.*\.$self->{strCompressExtension}\$")
{
$strDestinationOp .= "." . $self->{strCompressExtension};
}
open($hDestinationFile, ">", $strDestinationTmpOp) open($hDestinationFile, ">", $strDestinationTmpOp)
or confess &log(ERROR, "cannot open ${strDestinationTmpOp}: " . $!); or confess &log(ERROR, "cannot open ${strDestinationTmpOp}: " . $!);
} }
# If source or destination are remote # If source or destination are remote
if ($bSourceRemote || $bDestinationRemote) if ($bSourceRemote || $bDestinationRemote)
{ {
# print "got outside\n";
# Build the command and open the local file # Build the command and open the local file
my $hFile; my $hFile;
my $strOperation;
my %oParamHash; my %oParamHash;
my $hIn, my $hIn,
my $hOut; my $hOut;
@ -784,17 +854,26 @@ sub copy
if ($bSourceRemote && !$bDestinationRemote) if ($bSourceRemote && !$bDestinationRemote)
{ {
$hOut = $hDestinationFile; $hOut = $hDestinationFile;
$strOperation = OP_FILE_COPY_OUT;
$bCompress = $bCompress ? undef : $bCompress;
if ($strSourcePathType eq PIPE_STDIN) if ($strSourcePathType eq PIPE_STDIN)
{ {
$strRemote = 'in'; $strRemote = 'in';
$hIn = *STDIN; $hIn = *STDIN;
} }
else else
{ {
$strRemote = 'in'; $strRemote = 'in';
$strOperation = OP_FILE_COPY_OUT;
$oParamHash{source_file} = ${strSourceOp}; $oParamHash{source_file} = ${strSourceOp};
if (defined($bCompress))
{
$oParamHash{compress} = $bCompress;
}
$hIn = $self->{oRemote}->{hOut}; $hIn = $self->{oRemote}->{hOut};
} }
} }
@ -802,7 +881,8 @@ sub copy
elsif (!$bSourceRemote && $bDestinationRemote) elsif (!$bSourceRemote && $bDestinationRemote)
{ {
$hIn = $hSourceFile; $hIn = $hSourceFile;
$strOperation = OP_FILE_COPY_IN;
if ($strDestinationPathType eq PIPE_STDOUT) if ($strDestinationPathType eq PIPE_STDOUT)
{ {
$strRemote = 'out'; $strRemote = 'out';
@ -811,14 +891,19 @@ sub copy
else else
{ {
$strRemote = 'out'; $strRemote = 'out';
$strOperation = OP_FILE_COPY_IN;
$oParamHash{destination_file} = ${strDestinationOp}; $oParamHash{destination_file} = ${strDestinationOp};
$bCompress = $bCompress ? undef : $bCompress;
if (defined($bCompress))
{
$oParamHash{compress} = $bCompress;
}
$hOut = $self->{oRemote}->{hIn}; $hOut = $self->{oRemote}->{hIn};
} }
# Build debug string $bCompress = true;
# $strDebug = "${strOperation}: remote (" . $self->{oRemote}->command_param_string(\%oParamHash) . "): " . $strDebug;
# &log(DEBUG, $strDebug);
} }
# Else source and destination are remote # Else source and destination are remote
else else
@ -832,28 +917,25 @@ sub copy
return false; return false;
} }
# If an operation is defined then write it # Build debug string
if (defined($strOperation)) $strDebug = "${strOperation}: " . (%oParamHash ? "remote (" .
{ $self->{oRemote}->command_param_string(\%oParamHash) . ") :" : "") . $strDebug;
# Trace command &log(DEBUG, $strDebug);
&log(TRACE, "${strErrorPrefix} operation:" . $strOperation);
# Execute the operation # If an operation is defined then write it
if (%oParamHash)
{
$self->{oRemote}->command_write($strOperation, \%oParamHash); $self->{oRemote}->command_write($strOperation, \%oParamHash);
} }
# Transfer the file
# print "binary xfer start\n";
$self->{oRemote}->binary_xfer($hIn, $hOut, $strRemote);
# print "binary xfer stop\n";
if ($strSourcePathType ne PIPE_STDIN && $strDestinationPathType ne PIPE_STDOUT) # Transfer the file
$self->{oRemote}->binary_xfer($hIn, $hOut, $strRemote, $bCompress);
# If this is the controlling process then wait for OK from remote
if (%oParamHash)
{ {
$self->{oRemote}->output_read(false, $strErrorPrefix); $self->{oRemote}->output_read(false, $strDebug);
} }
# Wait for process exit (and error)
# $self->wait_pid($pId, $strCommand, $hIn, $hOut, $hErr);
} }
else else
{ {
@ -890,7 +972,6 @@ sub copy
or confess &log(ERROR, "unable to set time for local ${strDestinationTmpOp}"); or confess &log(ERROR, "unable to set time for local ${strDestinationTmpOp}");
} }
# Move the file from tmp to final destination # Move the file from tmp to final destination
$self->move(PATH_ABSOLUTE, $strDestinationTmpOp, PATH_ABSOLUTE, $strDestinationOp, $bPathCreate); $self->move(PATH_ABSOLUTE, $strDestinationTmpOp, PATH_ABSOLUTE, $strDestinationOp, $bPathCreate);
} }
@ -1114,72 +1195,6 @@ sub list
return @stryFileList; return @stryFileList;
} }
####################################################################################################################################
# EXISTS - Checks for the existence of a file, but does not imply that the file is readable/writeable.
#
# Return: true if file exists, false otherwise
####################################################################################################################################
sub exists
{
my $self = shift;
my $strPathType = shift;
my $strPath = shift;
# Set operation variables
my $strPathOp = $self->path_get($strPathType, $strPath);
# Set operation and debug strings
my $strOperation = OP_FILE_EXISTS;
my $strDebug = "${strPathType}:${strPathOp}";
# Run remotely
if ($self->is_remote($strPathType))
{
# Build param hash
my %oParamHash;
$oParamHash{path} = ${strPathOp};
# Build debug string
$strDebug = "${strOperation}: remote (" . $self->{oRemote}->command_param_string(\%oParamHash) . "): " . $strDebug;
&log(DEBUG, $strDebug);
# Execute the command
return $self->{oRemote}->command_execute($strOperation, \%oParamHash, true, $strDebug) eq "Y";
}
# Run locally
else
{
# Build debug string
$strDebug = "${strOperation}: local: " . $strDebug;
&log(DEBUG, ${strDebug});
# Stat the file/path to determine if it exists
my $oStat = lstat($strPathOp);
# Evaluate error
if (!defined($oStat))
{
# If the error is not entry missing, then throw error
if (!$!{ENOENT})
{
if ($strPathType eq PATH_ABSOLUTE)
{
confess &log(ERROR, $!, COMMAND_ERR_FILE_READ);
}
else
{
confess &log(ERROR, "${strDebug}: " . $!, COMMAND_ERR_FILE_READ);
}
}
return false;
}
}
return true;
}
#################################################################################################################################### ####################################################################################################################################
# REMOVE # REMOVE
#################################################################################################################################### ####################################################################################################################################

View File

@ -12,7 +12,9 @@ use Moose;
use Net::OpenSSH; use Net::OpenSSH;
use File::Basename; use File::Basename;
use POSIX ":sys_wait_h"; use POSIX ":sys_wait_h";
use IO::Compress::Gzip qw(gzip $GzipError);
use IO::Uncompress::Gunzip qw(gunzip $GunzipError);
use lib dirname($0) . "/../lib"; use lib dirname($0) . "/../lib";
use BackRest::Exception; use BackRest::Exception;
use BackRest::Utility; use BackRest::Utility;
@ -22,7 +24,7 @@ use BackRest::Utility;
#################################################################################################################################### ####################################################################################################################################
use constant use constant
{ {
DEFAULT_BLOCK_SIZE => 8192 DEFAULT_BLOCK_SIZE => 4
}; };
#################################################################################################################################### ####################################################################################################################################
@ -54,7 +56,7 @@ has iBlockSize => (is => 'bare', default => DEFAULT_BLOCK_SIZE); # Set block si
sub BUILD sub BUILD
{ {
my $self = shift; my $self = shift;
$self->{strGreeting} .= " " . version_get(); $self->{strGreeting} .= " " . version_get();
if (defined($self->{strHost})) if (defined($self->{strHost}))
@ -95,7 +97,7 @@ sub BUILD
} }
else else
{ {
} }
} }
@ -224,7 +226,7 @@ sub read_line
my $self = shift; my $self = shift;
my $hIn = shift; my $hIn = shift;
my $bError = shift; my $bError = shift;
my $strLine; my $strLine;
my $strChar; my $strChar;
my $iByteIn; my $iByteIn;
@ -232,7 +234,7 @@ sub read_line
while (1) while (1)
{ {
$iByteIn = sysread($hIn, $strChar, 1); $iByteIn = sysread($hIn, $strChar, 1);
if (!defined($iByteIn) || $iByteIn != 1) if (!defined($iByteIn) || $iByteIn != 1)
{ {
$self->wait_pid(); $self->wait_pid();
@ -241,10 +243,10 @@ sub read_line
{ {
return undef; return undef;
} }
confess &log(ERROR, "unable to read 1 byte" . (defined($!) ? ": " . $! : "")); confess &log(ERROR, "unable to read 1 byte" . (defined($!) ? ": " . $! : ""));
} }
if ($strChar eq "\n") if ($strChar eq "\n")
{ {
last; last;
@ -252,7 +254,7 @@ sub read_line
$strLine .= $strChar; $strLine .= $strChar;
} }
return $strLine; return $strLine;
} }
@ -266,7 +268,7 @@ sub wait_pid
if (defined($self->{pId}) && waitpid($self->{pId}, WNOHANG) != 0) if (defined($self->{pId}) && waitpid($self->{pId}, WNOHANG) != 0)
{ {
my $strError = "no error on stderr"; my $strError = "no error on stderr";
if (!defined($self->{hErr})) if (!defined($self->{hErr}))
{ {
$strError = "no error captured because stderr is already closed"; $strError = "no error captured because stderr is already closed";
@ -280,7 +282,7 @@ sub wait_pid
$self->{hIn} = undef; $self->{hIn} = undef;
$self->{hOut} = undef; $self->{hOut} = undef;
$self->{hErr} = undef; $self->{hErr} = undef;
confess &log(ERROR, "remote process terminated: ${strError}"); confess &log(ERROR, "remote process terminated: ${strError}");
} }
} }
@ -301,30 +303,85 @@ sub binary_xfer
$strRemote = defined($strRemote) ? $strRemote : 'none'; $strRemote = defined($strRemote) ? $strRemote : 'none';
my $iBlockSize = $self->{iBlockSize}; my $iBlockSize = $self->{iBlockSize};
my $iHeaderSize = 12;
my $iBlockIn; my $iBlockIn;
my $iBlockOut; my $iBlockOut;
my $strBlockHeader; my $strBlockHeader;
my $strBlock; my $strBlock;
my $oGzip;
my $hPipeIn;
my $hPipeOut;
my $pId;
if (!defined($hIn) || !defined($hOut)) if (!defined($hIn) || !defined($hOut))
{ {
confess &log(ASSERT, "hIn or hOut is not defined"); confess &log(ASSERT, "hIn or hOut is not defined");
} }
if ($strRemote eq "out")
{
pipe $hPipeOut, $hPipeIn;
# fork and exit the parent process
$pId = fork();
if (!$pId)
{
close($hPipeOut);
gzip($hIn => $hPipeIn)
or die confess &log(ERROR, "unable to compress: " . $GzipError);
close($hPipeIn);
exit 0;
}
close($hPipeIn);
$hIn = $hPipeOut;
}
elsif ($strRemote eq "in" && defined($bCompress) && !$bCompress)
{
pipe $hPipeOut, $hPipeIn;
# fork and exit the parent process
$pId = fork();
if (!$pId)
{
close($hPipeIn);
gunzip($hPipeOut => $hOut)
or die confess &log(ERROR, "unable to uncompress: " . $GunzipError);
close($hPipeOut);
exit 0;
}
# exit 0;
close($hPipeOut);
$hOut = $hPipeIn;
}
while (1) while (1)
{ {
if ($strRemote eq 'in') if ($strRemote eq 'in')
{ {
$strBlockHeader = $self->read_line($hIn); $strBlockHeader = $self->read_line($hIn);
if ($strBlockHeader !~ /^block [0-9]+$/) if ($strBlockHeader !~ /^block [0-9]+$/)
{ {
confess "unable to read block header ${strBlockHeader}"; confess "unable to read block header ${strBlockHeader}";
} }
$iBlockSize = trim(substr($strBlockHeader, index($strBlockHeader, " ") + 1)); $iBlockSize = trim(substr($strBlockHeader, index($strBlockHeader, " ") + 1));
# confess "found $iBlockSize to write";
if ($iBlockSize != 0) if ($iBlockSize != 0)
{ {
$iBlockIn = sysread($hIn, $strBlock, $iBlockSize); $iBlockIn = sysread($hIn, $strBlock, $iBlockSize);
@ -336,35 +393,73 @@ sub binary_xfer
} }
else else
{ {
#
# if ($strRemote eq 'in')
# {
# confess &log(ERROR, "block size $iBlockSize");
# }
$iBlockIn = 0; $iBlockIn = 0;
} }
} }
else else
{ {
if (!defined($bCompress)) $iBlockIn = sysread($hIn, $strBlock, $iBlockSize);
if (!defined($iBlockIn))
{ {
$iBlockIn = sysread($hIn, $strBlock, $iBlockSize); confess &log(ERROR, "unable to read");
if (!defined($iBlockIn))
{
confess "unable to read ${iBlockSize} bytes from remote: " . $!;
}
} }
} }
# if (defined($bCompress))
# {
# if ($iBlockIn > 0)
# {
# my $iBlockInTmp = $iBlockIn;
#
# # print "${iBlockIn} bytes to compress";
#
# if ($bCompress)
# {
# $iBlockIn = $oGzip->syswrite($hIn, $iBlockInTmp);
#
# if (!defined($iBlockIn))
# {
# confess &log(ERROR, "unable to compress stream: " . $GunzipError)
# }
#
# if ($iBlockIn != $iBlockInTmp)
# {
# confess &log(ERROR, "unable to read ${iBlockSize} bytes");
# }
# }
# else
# {
# $iBlockIn = $oGzip->sysread($strBlock, 8192);
#
# if (!defined($iBlockIn))
# {
# confess &log(ERROR, "unable to read compressed stream: " . $GunzipError)
# }
# # $strBlock = $strBlockTmp;
# }
# }
# else
# {
# if ($bCompress)
# {
# $oGzip->flush()
# or confess &log(ERROR, "unable to flush compressed stream");
# $bDone = true;
# }
# }
#
# $iBlockIn = length($strBlock);
# }
if ($strRemote eq 'out') if ($strRemote eq 'out')
{ {
$strBlockHeader = "block ${iBlockIn}\n"; $strBlockHeader = "block ${iBlockIn}\n";
# print "wrote block header: ${strBlockHeader}"; # REMOVE! # print "wrote block header: ${strBlockHeader}"; # REMOVE!
$iBlockOut = syswrite($hOut, $strBlockHeader); $iBlockOut = syswrite($hOut, $strBlockHeader);
if (!defined($iBlockOut) || $iBlockOut != length($strBlockHeader)) if (!defined($iBlockOut) || $iBlockOut != length($strBlockHeader))
{ {
confess "unable to write block header"; confess "unable to write block header";
@ -382,12 +477,63 @@ sub binary_xfer
{ {
confess "unable to write ${iBlockIn} bytes" . (defined($!) ? ": " . $! : ""); confess "unable to write ${iBlockIn} bytes" . (defined($!) ? ": " . $! : "");
} }
# $strBlock = undef;
# if ($bDone && $strRemote eq 'out')
# {
# $strBlockHeader = "block 0\n";
#
# # print "wrote block header: ${strBlockHeader}"; # REMOVE!
#
# $iBlockOut = syswrite($hOut, $strBlockHeader);
#
# if (!defined($iBlockOut) || $iBlockOut != length($strBlockHeader))
# {
# confess "unable to write block header";
# }
# }
} }
else else
{ {
last; last;
# if ($strRemote eq 'in')
# {
# confess "got out\n";
# }
#
# if (defined($hPipeIn))
# {
# close($hPipeIn)
# };
#
# $bDone = true;
} }
} }
if (defined($pId))
{
if ($strRemote eq "out")
{
close($hPipeOut);
}
elsif ($strRemote eq "in" && defined($bCompress) && !$bCompress)
{
# confess "waiting for child";
close($hPipeIn);
}
waitpid($pId, 0);
my $iExitStatus = ${^CHILD_ERROR_NATIVE} >> 8;
if ($iExitStatus != 0)
{
confess &log(ERROR, "compression/decompression child process returned " . $iExitStatus);
}
}
# print "got out\n";
} }
#################################################################################################################################### ####################################################################################################################################
@ -408,11 +554,11 @@ sub output_read
my $strError; my $strError;
# print "error read wait\n"; # print "error read wait\n";
# #
# if (!eof($self->{hErr})) # if (!eof($self->{hErr}))
# { # {
# $strError = $self->pipe_to_string($self->{hErr}); # $strError = $self->pipe_to_string($self->{hErr});
# #
# if (defined($strError)) # if (defined($strError))
# { # {
# $bError = true; # $bError = true;
@ -446,19 +592,19 @@ sub output_read
confess &log(ERROR, (defined($strErrorPrefix) ? "${strErrorPrefix}" : "") . confess &log(ERROR, (defined($strErrorPrefix) ? "${strErrorPrefix}" : "") .
(defined($strOutput) ? ": ${strOutput}" : ""), $iErrorCode); (defined($strOutput) ? ": ${strOutput}" : ""), $iErrorCode);
} }
$self->wait_pid(); $self->wait_pid();
if ($bOutputRequired && !defined($strOutput)) if ($bOutputRequired && !defined($strOutput))
{ {
my $strError = $self->pipe_to_string($self->{hErr}); my $strError = $self->pipe_to_string($self->{hErr});
if (defined($strError)) if (defined($strError))
{ {
$bError = true; $bError = true;
$strOutput = $strError; $strOutput = $strError;
} }
# Capture any errors # Capture any errors
if ($bError) if ($bError)
{ {

View File

@ -805,14 +805,14 @@ sub BackRestFileTest
for (my $bDestinationCompressed = 0; $bDestinationCompressed <= 0; $bDestinationCompressed++) for (my $bDestinationCompressed = 0; $bDestinationCompressed <= 0; $bDestinationCompressed++)
{ {
my $strRemote = $bBackupRemote ? 'backup' : $bDbRemote ? 'db' : undef; my $strRemote = $bBackupRemote ? 'backup' : $bDbRemote ? 'db' : undef;
# $oRemote = BackRest::Remote->new # $oRemote = BackRest::Remote->new
# ( # (
# strHost => $strHost, # strHost => $strHost,
# strUser => $strUser, # strUser => $strUser,
# strCommand => $strCommand, # strCommand => $strCommand,
# ); # );
my $oFile = BackRest::File->new my $oFile = BackRest::File->new
( (
strStanza => "db", strStanza => "db",
@ -862,7 +862,7 @@ sub BackRestFileTest
{ {
system("echo 'TESTDATA' > ${strSourceFile}"); system("echo 'TESTDATA' > ${strSourceFile}");
} }
my $strSourceHash = $oFile->hash(PATH_ABSOLUTE, $strSourceFile); my $strSourceHash = $oFile->hash(PATH_ABSOLUTE, $strSourceFile);
# Run file copy in an eval block because some errors are expected # Run file copy in an eval block because some errors are expected