#!/usr/bin/perl
# $Id$
#

use English;
use OAR::IO;
use Sys::Hostname;
use OAR::Conf qw(init_conf dump_conf get_conf is_conf);
use IPC::Open2;
use IPC::Open3;
use Data::Dumper;
use OAR::Modules::Judas qw(oar_debug oar_warn oar_error set_current_log_category);
use IO::Socket::INET;
use OAR::Tools;
use OAR::PingChecker qw(test_hosts);

# Log category
set_current_log_category('main');

init_conf($ENV{OARCONFFILE});
my $Server_hostname = get_conf("SERVER_HOSTNAME");
my $Server_port = get_conf("SERVER_PORT");

my $Deploy_hostname = get_conf("DEPLOY_HOSTNAME");
if (!defined($Deploy_hostname)){
    $Deploy_hostname = $Server_hostname;
}

my $Cosystem_hostname = get_conf("COSYSTEM_HOSTNAME");
if (!defined($Cosystem_hostname)){
    $Cosystem_hostname = $Server_hostname;
}

my $Server_epilogue = get_conf("SERVER_EPILOGUE_EXEC_FILE");

my $Openssh_cmd = get_conf("OPENSSH_CMD");
$Openssh_cmd = OAR::Tools::get_default_openssh_cmd() if (!defined($Openssh_cmd));

if (is_conf("OAR_SSH_CONNECTION_TIMEOUT")){
    OAR::Tools::set_ssh_timeout(get_conf("OAR_SSH_CONNECTION_TIMEOUT"));
}

if (is_conf("OAR_RUNTIME_DIRECTORY")){
    OAR::Tools::set_default_oarexec_directory(get_conf("OAR_RUNTIME_DIRECTORY"));
}

my $Exit_code = 0;

my $base = OAR::IO::connect();

#do it for all job in state LEON in the data base table fragJobs
OAR::IO::lock_table($base,["jobs","job_state_logs","resources","assigned_resources","frag_jobs","event_logs","moldable_job_descriptions","job_types","job_resource_descriptions","job_resource_groups","challenges","job_dependencies","gantt_jobs_predictions"]);

foreach my $j (OAR::IO::get_to_kill_jobs($base)){
    if (OAR::IO::is_job_desktop_computing($base,$j->{job_id})) {
        oar_debug("[Leon] Job $j->{job_id} is affected to a DesktopComputing resource, I do not handle it\n");
        next;
    }

    oar_debug("[Leon] Normal kill : I treate the job $j->{job_id}\n");
    if (($j->{state} eq "Waiting") || ($j->{state} eq "Hold")){
        oar_debug("[Leon] Job is not launched\n");
        OAR::IO::set_job_state($base,$j->{job_id},"Error");
        OAR::IO::set_job_message($base,$j->{job_id},"job killed by Leon directly");
        if ($j->{job_type} eq "INTERACTIVE"){
            oar_debug("[Leon] I notify oarsub in waiting mode\n");
            #answer($Jid,$refJob->{'infoType'},"JOB KILLED");
            my ($addr,$port) = split(/:/,$j->{info_type});
            if (!defined(OAR::Tools::notify_tcp_socket($addr, $port, "JOB KILLED"))){
                oar_debug("[Leon] Notification done\n");
            }else{
                oar_debug("[Leon] Cannot open connection to oarsub client for job $j->{job_id}, it is normal if user typed Ctrl-C !!!!!!\n");
            }
        }
        $Exit_code = 1;
    }elsif (($j->{state} eq "Terminated") || ($j->{state} eq "Error") || ($j->{state} eq "Finishing")){
        oar_debug("[Leon] Job is terminated or is terminating I do nothing\n");
    }else{
        my $types = OAR::IO::get_current_job_types($base,$j->{job_id});
        my @hosts = OAR::IO::get_job_current_hostnames($base,$j->{job_id});
        my $host_to_connect_via_ssh = $hosts[0];
        #deploy, cosystem and no host part
        if ((defined($types->{cosystem})) or ($#hosts < 0)){
            $host_to_connect_via_ssh = $Cosystem_hostname;
        }elsif (defined($types->{deploy})){
            $host_to_connect_via_ssh = $Deploy_hostname;
        }
        #deploy, cosystem and no host part
        if (defined($host_to_connect_via_ssh)){
            OAR::IO::add_new_event($base,"SEND_KILL_JOB",$j->{job_id},"[Leon] Send kill signal to oarexec on $host_to_connect_via_ssh for the job $j->{job_id}");
            OAR::Tools::signal_oarexec($host_to_connect_via_ssh, $j->{job_id}, "TERM", 0, $base, $Openssh_cmd, '');
        }
    }
    OAR::IO::job_arm_leon_timer($base,$j->{job_id});
}

#I treate jobs in state EXTERMINATED in the table fragJobs
foreach my $j (OAR::IO::get_to_exterminate_jobs($base)){
    oar_debug("[Leon] EXTERMINATE the job $j->{job_id}\n");
    OAR::IO::set_job_state($base,$j->{job_id},"Finishing");
    if ($j->{start_time} == 0){
        OAR::IO::set_running_date($base,$j->{job_id});
    }
    OAR::IO::set_finish_date($base,$j->{job_id});
    OAR::IO::set_job_message($base,$j->{job_id},"job exterminated by Leon");
    OAR::IO::job_arm_leon_timer($base,$j->{job_id});
    $Exit_code = 2;

    $SIG{PIPE}  = 'IGNORE';
    my $pid = fork();
    if ($pid == 0){
        #CHILD
        undef($base);
        $SIG{USR1} = 'IGNORE';
        $SIG{INT}  = 'IGNORE';
        $SIG{TERM} = 'IGNORE';
        my $str = "[Leon] I exterminate the job $j->{job_id}";
        my @events;
        push(@events, {type => "EXTERMINATE_JOB", string => $str});
        my $dbh = OAR::IO::connect();
        OAR::IO::job_finishing_sequence($dbh,$Server_epilogue,$Server_hostname,$Server_port,$j->{job_id},\@events);
        OAR::IO::disconnect($dbh);
        exit(0);
    }
}
OAR::IO::unlock_table($base);

OAR::IO::disconnect($base);

exit($Exit_code);
