#!/usr/bin/perl
#
# scan job execution log files from the NASA Ames iPSC/860 system, and use convert2swf.pm
# to convert the data into the standard workload format.
#

use warnings;
use strict;
use Time::Local;
use POSIX;
use convert2swf_v4;


############################
#
# DO THE CONVERSION:
#

my $tz_str    = "US/Pacific";
my $max_procs = 128;
my @queues    = ("interactive",
		 "batch"
		 );

$ENV{TZ} = $tz_str;
POSIX::tzset();

SWF::init( $tz_str, $max_procs, \@queues );

my $format_bugs;
my $jobs_data = get_jobs();

my ($zero, $maxtime) = SWF::convert( $jobs_data, $format_bugs );

my $header = generate_header( $zero, $maxtime, $max_procs );

SWF::print( $header );



#####################################
# SPECIFICS for NASA iPSC workload

#
# the format of each entry includes the following space-separated fields:
# 0  user (rootX, sysadminX, intelX, developX, supportX, or userX)
# 1  job (cmdX, nqsX, or Unix commands; nqs numbers are all unique)
# 2  nodes
# 3  runtime (secs)
# 4  start date
# 5  start time

my $job_cnt;

sub get_jobs {
##############
# parse input format and create a hash for each job

   my @list_of_jobs;

   #
   # scan trace and collect job info
   #
   while (<>) {

       #
       # parse line and extract info
       #

       if (/^\s*$/) {          # empty line
           next;
       }

       if (/special/) {        # special data -- not a job
           next;
       }

       $_ =~ /\s*(.*)\s*/;             # get rid of white space at ends
       $_ = $1;
       my @line = split('\s+');        # split into fields

       if ($#line != 5) {
           $format_bugs .= "format_problem $_\n";
           warn(">>>Format problem on $_\ngot $#line fields (should be 5)");
           next;
       }

       my %nj;

       #
       # set the desired fields as specified in convert2swf.pl
       #

       $nj{trace}  = $_;       # used for error messages

       # translate human readable start date and time into time array
       my @begtmarr;
       ($begtmarr[4],$begtmarr[3],$begtmarr[5]) = split('/',$line[4]);
       ($begtmarr[2],$begtmarr[1],$begtmarr[0]) = split(':',$line[5]);
       $begtmarr[4]--;
       my $start = &timelocal(@begtmarr);

       $nj{start} = $start;

       # no data about submit time, so use start time
       #$nj{submit} = $start;

       # no data about end time, so just use runtime
       $nj{run} = $line[3];


       # 0 procs indicates a job on the service node
       my $nodes = $line[2];

       if ($nodes == 0) {
	   next;
       }

       $nj{procs} = $nodes;

       # make users group 1, and all system guys group 2
       my $user = $line[0];

       $nj{user} = $user;

       if ($user =~ /user/) {
	   $nj{group} = 1;
       }
       else {	# sysadmin and friends
	   $nj{group} = 2;
       }

       # application data for NQS jobs is fake
       my $app = $line[1];

       if ($app =~ /nqs/) {
	   $nj{queue} = "batch";
       }
       else {
	   $nj{queue} = "interactive";
	   $nj{app}   = $app;
       }

       $list_of_jobs[$job_cnt++] = \%nj;
   }

   return \@list_of_jobs;
}


sub generate_header {
   my ($zero, $maxtime, $max_procs) = @_;

   my ($sec, $min, $hr, $mday, $mon, $year, $wday, $yday, $isdst);

   $header  = "; Version: 2.2
; Computer: Intel iPSC/860
; Installation: NASA Ames Research Center
;
; Acknowledge: Bill Nitzberg
; Information: http://www.nas.nasa.gov/
;              http://www.cs.huji.ac.il/labs/parallel/workload/
;
";

   $header .= sprintf("; Conversion: Dror Feitelson (feit\@cs.huji.ac.il) %s\n",
                      strftime("%d %b %Y", localtime()));

   $header .= sprintf("; MaxJobs: %d\n", $job_cnt);
   $header .= sprintf("; MaxRecords: %d\n", $job_cnt);
   $header .= "; Preemption: No\n";

   $header .= sprintf("; UnixStartTime: %d\n", $zero);
   $header .= "; TimeZone: -28800\n";
   $header .= sprintf("; TimeZoneString: %s\n", $tz_str);

   $header .= sprintf("; StartTime: %s\n",
          strftime("%a %b %d %H:%M:%S %Z %Y", localtime($zero)));

   $header .= sprintf("; EndTime:   %s\n",
          strftime("%a %b %d %H:%M:%S %Z %Y", localtime($maxtime)));

   $header .= "; MaxNodes: $max_procs\n";
   $header .= "; MaxProcs: $max_procs\n";

   $header .= "; Note: There is no information on wait times - the given submit\n";
   $header .= ";       times are actually start times\n";
   $header .= "; Note: group 1 is normal users\n";
   $header .= ";       group 2 is system personnel\n";

   $header .= "; Note: there is no data about batch queues\n";

   return $header;
}
