#!/usr/bin/perl
# Generates a Perl database of the jobs currently running or in the queue on Westgrid nodes
#
# Author: Daniel Graves
# Date:   2004/11/16
# Modified: Renee Poutissou - fixed error in computing the number of used CPUs
# Date:   2005/07/05

use strict;
use DB_File;
use CGI qw(:standard);

###############################################################
# Global Variables
my %jobs;
my @users;
my $total_nodes_used;
my $total_jobs_queued;
my $total_jobs_running;
my %user_summaries;
my $disk_db_path = "/home/e614/public_html/private/sysman/wg_jobsrunning_db";
my $default_db_name = "jobsrunning.YYY.db";  # YYY gets replaced with log number 0-$num_days
my @important_values = ('Job_Name','job_state','resources_used.cput','resources_used.mem','resources_used.walltime','Resource_List.nodes','exec_host');

###############################################################
# Colors
my $color;
my $bgcolor;
my $bg_norm_color = "\"#FFFFDF\"";
my $norm_color = "\"#000000\"";
my $table_header_color = "\"#221AA0\"";
my $bg_table_header_color = "\"#CCDDEE\"";
my $bg_e614_color = "\"#FFAA88\"";
my $e614_color = "\"#0F44AA\"";
my $total_color = "\"#004433\"";
my $bg_total_color = "\"#F0DD40\"";

###############################################################
# Open database file
my $db_name = $default_db_name;
$db_name =~ s/YYY/0/;
my $mode = 0555;
dbmopen(%jobs,"$disk_db_path/$db_name",$mode) or die "Could not open $disk_db_path/$db_name!\n";
# Get the parameters to the script using $ENV{QUERY_STRING}
my $user;
if($ENV{QUERY_STRING} !~ '') {
  $user = $ENV{QUERY_STRING};
}

###############################################################
# Print html headers
print header;
print start_html('Westgrid - Jobs Running Database');
print links_header(),
  p,
  "Last updated ".`date --date='$jobs{"date_modified"}'`."\n",
  p;
  
###############################################################
# Print main jobs running table
if($user) {
  print  h1("Westgrid - Jobs Running for User <B><I>$user</I></B>"),
    p;
  print "<TABLE border=\"1\"><TR ALIGN=\"center\" BGCOLOR=$bg_table_header_color>";
  print "<TH><FONT COLOR=$table_header_color>Job ID</FONT>";
  print "<TH><FONT COLOR=$table_header_color>Job Owner</FONT>";
  print "<TH><FONT COLOR=$table_header_color>Job Name</FONT>";
  print "<TH><FONT COLOR=$table_header_color>Job State</FONT>";
  print "<TH><FONT COLOR=$table_header_color>CPU Time Used</FONT>";
  print "<TH><FONT COLOR=$table_header_color>Memory Used (kb)</FONT>";
  print "<TH><FONT COLOR=$table_header_color>Walltime Used</FONT>";
  print "<TH><FONT COLOR=$table_header_color># CPU's Requested</FONT>";
  print "<TH><FONT COLOR=$table_header_color>Local Node(s) Used</FONT>";
  foreach my $job_id (sort keys %jobs) {
    print_job_info($job_id);
  }
  print "</TABLE>";
}
else {  # Just print a summary statistics table for all users
  print  h1("Westgrid - Jobs Running Summary"),
    p;
  print "<TABLE border=\"1\"><TR ALGIN=\"center\" BGCOLOR=$bg_table_header_color>";
  print "<TH><FONT COLOR=$table_header_color>User</FONT>";  # Create a link to the user usage page
  print "<TH><FONT COLOR=$table_header_color>Number of Jobs Queued</FONT>";
  print "<TH><FONT COLOR=$table_header_color>Number of Jobs Running</FONT>";
  print "<TH><FONT COLOR=$table_header_color>Number of CPU's Used</FONT>";
  foreach my $job_id (keys %jobs) {
    accumulate_user_summary($job_id);
  }
  foreach my $u (sort @users) {
    if($u =~ m/^\s*$/) {next;}
    
    if($u =~ 'e614') {
      $color = $e614_color;
      $bgcolor = $bg_e614_color;
    }
    else {
      $color = $norm_color;
      $bgcolor = $bg_norm_color;
    }
    
#     Fills blanks with -
    if(!$user_summaries{"$u"."-queued"}) {
      $user_summaries{"$u"."-queued"} = '-';
    }
    if(!$user_summaries{"$u"."-running"}) {
      $user_summaries{"$u"."-running"} = '-';
    }
    if(!$user_summaries{"$u"."-nodes"}) {
      $user_summaries{"$u"."-nodes"} = '-';
    }

    print "<TR ALGIN=\"center\" BGCOLOR=$bgcolor>";
    print "<TH><A HREF=\"websummary.pl?$u\">$u</A>";
    print "<TH><FONT COLOR=$color>".$user_summaries{"$u"."-queued"}."</FONT>";
    print "<TH><FONT COLOR=$color>".$user_summaries{"$u"."-running"}."</FONT>";
    print "<TH><FONT COLOR=$color>".$user_summaries{"$u"."-nodes"}."</FONT>";
  }
  $color = $total_color;
  $bgcolor = $bg_total_color;
  print "<TR ALGIN=\"center\" BGCOLOR=$bgcolor>";
  print "<TH><FONT SIZE=5 COLOR=$color>Total</FONT>";
  print "<TH><FONT SIZE=5 COLOR=$color>".$total_jobs_queued."</FONT>";
  print "<TH><FONT SIZE=5 COLOR=$color>".$total_jobs_running."</FONT>";
  print "<TH><FONT SIZE=5 COLOR=$color>".$total_nodes_used."</FONT>";
  print "</TABLE>";
}

