#!/usr/local/bin/perl

# When run in a directory that has the appropriate files or given the
# directory name with -d, it extracts the time for traversals or another
# string as specified by the -s option from these files in a useful manner
# (for the graphs)

sub usage_assert { # Parameter Boolean, string
    local($val, $str) = @_;
    if ($val) {return;}
    usage ($str);
}

sub usage { # Paramaters: Error string
    local($err) = @_;
    print "ERROR: $err\n";
    $usage = join(' ', "correct_lru_nums -f <file> [-s datastring]\n");
    print "$usage\n\n";
    exit;
}

sub rec_sort {
    if ($$a{PAGE} != $$b{PAGE}) {
	return $$a{PAGE} <=> $$b{PAGE};
    }
    if ($$a{EVICT} != $$b{EVICT}) {
	return $$a{EVICT} <=> $$b{EVICT};
    }
    $$a{CACHE} <=> $$b{CACHE};
}

$nargs = $#ARGV + 1;
$dirname = ".";
$datastring = "Time for traversal";
$fetch_file = "NULL";
for ($i = 0; $i < $nargs; $i += 2) {
    $option = @ARGV[$i];
    $val = @ARGV[$i+1];
    if ($option eq "-f") {
	$fetch_file = $val;
    } elsif ($option eq "-s") {
	$datastring = $val;
    } else {
	usage "Bad option: $option $val";
    }
}

sub key_sort {
    ($apage, $aeviction, $acache, $atname, $atemp) = split("_", $a);
    ($bpage, $beviction, $bcache, $btname, $btemp) = split("_", $b);
    $acache = substr($acache, 1);
    $apage = substr($apage, 1);
    $aeviction = substr($aeviction, 1);
    $bcache = substr($bcache, 1);
    $bpage = substr($bpage, 1);
    $beviction = substr($beviction, 1);
    if ($atname ne $btname) { $res = $atname cmp $btname;}
    elsif ($atemp ne $btemp) { $res = $atemp cmp $btemp;}
    else {
	$res = $acache <=> $bcache;
    }
    return $res;
}

usage_assert(-e $fetch_file, "Fetch data file $fetch_file should exist");
$lsoutput = `ls $dirname`;
# We need numbers for same traversal and temperature to be on the same graph
# So create a hash table that maps traversal+temp to a list
# that contains <cachesize, pagesize, pageinfo> entries
# Then we sort on cachesize and inside that on pagesize


@files = split("\n", $lsoutput);
foreach $file (@files) {
    # Get the page size, cache size, traversal name, hot or cold
    ($page, $eviction, $cache, $tname, $temp) = split("_", $file);
    $cache = substr($cache, 1);
    $page = substr($page, 1);
    $eviction = substr($eviction, 1);
    open(FILE, "$dirname/$file");

    # Get the final time for traversal. Take the average
    $num = 0;
    $data = $compaction_time =  $stackscan_time = $pagescan_time = 0;
    $total_fetch_time = $total_scans = $total_fetches = 0;
    $total_scans = -1;
    $total_fetches = -1;
    while (<FILE>) {
	if (/$datastring\s+=\s+(.*)/) {
	    $data += $1;
	    $num++;
	} elsif (/Page compaction time:\s+(.*)/) {
	    $compaction_time += $1;
	} elsif (/Stack scan time:\s+(.*)/) {
	    $stackscan_time += $1;
	} elsif (/Page scan time:\s+(.*)/) {
	    $pagescan_time += $1;
	} elsif (/Total fetch time.*including.*:\s+(.*)/) {
	    $total_fetch_time += $1;
	} elsif (/Number of scans.*compactions.*:\s+(.*)/) {
	    $total_scans += $1;
	} elsif (/Number of fetches.*:\s+(.*)/) {
	    $total_fetches += $1;
	}
    }
    if (!$num) {
	print "No information about point: $file\n";
	$num = -1;
    }
    $data = $data/$num;
    close(FILE);

    # printf("Info:      %2s, %4s, %6s, %2s\n", $tname, $temp, $cache, $page);
    $key = $file;
    $travinfo = $trav_hash{$key};
    # Map the traversal+temperature to array of records
    $rec = { CACHE => $cache, PAGE => $page, EVICT => $eviction, DATA => $data,
	     COMPACTION_TIME  => $compaction_time/$total_scans,
	     STACKSCAN_TIME   => $stackscan_time/$total_scans,
	     PAGESCAN_TIME    => $pagescan_time/$total_scans,
	     TOTAL_FETCH_TIME => $total_fetch_time/$num,
	     FETCHES          => $total_fetches/$num
	     };
    $trav_hash{$key} = $rec;
}

# Read the overheads file
open(FETCH_FILE, $fetch_file);
$trav = "NULL";
$cache = -1;
$page_size = -1;
$avg_fetch_time = -1;
while (<FETCH_FILE>) {
    if (/TRAVERSAL: (.*)$/) {
	$trav = $1;
    } elsif (/Page Size = (\d)K, Eviction = (\d)/) {
	$page_size = $1;
	$eviction = $2;
    } elsif (/(\d+) ::.*Fetch: (.*)/) {
	$cache = $1;
	$avg_fetch_time = $2;

	$rec = { CACHE => $cache, PAGE => $page_size, EVICT => $eviction,
		 AVG_FETCH_TIME => $avg_fetch_time };
	$key = "${trav}-${page_size}-$eviction-$cache";
	$overheads_hash{$key} = $rec;
    }
}
close(FETCH_FILE);
$prev_page = -1;
$prev_eviction = -1;
$prev_tname = "NULL";
$prev_temp = "NULL";

foreach $trav (sort key_sort keys %trav_hash) {
    ($page, $eviction, $cache, $tname, $temp) = split("_", $trav);
    $cache = substr($cache, 1);
    $page = substr($page, 1);
    $eviction = substr($eviction, 1);
    $rec = $trav_hash{"$trav"};

    # print "KKKKKKKKK $trav\n";

    $old_time = $$rec{DATA};
    $old_fetch_time = $$rec{TOTAL_FETCH_TIME};
    $fetch_key = "${tname}-${temp}-${page_size}-$eviction-$cache";

    $fetch_rec = $overheads_hash{$fetch_key};
    $new_fetch_time = $$rec{FETCHES} * $$fetch_rec{AVG_FETCH_TIME};
    $new_time = $old_time - $old_fetch_time + $new_fetch_time;
    if ($page != $prev_page || $eviction != $prev_eviction ||
	$tname ne $prev_tname || $temp ne $prev_temp) {
	print "\n\nTraversal: $tname  $temp,  ";
	print "Page Size = ${page}K, Eviction = $eviction\n\n";
	$prev_page = $page;
	$prev_eviction = $eviction;
	$prev_tname = $tname;
	$prev_temp = $temp;
    }
    printf("%5d :: Old::  F: %7.3f, T: %7.3f, ", $cache, $old_fetch_time,
	   $old_time);
    printf("New:: F: %7.3f, T: %7.3f\n", $new_fetch_time, $new_time);
}
