# $Header: emdprocstats.pl 01-sep-2007.00:31:52 vrajendr Exp $
#
# emdprocstats.pl
# 
# Copyright (c) 2002, 2007, Oracle. All rights reserved.  
#
#    NAME
#      emdprocstats.pl 
#
#    DESCRIPTION
#    CEMD self monitoring metric HostInfo script.
#    RETURNS: <process id of emd>|
#             <cpu usage of emd as a %>|
#             <virtual memory utilization in KB>|
#             <resident memory utilization in KB>|
#             <number threads created>|
#             <up time>
#    NOTES
#   
#
#    MODIFIED   (MM/DD/YY)
#    vrajendr    09/01/07 - Backport vrajendr_bug-6219312 from main
#    svrrao      08/01/07 - Backport svrrao_bug-6282337 from main
#    bguhatha    06/11/07 - Backport bguhatha_bug-5908032 from main
#    vrajendr    08/31/07 - Bug# 6219312: Avoiding Division by Zero if totalMem is 0
#    svrrao      07/30/07 - bug#6282337: tail +2 option breaks across linux
#                           versions
#    bguhatha    05/28/07 - bug-5908032 
#    nsharma     12/18/06 - Fix for 5719319, get rid of recursive ps on HPUX
#    cvaishna    06/23/06 - Bug Fix : 5282583 
#    cvaishna    06/23/06 - 
#    kganapat    08/31/05 - Fix for num_of_thread in new version of Redhat 
#    sksaha      07/26/05 - Fix numOfThreads in linux 
#    sksaha      07/22/05 - Don't set include_children for CPU usage 
#    xxu         07/13/05 - multiple CPUs 
#    njagathe    11/24/04 - Handle NT 
#    aaitghez    11/04/04 - bug 3843569. PLE changes 
#    mkiran      10/04/04 - 3620133: Exit if 'emctl status agent' fails
#    kduvvuri    09/17/04 - fix trace. 
#    kduvvuri    09/15/04 - add tracing. 
#    mbhoopat    03/10/04 - linux port 
#    skumar      01/13/04 - 10G changes for emd procstats 
#    rzkrishn    12/16/03 - get Agent only virtual and resident memory 
#    rlal        11/26/03 - Fix for bug 2911067
#    njagathe    10/28/03 - Stop printing uptime 
#    aaitghez    05/13/03 - bug 2916669
#    aaitghez    01/21/03 - change calls to process functions
#    vsekuboy    10/09/02 - Added comments for linux-specific code
#    vsekuboy    10/08/02 - Changes for HP and Linux
#    aaitghez    08/26/02 - add percentage column
#    aaitghez    08/21/02 - add more file types
#    aaitghez    07/16/02 - change function prototype
#    xxu         06/25/02 - remove /usr/local/bin/perl
#    aaitghez    06/24/02 - adding number threads and uptime
#    aaitghez    06/12/02 - remove total CPU metric info..
#    aaitghez    05/22/02 - add sum of all child processes column..
#    aaitghez    04/23/02 - aaitghez_bug-2334129
#    aaitghez    04/22/02 - Creation
# 

require "emdprocesschars.pl";
require "semd_common.pl";
require "emd_common.pl";

EMD_PERL_DEBUG("Entering emdprocstats.pl");

$os = get_osType();

if ( $os eq "WIN") {
  $emdRoot = $ENV{"EMD_ROOT"};
  $emdPid = $ARGV[0];
  system("$emdRoot/bin/nmupm ProcInfo  $emdPid");
  exit;
}

chomp ($os = `uname -s`) or die "Failed to run the uname command";
SWITCH: {
  $os eq "SunOS" && do {
                          chomp ($ver = `uname -r`);
                          if ( $ver !~ /^4./ ) {
                             $osType = "Sol";
                             last SWITCH;
                          }
                       };
  $os eq "HP-UX" && do {
                          $osType = "HP";
			  $ENV{UNIX95} = "XPG4";
                          last SWITCH;
                       };
  $os eq "Linux" && do {
                          $osType = "LNX";
                          last SWITCH;
                       };
  $os eq "OSF1" && do {
                          $osType = "OSF1";
                          last SWITCH;
                       };
  $os eq "AIX" && do {
                          $osType = "AIX";
                          last SWITCH;
                       };
  $os eq "Darwin" && do {
                          $osType = "MACOSX";
                          last SWITCH;
                       };
  die "Unsupported Operating System\n";
}

