# --
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --
package Kernel::System::PID;
use strict;
use warnings;
our @ObjectDependencies = (
'Kernel::Config',
'Kernel::System::DB',
'Kernel::System::Log',
);
=head1 NAME
Kernel::System::PID - to manage PIDs
=head1 DESCRIPTION
All functions to manage process ids
=head1 PUBLIC INTERFACE
=head2 new()
Don't use the constructor directly, use the ObjectManager instead:
my $PIDObject = $Kernel::OM->Get('Kernel::System::PID');
=cut
sub new {
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {};
bless( $Self, $Type );
# get fqdn
$Self->{Host} = $Kernel::OM->Get('Kernel::Config')->Get('FQDN');
return $Self;
}
=head2 PIDCreate()
create a new process id lock
$PIDObject->PIDCreate(
Name => 'PostMasterPOP3',
);
or to create a new PID forced, without check if already exists (this will delete any process
with the same name from any other host)
$PIDObject->PIDCreate(
Name => 'PostMasterPOP3',
Force => 1,
);
or to create a new PID with extra TTL time
$PIDObject->PIDCreate(
Name => 'PostMasterPOP3',
TTL => 60 * 60 * 24 * 3, # for 3 days, per default 1h is used
);
=cut
sub PIDCreate {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{Name} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need Name'
);
return;
}
# check if already exists
my %ProcessID = $Self->PIDGet(%Param);
if ( %ProcessID && !$Param{Force} ) {
my $TTL = $Param{TTL} || 3600;
if ( $ProcessID{Created} > ( time() - $TTL ) ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'notice',
Message => "Can't create PID $ProcessID{Name}, because it's already running "
. "($ProcessID{Host}/$ProcessID{PID})!",
);
return;
}
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'notice',
Message => "Removed PID ($ProcessID{Name}/$ProcessID{Host}/$ProcessID{PID}, "
. "because 1 hour old!",
);
}
# do nothing if PID is the same
my $PIDCurrent = $$;
return 1 if $ProcessID{PID} && $PIDCurrent eq $ProcessID{PID};
# delete if exists
$Self->PIDDelete(%Param);
# add new entry
my $Time = time();
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
SQL => '
INSERT INTO process_id
(process_name, process_id, process_host, process_create, process_change)
VALUES (?, ?, ?, ?, ?)',
Bind => [ \$Param{Name}, \$PIDCurrent, \$Self->{Host}, \$Time, \$Time ],
);
return 1;
}
=head2 PIDGet()
get process id lock info
my %PID = $PIDObject->PIDGet(
Name => 'PostMasterPOP3',
);
=cut
sub PIDGet {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{Name} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need Name'
);
return;
}
# get database object
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
# sql
return if !$DBObject->Prepare(
SQL => '
SELECT process_name, process_id, process_host, process_create, process_change
FROM process_id
WHERE process_name = ?',
Bind => [ \$Param{Name} ],
Limit => 1,
);
# fetch the result
my %Data;
while ( my @Row = $DBObject->FetchrowArray() ) {
%Data = (
PID => $Row[1],
Name => $Row[0],
Host => $Row[2],
Created => $Row[3],
Changed => $Row[4],
);
}
return %Data;
}
=head2 PIDDelete()
delete the process id lock
my $Success = $PIDObject->PIDDelete(
Name => 'PostMasterPOP3',
);
or to force delete even if the PID is registered by another host
my $Success = $PIDObject->PIDDelete(
Name => 'PostMasterPOP3',
Force => 1,
);
=cut
sub PIDDelete {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{Name} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need Name'
);
return;
}
# set basic SQL statement
my $SQL = '
DELETE FROM process_id
WHERE process_name = ?';
my @Bind = ( \$Param{Name} );
# delete only processes from this host if Force option was not set
if ( !$Param{Force} ) {
$SQL .= '
AND process_host = ?';
push @Bind, \$Self->{Host};
}
# sql
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
SQL => $SQL,
Bind => \@Bind,
);
return 1;
}
=head2 PIDUpdate()
update the process id change time.
this might be useful as a keep alive signal.
my $Success = $PIDObject->PIDUpdate(
Name => 'PostMasterPOP3',
);
=cut
sub PIDUpdate {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{Name} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need Name'
);
return;
}
my %PID = $Self->PIDGet( Name => $Param{Name} );
if ( !%PID ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Can not get PID'
);
return;
}
# sql
my $Time = time();
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
SQL => '
UPDATE process_id
SET process_change = ?
WHERE process_name = ?',
Bind => [ \$Time, \$Param{Name} ],
);
return 1;
}
1;
=head1 TERMS AND CONDITIONS
This software is part of the OTRS project (L).
This software comes with ABSOLUTELY NO WARRANTY. For details, see
the enclosed file COPYING for license information (GPL). If you
did not receive this file, see L.
=cut