# $Header: hostdiskactivity.pl 25-feb-2007.00:54:17 denath Exp $
#
# hostdiskactivity.pl
# 
# Copyright (c) 2001, 2007, Oracle. All rights reserved.  
#
#    NAME
#      hostdiskactivity.pl 
#
#    DESCRIPTION
#      returns system disk activity
#
#        On Linux, the result is :
#              Device
#              Transfers per second
#              Amount of data read from drive as blocks per second
#              Amount of data written to drive as blocks per second
#              Total number of blocks read
#              Total number of blocks written
#
#
#    NOTES
#        data collected and averaged over a 2 second interval
#
#    MODIFIED   (MM/DD/YY)
#    denath      02/25/07 - Backport denath_bug_5038684 from main
#    denath      10/10/06 - fix bug 5038684.Use LIMIT_TO instance property to
#                           limit number of Disk activity rows to upload.
#    skumar      06/11/04 - /proc/diskstats in 2.6 kernel
#    skumar      01/07/04 - Creation
# 

exit 1 if ($^O ne "linux");

use hostGenFunctions;

$ENV{PATH} = "/usr/bin:/bin:/usr/sbin:/usr/local/bin:/local/bin";

# Command Line Arguments

# Bug fix 5038684.Read number of Disk data to upload from instance property
# If instance property not passed then use default of 16.
my $limit_to   = $ARGV[0];
if (($limit_to == '') || ($limit_to < 1)) {
    $limit_to = 16 ;
}

#printf("limit_to=%d\n", $limit_to);

my $RIO_TAG    = "rio";
my $RSECT_TAG  = "rsect";
my $RTICKS_TAG = "rticks";
  
my $WIO_TAG    = "wio";
my $WSECT_TAG  = "wsect";
my $WTICKS_TAG = "wticks";
  
my $TICKS_TAG  = "ticks";
my $AVEQ_TAG   = "aveq";

my $k24 = 0;

my %iostats = ();

my @data = ();
my $header;
my $uptime = 0;

if (!open(FH, "/proc/diskstats")) { # 2.6 kernel
  open FH, "/proc/partitions" or die "Could not open /proc/partitions\n";
  $k24 = 1;
}

@data = (<FH>);
close FH;

if ($k24)
{
  @header = split(/[\s\t]+/, $data[0]);

  # Columns in /proc/partitions:
  # major minor #blocks name rio rmerge rsect ruse wio wmerge wsect wuse
  # running use aveq

  die "em_error=unknown format in /proc/partitions" if (scalar(@header) != 15);
}

# Elapsed time
$proc_uptime = `cat /proc/uptime` or die "Failed to cat /proc/uptime\n";
($uptime, $ignore) = split(/[\s\t]+/, $proc_uptime);

die "Failed to get uptime\n" if ($uptime == 0);

%iostats = get_iostats(@data);

my $count = 0 ;

foreach $key (keys %iostats)
{
  if ($count < $limit_to) {
  
    $count = $count + 1 ;
    $rio = $iostats{$key}{$RIO_TAG};
    $rsect = $iostats{$key}{$RSECT_TAG};
    $rticks = $iostats{$key}{$RTICKS_TAG};

    $wio = $iostats{$key}{$WIO_TAG};
    $wsect = $iostats{$key}{$WSECT_TAG};
    $wticks = $iostats{$key}{$WTICKS_TAG};

    $ticks = $iostats{$key}{$TICKS_TAG};

    $rticks = 0 if ($rticks < 0);
    $wticks = 0 if ($wticks < 0);

    printf("em_result=%s|%d|%d|%d|%d|%d|0|%d|0|%d\n", $key, $rio, $wio, $rsect, $wsect, $rticks+$wticks, $uptime, $ticks);
  } else {
    last;
  }
}

exit 0;

sub get_iostats
{
  my @data = @_;
  my $size = scalar(@data);
  my %iostats;
  my $devname;

  if (!$k24)
  {
    # 2.6 kernel /proc/diskstats
    for ($i = 0; $i < $size; $i++)
    {
      $_ = trim($data[$i]);
      next if /^$/;

      @tokens  = split(/[\s\t]+/, $_);

      $devname = $tokens[2];

      if (scalar(@tokens) == 7) # major minor name rio rsect wio wsect
      {
        $iostats{$devname}{$RIO_TAG} = $tokens[3];
        $iostats{$devname}{$RSECT_TAG}   = $tokens[4];
        $iostats{$devname}{$RTICKS_TAG}  = 0;

        $iostats{$devname}{$WIO_TAG}     = $tokens[5];
        $iostats{$devname}{$WSECT_TAG}   = $tokens[6];
        $iostats{$devname}{$WTICKS_TAG}  = 0;

        $iostats{$devname}{$TICKS_TAG}   = 0;
        $iostats{$devname}{$AVEQ_TAG}    = 0;
      }
      else
      {
        # major minor name rio rmerge rsect ruse wio wmerge wsect wuse
        # running use aveq

        $iostats{$devname}{$RIO_TAG} = $tokens[3];
        $iostats{$devname}{$RSECT_TAG}   = $tokens[5];
        $iostats{$devname}{$RTICKS_TAG}  = $tokens[6];

        $iostats{$devname}{$WIO_TAG}     = $tokens[7];
        $iostats{$devname}{$WSECT_TAG}   = $tokens[9];
        $iostats{$devname}{$WTICKS_TAG}  = $tokens[10];
  
        $iostats{$devname}{$TICKS_TAG}   = $tokens[12];
        $iostats{$devname}{$AVEQ_TAG}    = $tokens[13];
      }
    }

    return %iostats;
  }

  for ($i = 1; $i < $size; $i++)
  {
    # 2.4 kernel /proc/partitions

    $_ = trim($data[$i]);
    next if /^$/;
  
    # major minor #blocks name rio rmerge rsect ruse wio wmerge wsect wuse
    # running use aveq

    @tokens  = split(/[\s\t]+/, $_);
    $devname = $tokens[3];
    $iostats{$devname}{$RIO_TAG}     = $tokens[4];
    $iostats{$devname}{$RSECT_TAG}   = $tokens[6];
    $iostats{$devname}{$RTICKS_TAG}  = $tokens[7];
  
    $iostats{$devname}{$WIO_TAG}     = $tokens[8];
    $iostats{$devname}{$WSECT_TAG}   = $tokens[10];
    $iostats{$devname}{$WTICKS_TAG}  = $tokens[11];
  
    $iostats{$devname}{$TICKS_TAG}   = $tokens[13];
    $iostats{$devname}{$AVEQ_TAG}    = $tokens[14];
  }
  return %iostats;
}