#! c:\orant\ows\cartx\common\perl\bin\perl
#
# $Header: f60parse.pl@@/main/TOOLS_DEV2K_994/17 \
# Checked in on Fri Mar 16 16:16:05 PST 2001 by vobadm \
# Copyright (c) 2001 by Oracle Corporation. All Rights Reserved. \
# $
#
#
############################################################################
# Copyright (c) 1996, 2001 by Oracle Corporation */
#
#   NAME
#     parse.pl -- Oracle Forms Performance Collector Parsing routine
#
#   DESCRIPTION
#
#   PUBLIC FUNCTION(S)
#
#   PRIVATE FUNCTION(S)
#
#   RETURNS
#
#   NOTES
#
#   VERSION
# $Id: f60parse.pl /main/TOOLS_DEV2K_994/17 16-mar-1.16:16:4 vobadm $
#
#   MODIFIED    (MM/DD/YY)
#     vasokkum   06/02/00 -  Modify the Frontpage and more changes to Relative
#                         -  time;
#     vasokkum   05/31/00 -  Print the Handshake parameter correctly
#     vasokkum   05/30/00 -  Add description in the beginning 
#     vasokkum   05/26/00 -  Include Client Time also in processing
#     vasokkum   04/04/00 -  Comment the debug info 
#     vasokkum   01/31/00 -  A better string indicating user action 
#     vasokkum   01/25/00 -  A better feel for UI
#     vasokkum   12/28/99 -  Print Help info and Generate HTML outputs
#     vasokkum   12/28/99 -  Modify for the changes in Timestamp event renaming
#     vasokkum   12/05/99 -  Accept null activities in the log fine
#     vasokkum   12/03/99 -  Command Line arguments accepted
#     vasokkum   11/15/99 -  Make Eventfile as optional input
#     vasokkum   06/30/99 -  Commandline Parameters added
#     vasokkum   06/12/99 -  Creation
############################################################################
#
# This PERL script analyses the time stamps collected by the Performance
# collection option set during runform execution. The option to be set to
# enable performance collector is "record=collect" or "record=all".i
# This file takes care of user defined events and generates
# the corresponding data accordingly 
############################################################################
#use Getopt::Long;             # to take care of command line options 

#########################################################################
# Global variables
#########################################################################
$TIMESTKEY = 'TSE';    # timestamp info starts with this key
$CACHEKEY = 'CAC';     # cached info starts with this key
$ERRORKEY = 'ERROR';
$EVENTKEY = 'EVENT_PT:';       # event info starts with this key
$ACTIONKEY = '#####';  # Indicates the start of user action


#########################################################################
# Available options
#########################################################################  

    PrintHelp();
GetOptions( "input=s" => \$input,
#            "eventf=s" => \$eventf,
            "os=s" => \$os_type,
            "output=s" => \$output );
#########################################################################
# Processing Starts from here 
#########################################################################  

    $Tempfptr = 0;    # temporary variable to store the file pointer 
    $Orgfptr = 0;     # File pointer where the actual data starts   
    $Stuseract = 0;   # First Useraction named as Start
    $TSEventcnt = 0;  # Number of time stamp events
    $Ceventcnt = 0;   # Number of cache events.
    $Curline = "";    # Line to read data from inputfile
    $Actioncnt = 0;   # Number of User actions
    $Totalcnt = 0;
    $Totaltime = 0;
    $Mintime = 100000;
    $Maxtime = 0;
    $Linecnt = 0;         # Count the number of lines already processed.
    ##
    ##Parse the command line and get the Parameters 
    ##
    ($Infile, $Eventfile, $Outfile) = GetParams($input, $eventf, $output);

    for (;;) 
    {
        chomp($os_type);
        $uos_type = uc($os_type);
        if (($uos_type eq "N") )
        {
            $div_factor = 1;
            last;
        }
        if ( ($uos_type eq "U"))
        {
            $div_factor = 1000000;
            last;
        }
        print "\n Please specify the OS on which the data was collected ";
        print "\n Press (N) for NT and (U) for all Unix Systems :";
        $os_type = <STDIN>;
    }
    $output = 1;
    ##
    ##Open the input file
    ##
    open(INPUT, "$Infile") ||
        die "Not able to open Input file $Infile $!";
    
        ##
    ##Skip the header information in the Input file
    ##
    SkipHeader();

    ProcessData();
    PrintIntro();
    ##
    ##Open the output file
    ##
    $sumoutput = "summary.html";
    $lvl1out   = "detailed.html";
    $lvl2out   = "detailed2.html";
    print "Output files are $sumoutput $lvl1out and $lvl2out";
    ##
    ##Prepare the event list by reading the event file
    ##
    print "\n Processing Event File $Eventfile .....";
    GetEvents($Eventfile);
#    print " Done eventfile"; # $test = <STDIN>;
    ##
    ##Generate the list of event intervals
    ##
    open(INPUT, "perf.out") ||
        die "Not able to open Input file $Infile $!";
    $Orgfptr = 0;

    print "\n Creating Event Intervals .....";
    CreateTSEventIntervals();
    print " Done    "; 

    print "\n Creating Time Stamp Events .....";    
    CreateTSEventList();
    print " Done";

    print "\n Creating User Defined Intervals .....";
    #CreateUserEventList();
    print " Done";
    if ( $Outfile ne "" )
    {
        open (OUTPUT, "> $Outfile") ||
            die "Not able to open Output file $Outfile $!";
    }

    select (OUTPUT);
    PrintSummary();
    PrintDetails($Actioncnt);
    PrintSummaryXML();
    PrintDetailsXML();
    PrintGlossaryHTML ();
    

#########################################################################
#   Subroutine : GetParams()
#   This routine gets the arguments from the user when used in the
#   interactive mode
#########################################################################

sub GetParams()
{
    my ($Infile, $Eventfile, $Outfile) = @_;

#    print "input file is $input \n";
    $Infile = $input;
    for ( ;; )
    {
        if ( $Infile ne "" )
        {
            if (! -r $Infile )
            {   
                print " File not found: $Infile\n";
                $Infile = "";
            }
            elsif (! -f $Infile )
            {
                print " Not a plain file: $Infile\n";
                $Infile = "";
            }
            else
            {
                last;
            }
        }
        print "\n Specify the input file name: "; 
        chomp ($Infile = <STDIN> );
    }
    $Eventfile = $eventf;
    if ( $Eventfile eq "" )
    {
#        print "\n Event file is not specified. Using the Default events";
    }
    else
    {
        print "Event file is $eventf \n";
    }
    $Outfile = $output; 
    if ( $Outfile eq "" )
    {
#        print "\n Output file not specified. ";
#        print "\n Generating only the HTML output in index.html ";
        print "\n Specify CSV output file (leave blank if CSV not desired): ";
        chomp ($Outfile = <STDIN> );
    }
    else
    {
#        print "\n Output file is $output \n";

    } 
    if ( $Outfile )
    {
        $output = 1;
    }
    return ($Infile, $Eventfile, $Outfile);
}        

#########################################################################
#  Subroutine : SkipHeader ()
#  This routine reads the input file and skips the header partof it.
#########################################################################

sub SkipHeader( )
{
    my ($Action, $Event, $Val, $Curfptr);

    open(RUNDET, "> runtime.html") ||
           die "Not able to open the Runtime details file $!";
    select (RUNDET);
    print "<HTML> <HEAD>";
    print "<title>Forms 6i Performance Collector Analysis</title>";
    print "<center> <H1>Forms Server Platform Configuration and Runtime Details </H1> </center></HEAD> <BODY>";
    $Action = "";

    print "The information listed on this page refers to the Forms Server unless labelled otherwise.";

    while ( $TIMESTKEY ne $Action )
    {
         print "<h4>$Curline</h4>";
         $Curfptr = tell(INPUT);
         chomp($Curline = <INPUT> );
         $Linecnt++;
         ($Action, $Event) = split(' ', $Curline, 2);
    }
    print "</BODY> </HTML>";
    close(RUNDET);
    select(STDOUT);

    @array1 = split(' ', $Curline);
    $StartUpTime = $array1[4];
    chomp($Curline = <INPUT> );

   @array1 = split(' ', $Curline);
    $HandShake = $array1[4];

    $Resevent = "Handshake"." ".$HandShake;
    $Linecnt += 2;

}

#########################################################################
#  Subroutine : ProcessData ()
#  This routine reads the input file processes the data and generates
#  the intermediate file. 
#########################################################################

