# ProcsReqWorker is a helper class for the Requester::Procs class
# below. ProcsReqWorker lists the processes running on the local
# system in the background.
package ProcsReqWorker;

use CmdWorker;

@ProcsReqWorker::ISA = qw( CmdWorker );
my $pswarned = 0;

# create a new Worker executing command $comm and putting
# the results into $info hash
sub new {
    my( $this, $info, $comm ) = @_;
    print "  creating ProcReqWorker for $comm\n" if( $BigSister::common::dl > 2 );
    my $self = CmdWorker::new( $this, $comm );
    $self->{"procs.info"} = $info;
    $info->{0}->{"processes"} = 0;
    return $self;
}


sub process {
    my( $self, $line ) = @_;

    print "      processing procs:$line\n" if( $BigSister::common::dl > 6 );
    my $index = $self->{"procs.index"} + 1;
    if( $line =~ /^[\s\t]*(\d+)[\s\t]/ ) {
        $index = $1;
    }
    $self->{"procs.index"} = $index;
    my $comm;
    if( $line =~ /^.*[\s]+([^\s]+)[\s]*$/ ) {
        $comm = $1;
    }
    $comm =~ s#.*/##;
    $self->{"procs.info"}->{$index}->{"hrSWRunName"} = $comm;
    $self->{"procs.info"}->{0}->{"processes"}++;
}



package Requester::procs;

use strict;
use Requester::Requester;

@Requester::procs::ISA = qw(Requester::Requester);

my $requester = new Requester::procs;
my $pscomm_cached;


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

    bless($self, $class);
    $self->register( "procs" );
    return $self;
}




# the default "request()" method is good enough for our purposes


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

    my $pscomm = $self->{"env"}->expand_value( "pscomm" );
    unless( $pscomm ) {
        $self->guess_pscomm();
	$pscomm = $self->{"pscomm"};
    }
    my $info = { 0 => {} };
    my $worker = new ProcsReqWorker( $info, $pscomm );
    $worker->{"Test.info"} = $info;
    return $worker;
}



sub guess_pscomm {
    my( $self ) = @_;
    my $nextbest;
    unless( $pscomm_cached ) {
      outer:
	foreach my $comm ("/usr/ucb/ps cax", "/bin/ps -e", "/bin/ps cax", "/usr/bin/ps -e", "/usr/bin/ps cax" ) {
	    open( "_PS", "$comm|" ) || next;
	    while( <_PS> ) {
		chomp;
		$nextbest = $comm;
		if( /^[\s\t]*1[\s\t].*[\s\t]init$/ ) {
		    $pscomm_cached = $comm;
		    last outer;
		}
	    }
	}
	unless( $pscomm_cached ) {
	    $pscomm_cached = $nextbest;
	}
	unless( $pscomm_cached ) {
	    $pscomm_cached = "ps cax";
	}
    }
    $self->{"pscomm"} = $pscomm_cached;
}


# -----------------------------------------
# Utilities available to tests.cfg
# -----------------------------------------

# accepts a process table where at each index (usually equal to the
# process ID) a process name is stored as an argument
#
# counts the number of processes per name and returns an array
# with at each index a "processname:processcount" value.
# This array can be used as an argument to selectproc
sub countprocs {
    my( $proctable ) = @_;

    my %procs;
    while( my( $index, $proc ) = each %$proctable ) {
	$proc = $proc->{"value"};
	$proc =~ s#.*/##;  
	$proc =~ s#^\((.*)\)$#$1#;
        if( defined $procs{$proc} ) {
	    $procs{$proc}++;
	}
	else {
	    $procs{$proc} = 1;
	}
    }
    my $index = 0;
    my %result;
    while( my( $proc, $count ) = each %procs ) {
        $result{$index++} = { "value" => "$proc:$count" };
    }
    return \%result;
}
    


# accepts a table as returned by countprocs plus a single
# process name as arguments.
#
# returns how many processes of this name are running
sub selectproc {
    my( $procs, $thisproc ) = @_;

    $thisproc = Monitor::Tester::var_to_value( $thisproc );
    while( my( $index, $proc ) = each %$procs ) {
        if( $proc->{"value"} =~ /^\Q$thisproc\E:(\d+)$/ ) {
	    return {
	        "0" => { "value" => $1 }
	    };
	}
    }
    return { "0" => { "value" => 0 } };
}

1;

