#!/usr/bin/perl
#Hold a job --> it will not be scheduled

use strict;
use warnings;
use Data::Dumper;
use DBI();
use OAR::IO;
use OAR::Conf qw(init_conf dump_conf get_conf is_conf);
use OAR::Tools;
use Getopt::Long;
use OAR::Version;

my $Old_umask = sprintf("%lo", umask());
umask(oct("022"));

sub usage {
    print <<EOS;
Usage: $0 [--array][job_ids][--sql "sql syntax"][-r][-V][-h]
Ask OAR to not schedule job_id until oarresume command will be executed.
  -r, --running manage not only Waiting jobs but also Running one
                (can suspend the job)
      --array   hold array job(s) passed as parameter (all the sub-jobs)
      --sql     hold jobs which respond to the SQL where clause on the table
                jobs (ex: "project = 'p1'")
  -h, --help    show this help screen
  -V, --version print OAR version number
EOS
}

my $Help;
my $Version;
my $Suspend_running;
my $Sql_property;
my $array;
GetOptions(
    "help|h"    => \$Help,
    "version|V" => \$Version,
    "array"     => \$array,
    "sql=s"     => \$Sql_property,
    "running|r" => \$Suspend_running
  ) or
  exit(1);

if (defined($Help)) {
    usage();
    exit(0);
}

if (defined($Version)) {
    print("OAR version: " . OAR::Version::get_version() . "\n");
    exit(0);
}

init_conf($ENV{OARCONFFILE});
my $remote_host = get_conf("SERVER_HOSTNAME");
my $remote_port = get_conf("SERVER_PORT");

my $Cpuset_field = get_conf("JOB_RESOURCE_MANAGER_PROPERTY_DB_FIELD");

if ((@ARGV < 1) and (!defined($Sql_property))) {
    usage();
    exit(1);
}

my @job_ids;
my $exit_code = 0;

foreach my $j (@ARGV) {
    if ($j =~ m/^\d+$/m) {

        #if defined --array, delete all the sub-jobs
        if (defined($array)) {
            my $db       = OAR::IO::connect_ro();
            my @tmp_jobs = OAR::IO::get_array_job_ids($db, $j);
            if (scalar @tmp_jobs == 0) {
                warn("[ERROR] \"$j\" is not a valid array job\n");
                $exit_code = 2;
            } else {
                foreach my $j (@tmp_jobs) {
                    push(@job_ids, $j);
                }
            }
            OAR::IO::disconnect($db);
        } else {
            push(@job_ids, $j);
        }
    } else {
        if (defined($array)) {
            warn("[ERROR] \"$j\" is not a valid job array identifier\n");
        } else {
            warn("[ERROR] \"$j\" is not a valid job identifier\n");
        }
        $exit_code = 2;
    }
}

if (defined($Sql_property)) {
    my $db = OAR::IO::connect_ro();
    foreach my $j (OAR::IO::get_jobs_with_given_properties($db, $Sql_property)) {
        push(@job_ids, $j->{job_id});
    }
    OAR::IO::disconnect($db);
}

my $base = OAR::IO::connect();
foreach my $j (@job_ids) {
    my $err_job = 0;
    if (defined($Suspend_running)) {
        my $types = OAR::IO::get_job_types_hash($base, $j);
        if (!defined($Cpuset_field)) {
            warn("CPUSET tag is not configured in the oar.conf.\n");
            $err_job = 2;
        } elsif (defined($types->{cosystem})) {
            warn("This job is of the cosystem type. We cannot suspend this kind of jobs.\n");
            $err_job = 3;
        } elsif (defined($types->{deploy})) {
            warn("This job is of the deploy type. We cannot suspend this kind of jobs.\n");
            $err_job = 4;
        }
    }
    if ($err_job == 0) {
        my $err = OAR::IO::hold_job($base, $j, $Suspend_running);

        if ($err != 0) {
            my $str = "/!\\ Cannot hold $j:";
            if ($err == -1) {
                warn("$str this job does not exist.\n");
            } elsif ($err == -2) {
                warn("$str you are not the right user.\n");
            } elsif ($err == -3) {
                warn("$str the job is not in the right state (try '-r' option).\n");
            } elsif ($err == -4) {
                warn("$str only oar or root users can use '-r' option.\n");
            } else {
                warn("$str unknown reason.\n");
            }
            $exit_code = 1;
        } else {
            print("[$j] Hold request was sent to the OAR server.\n");
        }
    } else {
        $exit_code = 2;
    }
}

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

#Signal Almigthy
OAR::Tools::notify_tcp_socket($remote_host, $remote_port, "ChState");

exit($exit_code);