sub ProcessData()
{
    my ($i); $first=0;

    #$Val = seek(INPUT, $Orgfptr, 0);
    $FilePtr[0] = tell(INPUT); # $Orgfptr;
   
    open(OUTPUT, "> perf.out") ||
         die "Not able to open output file $Outfile";
    select(STDOUT);
    while( <INPUT> )
    {
        chomp($Curline = $_);
       
        $Linecnt++;
        ($Temp, $Event) = split(' ', $Curline, 2);
        if ( $Temp eq $ACTIONKEY )
        {
            $Val =  tell(INPUT);
            $FilePtr[$i++] = tell(INPUT);
        }
        if ( $Temp eq '#')        {
            chomp($Curline = <INPUT>);
            if ( $first == 1 )
            {
		$FilePtr[$i++] = tell(INPUT);
	    } 
	    if ( $ActionList[$i-1] eq "")
            {
		$ActionList[$i-1] = $Curline;	     
		$first++;
	    }
	    else
	    {                
		#print "Actionlist is $ActionList[$i] for value $i";
	    }
        }
        
    }
    print "\n Processed $Linecnt lines"; 
    $FilePtr[$i] = tell(INPUT);
  
    $Eventcnt = $i;
    #for ( $i = 0; $i < $Eventcnt; $i++ )
    #{
	#print "\n $i is Actionlist is $ActionList[$i] ";
    #}
    select(OUTPUT);
    $cnt = 0;
    for ( $i = 0;$i < $Eventcnt; $i++ )
    {
        $Val = seek(INPUT, $FilePtr[$i], 0);
        if ( $ActionList[$i] ne '')
        {
            print "\n EVENT_PT: $cnt $ActionList[$i]";
            $cnt++;	   
        }      
        while ( $Val < $FilePtr[$i+1] )
        {
            chomp($Curline = <INPUT>);
            ($Temp , $Event) = split(' ', $Curline, 2);
            if ( $Temp eq $TIMESTKEY )
            {
		print "\n $Curline";
            }
	    $Val = tell(INPUT);
	}
    }
    close (INPUT);
    close (OUTPUT);
} 
       


#########################################################################
#  Subroutine : GetEvents()
#  This routine opens and reads the event file.
#  Creates two hash lists for storing the details
#  EventHash has the EventStart and ends and the nick names
#  GroupHash has the name of the group to which it belongs to.
#  The grouphash is used to maintain multiple levels of data
#  for the end user. 
#########################################################################
sub GetEvents( )
{
    my ($Efile) = @_;
    my ($nick, $Pgroup, $Stactual, $Endactual, $Actual, $count, $ival, $failed);
    $evfile = "event.html";
    open (EVENTDEF, ">$evfile ") || 
            die "Not able to create Event Definition File event.html $!";

    
    $failed = 0;
    $count = 12; 
    ##
    ##Open the event file 
    ##
    if (! -r $Efile )
    {   
         print "Not able to read event file $Efile";
         $failed = 1;
    }
    if (! -f $Efile )
    {
        print "Input file $Efile is not a plain file \n";
        $failed = 1;
    }
   
    open( EVENT, "$Efile") ;

    if ( !EVENT )
    {
         print "Not able to open Event file $Efile $!";
         $failed = 1;
    }
    if ( $failed == 1 )
    {
        #print "\n Assuming Default Events as below";
        $tempevt[0] ="Network       Network    FSERVER_END    FSERVER_START";
        $tempevt[1] ="Database      DBLogon        DBLOGON_START  DBLOGON_END";
        $tempevt[2] ="FormsServer   FSPostLogon     DBLOGON_END    FSERVER_END";
        $tempevt[3] ="Database      DBPROC        DB_START       DB_END";
        $tempevt[4] ="FormsServer   FSMidDB       DB_END         DB_START";
        $tempevt[5] ="FormsServer   FSPostDB     DB_END         FSERVER_END";
        $tempevt[6] ="FormsServer   FSPreLogoff    FSERVER_START   DBLOGOFF_START";
        $tempevt[7] ="Database      DBLogoff       DBLOGOFF_START DBLOGOFF_END"; 
        $tempevt[8] ="FormsServer   FSPreLogon       FSERVER_START DBLOGON_START"; 
        $tempevt[9] ="FormsServer   FSPreDB       FSERVER_START DB_START"; 
        $tempevt[10] ="FormsServer  FSPostLogoff  DBLOGOFF_END DB_START"; 
        $tempevt[11] ="ClientTime   ClientTime  temp1           temp1        "; 

        for ( $ival = 0; $ival < $count; $ival++ )
        { 
            ($Pgroup, $nick, $Stactual, $Endactual) = split ' ',$tempevt[$ival];
            $Actual = $Stactual.'-'.$Endactual;
            $EventHash{$Actual} = $nick;
            $GroupHash{$Actual} = $Pgroup;
        }
        
    }
    else 
    {
        $ival = 0;
        while ( <EVENT> )
        {
            $tempevt[$ival] = $_;
            ($Pgroup, $nick, $Stactual, $Endactual) = split ' ', $_ ;
            $Actual = $Stactual.'-'.$Endactual;
            #print "Event is $Actual"; $test = <STDIN>;
            $EventHash{$Actual} = $nick;
            $GroupHash{$Actual} = $Pgroup;
            $ival++;   
        }
        $count = $ival-1; 
    }
    select(EVENTDEF);
    print "\n <html> \n <head>";
    print "\n<title>Forms 6i Performance Collector Analysis</title>";
    print "\n<\/head> \n    <body>";
    print "\n <h1> <center> Within-Tier Event Definitions</center> </h1>";
    print "<p>Presents the formulas used to calculate various ";
    print "\n<a href=\"glossary.html#within_tier_event\">within-tier events<\/a>.";
    print "\n<p><b>Note<\/b> that Client and Network each have only one within-tier event defined.";
    print "\n<p><b>Note<\/b> that the formulas used to calculate <a href=\"glossary.html#duration\">durations<\/a> ";
    print "\nof within-tier events use labels from the <a href=\"$Infile\">input file</a> ";
    print "\nto denote <a href=\"glossary.html#system_time_stamp\">system timestamps</a>.<br>";

    print("\n<table width=100% border=1> <thead>");
    print "\n  <th><a href=\"glossary.html#tier\">Tier<\/a><\/th>";
    print "\n  <th><a href=\"glossary.html#within_tier_event\">Within-Tier Event<\/a><\/th>";
    print "\n  <th><a href=\"glossary.html#duration\">Duration<\/a><\/th>";
    print "\n.";

    print "\n <\/thead> <tbody>";

    for ( $ival = 0; $ival < $count; $ival++ )
    { 
        ($Pgroup, $nick, $Stactual, $Endactual) = split ' ',$tempevt[$ival];
        $Actual = $Stactual.'-'.$Endactual;

        # Catch 'ClientTime' event. Needs special explanation.
        if ( $Pgroup eq "ClientTime" )
        {
            $special_text = "Special case: included with FSERVER_START label";
            print "<tr> <td>$Pgroup <\/td> <td>$nick<\/td><td>$special_text<\/td><\/tr>";
        }
        else
        {
            print "<tr> <td>$Pgroup <\/td> <td>$nick<\/td><td>$Actual<\/td><\/tr>";
        }
    } 
    print "<\/tbody> <\/table>";

    print "<\/body><\/html>  ";       

    ##
    ## Add temporary values to take care of other events
    ##
    $EventHash{"temp"} = "FormsServer";
    $GroupHash{"temp"} = "FormsServer";
    #while ( ($k, $v) = each %EventHash) 
    #{
    #     print "$k => $v \n";
    #}
    select(STDOUT); 
    return (EventHash);
}   

#########################################################################
#  Subroutine : GroupInit()
#  This routine initialises the Hash to store group details.
#  The grouphash is used to maintain multiple levels of data
#  for the end user. 
#########################################################################
sub GroupInit ( )
{
    my (@Gvalue,$Gstr);

    my ($Str, $Total, $Min, $Max) = ( "", 0, 100000, 0);
    $Str = join ',', $Total, $Min, $Max;

    @Gvalue = values % GroupHash;
    foreach $Gstr ( @Gvalue ) 
    {
        $GdataHash{$Gstr} = $Str;
    }
    # print "GroupInit called now ................."; $test = <STDIN>;
    #@Gvalue = keys % GdataHash;
}
#########################################################################
#  Subroutine : ClientInit()        
#  This routine initialises the ClientTime variables
#########################################################################
sub ClientandNetInit( )
{
    $Clientcnt = 0;
    $CMintime = 0;
    $CMaxtime = 0;
    $Clienttime = 0;
    $Netcnt    = 0;
    $NMintime = 0;
    $NMaxtime = 0;
    $Nettime = 0;
}

