2017-01-27 17:06:16 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# PROTOCOL COMMAND MASTER MODULE
|
|
|
|
####################################################################################################################################
|
2017-05-15 17:12:14 +02:00
|
|
|
package pgBackRest::Protocol::Command::Master;
|
2017-06-09 23:51:41 +02:00
|
|
|
use parent 'pgBackRest::Protocol::Base::Master';
|
2017-01-27 17:06:16 +02:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings FATAL => qw(all);
|
|
|
|
use Carp qw(confess);
|
|
|
|
use English '-no_match_vars';
|
|
|
|
|
|
|
|
use File::Basename qw(dirname);
|
|
|
|
use Time::HiRes qw(gettimeofday);
|
|
|
|
|
|
|
|
use pgBackRest::Common::Exception;
|
|
|
|
use pgBackRest::Common::Ini;
|
|
|
|
use pgBackRest::Common::Log;
|
2017-06-09 23:51:41 +02:00
|
|
|
use pgBackRest::Common::Io::Process;
|
|
|
|
use pgBackRest::Protocol::Base::Master;
|
2017-01-27 17:06:16 +02:00
|
|
|
use pgBackRest::Version;
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# CONSTRUCTOR
|
|
|
|
####################################################################################################################################
|
|
|
|
sub new
|
|
|
|
{
|
|
|
|
my $class = shift; # Class name
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$strName, # Name of the protocol
|
|
|
|
$strId, # Id of this process for error messages
|
|
|
|
$strCommand, # Command to execute on local/remote
|
|
|
|
$iBufferMax, # Maximum buffer size
|
|
|
|
$iCompressLevel, # Set compression level
|
|
|
|
$iCompressLevelNetwork, # Set compression level for network only compression
|
|
|
|
$iProtocolTimeout, # Protocol timeout
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
|
|
|
__PACKAGE__ . '->new', \@_,
|
|
|
|
{name => 'strName'},
|
|
|
|
{name => 'strId'},
|
|
|
|
{name => 'strCommand'},
|
|
|
|
{name => 'iBufferMax'},
|
|
|
|
{name => 'iCompressLevel'},
|
|
|
|
{name => 'iCompressLevelNetwork'},
|
|
|
|
{name => 'iProtocolTimeout'},
|
|
|
|
);
|
|
|
|
|
|
|
|
# Set command
|
|
|
|
if (!defined($strCommand))
|
|
|
|
{
|
|
|
|
confess &log(ASSERT, 'strCommand must be set');
|
|
|
|
}
|
|
|
|
|
|
|
|
# Execute the command
|
2017-06-09 23:51:41 +02:00
|
|
|
my $oIo = new pgBackRest::Common::Io::Process(
|
|
|
|
new pgBackRest::Common::Io::Buffered(
|
|
|
|
new pgBackRest::Common::Io::Handle($strId), $iProtocolTimeout, $iBufferMax), $strCommand);
|
2017-01-27 17:06:16 +02:00
|
|
|
|
|
|
|
# Create the class hash
|
2017-06-09 23:51:41 +02:00
|
|
|
my $self = $class->SUPER::new($strName, $strId, $oIo);
|
2017-01-27 17:06:16 +02:00
|
|
|
bless $self, $class;
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'self', value => $self}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# close
|
|
|
|
####################################################################################################################################
|
|
|
|
sub close
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$bComplete,
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
|
|
|
__PACKAGE__ . '->close', \@_,
|
|
|
|
{name => 'bComplete', default => false, trace => true},
|
|
|
|
);
|
|
|
|
|
|
|
|
# Exit status defaults to success
|
|
|
|
my $iExitStatus = 0;
|
|
|
|
my $bClosed = false;
|
|
|
|
|
|
|
|
# Only send the exit command if the process is running
|
2017-06-09 23:51:41 +02:00
|
|
|
if (defined($self->io()) && defined($self->io()->processId()))
|
2017-01-27 17:06:16 +02:00
|
|
|
{
|
|
|
|
&log(TRACE, "sending exit command to process");
|
|
|
|
|
|
|
|
eval
|
|
|
|
{
|
2017-06-09 23:51:41 +02:00
|
|
|
$self->cmdWrite(OP_EXIT);
|
2017-01-27 17:06:16 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
or do
|
|
|
|
{
|
|
|
|
my $oException = $EVAL_ERROR;
|
|
|
|
my $strError = 'unable to shutdown protocol';
|
|
|
|
my $strHint = 'HINT: the process completed all operations successfully but protocol-timeout may need to be increased.';
|
|
|
|
|
2017-10-16 16:47:31 +02:00
|
|
|
if (isException(\$oException))
|
2017-01-27 17:06:16 +02:00
|
|
|
{
|
|
|
|
$iExitStatus = $oException->code();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!defined($oException))
|
|
|
|
{
|
|
|
|
$oException = 'unknown error';
|
|
|
|
}
|
|
|
|
|
|
|
|
$iExitStatus = ERROR_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
&log(WARN,
|
2017-04-12 18:41:34 +02:00
|
|
|
$strError . ($iExitStatus == ERROR_UNKNOWN ? '' : sprintf(' [%03d]', $oException->code())) . ': ' .
|
2017-01-27 17:06:16 +02:00
|
|
|
($iExitStatus == ERROR_UNKNOWN ? $oException : $oException->message()) .
|
|
|
|
($bComplete ? "\n${strHint}" : ''));
|
|
|
|
};
|
|
|
|
|
2017-06-09 23:51:41 +02:00
|
|
|
$self->{oIo}->close();
|
|
|
|
undef($self->{oIo});
|
2017-01-27 17:06:16 +02:00
|
|
|
$bClosed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'iExitStatus', value => $iExitStatus, trace => !$bClosed}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|