###############################################################
# Close the database
print p,
  "Last updated ".`date --date='$jobs{"date_modified"}'`."\n",
  p;
print end_html;
dbmclose(%jobs) or warn "Could not close $disk_db_path/$db_name\n";
exit(0);

sub print_job_info($) {
  my $id = shift;
  my $owner;
  
  my $e = $jobs{"$id"};
  $color = $norm_color;
  $bgcolor = $bg_norm_color;

  $e =~ m/Job_Owner\s=\s(.+)\@.+\n/;  # Get just the name
  $owner = $1;
  
  if($owner !~ $user) {
    return;
  }
  
  print "<TR ALGIN=\"center\" BGCOLOR=$bgcolor>";
  print "<TH><FONT COLOR=$color>".$id."</FONT>";
  print "<TH><FONT COLOR=$color>".$owner."</FONT>";
  foreach my $search (@important_values) {
      if($search =~ "Resource_List.nodes"){
	  my $ppn = 1;
	  my $nodes = -1;
          my $count = 0;
	  if($e =~ m/nodes\s=\s(\d+)/ ) { 
	      $nodes = $1;
	      if($e =~ m/:ppn=(\d+)\n/) {
		  $ppn = $1;
	      }
	  }
	  $count = $nodes * $ppn;
	  print "<TH><FONT COLOR=$color>".$count."</FONT>";
      }
      else {
	  if($e =~ m/$search\s=\s(.+)\n/) {
	      print "<TH><FONT COLOR=$color>".$1."</FONT>";
	  }
	  else {
	      print "<TH><FONT COLOR=$color>"."-"."</FONT>";
	  }
      }
  }
  print "\n";
}

sub accumulate_user_summary($) {
  my $id = shift;
  my $owner;
  
  my $e = $jobs{"$id"};
  $color = $norm_color;
  $bgcolor = $bg_norm_color;

  $e =~ m/Job_Owner\s=\s(.+)\@.+\n/;  # Get just the name
  $owner = $1;
  my $add = 1;
  foreach my $u (@users) {
    if($u =~ $owner) {
      $add = 0;
    }
  }
  if($add) {
    push(@users,$owner);
  }
  
  $e =~ m/job_state\s=\s(.+)\n/;
  my $job_state = $1;
  my $count = 0;
  if($job_state =~ 'Q') {
    $user_summaries{"$owner"."-queued"}++;
    $total_jobs_queued++;
  }
  elsif($job_state =~ 'R') {
    $user_summaries{"$owner"."-running"}++;
    $total_jobs_running++;

# RP  New method of calculating the number of Cpu's used
 
    my $ppn = 1;
    my $nodes = -1;
    $e =~ m/nodes\s=\s(\d+)/ ; 
    $nodes = $1;
    if($e =~ m/:ppn=(\d+)\n/) {
	$ppn = $1;
    }
    $count = $nodes * $ppn;
  }
# The following method does not work because there could be more than one
#line of text containing the host names
#  $e =~ m/exec_host\s=\s(.+)\n/;
#  my $exec_host = $1;
#  my $count = 0;
#  while($exec_host =~ m/ice/) {
#    $count++;
#    $exec_host =~ s/ice/ICE/;
#  }

  if($count) {
    $user_summaries{"$owner"."-nodes"} = $count + $user_summaries{"$owner"."-nodes"};
    $total_nodes_used = $total_nodes_used + $count;
  }
}

sub links_header {
  return "<CENTER><TABLE cellpadding=\"10pt\" BGCOLOR=\"#DCDCAC\"><TR>"
      ."<TD WIDTH=\"15%\"><CENTER><A HREF=\"websummary.pl\">Show Job Summary for All Users</A></CENTER></TD>"
      ."<TD WIDTH=\"15%\"><CENTER><A HREF=\"history_websummary.pl\">Show History of e614 Jobs</A></CENTER></TD>"
      ."</TABLE></CENTER>\n";
}
