You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-06-23 00:07:44 +02:00
copy() works with remote in either direction.
This commit is contained in:
@ -103,6 +103,16 @@ while ($strCommand ne OP_EXIT)
|
|||||||
$oFile->copy(PIPE_STDIN, undef, PATH_ABSOLUTE, $oParamHash{destination_file});
|
$oFile->copy(PIPE_STDIN, undef, PATH_ABSOLUTE, $oParamHash{destination_file});
|
||||||
$oRemote->output_write();
|
$oRemote->output_write();
|
||||||
}
|
}
|
||||||
|
elsif ($strCommand eq OP_FILE_COPY_OUT)
|
||||||
|
{
|
||||||
|
if (!defined($oParamHash{source_file}))
|
||||||
|
{
|
||||||
|
confess "source_file must be defined";
|
||||||
|
}
|
||||||
|
|
||||||
|
$oFile->copy(PATH_ABSOLUTE, $oParamHash{source_file}, PIPE_STDOUT, undef);
|
||||||
|
$oRemote->output_write();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ($strCommand ne OP_NOOP)
|
if ($strCommand ne OP_NOOP)
|
||||||
|
@ -119,16 +119,16 @@ use constant
|
|||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
use constant
|
use constant
|
||||||
{
|
{
|
||||||
OP_FILE_LIST => "list",
|
OP_FILE_LIST => "File->list",
|
||||||
OP_FILE_EXISTS => "File->exists",
|
OP_FILE_EXISTS => "File->exists",
|
||||||
OP_FILE_HASH => "hash",
|
OP_FILE_HASH => "File->hash",
|
||||||
OP_FILE_REMOVE => "remove",
|
OP_FILE_REMOVE => "File->remove",
|
||||||
OP_FILE_MANIFEST => "manifest",
|
OP_FILE_MANIFEST => "File->manifest",
|
||||||
OP_FILE_COMPRESS => "compress",
|
OP_FILE_COMPRESS => "File->compress",
|
||||||
OP_FILE_MOVE => "move",
|
OP_FILE_MOVE => "File->move",
|
||||||
OP_FILE_COPY_OUT => "copy_out",
|
OP_FILE_COPY_OUT => "File->copy_out",
|
||||||
OP_FILE_COPY_IN => "File->copy_in",
|
OP_FILE_COPY_IN => "File->copy_in",
|
||||||
OP_FILE_PATH_CREATE => "path_create"
|
OP_FILE_PATH_CREATE => "File->path_create"
|
||||||
};
|
};
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
@ -599,105 +599,105 @@ sub move
|
|||||||
#
|
#
|
||||||
# Copies data from a file handle into a string.
|
# Copies data from a file handle into a string.
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
sub pipe_to_string
|
# sub pipe_to_string
|
||||||
{
|
# {
|
||||||
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;
|
||||||
}
|
# }
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# PIPE Function
|
# PIPE Function
|
||||||
#
|
#
|
||||||
# Copies data from one file handle to another, optionally compressing or decompressing the data in stream.
|
# Copies data from one file handle to another, optionally compressing or decompressing the data in stream.
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
sub pipe
|
# sub pipe
|
||||||
{
|
# {
|
||||||
my $self = shift;
|
# my $self = shift;
|
||||||
my $hIn = shift;
|
# my $hIn = shift;
|
||||||
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)
|
||||||
{
|
# {
|
||||||
if (!gzip($hIn => $hOut))
|
# if (!gzip($hIn => $hOut))
|
||||||
{
|
# {
|
||||||
confess $GzipError;
|
# confess $GzipError;
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
# If no compression is requested and the file is already compressed
|
# # If no compression is requested and the file is already compressed
|
||||||
elsif (defined($bUncompress) && $bUncompress)
|
# elsif (defined($bUncompress) && $bUncompress)
|
||||||
{
|
# {
|
||||||
if (!gunzip($hIn => $hOut))
|
# if (!gunzip($hIn => $hOut))
|
||||||
{
|
# {
|
||||||
confess $GunzipError;
|
# confess $GunzipError;
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
# Else it's a straight copy
|
# # Else it's a straight copy
|
||||||
else
|
# else
|
||||||
{
|
# {
|
||||||
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)
|
||||||
{
|
# {
|
||||||
if (!defined($iResultRead))
|
# if (!defined($iResultRead))
|
||||||
{
|
# {
|
||||||
confess $!;
|
# confess $!;
|
||||||
last;
|
# last;
|
||||||
}
|
# }
|
||||||
else
|
# else
|
||||||
{
|
# {
|
||||||
# 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 $!;
|
||||||
last;
|
# last;
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# WAIT_PID
|
# WAIT_PID
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
sub wait_pid
|
# sub wait_pid
|
||||||
{
|
# {
|
||||||
my $self = shift;
|
# my $self = shift;
|
||||||
my $pId = shift;
|
# my $pId = shift;
|
||||||
my $strCommand = shift;
|
# my $strCommand = shift;
|
||||||
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 . ": " .
|
||||||
(defined($strError) ? $strError : "[unknown]"));
|
# (defined($strError) ? $strError : "[unknown]"));
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
|
|
||||||
####################################################################################################################################
|
####################################################################################################################################
|
||||||
# COPY
|
# COPY
|
||||||
@ -783,23 +783,38 @@ sub copy
|
|||||||
# If source is remote and destination is local
|
# If source is remote and destination is local
|
||||||
if ($bSourceRemote && !$bDestinationRemote)
|
if ($bSourceRemote && !$bDestinationRemote)
|
||||||
{
|
{
|
||||||
$strRemote = 'in';
|
|
||||||
$hOut = $hDestinationFile;
|
$hOut = $hDestinationFile;
|
||||||
|
|
||||||
if ($strSourcePathType eq PIPE_STDIN)
|
if ($strSourcePathType eq PIPE_STDIN)
|
||||||
{
|
{
|
||||||
|
$strRemote = 'in';
|
||||||
$hIn = *STDIN;
|
$hIn = *STDIN;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$strRemote = 'in';
|
||||||
|
$strOperation = OP_FILE_COPY_OUT;
|
||||||
|
$oParamHash{source_file} = ${strSourceOp};
|
||||||
|
$hIn = $self->{oRemote}->{hOut};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
# Else if source is local and destination is remote
|
# Else if source is local and destination is remote
|
||||||
elsif (!$bSourceRemote && $bDestinationRemote)
|
elsif (!$bSourceRemote && $bDestinationRemote)
|
||||||
{
|
{
|
||||||
$strRemote = 'out';
|
|
||||||
$hIn = $hSourceFile;
|
$hIn = $hSourceFile;
|
||||||
|
|
||||||
|
if ($strDestinationPathType eq PIPE_STDOUT)
|
||||||
|
{
|
||||||
|
$strRemote = 'out';
|
||||||
|
$hOut = *STDOUT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$strRemote = 'out';
|
||||||
$strOperation = OP_FILE_COPY_IN;
|
$strOperation = OP_FILE_COPY_IN;
|
||||||
$oParamHash{destination_file} = ${strDestinationOp};
|
$oParamHash{destination_file} = ${strDestinationOp};
|
||||||
$hOut = $self->{oRemote}->{hIn};
|
$hOut = $self->{oRemote}->{hIn};
|
||||||
|
}
|
||||||
|
|
||||||
# Build debug string
|
# Build debug string
|
||||||
# $strDebug = "${strOperation}: remote (" . $self->{oRemote}->command_param_string(\%oParamHash) . "): " . $strDebug;
|
# $strDebug = "${strOperation}: remote (" . $self->{oRemote}->command_param_string(\%oParamHash) . "): " . $strDebug;
|
||||||
|
@ -386,7 +386,7 @@ sub output_read
|
|||||||
# Capture any errors
|
# Capture any errors
|
||||||
if ($bError)
|
if ($bError)
|
||||||
{
|
{
|
||||||
print "error: " . $strOutput->message();
|
# print "error: " . $strOutput->message();
|
||||||
|
|
||||||
confess &log(ERROR, (defined($strErrorPrefix) ? "${strErrorPrefix}" : "") .
|
confess &log(ERROR, (defined($strErrorPrefix) ? "${strErrorPrefix}" : "") .
|
||||||
(defined($strOutput) ? ": ${strOutput}" : ""));
|
(defined($strOutput) ? ": ${strOutput}" : ""));
|
||||||
@ -407,12 +407,8 @@ sub output_read
|
|||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
|
|
||||||
print "output read wait\n";
|
|
||||||
|
|
||||||
while ($strLine = $self->read_line($self->{hOut}, false))
|
while ($strLine = $self->read_line($self->{hOut}, false))
|
||||||
{
|
{
|
||||||
print "read a line ${strLine}\n";
|
|
||||||
|
|
||||||
if ($strLine =~ /^ERROR.*/)
|
if ($strLine =~ /^ERROR.*/)
|
||||||
{
|
{
|
||||||
$bError = true;
|
$bError = true;
|
||||||
@ -424,15 +420,12 @@ sub output_read
|
|||||||
|
|
||||||
if ($strLine =~ /^OK$/)
|
if ($strLine =~ /^OK$/)
|
||||||
{
|
{
|
||||||
print "found OK\n";
|
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
|
|
||||||
$strOutput .= (defined($strOutput) ? "\n" : "") . substr($strLine, 1);
|
$strOutput .= (defined($strOutput) ? "\n" : "") . substr($strLine, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
print "and here\n";
|
|
||||||
|
|
||||||
# Capture any errors
|
# Capture any errors
|
||||||
if ($bError)
|
if ($bError)
|
||||||
{
|
{
|
||||||
@ -453,8 +446,6 @@ sub output_read
|
|||||||
# Capture any errors
|
# Capture any errors
|
||||||
if ($bError)
|
if ($bError)
|
||||||
{
|
{
|
||||||
print "error: " . $strOutput->message();
|
|
||||||
|
|
||||||
confess &log(ERROR, (defined($strErrorPrefix) ? "${strErrorPrefix}" : "") .
|
confess &log(ERROR, (defined($strErrorPrefix) ? "${strErrorPrefix}" : "") .
|
||||||
(defined($strOutput) ? ": ${strOutput}" : ""));
|
(defined($strOutput) ? ": ${strOutput}" : ""));
|
||||||
}
|
}
|
||||||
|
@ -790,10 +790,10 @@ sub BackRestFileTest
|
|||||||
{
|
{
|
||||||
$iRun = 0;
|
$iRun = 0;
|
||||||
|
|
||||||
for (my $bBackupRemote = 0; $bBackupRemote <= 0; $bBackupRemote++)
|
for (my $bBackupRemote = 0; $bBackupRemote <= 1; $bBackupRemote++)
|
||||||
{
|
{
|
||||||
# Loop through source compression
|
# Loop through source compression
|
||||||
for (my $bDbRemote = 1; $bDbRemote <= 1; $bDbRemote++)
|
for (my $bDbRemote = 0; $bDbRemote <= 1; $bDbRemote++)
|
||||||
{
|
{
|
||||||
# Backup and db cannot both be remote
|
# Backup and db cannot both be remote
|
||||||
if ($bBackupRemote && $bDbRemote)
|
if ($bBackupRemote && $bDbRemote)
|
||||||
@ -852,6 +852,8 @@ sub BackRestFileTest
|
|||||||
system("echo 'TESTDATA' > ${strSourceFile}");
|
system("echo 'TESTDATA' > ${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
|
||||||
my $bReturn;
|
my $bReturn;
|
||||||
|
|
||||||
@ -937,6 +939,13 @@ sub BackRestFileTest
|
|||||||
{
|
{
|
||||||
confess "could not find destination file ${strDestinationFile}";
|
confess "could not find destination file ${strDestinationFile}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $strDestinationHash = $oFile->hash(PATH_ABSOLUTE, $strDestinationFile);
|
||||||
|
|
||||||
|
if ($strSourceHash ne $strDestinationHash)
|
||||||
|
{
|
||||||
|
confess "source ${strSourceHash} and destination ${strDestinationHash} file hashes do not match";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user