my ($self, $bacct_source_line) = @_;
print "LSF::parse_report_source_line( \"$bacct_source_line\" )\n";
# Conplete list of exit codes is available at
# https://www.ibm.com/support/knowledgecenter/SSETD4_9.1.3/lsf_admin/termination_reasons_lsf.html
my %status_2_cod = (
'TERM_MEMLIMIT' => 'MEMLIMIT',
'TERM_RUNLIMIT' => 'RUNLIMIT',
'TERM_OWNER' => 'KILLED_BY_USER', # bkill (wait until it dies)
'TERM_FORCE_OWNER' => 'KILLED_BY_USER', # bkill -r (quick remove)
'TERM_BUCKET_KILL' => 'KILLED_BY_USER', # bkill -b (kills large numbers of jobs as soon as possible)
'TERM_REQUEUE_OWNER'=> 'KILLED_BY_USER', # Job killed and requeued by owner
);
my %units_2_megs = (
'K' => 1.0/1024,
'M' => 1,
'G' => 1024,
'T' => 1024*1024,
);
local $/ = "------------------------------------------------------------------------------\n\n";
open(my $bacct_fh, '-|', $bacct_source_line);
my $record = <$bacct_fh>; # skip the header
my %report_entry = ();
for my $record (<$bacct_fh>) {
chomp $record;
# warn "RECORD:\n$record";
my @lines = split(/\n/, $record);
if( my ($process_id) = $lines[0]=~/^Job <(\d+(?:\[\d+\])?)>/) {
my ($exit_status, $exception_status) = ('' x 2);
my ($when_born, $meadow_host);
my ($when_died, $cause_of_death);
my (@keys, @values);
my $line_has_key_values = 0;
foreach (@lines) {
if( /^(\w+)\s+(\w+\s+\d+\s+\d+:\d+:\d+)(?:\s+(\d{4}))?:\s+(?:\[\d+\]\s+)?[Dd]ispatched to\s<([\w\-\.]+)>/ ) {
$meadow_host = $4;
}
elsif( /^(\w+)\s+(\w+\s+\d+\s+\d+:\d+:\d+)(?:\s+(\d{4}))?:\s+Completed\s<(\w+)>(?:\.|;\s+(\w+))/ ) {
$cause_of_death = $5 && ($status_2_cod{$5} || 'SEE_EXIT_STATUS');
$exit_status = $4 . ($5 ? "/$5" : '');
}
elsif(/^\s*EXCEPTION STATUS:\s*(.*?)\s*$/) {
$exception_status = $1;
$exception_status =~s/\s+/;/g;
}
elsif(/^\s*CPU_T/) {
@keys = split(/\s+/, ' '.$_);
$line_has_key_values = 1;
}
elsif($line_has_key_values) {
@values = split(/\s+/, ' '.$_);
$line_has_key_values = 0;
}
}
#warn join(', ', map {sprintf('%s=%s', $_, $usage{$_})} (sort keys %usage)), "\n";
my ($mem_in_units, $mem_unit) = $usage{'MEM'} =~ /^([\d\.]+)([KMGT])$/;
my ($swap_in_units, $swap_unit) = $usage{'SWAP'} =~ /^([\d\.]+)([KMGT])$/;
$report_entry{ $process_id } = {
# entries for 'worker' table:
'meadow_host' => $meadow_host,
'when_born' => $when_born,
'when_died' => $when_died,
'cause_of_death' => $cause_of_death,
# entries for 'worker_resource_usage' table:
'exit_status' => $exit_status,
'exception_status' => $exception_status,
'mem_megs' => $mem_in_units * $units_2_megs{$mem_unit},
'swap_megs' => $swap_in_units * $units_2_megs{$swap_unit},
'pending_sec' => $usage{'WAIT'},
'cpu_sec' => $usage{'CPU_T'},
'lifespan_sec' => $usage{'TURNAROUND'},
};
}
}
close $bacct_fh;
my $exit = $? >> 8;
die "Could not read from '$bacct_source_line'. Received the error $exit\n" if $exit;
return \%report_entry;
}