EMD_PERL_DEBUG("The OS is determined to be $osType");

$cmd=`$ENV{ORACLE_HOME}/bin/emdctl status agent` or die "emctl status agent returned agent not running.\n";
chomp ($cmd);

@pids = getPIDS($cmd);
$emd_pid = $pids[0];
$parent_pid = $pids[1];

EMD_PERL_DEBUG("Agent & Parent  Process ID $emd_pid, $parent_pid");

$command = `ps -p $emd_pid -o args |tail -1` or die "emd_pid doesn't exist.\n";
chomp($command);
EMD_PERL_DEBUG("Agent Process Name is:$command");

#
# Number of files and number of threads is not avlbl on linux
#

my @result_vec;
my @stats = ("vsz", "rss", "pmem", "nlwp");
my @agentonlystats = ("vsz", "rss", "pcpu");
my @agentonly_result_vec;
my $getFileHandles = 1;


	if ($osType eq "LNX" || $osType eq "OSF1" || $osType eq "AIX" || $osType eq "MACOSX") 
	{

	   $getFileHandles = 0;
	   @stats = ("vsz", "rss", "pmem");
	}
	elsif ( $osType eq "HP" )
	{
	   $getFileHandles = 0;
	   @stats = ("vsz", "sz", "sz"); # no pmem option on HP, replaced with sz as placeholder only
           @agentonlystats = ("vsz", "sz", "pcpu");
        }
	
	getProcessChars($getFileHandles, 
			1, $emd_pid, \@stats, \@result_vec);
	
	getProcessChars(0, 0, 
			$emd_pid, \@agentonlystats, \@agentonly_result_vec);
	
	$virtual_mem = @result_vec[0];
	if ($osType eq "HP")
	{

	  $physical_mem = @result_vec[1] * `/usr/bin/getconf _SC_PAGE_SIZE` / 1024 ;

          my $REAL_MEM_COL = 12; #As per nmupm osLoad command
          my $mem_output = `$ENV{EMDROOT}/bin/nmupm osLoad`;
          my @mem_lines = split( '\|', $mem_output );
	  # pull out pageSize, realMem and freeMemRaw
	  my $totalMem = $mem_lines[$REAL_MEM_COL];
          if (totalMem == 0) # Bug # 6219312
          {
             $physical_mem_percentage = "";
          }
          else
          {
             $physical_mem_percentage = sprintf("%.2f",$physical_mem/$totalMem*100);
          }

	}
	else
	{
	  $physical_mem = @result_vec[1];
	  $physical_mem_percentage = @result_vec[2];
	}

	$cpu_util = @agentonly_result_vec[2];
	$agentonly_virtual_mem = @agentonly_result_vec[0];
	if ($osType eq "HP")
	{
	   $agentonly_physical_mem = @agentonly_result_vec[1] * `/usr/bin/getconf _SC_PAGE_SIZE` / 1024 ;
	}
        else
	{
	   $agentonly_physical_mem = @agentonly_result_vec[1];
	}

    if($osType eq "Sol")
    {
        $number_files = `/bin/ls /proc/$emd_pid/fd/* | /usr/bin/wc -l`;
        chomp($number_files);
        $number_files =~ s/^\s+//;
	$num_threads = @result_vec[3];
    }
    elsif ($osType eq "LNX")
    {
	my $diststring='';
        
        open(IFH, "/etc/issue");
        while (<IFH>)
        {
          next if (/^$/);
          chomp;
          $diststring = $_;
          last;
        }

        $num_threads = 0;
        if ( $diststring !~ /UnitedLinux 1.0/ && $diststring !~ /Red Hat Linux Advanced Server release 2.1AS/ &&  $diststring !~ /SLES 8/ ) # Older distributions, do nothing
        {
          if  ( $diststring =~ /Red Hat Enterprise Linux AS release 3/ )
          {
            $command_threads = `/bin/ps -eo \"ppid,pid,args\" -m | /bin/grep $command | /bin/grep -v grep`;
            EMD_PERL_DEBUG ("Got the following threads ...\n$command_threads");

            # Recursively find all threads belonging to $parent_pid
            $num_threads = getThreadCount_LNX($parent_pid, $command_threads);
          }
          else  # SLES9 and later distributions
          {
            
            $num_threads = `/bin/ps -p  $emd_pid -o nlwp h 2>/dev/null`;
            $num_threads =~ s/^\s+//;
          }
          chomp($num_threads);
        }

        if ($num_threads == 0)
        {
	    $threads_cmd = `/bin/ps -m wwx | /bin/grep $command | /bin/grep -v grep | /bin/awk '{print \$1}'`;
	    chomp($threads_cmd);
	    @threads = split ( /\n/ , $threads_cmd );
	    $num_threads = $#threads;
	    $cpu_util = 0;
	    foreach $tid (@threads)
	    {
                EMD_PERL_DEBUG("Getting info for thread id $tid");
                $cpu_tid = `/bin/ps -o pcpu -p $tid h`;
                chomp($cpu_tid);
                $cpu_util += $cpu_tid;
	    }
	}

        my $num_cpus = `grep cpu /proc/stat | wc -l` - 1;
        EMD_PERL_DEBUG ("Number of CPUs $num_cpus, total CPU Usage $cpu_util");
        $cpu_util /= $num_cpus;
        EMD_PERL_DEBUG ("divide by number of CPUs, now CPU Usage $cpu_util");

        $number_files = `/bin/ls /proc/$emd_pid/fd/* | /usr/bin/wc -l`;
        chomp($number_files);
        $number_files =~ s/^\s+//;
    }
    elsif ($osType eq "OSF1")
    {
	$number_files = 0;
	$num_threads = `ps -m -p $emd_pid | tail +3 | wc -l`;
	chomp($num_threads);
    }
    elsif ($osType eq "AIX")
    {
	$number_files = 0;
	$num_threads = `ps -p $emd_pid -o thcount=`;
	chomp($num_threads);
	$num_threads =~ s/^\s+//;
    }
    elsif ($osType eq "HP") {
        $number_files = getFileHandles($emd_pid, 1);
        $num_threads = `$ENV{EMDROOT}/bin/nmupm lwp $emd_pid`;
        chomp($num_threads);
    }
    elsif ($osType eq "MACOSX")
    {
	$number_files = 0;
        if (-x "/usr/sbin/lsof")
        {
          $number_files = `/usr/sbin/lsof -p $emd_pid | wc -l`;
          chomp($number_files);
          $number_files =~ s/^\s+//;
        }
	$num_threads = `ps -M -p $emd_pid | tail +3 | wc -l`;
        chomp($num_threads);
        $num_threads =~ s/^\s+//;
        if ($physical_mem_percentage < 0.0)
        { $physical_mem_percentage = -$physical_mem_percentage; };
        if ($physical_mem_percentage == -0.0)
        { $physical_mem_percentage = 0.0; };
    }
    else
    {
	$number_files = 0;
	$num_threads = 0;
    }

    EMD_PERL_DEBUG ("emd_pid=$emd_pid,cpu_util=$cpu_util,virtual_mem=$virtual_mem,physical_mem=$physical_mem,physical_mem_percentage=physical_mem_percentage,number_files=$number_files,num_threads=$num_threads,agent_only_virtual_mem=$agentonly_virtual_mem,agent_only_physical_mem=$agentonly_physical_mem");

    print "em_result=$emd_pid|$cpu_util|$virtual_mem|$physical_mem|$physical_mem_percentage|$number_files||$num_threads|$agentonly_virtual_mem|$agentonly_physical_mem\n";




