#!/usr/bin/perl
use strict;
my($app_svnid) = '$HeadURL$ $LastChangedRevision$';
#  Allow bare words, so &ade_err_error() calls look nicer.
no strict 'subs';
use lib substr `ade-config ade_include_prefix`,0,-1;
use ADE;
use lib substr `js-config js_include_prefix`,0,-1;

my(%jsq_defined_errors) = (
    jsq_err_misc         => { fmt => "%s" },
);

#  Options
my($opt_lock_file);
my($opt_show_all_flag);

#  Other globals

sub jsq
{
    my($errstack_ref) = @_;
    my($rc, $select_result,@select_results, $job_id, $dbh, $command, $i, $sql_statement, $resource);
    my($db_file);			#  temporary
    my($pending_jobs_count, $running_jobs_count, $completed_jobs_count, $jsd_pid, $running_flag);

    #  Set ADE options
    &ade_err_registerdefderrs(\%jsq_defined_errors);
    &ade_err_resetstack($errstack_ref, dumpall=>0);

    #  Defaults for options
    #  (identical line in jsd, jss, jsq).
    $opt_lock_file = $ENV{JSD_LOCKFILE} ? $ENV{JSD_LOCKFILE} : "$ade_tmp_dir/jsd-$ENV{'LOGNAME'}.lock";
    $opt_show_all_flag = 0;

    #  Register options
    if (($rc=&ade_opt_register($errstack_ref, "l:sa", "lockfile:s,all", "main::jsq_opt_handler_%s")) != $ade_err_ok) {
        return($rc);
    }

    #  Register handler functions
    if (($rc=&ade_msg_register($errstack_ref, \&jsq_usage, \&jsq_version, \&jsq_listpaths)) != $ade_err_ok) {
        return($rc);
    } 

    #  Process options
    &ade_err_debug($errstack_ref, 10, "jsq: processing options ...");
    if (($rc=&ade_opt_process($errstack_ref)) != $ade_err_ok) {
        return($rc);
    } 

    #  Process arguments
    &ade_msg_usage($errstack_ref, \&app_usage, 1) if ($#ARGV+1 != 0);

    #  Sanity checks and derivations
    if (($rc=&ade_lck_checklock($errstack_ref, $opt_lock_file, \$jsd_pid, \$running_flag)) != $ade_err_ok) {
        &ade_err_debug($errstack_ref, 20, "ade_lck_lock: ade_lck_checklock failed");
        return($rc);
    }
    if (!$running_flag) {
        &ade_err_error($errstack_ref, jsq_err_misc, "jsd: not running");
        return($ade_err_fail); 
    }
    #  Predicable path to database. Tests should not normally need to access the database.
    $db_file = "/var/tmp/jsd-$jsd_pid.sqlite";

    #  Initialise database
    if (! -w $db_file) {
        &ade_err_error($errstack_ref, jsq_err_misc, "$db_file: not accessible");
        return($ade_err_fail);
    }
    my %attr = ( RaiseError => 1, HandleError => sub { return 1; } );
    if (!defined($dbh = DBI->connect("dbi:SQLite:dbname=$db_file","","", \%attr))) {
        &ade_err_error($errstack_ref, jsq_err_misc, $DBI::errstr);
        return($ade_err_fail);
    }

    #  Enforce foreign key constraints
    $sql_statement = "PRAGMA foreign_keys=ON;";
    if (($rc=&ade_sql_execute($errstack_ref, $dbh, $sql_statement)) != $ade_err_ok) {
        return($rc);
    }
    #  Set 10s timeout
    $dbh->sqlite_busy_timeout(10000);

    $sql_statement = "SELECT count(*) from jobs where job_state=='pending';";
    if (($rc=&ade_sql_select($errstack_ref, $dbh, \@select_results, $sql_statement)) != $ade_err_ok) {
        return($rc);
    }
    $pending_jobs_count = ${$select_results[0]}[0];
    $sql_statement = "SELECT count(*) from jobs where job_state=='running';";
    if (($rc=&ade_sql_select($errstack_ref, $dbh, \@select_results, $sql_statement)) != $ade_err_ok) {
        return($rc);
    }
    $running_jobs_count = ${$select_results[0]}[0];
    $sql_statement = "SELECT count(*) from jobs where job_state=='completed';";
    if (($rc=&ade_sql_select($errstack_ref, $dbh, \@select_results, $sql_statement)) != $ade_err_ok) {
        return($rc);
    }
    $completed_jobs_count = ${$select_results[0]}[0];
    if ($opt_show_all_flag) {
        printf("jobs (%d running, %d pending, %d completed)\n----\n\n", $running_jobs_count, $pending_jobs_count, $completed_jobs_count);
    } else {
        printf("jobs (%d running, %d pending)\n----\n\n", $running_jobs_count, $pending_jobs_count);
    }
    printf("%-4s %9s %5s %3s %s\n%s\n","id","state","pid","rc","command","-"x78);
    if ($opt_show_all_flag) {
        $sql_statement = "SELECT job_id,job_state,pid,exit_code>>8,command FROM jobs order by job_state,job_id;";
    } else {
        $sql_statement = "SELECT job_id,job_state,pid,exit_code>>8,command FROM jobs where job_state!='completed' order by job_state,job_id;";
    }
    if (($rc=&ade_sql_select($errstack_ref, $dbh, \@select_results, $sql_statement)) != $ade_err_ok) {
        return($rc);
    }
    foreach $select_result (@select_results) {
        printf("%-4d %9s %5d %3d %s\n", @{$select_result});
    }
    print("\n");

    printf("resources\n---------\n\n");
    printf("%-8s %4s %4s\n%s\n","id","max","curr","-"x78);
    $sql_statement = "select resources.resource_id, quantity_total, sum(coalesce(quantity_used,0)) as quantity_used from resources left outer join running_job_resource_pools on resources.resource_id = running_job_resource_pools.resource_id group by resources.resource_id order by resources.resource_id;";
    if (($rc=&ade_sql_select($errstack_ref, $dbh, \@select_results, $sql_statement)) != $ade_err_ok) {
        return($rc);
    }
    foreach $select_result (@select_results) {
        printf("%-8s %4d %4d\n", @{$select_result});
    }
    print("\n");

    #  Tidy up
    $dbh->disconnect;

    return($ade_err_ok);
}

sub jsq_opt_handler_l
{
    my($errstack_ref,$lock_file) = @_;

    $opt_lock_file = $lock_file;

    return $ade_err_ok;
}

sub jsq_opt_handler_lockfile
{
    return(&jsq_opt_handler_l(@_));
}

sub jsq_opt_handler_a
{
    my($errstack_ref) = @_;

    $opt_show_all_flag = 1;

    return $ade_err_ok;
}

sub jsq_opt_handler_all
{
    return(&jsq_opt_handler_a(@_));
}

sub jsq_version
{
    my($errstack_ref, $version_text_ref) = @_;

    return(&ade_smf_extractversionfromsvnstring($errstack_ref, $app_svnid, $version_text_ref));
}

sub jsq_listpaths
{
    my($errstack_ref, $pathlist_text_ref) = @_;
    my($rc);

    ${$pathlist_text_ref} = "Lock-File: $opt_lock_file\n";

    return($ade_err_ok);
}

sub jsq_usage
{
    my($errstack_ref, $usage_text_ref, $passno) = @_;

    if ($passno == 1) {
        ${$usage_text_ref} = "\n";
    } elsif ($passno == 2) {
        ${$usage_text_ref} = "         -l <file> | --lockfile=<file>       set lock file\n" .
                             "         -a        | --all                   show all jobs\n";
    }

    return($ade_err_ok);
}

&ade_gep_main(\&jsq);
