 # *-*-perl-*-*
    eval 'exec perl -S $0 "$@"'
    if $running_under_some_shell;
# ------------------------------------------------
# Get the most recent checker error report
#			erhyuant@catarina.usc.edu
# ------------------------------------------------

$PATTERN = "CHECKER PROCESSING STATISTICS";	#pattern of start of record
$INPUT = "/usr/checker/checker-err.stats";			#default input file
$URL = "http://excalibur.usc.edu/research/checker/man/checker";
# for explain rcode in QUERY/RESPONSE table
$RCODE = "http://excalibur.usc.edu/research/checker/checker-rcode.html";

$LastMatched = "";		#last matched item

#mapping: reference name --> HTML explanation file name
$external_labels{"Traffic"} = "$URL/subsubsection3_4_4_1.html#Traffic";
$external_labels{"Config"} = "$URL/subsubsection3_4_4_1.html#Config";
$external_labels{"Memory"} = "$URL/subsubsection3_4_4_1.html#Memory";
$external_labels{"Control"} = "$URL/subsubsection3_4_4_1.html#Control";
$external_labels{"Chart"} = "$URL/subsubsection3_4_4_1.html#Chart";
$external_labels{"Query"} = "$URL/subsubsection3_4_4_2.html";
$external_labels{"Server"} = "$URL/subsubsection3_4_4_3.html";
$external_labels{"QR_Table"} = "$URL/subsubsection3_4_4_4.html";
$external_labels{"Err_Table"} = "$URL/subsubsection3_4_4_5.html";
$external_labels{"PurgedRcd"} = "$URL/subsubsection3_4_5_2.html#PurgedRcd";

# for the error coditions in ERROR TABLE
$external_labels{"Err_con0"} ="$URL/subsubsection3_4_4_6.html#Err_con0";
$external_labels{"Err_con1"} ="$URL/subsubsection3_4_4_6.html#Err_con1";
$external_labels{"Err_con2"} ="$URL/subsubsection3_4_4_6.html#Err_con2";
$external_labels{"Err_con3"} ="$URL/subsubsection3_4_4_6.html#Err_con3";
$external_labels{"Err_con4"} ="$URL/subsubsection3_4_4_6.html#Err_con4";
$external_labels{"Err_con5"} ="$URL/subsubsection3_4_4_6.html#Err_con5";
$external_labels{"Err_con6"} ="$URL/subsubsection3_4_4_6.html#Err_con6";
$external_labels{"Err_con7"} ="$URL/subsubsection3_4_4_6.html#Err_con7";
$external_labels{"Err_con8"} ="$URL/subsubsection3_4_4_6.html#Err_con8";
$external_labels{"Err_con9"} ="$URL/subsubsection3_4_4_6.html#Err_con9";
$external_labels{"Err_con10"} ="$URL/subsubsection3_4_4_6.html#Err_con10";

@err_condition =  (
      "Resolver NoSrvfail",	# SERVER_FAILURE_A
      "Namservr NoSrvfail",	# SERVER_FAILURE_B
      "Fast Retransmit",	# FAST_RX
      "Ignored Referrals",	# RECURSION_A
      "Ignored No Record",	# ZERO_ANSWER
      "Requery Inside TTL",	# CACHE_LEAK
      "Too Many Referrals",	# RECURSION_B
      "Host Named Self",	# RECURSION_C
      "Ignored No Domain",	# NAME_ERROR
      "No Central Cache",	# NO_CENTRAL_CACHE
      "Format Error"		# FORMAT_ERROR
      );

# for explain rcode in Response/Query Table
$external_labels{"Rcode_0"} ="$RCODE#OK";
$external_labels{"Rcode_1"} ="$RCODE#formerr";
$external_labels{"Rcode_2"} ="$RCODE#servfail";
$external_labels{"Rcode_3"} ="$RCODE#nxdomain";
$external_labels{"Rcode_4"} ="$RCODE#not_impl";
$external_labels{"Rcode_5"} ="$RCODE#refused";
$external_labels{"Rcode_6"} ="$RCODE#bad_code";

@rcode_text = (
	"OK", 
	"formerr", 
	"servfail", 
	"nxdomain",
	"not impl", 
	"refused", 
	"bad code" 
	);


require 'getopts.pl';
$USAGE = "USAGE: $0 options
        (ex $0 -f /usr/checker/checker-err.stats)
        -h      this message
        -f      input file  (default: checker-err.stats)
";

&Getopts ('hf:o:');
if ($opt_h) { print $USAGE; exit; }

# setup file handler (RPT_IN) for input 
$in_file = ($opt_f)? $opt_f : $INPUT;
open (RPT_IN,"$in_file") || die "Error: Open $in_file for reading!";

# search the start position of the most recent report
$recent_position = -1;
while (!eof (RPT_IN)) {
  $file_posi = tell (RPT_IN);
  $_ = <RPT_IN>;
  if (/$PATTERN/) { $recent_position = $file_posi; }
}

#position file to the start of most recent record then copy to output file
if ($recent_position >= 0) { 
  seek (RPT_IN, $recent_position, 0);
  &gen_html (); 
}
else { die "No report yet!"; }

close (RPT_IN);
exit;
#--------------------------------------------