#########################################################################
#   Subroutine : CreateTSEventIntervals()
#   This routine prepares a list of Time Stamp Events from the input file
#########################################################################
sub CreateTSEventIntervals()
{
    my ($Stevent, $Endevent,$Stendevent);

    $Val = seek(INPUT, $Orgfptr, 0);
    $Actioncnt = 0;  
    $tempfptr = $Orgfptr;
    while ( <INPUT> )
    {
        @array1 = split ' ',$_;
        if ( $array1[0] ne "" )   # Skip the empty lines
        {
            while ( ($array1[0] ne $EVENTKEY) && ($array1[0] ne $ERRORKEY) ) 
            {
	        if ( ($array1[0] eq $TIMESTKEY) )
                {
                    $Curline = $_;
                    $tempfile = tell(INPUT);
                   
                    if ( $Stevent ne $array1[1] )
                    {
                        $Stendevent = $Stevent.'-'.$array1[1];
                        $Stevent = $array1[1];
                        $TSEventcnt = $#TSEventlist + 1;
                        for ( $i= 0; $i < $TSEventcnt; $i++ )
                        {
                           if ( $TSEventlist[$i] eq $Stendevent )
                           {
                               last;
                           }
                        }
                        # 
                        # it is a new event. So, insert into array
                        #
                        if ( $i == $TSEventcnt )
                        {
                             $TSEventlist[$i] = $Stendevent;
                             $TSEventcnt ++;
                             last;
		        }
                    }
                    else   # Someother event, so skip that
		    {
                       last;
	            }
                }
                else  # skip the lines which do not have a 
                  # TIMESTKEy or EVENTKEy 
                {
                     last;
                }
            }
            #
            # This is where the time stamp of the actual user events
            # get stored. 
            #
            if ( $array1[0] eq $EVENTKEY )
            {
               
                $Resstr = $array1[2]."_".$array1[4].",".$array1[5];
                $ActionList[$Actioncnt] = $Resstr;
                #print "The Resstr here is $Resstr .... "; $test = <STDIN>;
                $FPList[$Actioncnt] = tell(INPUT); 
                chomp($Curline = <INPUT>);
              
	        @array1 = split ' ',$Curline;
	        if ( $array1[0] eq $TIMESTKEY )
	        {
	            $Stevent = $array1[1];
		    $CTimeList[$Actioncnt] = $array1[3];
		    $TimeList[$Actioncnt++] = $array1[4];
	        }
                else
                {
                    print "Invalid sequence in the intermediate file";
		    $test = <STDIN>;
                }
            }
            $EndTimeList[$Actioncnt] = $array1[4];
       }
       $tempfptr = tell(INPUT);
   }
   $FPList[$Actioncnt] = $tempfile;
    $EndTimeList[0] = $TimeList[0];

    
}
#########################################################################
#   Subroutine : CreateTSEventList()
#   This routine prepares a list of Time Stamp Events from the input file
#   This routine reads the list of events between any two user actions as
#   shown by the FPList and estimates the duration of different events.
#   
#   FPList  is the list of file pointers pointing to the User action point
#           in the logged information
#   TSEventList is the list of TimeStamp events that are available
#   
#   ActionList  is the list of User actions, i.e. names 
#   ThinkList   list of think times
#   
#########################################################################
sub CreateTSEventList()
{

    for $i ( 0 .. $#FPList )
    {
         #print "Entering CreateTSeventlist for $i in $#FPList"; $test=<STDIN>;
         $Actendtime = 0;
         $Enduseract = $ActionList[$i];
         GroupInit();
         $Stfptr = $FPList[$i];
         $Endfptr = $FPList[$i+1];

         for ( $j = 0; $j < @TSEventlist; $j++ )
         {

             $Totalcnt = 0;
             $Totaltime = 0;
             $Mintime = 100000;
             $Maxtime = 0;
             seek(INPUT, $Stfptr, 0);
             $Curfptr = tell(INPUT);
             ($Stevent, $Endevent) = split('-', $TSEventlist[$j]);
             while( ($Endfptr > $Curfptr) )
             {
                 $Curline = GetNewLine ($Stevent, $Endfptr);
                 $filepos = tell(INPUT);
                 if ( $Curline )
                 {
                     ($Event1, $Bytes1, $Cstime, $Sttime) 
			 = split ' ',$Curline;
		     chomp($Newline = <INPUT>);
                     $filepos = tell(INPUT);
                     ($Readval, $Str) = split(' ', $Newline, 2);
                     if ( $Readval ne $TIMESTKEY )
		     {
			 $Curfptr = tell (INPUT);
		     }
		     ($Actstr, $Evstr) = split  ' ', $Str;
		     if ($Actstr eq $Endevent)
		     {
			 #print "Finding a match for $Actstr with $Endevent"; 
			 #$test=<STDIN>;
			 ($Action, $Bytes2, $Cetime, $Endtime) 
			     = split ' ',$Str;
			 if ($Actendtime < $Endtime )
			 {
			     $Actendtime = $Endtime;
			     $Lastevent = $Str;
			 }
			 #print "\n Endtime $Endtime and Starttime $Sttime"; 
			 $Time = ($Endtime - $Sttime) /$div_factor;
			 if ( ($Stevent eq 'FSERVER_END' ) &&
			     ($Endevent eq 'FSERVER_START') )
			 {
			     $CTime = ($Cetime - $Cstime);
			     if ( $CTime > $Time )
			     {
				 $CTime = $Time;
			     }
			     #print "\n Diff is $Time $CTime"; $test=<STDIN>;
			     UpdateClientTotal($CTime);
			     UpdateNetTotal($Time - $CTime);
			     UpdateGTotal("Network", $Time - $CTime);
			 } 
			 else
			 {
			     #print "\n Diff is $Time"; $test=<STDIN>;
			     UpdateTotal($Time);
			 }
		     }
		 }
		 $Curfptr = tell (INPUT);
	     }
  
	     $Curaction = $Stevent.'-'.$Endevent;
	     if ( exists ($EventHash{$Curaction}) )
	     {
		 $Resevent = $EventHash{$Curaction};
		 $Resstr = join(' ', $Resevent, $Totalcnt,
				$Totaltime, $Mintime, $Maxtime);
		 #print "Resstr here is $Resstr Action cnt $Actioncnt"; 
		 #$test = <STDIN>;
	     }
	     else
	     {
		 $Curaction = "temp";
		 $Resevent = $EventHash{$Curaction};
		 $Resstr = join(' ', $Resevent, $Totalcnt,
				$Totaltime, $Mintime, $Maxtime);
	     }

	     #
	     ##If the group name exists for the action in the
	     ##current list, add to that grouplist. Otherwise,
	     ##add to the group with name Groupname list  
	     ##Otherwise assume the groupname as FormsServer and
	     ##update in that.
	     if ( exists ($GroupHash{$Curaction}) )
	     {
		 $Pgroup = $GroupHash{$Curaction};
		 #print "\n Getting the gname $Pgroup for $Curaction"; 
		 #$test=<STDIN>;
		 UpdateGTotal($Pgroup, $Totaltime);
             }
          
             if ( $Totalcnt > 0 )
             {
                 if ( $Resstr )
                 {
                     push(@ResList, $Resstr);
                 }
             }  
	 }
	 
	 if ( $i > 0 )
	 {
	     $temp =  ($TimeList[$i] - $EndTimeList[$i])/$div_factor;
	     $ctime = $CTimeList[$i];
	     if ( $ctime > $temp )
	     {
		 $ctime = $temp ;
	     }               
	     UpdateNetTotal($temp - $ctime);
	     UpdateGTotal("Network", $temp - $ctime);
	     UpdateClientTotal($ctime);
	 }
	 if ( $Clientcnt > 0 )
	 {
	     
	     $Resevent = "Network";
	     $Resstr = join(' ', $Resevent, $Netcnt, 
			   $Nettime, $NMintime, $NMaxtime);
	    
	     push(@ResList, $Resstr); 
	     $Resstr = join(' ', "ClientTime", $Clientcnt,
			    $Clienttime, $CMintime , $CMaxtime);
	     
	     push(@ResList, $Resstr);
	     if ( exists ($GroupHash{"temp1-temp1"}))
	     {
		 $Pgroup = $GroupHash{"temp1-temp1"};
		 UpdateGTotal($Pgroup, $Clienttime);
	     }
	     ClientandNetInit();
	     
	 }
        if ( $#ResList >= 0)
        {
            push @ActResults, [@ResList];
           
            push @GroupResults, [%GdataHash];
            #while ( ($k, $v) = each %GdataHash) 
            #{
            #     print "$k => $v \n";
            #}
            #$test = <STDIN>;
            ResetGTotal("Network");
            ResetGTotal("temp1-temp1");
            $#ResList = -1;
        }
        else
        {
            #print "Trying to push empty here ????????"; $test=<STDIN>; 
            push @ActResults, "Here comes the nulvalues";
            push @GroupResults, "Here comes emptty group";
            $#ResList = -1;
        }
    }
    $EndTimeList[$Actioncnt] = $Endtime;
    for ( $k = 0; $k <= $Actioncnt  ;$k++ )
    {
         #print "EndTimelist is $EndTimeList[$k] ?????"; $test=<STDIN>;
    }
}

#########################################################################
sub CreateUserEventList()
{
    my (@UserEventlist);

    @UserEventlist = keys %EventHash;

    for $i ( 0 .. $#FPList )
    {
         # Read from the Actionlist
         $Actendtime = 0;
         $Enduseract = $ActionList[$i];
         $Stfptr = $FPList[$i];
         $Endfptr = $FPList[$i+1];
         
         foreach $UserEvent (@UserEventlist) 
         {
             $Totalcnt = 0;
             $Totaltime = 0;
             $Mintime = 100000;
             $Maxtime = 0;
             seek(INPUT, $Stfptr, 0);
             $Curfptr = tell(INPUT);
             ($Stevent, $Endevent) = split('-', $UserEvent);
             #print "Looking for event $UserEvent "; $test = <STDIN>;
 
             while( ($Endfptr > $Curfptr) )
             {
                 $Curline = GetNewLine ($Stevent, $Endfptr);
                 #print "Coming here current line  $Curline"; $test=<STDIN>;
                 if ( $Curline )
                 {
                     ($Event1, $Bytes1, $Stctime, $Sttime)
			 = split ' ',$Curline;
                      $Newline = GetNewLine($Endevent, $Endfptr);
                      #print "Reading new line $Newline"; $test=<STDIN>;
                      ($Action, $Bytes2, $Endetime, $Endtime) 
			  = split ' ',$Newline;
                      if ($Action eq $Endevent)
                      {
                          #print "Finding a match"; $test=<STDIN>;
                          if ($Actendtime < $Endtime )
                          {
                              $Actendtime = $Endtime;
                              $Lastevent = $Actstr;
                          }
                          #print "Endtime $Endtime and sttime $Sttime\n";
                          $Time = ($Endtime - $Sttime) /$div_factor;
                          #print "Updating time $Time"; $test=<STDIN>;
			  $CTime = ($Endctime - $Stctime);
                          UpdateTotal($Time);
                       }
                   }
                   $Curfptr = tell (INPUT);
              }
              $Resevent = $EventHash{$UserEvent};
              #print "UserEventlist is $UserEvent";
              $Resstr = join(' ', $Resevent, $Totalcnt,
                                 $Totaltime, $Mintime, $Maxtime);
              #print "\n Resstr here is $Resstr Action cnt $Actioncnt"; 
              #$test = <STDIN>;
              if ( $Resstr )
              {
                  #print "pushing now..."; $test=<STDIN>;
                  push(@UserList, $Resstr);
              }
          }
          if ( $#UserList > 0 )
          {
              #print "User list here is @UserList\n"; $test=<STDIN>;
              push @TUserList, [@UserList];
              $#UserList = -1;
          }
    }
}
#########################################################################
#  Subroutine : GetNewLine()
#  This routine reads the input file and returns the next valid line for
#  processing. 
#  Input : Event of interst
#  Output : Line containing the event of interest
#########################################################################

sub GetNewLine {
    my ($EndAction) = $_[0];

    my ($Test, $Readval, $Str, $Actstr, $Evstr, $Tval, $lptr, $tptr );

    $Tval = $Action;
    $lptr = tell(INPUT);
    while ( $lptr < $Endfptr )
    {
        if ( !eof(INPUT) )
        {
             chomp ($_ = <INPUT>);
             ($Readval, $Str) = split (' ', $_, 2);
             $lptr = tell (INPUT);
             if ( $Readval eq $TIMESTKEY )
             {
                 ($Actstr, $Evstr) = split ' ', $Str;
                 if ( $Actstr eq $EndAction )
                 {
                     return ($Str);
                 }
             }
             else
             {
                 $Str = "";
                 return $Str;
             }
        }
        else
        {
             $Endfptr = $lptr; 
        }
    }
    return "";
}
#########################################################################
#  Subroutine : UpdateTotal()
#  This routine updates the global variables $Mintime, $Maxtime
#  $Totalcnt and $Totaltime for an event
#  Input : Time value to be used for updating the global variables 
#  Output : NULL
#########################################################################
sub UpdateTotal( )
{
    my $ttime = $_[0];

    $Totalcnt++;
    $Totaltime += $ttime;
    if ( $ttime < $Mintime )
    {
        $Mintime = $ttime;
    }
    else
    {
        if ( $Totalcnt == 1 )
        {
            $Mintime = $ttime;
        }
    }
    if ( $ttime > $Maxtime )
    {
        $Maxtime = $ttime;
    }
} 
#########################################################################
#  Subroutine : UpdateTotal()
#  This routine updates the global variables $Mintime, $Maxtime
#  $Totalcnt and $Totaltime for an event
#  Input : Time value to be used for updating the global variables 
#  Output : NULL
#########################################################################

sub UpdateClientTotal( )
{
    my $ttime = $_[0];

    $Clientcnt++;
    $Clienttime += $ttime;
    if ( $ttime < $CMintime )
    {
        $CMintime = $ttime;
    }
    else
    {
        if ( $Clientcnt == 1 )
        {
            $CMintime = $ttime;
        }
    }
    if ( $ttime > $CMaxtime )
    {
        $CMaxtime = $ttime;
    }  
} 
sub UpdateNetTotal()    
{
    my $ttime = $_[0];

    $Netcnt++;    
    if ( $ttime < 0 )
    {
        $ttime = 0;
    }
    $Nettime += $ttime;
    if ( $ttime < $NMintime )
    {
        $NMintime = $ttime;
    }
    else
    {
        if ( $Netcnt == 1 )
        {
            $NMintime = $ttime;
        }
    }
    if ( $ttime > $NMaxtime )
    {
        $NMaxtime = $ttime;
    }
   
} 
#########################################################################
#  Subroutine : UpdateGTotal()
#  This routine updates the global variables $Minval, $Maxval and
#  TotalTime for a group of events 
#  Creates the Event list and returns to the calling routine
#  Input : Groupname, Time to be addeded to the group
#  Output : NULL, Adds in the global % and returns 
#########################################################################

sub UpdateGTotal( )
{
    my ($groupname, $ttime) = @_;

    my ($Outstr, $TotalTime) = ("", 0);
    my ($Minval, $Maxval) = (100000, 0);
    
    $Outstr = $GdataHash{$groupname};
    ($TotalTime, $Minval, $Maxval) = split (',',$Outstr,3);
    $TotalTime += $ttime;
    if ( $ttime < $Minval )
    {
        $Minval = $ttime;
    }
    if ( $ttime > $Maxval )
    {
        $Maxval = $ttime;
    }
    $Outstr = $TotalTime.','.$Minval.','.$Maxval;
    $GdataHash{$groupname} = $Outstr;
}
#########################################################################
#  Subroutine : UpdateGTotal()
#  This routine updates the global variables $Minval, $Maxval and
#  TotalTime for a group of events 
#  Creates the Event list and returns to the calling routine
#  Input : Groupname, Time to be addeded to the group
#  Output : NULL, Adds in the global % and returns 
#########################################################################

sub ResetGTotal(  )
{
    my ($groupname)  = @_;

    my ($Outstr, $TotalTime) = ("", 0);
    my ($Minval, $Maxval) = (100000, 0);
    
    $Outstr = $GdataHash{$groupname};

    $Outstr = $TotalTime.','.$Minval.','.$Maxval;
    $GdataHash{$groupname} = $Outstr;
}        

#########################################################################
#  Subroutine : PrintSummary
#  This routine Prints the Summary list. This mainly concentrats on the
#  user think time.
#  
#########################################################################

sub PrintSummary( )
{
    my ($i, $Sttime, $Tmptime, $Oldtime, $Duration, $Diff);
    
	
    print "\n",'-' x 80, "\n";
    print " , , ,Summary \n";
    print "\n";
    print "No, Action, , Time of , , Client+ \n";
    print ", , , Occurance,  , Net Time\n";
    print " , , ,Absolute,Relative \n";
    print " , , ,(msec),(msec),(msec) \n";
    print '-' x 80, "\n";

    # print 'STARTUP' action
    $Duration = $StartUpTime/$div_factor;
    $Diff     = ($HandShake - $StartUpTime)/$div_factor;
    printf (",STARTUP,STARTUP,%20f,%10.3f \n",
                     $Duration, $Diff);

    # print 'Handshake' action
    $Duration = $HandShake/$div_factor;
    $Diff     = ($TimeList[0] - $HandShake)/$div_factor;
    printf (",Handshake,Handshake,%20f,%10.3f \n",
                     $Duration, $Diff);

    $Sttime = 0;
    $Oldtime = $TimeList[0];

    for $i ( 0 .. $Actioncnt-1)
    {
        $Tmptime = $TimeList[$i];
#        $Duration = ($Tmptime)/$div_factor;
        $Duration = ($EndTimeList[$i] - $Sttime)/$div_factor;
#        $Diff = ($Tmptime - $Oldtime)/$div_factor;

        # Don't calculate 'diff' if this is the last in the list
        if ( $i < $Actioncnt - 1)
        {
            $Diff = ($EndTimeList[$i+1] - $EndTimeList[$i])/$div_factor;
        }
        else
        {
            $Diff = 0;
        }

        printf ("%4d,%25s,%20f,%10.3f \n",
                         $i+1,$ActionList[$i],
                         $Duration, $Diff);
                        
    }
    print "\n \n \n"; 

}

sub PrintSummaryXML( )
{
    my ($i, $Sttime, $Tmptime, $Oldtime, $Duration, $Diff);

    open (SUMOUTPUT, "> $sumoutput") || 
            die "Not able to open Output file $Outfile $!";

    select(SUMOUTPUT);

    print "\n <html> \n <head>";
    print "\n<title>Forms 6i Performance Collector Analysis</title>";
    print "\n<\/head> \n    <body>";
    print "\n<center><h1>Summary List of User Actions<\/h1></center>";

    print "\n<p>";
    print "\nThe following is a list of user actions,";
    print "\nsystem time stamps recorded at the start of each user action,";
    print "\nand lengths of time spent responding to each user action.";
    print "\n<\/p>";

    print "\n<table width=100% border=1><thead>";
    print "\n <tr> <th>#<\/th> ";
    print "\n<th><a href=\"glossary.html#user_action\">User Action<\/a><\/th> ";

    print "\n  <th><a href=\"glossary.html#system_time_stamp\">";
    print "\n  System Time Stamp of User<br>Action in milliseconds<\/a><\/th>";
    print "\n  <th><a href=\"glossary.html#duration\">";
    print "\n  Duration of User Action<br>in milliseconds<\/a><\/th>";
    print "\n <\/thead>";
    $Sttime = 0;
    $Oldtime =$StartUpTime ;
 printf (" <\/tr> ");
    printf("\n<td><\/td>");
    printf("\n<td><a href=\"glossary.html#startup\">STARTUP<\/a><\/td>");
    printf("\n<td>%20f<\/td>", $StartUpTime/$div_factor);
    printf("\n<td>%20f<\/td>", ($HandShake- $StartUpTime)/$div_factor);
      printf (" <\/tr> ");

    printf("\n<td><\/td>");
    printf("\n<td><a href=\"glossary.html#startup\"> Handshake<\/a><\/td>");
    printf("\n<td>%20f<\/td>", ($HandShake)/$div_factor);
    printf ("<td> %10.3f </\td>  ",($TimeList[0] - $HandShake)/$div_factor);
    printf (" <\/tr> <tr> ");
    printf ("\n<td>0 <\/td> \n <td> <a href=\"%s#0\" <\/a> ", $lvl1out);
    printf (" %25s <\/td>  ", $ActionList[0]);
    printf ("<td> %20f </td>  ",($TimeList[0])/$div_factor);

    # only print duration if there is a subsequent timestamp
    if ( $#TimeList >= 1)
    {
        printf ("<td> %10.3f</\td> </tr>  ",
	        ($EndTimeList[1] - $EndTimeList[0])/$div_factor);
    }
    else
    {
        print (" <\/tr> ");
    }

    #$Actioncnt--; $cnt = 0;
    for $i ( 1 .. $Actioncnt-1 )
    {
        printf ("<tr>");
        #$Tmptime = $TimeList[$i];
        $Duration = ($EndTimeList[$i] - $Sttime)/$div_factor;
        #$Diff = ($Tmptime - $Oldtime)/$div_factor;

        # Don't calculate 'diff' if this is the last in the list
        if ( $i < $Actioncnt - 1)
        {
            $Diff = ($EndTimeList[$i+1] - $EndTimeList[$i])/$div_factor;
        }
        else
        {
            $Diff = 0;
        }

        printf ("\n<td> %4d <\/td>  ", $i);
        printf ("\n<td> <a href=\"%s#%d\" <\/a> ", $lvl1out, $i);
        printf (" %25s <\/td>  ", $ActionList[$i]);
        printf ("<td> %20f </td>  ",$Duration);
        if ( $i < $Actioncnt - 1)
        {
            printf ("<td> %10.3f </\td>  ",$Diff);
        }
        else
        {
            print ("<tr>");
        }
        # 
        # This part gives the Client + User + Net time. Since it may not
        # be correct always, this has been removed.
        #if ( $i > 0 )
        #{
        #    printf ("<td>%10.3f </\td> ",
	#	    ($TimeList[$i]-$EndTimeList[$i])/$div_factor);
        #}
        $Oldtime = $Tmptime;
        printf (" <\/tr> \n\n");
    }
   # print '-'x80, "\n";
    print("\n<\/table>");
    print("\n<\/tbody>");
    print("\n<\/table>");
    print("\n<\/body>");
    print("\n<\/html>");    print "\n \n \n";
}
#########################################################################
#  Subroutine : PrintDetails
#  This routine Prints the Details of the events between user actions.
#########################################################################

sub PrintDetails()
{
    my ($i, $Tmpst, $Tmpend, $Ans, $Oldtime, $Duration, $Diff);
    $Stno = 0;
    $Endno = $Actioncnt;

    PrintQuery();
    #PrintUserEvents();
    PrintActions();
}


sub PrintDetailsXML()
{
    my ($i, $Tmpst, $Tmpend, $Ans, $Oldtime, $Duration, $Diff);
    $Stno = 0;
    $Endno = $Actioncnt;

    PrintActionsXML();
    PrintCollectHTML();
#   PrintActionsAllXML();
}

sub PrintQuery()
{
    my ($i, $Tmpst, $Tmpend, $Ans, $Oldtime, $Duration, $Diff);

    if ( !$output )
    {
        until ($Ans eq "y" || $Ans eq "n" || $Ans eq "Y" || $Ans eq "N")
        {
            print "Do you want to see the detailed results? [Y]/[N] \n";
            chomp($Ans = <STDIN>);
        }
	    if ( $ans eq 'n' || $ans eq 'N' )
        {
            exit;
        }
        print "The Detailed results can be displayed between any two \n";
        print "User Actions listed above. Enter the Starting and Ending\n";
        print "action numbers\n";
		print '-' x 80, "\n";
        print "Enter the Starting Action Number default[0]";
        chomp($Stno = <STDIN>);
        if ( !$Stno ) 
        {
            $Stno = 0;
        }
        print "Enter the Ending Action Number default[$Actioncnt]";
        chomp($Endno = <STDIN>);
        if ( !$Endno )
        {
            $Endno = $Actioncnt;
        }
        print "Start no $Stno   End No $Endno\n "; $test=<STDIN>;
    }
   #print '-'x100,"\n";
    print ", , Detailed  Results \n";
    print " ,           BETWEEN ACTION $ActionList[$Stno] and     $ActionList[$Endno] \n,";
}

sub PrintUserEvents()
{
    print "UserAction, , Event, Count, Total,Total,Min,Max,Avg\n";
    print " , , , , , Time,Time,Time,Time,Time\n";
    print" , , , , , (msec),(%),(msec),(msec),(msec)\n";
   # print "\n into Userlist print $Stno    $Endno"; $test=<STDIN>;
    
    for $i ( $Stno+1 .. $Endno-1 )
    {
        print "\n,$ActionList[$i-1],"; 
        $temptotal = 0;
        $tempper = 0;
        $tempval = $TimeList[$i] - $TimeList[$i-1];
        for ( $j = 0; $j <=  $#{$TUserList[$i]} ; $j+=1 )
        {
             $UEvent = $TUserList[$i][$j];
             ($Prevent, $Prcnt, $Prttime, $Prmintime, $Prmaxtime)
                               = split (' ', $UEvent);
             if ( $Prcnt > 0 )
             {
                 $Pravtime = $Prttime/($Prcnt);
             
             printf "%15s,%8d,%11.3f,%11.3f,%10.3f,%11.3f,%11.3f\n, , ,",
                     $Prevent, $Prcnt, $Prttime,$Prttime*100/$tempval,$Prmintime, 
                     $Prmaxtime, $Pravtime;
             }
        }
   }        
   print "\n \n \n,";
        
}

sub PrintActions()
{
    print "UserAction, , Event, Total,Total\n";
    print ", , , ,Time,Time\n";
    print" , , , ,(msec),(%)\n";
    for $i ( $Stno .. $Endno-1 )
    {
        print ",$ActionList[$i],";
        $temptotal = 0;
        $tempper = 0;
        #print "GroupResults is $#{$GroupResults[$i]}"; $test= <STDIN>;
        if($#{$GroupResults[$i]}) 
        {
            $Tempoff = 1;
            if (($TimeList[$i+$tempoff] == $TimeList[$i]) )
            {
                 $tempoff ++;
            }
            $tempval = ($EndTimeList[$i+$tempoff]-$EndTimeList[$i])/$div_factor;
            #print "Tempoval for $i value is $tempval"; $stdin = <STDIN>; 
        }
        for ( $j = 0; $j <  $#{$GroupResults[$i]} ; $j++ )
        {
            $Ghash = $GroupResults[$i][$j];
            @Times = split (',', $GroupResults[$i][$j+1]);
            if ( $Times[0] != "0" ) 
            {
                if ( $tempval != 0 )
                {
                    printf("%15s,%10.3f,%10.3f\n,,,", 
                                   $GroupResults[$i][$j], 
                                   $Times[0], $Times[0]*100/$tempval );
                $temptotal += $Times[0];
                $tempper += ($Times[0]*100/$tempval);
                }
            }
        }
        printf ("GrandTotal, %10.3f, %10.3f", $temptotal, $tempper);
        print "\n \n \n";
    }  
    print "\n\n\n,";
    print "UserAction, , Event,Count,Total,Total,Min,Max,Average\n";
    print " , , ,, ,Time,Time, Time,Time,Time \n";
    print" , , , , ,(msec),(%),(msec),(msec),(msec)\n";

    for $i ( $Stno .. $Endno-1 )
    {
        print ",$ActionList[$i]\n";
        print ", ,RegularEvents,";

        $temptotal = 0;
        $tempper = 0;
        $tempval = ($EndTimeList[$i+1]-$EndTimeList[$i])/$div_factor;
        for $j ( 0 .. $#{$ActResults[$i]} )
        {
            ($Prevent, $Prcnt, $Prttime, $Prmintime, $Prmaxtime)
                               = split (' ', $ActResults[$i][$j]);
             $Pravtime = $Prttime/($Prcnt);
             if ( $tempval > 0 )
             {
                  printf "%15s,%8d,%11.3f,%11.3f,%10.3f,%11.3f,%11.3f\n ,, ,",
		  $Prevent, $Prcnt,                                           
                   $Prttime,$Prttime*100/$tempval,$Prmintime, 
                     $Prmaxtime, $Pravtime;
             
             $temptotal += $Prttime;
             $tempper += ($Prttime*100/$tempval);
             }
        }
        printf "GrandTotal, ,%10.3f, %10.3f,,\n ", $temptotal, $tempper;
    }
    #print "The action count is $Actioncnt \n"; $test = <STDIN>;
    for ( $i = 0; $i < $#Actresults ; $i++ )
    {
        $Aref = $Actresults[$i];
        print "\n Aref is $Aref with count $#Aref";
        for $j ( 0..$#{Aref} )
        {
            print "element $i $j is $Aref->[$j]\n";
            $test = <STDIN>;
        }
    }
}


sub PrintActionsXML()
{
   
    open (LVL1OUTPUT, "> $lvl1out") || 
            die "Not able to open Output file $lvl1out $!";

#    select(STDOUT);
    select(LVL1OUTPUT);
    print "\n <html> \n <head>";
    print "\n<title>Forms 6i Performance Collector Analysis</title>";
    print "\n<\/head> \n    <body>";
    print "\n<center><h1>Detailed List of User Actions<\/h1></center>";

    print "\nThe system timestamps recorded at the boundaries between the three Forms 6i layers";
    print "\n(Forms Client, Forms Server, and Database Server)";
    print "\nallow for the following analysis:";
    print "\n<ul><li>per user action how much time was spent in each tier<\/li>";
    print "\n<li>per user action and per tier how much time was spent performing different tasks within a tier<\/li><\/ul>";

    print "\n<p><b>Note</b> that a fourth tier - <b>Network</b> - has been added to this analysis.";
    print "\nNetwork represents the time spent communicating between the Forms Client and Forms Server.";
    print "\nNetwork does not include time spent communicating between the Forms Server and Database Server.";

    print "\n<p><b>Note</b> that timing values of <b>0</b> mean that time was spent performing an";
    print "\naction but the time taken was less than one millisecond.";

    $Stno = 0;
    for $i ( $Stno .. $Endno-1  )
    {
    printf("\n <a name=%d>", $i);
   # print "\n<center><h2> $i $ActionList[$i]<\/h2></center> <\/a>";
    printf("\n<td> <a href=\"%s#%d\" > ", $lvl2out, $i);
    print "<center><h4>Action $i: $ActionList[$i]<\/h4></center><\/a><\/a>", ;
    printf("\n <\/a> ", $lvl2out, $i);
    print "\n<table width=100% border=1><thead>";
    print "\n  <th colspan=5>User Action Timing Breakdown By Tier<\/th>";
    print "\n  <\/tr>";
    print "\n  <th><a href=\"glossary.html#tier\">Tier<\/a><\/th>";
    print "\n  <th>Total Time<br>in milliseconds<\/th>";
    print "\n  <th>Total Time (%)<\/th>";
#    print "\n  <th><a href=\"glossary.html#min_time\">Min Time<br>in milliseconds<\/a><\/th>";
#    print "\n  <th><a href=\"glossary.html#max_time\">Max Time<br>in milliseconds<\/a><\/th>";
    print "\n <\/thead>";
    print "\n <tr>";
        PrintNextLevel($i);
    print "\n</\tr>  <tr>";
    print("\n<\/table>");

    
    print "\n<br><table width=100% border=1><thead>";
  
    print "\n  <th colspan=7>User Action Timing Breakdown Within Tiers<\/th>";
    print "\n  <\/tr>";
    print "\n  <th><a href=\"glossary.html#within_tier_event\">Within-Tier <br> Event <\/a> <\/th>";
    print "\n  <th><a href=\"glossary.html#count\">Count  <\/a><\/th>";
    print "\n  <th>Total Time<br>in milliseconds<\/th>";
    print "\n  <th>Total Time (%)<\/th>";
    print "\n  <th><a href=\"glossary.html#min_time\">Min Time<br>in milliseconds<\/a><\/th>";
    print "\n  <th><a href=\"glossary.html#max_time\">Max Time<br>in milliseconds<\/a><\/th>";
    print "\n  <th><a href=\"glossary.html#avg_time\">Avg Time<br>in milliseconds<\/a><\/th>";
    print "\n <\/thead>";
    print "\n <tr>";
         PrintNextDetailedLevel($i);
         print "\n</\tr>  <tr>";
    print("\n<\/table>");

    }
    print("\n<\/body>");
    print("\n<\/html>");    print "\n \n \n";

}

sub PrintNextLevel()
{
     my($i) = @_;

       
#     printf("\n<td> <a href=\"%s#%d\" <\/a> ", $lvl2out, $i);
#     print "\n $ActionList[$i] </\td>";
        
     $temptotal = 0;
     $tempper = 0;
     #print "GroupResults is $#{$GroupResults[$i]}"; $test= <STDIN>;
     if($#{$GroupResults[$i]} > 0) 
     {
         $Tempoff = 1;
         if (($TimeList[$i+$tempoff] == $TimeList[$i]) )
         {
              $tempoff ++;
         }
         $tempval = ($EndTimeList[$i+1]-$EndTimeList[$i])/$div_factor;
         #print "Tempoval for $i value is $tempval"; $test = <STDIN>; 
         for ( $j = 0; $j <  $#{$GroupResults[$i]} ; $j++ )
         {
             $Ghash = $GroupResults[$i][$j];
             @Times = split (',', $GroupResults[$i][$j+1]);
            if ( $Times[0] != "0" ) 
            {
                #print "for Groupresult $GroupResults[$i][$j+1]";$test = <STDIN>;
                if ( $tempval != 0 )
                {
                      printf("\n<td><a href=\"event.html\"> %15s </\td></\a>",                                 $GroupResults[$i][$j]);
                      printf("\n<td> %10.3f </\td>", $Times[0]);
                      printf("\n<td> %10.3f </\td>", $Times[0]*100/$tempval);           
#                      printf("\n<td> %10.3f </\td>", $Times[1]);           
#                      printf("\n<td> %10.3f </\td>\n", $Times[2]);                                  			
                      $temptotal += $Times[0];
                      $tempper += ($Times[0]*100/$tempval);
                      print "\n </\tr> <tr>  ";         
		  }
             
            }

           }
           print "\n<\/tr> <tr>   ";         
       }
         
       printf ("\n<td>GrandTotal</\td><td> %10.3f</\td><td> %10.3f</\td>", 
                 $temptotal, $tempper);
       print "</\tr>";         

}

sub PrintActionsAllXML()
{

    open (LVL2OUTPUT, "> $lvl2out") || 
            die "Not able to open Output file $lvl1out $!";
    
    select(LVL2OUTPUT);
    print("<?xml version=\"1.0\" ?>\n");
    print("<?xml-stylesheet type=\"text/xsl\" href=\"detail2.xsl\" ?>\n");
    print("<detail2>");
    print "<item>";
    for $i ( $Stno .. $Endno-1 )
    {
    }
}

sub PrintNextDetailedLevel()
{

     my($i) = @_;

        $temptotal = 0;
        $tempper = 0;
        $tempval = ($EndTimeList[$i+1]-$EndTimeList[$i])/$div_factor;

        for $j ( 0 .. $#{$ActResults[$i]} )
        {
            ($Prevent, $Prcnt, $Prttime, $Prmintime, $Prmaxtime)
                               = split (' ', $ActResults[$i][$j]);
             $Pravtime = $Prttime/($Prcnt);
             if ( $tempval > 0 )
             {
                      printf("\n<td><a href=\"event.html\"> %15s </\a></\td>",
                                   $Prevent );
                      printf("\n<td> %8d </\td>",$Prcnt );
                      printf("\n<td> %10.3f </\td>", $Prttime);
                      printf("\n<td> %10.3f </\td>", $Prttime*100/$tempval);           
                      printf("\n<td> %10.3f </\td>", $Prmintime);           
                      printf("\n<td> %10.3f </\td>\n", $Prmaxtime);
                      printf("\n<td> %10.3f </\td>\n", $Pravtime);                         
                          
                     $temptotal += $Prttime;
                     $tempper += ($Prttime*100/$tempval);
             }
           
             print "</\tr>  <tr>";         
             
        }
        printf "\n<td>GrandTotal</\td> <td> </\td> \n <td>%10.3f</\td>\n<td>%10.3f</\td>\n ",
                        $temptotal, $tempper;
        print "\n</\tr>";   
 }

sub GetOptions {

    my @optionlist = @_;    # local copy of the option descriptions
    my $argend = '--';      # option list terminator
    my %opctl;          # table of arg.specs
    my %aliases;        # alias table
    my @ret = ();       # accum for non-options
    my %linkage;        # linkage
    my $userlinkage;        # user supplied HASH
    $error = 0;
    $genprefix = "(--|-|\\+)";


    # Verify correctness of optionlist.
    %opctl = ();
    while ( @optionlist > 0 ) 
    {
        my $opt = shift (@optionlist);

        # Strip leading prefix so people can specify "-foo=i" if they like.
        $opt = $' if $opt =~ /^($genprefix)+/;


        if ( $opt !~ /^(\w+[-\w|]*)?(!|[=:][infse]@?)?$/ ) 
        {
            warn ("Error in option spec: \"", $opt, "\"\n");
            $error++;
            next;
        }
        my ($o, $c, $a) = ($1, $2);

        if ( ! defined $o ) 
        {
            # empty -> '-' option
            $opctl{$o = ''} = defined $c ? $c : '';
        }
        else 
        {
            # Handle alias names
            my @o =  split (/\|/, $o);
            $o = $o[0];
            foreach ( @o ) 
            {
                if ( defined $c && $c eq '!' ) 
                {
                    $opctl{"no$_"} = $c;
                    $c = '';
                }
                $opctl{$_} = defined $c ? $c : '';
                if ( defined $a ) 
                {
                    # Note alias.
                    $aliases{$_} = $a;
                }
                else 
                {
                    # Set primary name.
                    $a = $_;
                }
            }
        }

        # Copy the linkage. If omitted, link to global variable.
        if ( @optionlist > 0 && ref($optionlist[0]) ) 
        {
            print STDERR ("=> link \"$o\" to $optionlist[0]\n")
            if $debug;
            if ( ref($optionlist[0]) eq 'SCALAR') 
            {
                $linkage{$o} = shift (@optionlist);
            }
            else 
            {
                warn ("Invalid option linkage for \"", $opt, "\"\n");
                $error++;
            }
        }
    }

    # Bail out if errors found.
    return 0 if $error;

    # Show if debugging.
    if ( $debug ) 
    {
        my ($arrow, $k, $v);
        $arrow = "=> ";
        while ( ($k,$v) = each(%opctl) ) 
        {
            print STDERR ($arrow, "\$opctl{\"$k\"} = \"$v\"\n");
            $arrow = "   ";
        }
    }

    my $opt;            # current option
    my $arg;            # current option value
    my $array;          # current option is array typed

    # Process argument list
    while ( @ARGV > 0 ) 
    {
        # >>> See also the continue block <<<

        #### Get next argument ####

        $opt = shift (@ARGV);
        $arg = undef;
        my $optarg = undef;
        $array = 0;
        print STDERR ("=> option \"", $opt, "\"\n") if $debug;

        #### Determine what we have ####

        # Double dash is option list terminator.
        if ( $opt eq $argend ) 
        {
            # Finish. Push back accumulated arguments and return.
            unshift (@ARGV, @ret)
        }

        if ( $opt =~ /^$genprefix/ ) 
        {
            ($temp, $optarg) = split ('=',$opt,2);
            #oks like an option.
            $opt = $';      # option name (w/o prefix)
        }

        # ...otherwise, terminate.
        else 
        {
            # Push this one back and exit.
            unshift (@ARGV, $opt);
            return ($error == 0);
        }

        #### Look it up ###
        ($temp, $optarg) = split('=',$opt, 2);
        $opt = $temp;
        $tryopt = $opt;
        my $type;
        unless  ( defined ( $type = $opctl{$tryopt} ) ) 
        {
            print STDERR ("Unknown option: ", $opt, "\n");
            $error++;
            next;
        }

        $opt = $tryopt;
        print STDERR ("=> found \"$type\" for ", $opt, "\n") if $debug;

        #### Determine argument status ####

        # Get mandatory status and type info.
        my $mand;
        ($mand, $type, $array) = $type =~ /^(.)(.)(@?)$/;
        # Check if there is an option argument available.
        if ( defined $optarg ? ($optarg eq '') : (@ARGV <= 0) ) 
        {
            # Complain if this option needs an argument.
            if ( $mand eq "=" ) 
            {
                print STDERR ("Option ", $opt, " requires an argument\n");
                $error++;
            }
            next;
        }

        # Get (possibly optional) argument.
        $arg = defined $optarg ? $optarg : shift (@ARGV);
        #print "\n Latest arg value comes here ...2 $arg"; $value = <STDIN>;

        #### Check if the argument is valid for this option ####

        if ( $type eq "s" ) 
        {   
            # string
            # A mandatory string takes anything.
            next if $mand eq "=";
            # An optional string takes almost anything.
            next if defined $optarg;
            next if $arg eq "-";

            # Check for option or option list terminator.
            if ($arg eq $argend || $arg =~ /^$genprefix.+/) 
            {
                # Push back.
                unshift (@ARGV, $arg);
                # Supply empty value.
                $arg = '';
            }
            next;
         }

        die ("Internal error (Can't happen)\n");
    }

    continue 
    {
        if ( defined $arg ) 
        {
            $opt = $aliases{$opt} if defined $aliases{$opt};
            if ( defined $linkage{$opt} ) 
            {
                print STDERR ("=> ref(\$L{$opt}) -> ",
                  ref($linkage{$opt}), "\n") if $debug;

                if ( ref($linkage{$opt}) eq 'SCALAR' ) 
                {
                    print STDERR ("=> \$\$L{$opt} = \"$arg\"\n") if $debug;
                    #print "assigning $arg for $opt"; $value = <STDIN>;
                    ${$linkage{$opt}} = $arg;
                }
            }
            # No entry in linkage means entry in userlinkage.
            else 
            {
                print STDERR ("=>\$L{$opt} = \"$arg\"\n") if $debug;
                $userlinkage->{$opt} = $arg;
             }
         }
    }

    # Finish.
    if ( $error == 0)
    {
        #  Push back accumulated arguments
        unshift (@ARGV, @ret) if @ret > 0;
    }

    return ($error);
}


sub PrintHelp {
    print "\n################################################################";
    print "\n##         Forms 6i Performance Collector Data Parser         ##";
    print "\n################################################################";
    print "\n## Run in either interactive mode or batch mode               ##";
    print "\n##                                                            ##";
    print "\n## Batch mode command line:                                   ##";
    print "\n##                                                            ##";
    print "\n##   perl f60parse.pl -input=f1 -ouput=f2 -os=n_or_u          ##";
    print "\n##                                                            ##";
    print "\n##     f1 - input time stamp log file                         ##";
    print "\n##     f2 - optional output CSV (Comma Separated Value) file  ##";
    print "\n##     n_or_u - specify 'n' for NT and 'u' for Unix           ##";
    print "\n################################################################";
    print "\n## Input : Raw data collected by specifying Forms Server      ##";
    print "\n##         parameter 'record=performance' or 'record=all'     ##";
    print "\n## Output: index.html, summary.html, runtime.html,            ##";
    print "\n##         detailed.html, detailed2.html, glossary.html       ##";
    print "\n## Optional Output: CSV (Comma Separated Value) file          ##";
    print "\n################################################################";
    print "\n";

#    print "\n##     EventFile : Lists the events of interest to the user.  ##";
#    print "\n##                 <Optional> If not defined default events   ##";
#    print "\n##                 will be taken                              ##";
#    print "\n##     OutputFile : The file to store the result in xls format##";
#    print "\n##                                                            ##";
}


sub PrintCollectHTML {

    open (LVL2OUTPUT, "> $lvl2out") || 
            die "Not able to open Output file $Outfile $!";

    select(LVL2OUTPUT);
    #select(STDOUT);
    $Actioncnt++;
    $eventfound = 0; 
    print "\n <html> \n <head>";
    print "\n<title>Forms 6i Performance Collector Analysis</title>";
    print "\n<\/head> \n    <body> ";
    print "\n<center><h1>Extracted Time Stamp Data<\/h1></center>";
    print "\nThe following is a list of labels, client times, and time stamps ";
    print "\nextracted from the raw text <a href =\"$Infile\">input file<\/a>.";

    print "\n<table>";
    seek(INPUT, $Orgfptr, 0);
    printf("\n <a name=%d>", $i); print "<\/a>";
    printf("\n<center><h3>Action ", $i);
        
    chomp($Curline = <INPUT>);
    chomp($Curline = <INPUT>);
    ($temp, $optarg) = split(' ',$Curline, 2);
    print "$optarg <\/h3></center>";
    print("\n<table width=100% border=1> <thead>");
    print "\n  <th><a href =\"glossary.html#label\">Label<\/a><\/th>";
    print "\n  <th><a href =\"glossary.html#client_time\">ClientTime<\/a><\/th>";
    print "\n  <th><a href =\"glossary.html#system_time_stamp\">System Time Stamp <br> in milliseconds<\/a> <\/th>";
    print "\n <\/thead> <tbody>";

    while (<INPUT>)
    {
            chomp($Curline = $_);
            #print "Current line read $Curline and i is $i"; $test = <STDIN>;
 
            if ( $Curline ne "" )
            {
		($temp, $optarg) = split(' ',$Curline, 2);
                if ( ($temp eq $EVENTKEY) ) 
                {
		     print "<\/tbody> <\/table>";
				    $i++;
		    printf("\n <a name=%d>", $i); print "<\/a>";
		    printf("\n<center><h3>Action  ", $i);
		  
		    print "$optarg <\/h3></center>";
		    print("\n<table width=100% border=1> <thead>");
            print "\n  <th><a href =\"glossary.html#label\">Label<\/a><\/th>";
            print "\n  <th><a href =\"glossary.html#client_time\">ClientTime<\/a><\/th>";
            print "\n  <th><a href =\"glossary.html#system_time_stamp\">System Time Stamp <br> in milliseconds<\/a> <\/th>";
		    print "\n <\/thead> <tbody>";
		    next;
		}
		else
		{
		    #print "Reading teh Timestkey "; $test=<STDIN>;
		    ($temp, $no, $ctime, $time) = split(' ',$optarg, 4);
		    print "<tr> <td> $temp <\/td> \n  <td>$ctime <\/td> <td>$time <\/td> <\/tr>"; 
		}
            }
            else
            {
		#print "The current line is empty"; $test=<STDIN>;
            }
	}
    $eventfound = 0;
    print "<\/tbody> <\/table>";
    print "\n </body> </html>";
}       
 

sub PrintIntro()
{
           
    open (INTRO, "> index.html") || 
            die "Not able to open Output file intro.html $!";
    select(INTRO);
print "<html><head><title>Forms 6i Performance Collector Analysis</title> ";
print "<center><h1> Forms 6i Performance Collector Analysis</h1></center></head> <body>";
# print "<h2><hr WIDTH=\"100%\">Table of Contents</h2>";
print "<blockquote>&nbsp;<a href=\"summary.html\">Summary List of User Actions</a>";
print "<br>&nbsp;<a href=\"detailed.html\">Detailed List of User Actions</a>";
print "<br>&nbsp;<a href=\"runtime.html\">Platform Configuration and Runtime Details</a>";
print "<br>&nbsp;<a href=\"detailed2.html\">Extracted Timestamp Data</a>";
print "<br>&nbsp;<a href=\"event.html\">Within-Tier Event Definitions</a>";
print "<br>&nbsp;<a href=\"glossary.html\">Glossary</a>";
print "<br>&nbsp;<a href=\"$Infile\">Input File</a></blockquote>";

# print"<center><h2><b>ACCURACY OF THE RESULTS</b></h2></center>";
# print"<ul><li>The accuracy of the results depend on the accuracy ";
# print "of the data supported by the underlying Operating System.</li>";
# print "<li>The 'ClientTime'&nbsp; factor includes the Client CPU time and ";
# print "the User Think Time.</li>";
# 
# print "<li>";
# print "The 'ClientTime' is the factor determined  at the Java client UI ";
# print "and thus depends on the accuracy with which the JVM provides the ";
# print "timestamp values. Our experiments with clients of reasonable speed  ";
# print "&nbsp (450MHz PIII, 128 MB RAM) ( show a deviation of 10-20msec, ";
# print "during random user actions. ";
# print "<li>";
# print "The 'Network' factor is derived using the 'ClientTime' and the  ";
# print "Forms Server TimeStamp instants. ";
# print "Thus, the accuracy of value presented in 'Network' depends on the ";
# print "accuracy of the ClientTime.</li>";
# print "</ul>";
# print "<br>";
print"</body></html>";
    close (INTRO);
}

# PrintGlossaryHTML
#
# Write out glossary to file glossary.html
sub PrintGlossaryHTML ()
{
    open (FILE_GLOSSARY, "> glossary.html") || 
            die "Not able to open Output file $lvl1out $!";

    select (FILE_GLOSSARY);
    print "\n <html> \n <head> ";
    print "\n<title>Forms 6i Performance Collector Analysis</title>";
    print "\n<\/head> \n    <body>";
    print "\n<center><h1>Performance Collector Glossary<\/h1></center>";

    # Avg Time
    print "\n<h2><a NAME=\"avg_time\"><\/a>Avg Time<\/h2>";
    print "\nThe average <a href=\"glossary.html#duration\">duration<\/a> for a particular ";
    print "\n<a href=\"glossary.html#within_tier_event\">within-tier event<\/a> ";
    print "\nper <a href=\"glossary.html#user_action\">user action<\/a>.";

    # ClientTime
    print "\n<h2><a NAME=\"client_time\"><\/a>ClientTime<\/h2>";
    print "\nThe time spent on the Forms Client not including time spent communicating across the network.";
    print "\n<p>The only <a href=\"glossary.html#label\">time stamp label<\/a> ";
    print "\nin the <a href=\"$Infile\">input file<\/a> that has client time associated";
    print "\nwith it is the FSERVER_START label since only FSERVER_START can directly ";
    print "\nfollow user action on the client.";

    # Count
    print "\n<h2><a NAME=\"count\"><\/a>Count<\/h2>";
    print "\nThe number of times a within-tier event occurred per user action.";

    # Duration
    print "\n<h2><a NAME=\"duration\"><\/a>Duration<\/h2>";
    print "\nThe duration of an action (or ";
    print "\n<a href=\"glossary.html#within_tier_event\">within-tier event<\/a>)";

    print "\nis the interval of time starting at the time stamp";
    print "\nrecorded in response to that action (or event) and ending at the time stamp";
    print "\nrecorded in response to the next action (or event).";
    print "\n<p>System time stamps are used to calculate the duration. ";
    print "\n<p>Duration for action <b>i</b> is <b>System Time Stamp i+1 - System Time Stamp i</b>";

    print "\n<blockquote><h4>User Action Duration<\/h4>";
    print "\nSince the system time stamp for a user action represents the exact ";
    print "\ntime at which the response to a user ";
    print "\naction was initiated by the Forms Server therefore the duration of a user action";
    print "\nis the time from when the Forms Server first responds to that user action ";
    print "\nto when the Forms Server first responds to the next user action.";
    print "\nThis includes the time spent in the Forms Server responding to the user action,";
    print "\ntime spent in the Database Server,";
    print "\nthe time spent communicating across the network, and the time spent by the client and user";
    print "\nbefore the Forms Server responds to the next user action.<\/blockquote>";

    # Handshake
    print "\n<h2><a NAME=\"handshake\"><\/a>Handshake<\/h2>";
    print "\nThe communication that occurs between Forms Client and Forms Server to";
    print "\nestablish a connection.";

    # Label
    print "\n<h2><a NAME=\"label\"><\/a>Label<\/h2>";
    print "\nLabel attached to a <a href=\"glossary.html#system_time_stamp\">system time stamp<\/a> ";
    print "\nin the <a href=\"$Infile\">input file<\/a>.";
    print "\n<p>Possible labels are<ul>";
    print "\n<li>FSERVER_START<\/li>";
    print "\n<li>FSERVER_END<\/li>";
    print "\n<li>DBLOGON_START<\/li>";
    print "\n<li>DBLOGON_END<\/li>";
    print "\n<li>DB_START<\/li>";
    print "\n<li>DB_END<\/li>";
    print "\n<li>DBLOGOFF_START<\/li>";
    print "\n<li>DBLOGOFF_END<\/li>";
    print "\n<\/ul>";

    # Max Time
    print "\n<h2><a NAME=\"max_time\"><\/a>Max Time<\/h2>";
    print "\nThe maximum <a href=\"glossary.html#duration\">duration<\/a> for a particular ";
    print "\n<a href=\"glossary.html#within_tier_event\">within-tier event<\/a> ";
    print "\nper <a href=\"glossary.html#user_action\">user action<\/a>.";

    # Min Time
    print "\n<h2><a NAME=\"min_time\"><\/a>Min Time<\/h2>";
    print "\nThe minimum <a href=\"glossary.html#duration\">duration<\/a> for a particular ";
    print "\n<a href=\"glossary.html#within_tier_event\">within-tier event<\/a> ";
    print "\nper <a href=\"glossary.html#user_action\">user action<\/a>.";

    # Startup
    print "\n<h2><a NAME=\"startup\"><\/a>Startup<\/h2>";
    print "\nThe instant at which the Forms Client gets connected to the Forms Server.";

    # System Time Stamp
    print "\n<h2><a NAME=\"system_time_stamp\"><\/a>System Time Stamp<\/h2>";
    print "\nSystem time stamps are measurements written to the text log file by the ";
    print "\nPerformance Collector. They record the exact time that the Forms Server";
    print "\ncommunicated with either the Forms Client or the Database Server and.";
    print "\nare used to calculate how much time was spent in each of the Forms Client,";
    print "\n the network, the Forms Server, and the Database Server.";
    print "\n<p>System time stamps are extracted from the operating system and indicate ";
    print "\nthe time elapsed since the computer was rebooted in units of either ";
    print "\nmilliseconds or nanoseconds.";
    print "\nAll time units are converted to milliseconds in this presentation.";
    print "\n<p>The system time stamp for a user action represents the exact ";
    print "\ntime at which the response to a user ";
    print "\naction was initiated by the Forms Server.";

    # Tier
    print "\n<h2><a NAME=\"tier\"><\/a>Tier<\/h2>";
    print "\nForms 6i has a three tier architecture made up of Forms Client, ";
    print "\nForms Server, and Database Server.";
    print "\nFor the performance collector analysis these three tiers plus another category are used";
    print "\n<ul>";
    print "\n<li>Client<\/li>";
    print "\n<li>FormsServer<\/li>";
    print "\n<li>Database<\/li>";
    print "\n<li>Network<\/li>";
    print "\n<\/ul>";
    print "\nThe fourth category <b>Network<\/b> is provided to differentiate between ";
    print "\ntime spent in the Forms Client and time spent communicating between ";
    print "\nForms Client and Forms Server.";

    # User Action
    print "\n<h2><a NAME=\"user_action\"><\/a>User Action<\/h2>";
    print "\nA user action is any action performed by the user on the client";
    print "\nthat requires communication with the Forms Server.";
    print "\nSome startup actions (STARTUP, HandShake Duration) are not directly";
    print "\ninitiated by the user but are recorded as user actions.";
    print "\n<p>The system time stamp for a user action represents the exact ";
    print "\ntime at which the response to a user ";
    print "\naction was initiated by the Forms Server.";

    # Within-Tier Event
    print "\n<h2><a NAME=\"within_tier_event\"><\/a>Within-Tier Event<\/h2>";

    print "\nA subdivision of the possible actions within a tier.";
    print "\nProvides finer granularity for performance analysis.";

    print "\n<p>In the <a href=\"detailed.html\">Detailed List of User Actions<\/a>";
    print "\nanalysis is done both by tier and by \"within-tier event\"";

    print "\n<p>For example, the <b>FormsServer<\/b> tier includes the categories";
    print "\n<b>FSPreDB<\/b>, <b>FSMidDB<\/b>, and <b>FSPostDB<\/b>. This allows you to narrow down";
    print "\npotential performance problems by analyzing separately the time spent by the Forms";
    print "\nServer preparing for the first database access, processing the results from the database,";
    print "\nand preparing the";
    print "\nresults to be returned to the Forms Client. Using only the per tier summary";
    print "\ndoes not allow for differentiation between these three areas - instead only";
    print "\nthe sum of the three within-tier event times would be presented.";

    print "\n<\/body>";
    print "\n<\/html>";    print "\n \n \n";

    close (FILE_GLOSSARY);
}
