package Monitor::sar;

require 5.002;

use strict;
use FileHandle;

@Monitor::sar::ISA = qw(Monitor::Monitor);

sub new
{
    my ($this, $comm) = @_;
    my  $class = ref($this) || $this;
    my  $self = {};

    bless($self, $class);

    unless( $comm ) {
	$comm = "sar -A 240 1";
    }

    $self->{"comm"} = $comm;
    my( @bla)  = ();
    $self->{"htable"} = \@bla;
    $self->{"fh"} = FileHandle->new();

    return($self);
}


sub DESTROY {
    my( $self ) = @_;

    return unless( $self->{"pid"} );
    kill "TERM", $self->{"pid"};
    close( $self->{"fh"} );
}



sub add_check {
    my( $self, $name, $item, $min1, $min2, $max1, $max2 ) = @_;
    my( $htable ) = $self->{"htable"};

    ($item = $uxmon::hostname.".cpu") unless( $item );
    push( @$htable, join( "\x00", $name, $item, $min1, $min2, $max1, $max2 ) );
}



sub get_data {
    my ($self) = @_;
    my( $rbits, @table, $data );
    my( $nfound, $nread );

    print "get_data()\n" if( $BigSister::common::dl>4 );
    $data = "";
    $nfound = 1;
    while( $nfound ) {
	$rbits = "";
	vec( $rbits, fileno($self->{"fh"}), 1 ) = 1;
	$nfound = select( $rbits, undef, undef, 1 );
	if( $nfound ) {
	    $nread = sysread( $self->{"fh"}, $data, 8192, length( $data ) );
	    last unless( (defined $nread) && ($nread>0) );
	}
    }
    return $data;
}


sub check
{
    my ($self) = @_;
    my( $htable ) = $self->{"htable"};
    my( @nametable, $i, $j, $n, @names, @values );
    my( %sar );
    my( $name, $item, $min1, $min2, $max1, $max2, $val );

    return if( $self->{"start"} && ((time-$self->{"start"}) < 290) );
    if( $self->{"pid"} ) {
	@nametable = split( "\n", $self->get_data );
	(shift @nametable) while( @nametable && ! ($nametable[0] =~ /^\d+:/ ) );
	$nametable[0] =~ s/^[^\s\t]+//;

	for( $n=1; ($n<=$#nametable) && ! ($nametable[$n] =~ /^\d+:/); $n++ ) {;}
	$nametable[$n] =~ s/^[^\s\t]+//;

	for( $i=0; ($i<=$#nametable) && $nametable[$i]; $i++ ) {
	    @names = split( /[\s\t]+/, $nametable[$i] );
	    shift @names;
	    @values = split( /[\s\t]+/, $nametable[$n++] );
	    shift @values;
	    for( $j=0; $j<=$#names; $j++ ) {
		$sar{$names[$j]} = $values[$j];
	    }
	    if( $names[0] eq "device" ) {
		my( $div, $dev );

		$div = 0;
		$n--;
		while( $nametable[$n] =~ /^[\s\t]*[a-z]+[a-z0-9]+/ ) {
		    @values = split( /[\s\t]+/, $nametable[$n] );
		    last unless( $#values>1 );
		    shift @values;
		    $dev = $values[0];
		    for( $j=1; $j<=$#names; $j++ ) {
			$sar{$names[$j].".$dev"} = $values[$j];
			if( $sar{$names[$j]} ) {
			    $sar{$names[$j]} += $values[$j];
			}
			else {
			    $sar{$names[$j]} = $values[$j];
			}
		    }
		    $div++;
		    $n++;
		}
		if( $div ) {
		    for( $j=1; $j<=$#names; $j++ ) {
			$sar{$names[$j]} /= $div;
		    }
		}
	    }
	    $n++ unless( $nametable[$n] =~ /[0-9]+/ );
	}
	kill "TERM", $self->{"pid"};
	close $self->{"fh"};

	while( my( $sarkey, $sarvalue ) = each %sar ) {
	    $self->set_variable( "", "sar.$sarkey", $sarvalue );
	}

	for( $i=0; $i<=$#$htable; $i++ ) {
	    ( $name, $item, $min1, $min2, $max1, $max2 ) = split( "\x00", $$htable[$i] );
	    $val = $sar{$name};
	    next unless( length($val)>0 );
	    $val =~ s#/.*##;
	    if( (length($min1) && ($val<$min1)) ) {
		$self->report( $item, $BigSister::common::status_codes{"red"}, "$name <<($val)" );
	    }
	    elsif( (length($min2) && ($val<$min2)) ) {
		$self->report( $item, $BigSister::common::status_codes{"yellow"}, "$name <($val)" );
	    }
	    elsif( (length($max2) && ($val>$max2)) ) {
		$self->report( $item, $BigSister::common::status_codes{"red"}, "$name >>($val)" );
	    }
	    elsif( (length($max1) && ($val>$max1)) ) {
		$self->report( $item, $BigSister::common::status_codes{"yellow"}, "$name >($val)" );
	    }
	    else {
		$self->report( $item, $BigSister::common::status_codes{"green"}, "$name = $val" );
	    }
	}
    }

    $self->{"pid"} = open( $self->{"fh"}, $self->{"comm"}."|" );
    $self->{"start"} = time;
#    $j = 0;
#    foreach $i( sort( keys %sar )) {
#	print sprintf( "%-20s  ", "$i: $sar{$i}" );
#	if( $j++ > 2 ) { $j = 0; print "\n"; }
#    }
}

1;