# parse error report into a HTML document
sub gen_html {
print "\n\n";
print <<EOM;
<html> <body>
<center> <h2>
Checker Processing Statistics Report
</h2> </center>
EOM
;

# setup links at head of pages
print "<P>\n";
&setup_link ("Traffic","Packets Traffic");
print "||    ";
&setup_link ("Config","Configuration Flags");
print "||    ";
&setup_link ("Memory","Memory Usage");
print "||    ";
&setup_link ("Control","Control Parameters");
print "||    ";
&setup_link ("Chart","Usage Rate Chart");
print "||    ";
&setup_link ("Query","Unique Queries Report");
print "||    ";
&setup_link ("Server","Name Server Usage");
print "||    ";
&setup_link ("QR_Table","Query/Response Table");
print "||    ";
&setup_link ("Err_Table","Error Table Report");

$_ = <RPT_IN>;
print "<h4>$_</h4>";
print "<PRE>";
# loop each line and insert necessary links
#--------------------------------------------
  while (<RPT_IN>) { 
    if (&insert_link ($_,"packets seen","Traffic","Packets Traffic:")) {}
    elsif (&insert_link ($_,"nocheck_auth","Config","Configuration Flags:")) {}
    elsif (&insert_link ($_,"dynamic database","Memory","Memory Usage:")) {}
    elsif (&insert_link ($_,"expected for requery","Control","Control Parameters:")) {}
    elsif (&insert_link ($_,"Usage Rate Chart","Chart","Usage Rate Chart:")) {}
    elsif (&insert_link ($_,"UNIQUE QUERIES","Query","Unique Queries Report:")) {}
    elsif (&insert_link ($_,"SERVER USAGE","Server","Name Server Usage:")) {}
    elsif (&insert_link ($_,"RESPONSE TABLE","QR_Table","Query/Response Table:")) {}
    elsif (&insert_link ($_,"ERROR TABLE","Err_Table","Error Table:")) {}
    elsif (&insert_link ($_,"ERROR TABLE","PurgedRcd","Records purged due to no reference within timeout:")) {}
    # insert rcode (response error code) in "RESPONSE TABLE" section
    elsif ($LastMatched eq "QR_Table") 
    {
      if (!&insert_rcode_explain_link ($_)) {
        print "$_"; 
      }
    }
    # insert Error condition explanation
    elsif ($LastMatched eq "Err_Table" || $LastMatched eq "PurgedRcd") 
    {
      if (!&insert_err_explain_link ($_)) {
        print "$_"; 
      }
    }
    else 
    { 
      print "$_"; 
    }
  }
#--------------------------------------------
print "</PRE>";
print "</body> </html>";
EOM
}
#--------------------------------------------

sub insert_link {
  local ($text,$pattern,$name,$msg) = @_;
   
  if ($matched{$name} == 0 && $text =~ /$pattern/) {
      # Multiple index onpurged record due to timeout
      if ($name ne "PurgedRcd") { $matched{"$name"} = 1;}
      $LastMatched = $name;
      $external_labels = &name2html ($name);
      print "</PRE>";
      print "<A NAME=\"$name\"><H4>$msg ";
      print "<A HREF=\"$external_labels\">(detailed explanation)</H4></A>";
      print "<PRE>";
      print "$text";
      return (1);
  }
  return (0);
}


sub setup_link {
  local ($name,$msg) = @_;

  print "<A HREF=\"\#$name\"><STRONG>$msg   </STRONG></A>\n";
}
#--------------------------------------------

# mapping reference name into a html file name
sub name2html {
  return ($external_labels{"$_[0]"});
}
#--------------------------------------------
# check and insert error condition explain
sub insert_err_explain_link {
  local ($text) = @_;
  local ($i, $pattern);
  local ($ext_labels);

  # eliminate unnecessary checking
  # check only lines which begin with 6 blank spaces
  if (substr($text,0,6) ne "      ") { return (0);}

  # separate the text into 3 field, try to match second field only */
  for ($i=0; $i < scalar(@err_condition); ++$i) {
    $pattern = $err_condition[$i];
    if ($text =~ /^([\s]*)($pattern)(.*)$/) {
      $ext_labels = &name2html ("Err_con$i");
      print "$1<A HREF=\"$ext_labels\">$2</A>$3\n";
      return (1);
    }
  }
  return (0);
}
#--------------------------------------------
# check and insert rcode(response error code) explain
sub insert_rcode_explain_link {
  local ($text) = @_;
  local ($i, $pattern);
  local ($ext_labels);

  # eliminate unnecessary checking
  # check only lines which begin with a fromat " ddd.d"
  if (!(substr($text,0,6) =~  /^[ ]*[\d]+\.\d$/)) { return (0);}

  # separate the text into 3 field, try to match second field only */
  $text =~ /(\s*\d+\.\d+\s*\d+\s*\d+\s*\d+\.\d+\s*)(\w+)(.*)/;
  for ($i=0; $i < scalar(@rcode_text); ++$i) {
    $pattern = $rcode_text[$i];
    if ($pattern eq $2) {
      $ext_labels = &name2html ("Rcode_$i");
      print "$1<A HREF=\"$ext_labels\">$2</A>$3\n";
      return (1);
    }
  }
  return (0);
}

