# -*-Perl-*-

# this module is a hack; it isn't a widget builder.  It sits in the
# background and reads /proc/stat, /proc/net/dev and
# /proc/net/wireless for other modules to reduce opens/closes.

# It defines an init method that installs the /proc/stat listener,
# then marks itself 'inactive' so that mgm doesn't try to call _run,
# _update or allocate space.  The last part of the hack is the name
# beginning with 00 so that it loads before the other modules that
# depend on it


package MGMmodule::helperST;
use vars qw(%disk26 %vm26 %proc %net %wi $lastmod $stat_active $net_active $active_if $wi_count $wi_active $vm_active $disk26_active);
use IO::Seekable;

sub module_init{
    my$this=shift;
    my$xclass=$this->{"xclass"};
    my$toplevel=$this->{"toplevel"};
    my$widget=$this->{"widget"};
    
    $toplevel->optionAdd("$xclass.scalerefresh",500,21); # keep up with cpustat
    my$refresh=$widget->optionGet("scalerefresh","");
    
    $lastmod=0;
    $stat_active=0;
    $net_active=0;
    $vm_active=0;
    $disk26_active=0;
    $wi_active=0;
    if(open(PROC,"/proc/stat")){
	$stat_active=1;
    }
    if(open(WI,"/proc/net/wireless")){
	$wi_active=1;
    }
    if(open(NET,"/proc/net/dev")){
	$net_active=1;
    }
    if(open(VM,"/proc/vmstat")){
	$vm_active=1;
    }
    if(open(DISK,"/proc/diskstats")){
	# ...2.6 moves these out of /proc/stat
	$disk26_active=1;
    }

    if($stat_active || $wi_active || $net_active || $disk26_active || $vm_active){
	$this->module_update;
	$toplevel->repeat($refresh,\&module_update)if(defined(%proc));
    }

    $toplevel->optionAdd("$xclass.active",0,21);
    $this;
}

sub module_instance{
    shift;
}

sub module_update{
    my$data;

    if($net_active){
	$active_if=0;
	undef%net;
	sysseek NET, 0, SEEK_SET;
	sysread NET,$data,1024;

	map{
	    my$pos=rindex $_, ":";
	    if($pos>0){
		my$key=substr $_,0,$pos;
		my$vals=$_;
		$key=~s/^\s*(\S+)\s*/$1/;
		unless ($key=~m/sit/) {
		    $net{$key}=substr $vals, $pos+1;
		    $active_if++;
		} 
	    }
	} split "\n", $data;
    }

    if($wi_active){
	sysseek WI, 0, SEEK_SET;
	sysread WI,$data,4096;
	$wi_count=0;
	undef %wi;
	map{
	    my$pos=rindex $_, ":";
	    if($pos>0){
		my$key=substr $_,0,$pos;
		$key=~s/^\s*(\S+)\s*/$1/;
		$wi{$key}=substr $_, $pos+1;
		$wi_count++;
	    }
	} split "\n", $data;
    }
	
    if($stat_active){
	sysseek PROC, 0, SEEK_SET;
	sysread PROC,$data,4096;
	
	map{
	    m/^(\S+)\s+(.*)/;
	    $proc{$1}=$2;
	} split "\n", $data;
	
    }

    if($disk26_active){
	sysseek DISK, 0, SEEK_SET;
	sysread DISK,$data,4096;
	undef %disk26;
	map{
	    m/\d+\s+\d+\s+(\S+)\s+(.*)/;
	    $disk26{$1}=$2;
	} split "\n", $data;
	
    }

    if($vm_active){
	sysseek VM, 0, SEEK_SET;
	sysread VM,$data,4096;
	map{
	    m/^(\S+)\s+(.*)/;
	    $vm26{$1}=$2;
	} split "\n", $data;
    }


    # what a great hack
    $proc{"cpu"}=~m/(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
    $lastmod=$1+$2+$3+$4; # 100ths of a second, even with 'broken' 2.0 SMP proc
}

bless {};


