#! /usr/bin/env perl
##**************************************************************
##
## Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
## University of Wisconsin-Madison, WI.
## 
## Licensed under the Apache License, Version 2.0 (the "License"); you
## may not use this file except in compliance with the License.  You may
## obtain a copy of the License at
## 
##    http://www.apache.org/licenses/LICENSE-2.0
## 
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
##**************************************************************

use warnings;
use strict;

# Prototypes
sub GatherMeminfo( $$ );
sub GatherFree( $$ );
sub GatherSolaris( $$ );
sub GatherError( $$ );

# Update the module include path
BEGIN
{
    my $Dir = $0;
    if ( $Dir =~ /(.*)\/.*/ )
    {
	push @INC, "$1";
    }
}
use HawkeyePublish;
use HawkeyeLib;

# Setup the hawkeye stuff
my $Hawkeye;

# Table of ways to gather data..
my @GatherMethods =
(
 { Description => "Linux /proc/meminfo", Function => \&GatherMeminfo, },
 { Description => "Linux free", Function => \&GatherFree, },
 { Description => "Solaris", Function => \&GatherSolaris, },
 { Description => "Error", Function => \&GatherError, },
);

# Do it
Init();
RunIt();

# Init logic
sub Init
{
    HawkeyeLib::DoConfig( );

    $Hawkeye = HawkeyePublish->new;
    $Hawkeye->Quiet( 1 );
    $Hawkeye->AutoIndexSet( 1 );
}

# The runtime logic
sub RunIt
{
    # Try various methods..
    # Let each method determine if it's 
    my $Count = 0;
    foreach my $Method ( @GatherMethods )
    {
	# Create the hash to use...
	my $Hash = HawkeyeHash->new( \$Hawkeye, "" );

	# Start things off
	my $Error = "";
	my $Status = $Method->{Function}( $Hash, \$Error );

	# >= 0 : ok
	if ( $Status >= 0 )
	{
	    # Ok, go "store" the data; done if there was data to store...
	    $Count = $Hash->Store( );
	    last if ( $Count > 0 );
	}
	# < 0 : Error
	else
	{
	    print STDERR "$Method->{Description}: $Error\n";
	}
    }

    # Store 'em all & publish them.
    if ( $Count > 0 )
    {
	$Hawkeye->Publish( );
    }
}

# Gather data via "/proc/meminfo" (Linux)
sub GatherMeminfo( $$ )
{
    my $Hash = shift;
    my $Error = shift;

    # Here's the meminfo file..
    my $Meminfo = "/proc/meminfo";
    return 0 if ( ! -f $Meminfo );

    # Run it, parse it
    Carp::confess( "Can't open '$Meminfo'" ) if ( ! open ( MEMINFO, "$Meminfo" ) );
    my @Fields;
    my %Offsets;
    while( <MEMINFO> )
    {
	if ( /^\s+(.*)/ )
	{
	    my $Str = $1;
	    $Str =~ s/://g;
	    @Fields = split( /\s+/, $Str );
	    foreach my $FieldNo ( 0 .. $#Fields )
	    {
		$Offsets{$Fields[$FieldNo]} = $FieldNo;
	    }
	    next;
	}

	# Mem line
	if ( /Mem:\s+(.*)/ )
	{
	    my @Values = split( /\s+/, $1 );
	    for my $Num ( 0 .. $#Values )
	    {
		$Hash->Add( "mem_$Fields[$Num]",
			    HawkeyePublish::TypeNumber,
			    $Values[$Num] );
	    }
	    if ( ( exists $Offsets{total} ) && ( exists $Offsets{used} ) )
	    {
		my $Percent = ( 100 *
				$Values[ $Offsets{used} ] /
				$Values[ $Offsets{total} ] );
		$Hash->Add( "mem_used_pct",
			    HawkeyePublish::TypeNumber,
			    sprintf( "%.2f", $Percent) );
	    }
	}
	# Swap line
	elsif( /Swap:\s+(.*)/ )
	{
	    my @Values = split( /\s+/, $1 );
	    for my $Num ( 0 .. $#Values )
	    {
		$Hash->Add( "swap_$Fields[$Num]",
			    HawkeyePublish::TypeNumber,
			    $Values[$Num] );
	    }
	    if ( ( exists $Offsets{total} ) && ( exists $Offsets{used} ) )
	    {
		my $Percent = ( 100 *
				$Values[ $Offsets{used} ] /
				$Values[ $Offsets{total} ] );
		$Hash->Add( "swap_used_pct",
			    HawkeyePublish::TypeNumber,
			    sprintf( "%.2f", $Percent) );
	    }
	}
	# Other lines
	elsif ( /(\S+):\s+(\d+) kB/)
	{
	    $Hash->Add( $1, HawkeyePublish::TypeNumber, $2 * 1024 );
	}
    }

    # Ok...
    return 1;
}

# Gather data via the "free" program (Linux)
sub GatherFree( $$ )
{
    my $Hash = shift;
    my $Error = shift;

    # Run it, parse it
    my $Program = "/usr/bin/free";
    return 0 if ( ! -x $Program );

    my $Cmd = "$Program -b";
    Carp::confess( "Can't run free '$Cmd'" ) if ( ! open ( FREE, "$Cmd|" ) );
    my @Fields;
    my %Offsets;
    while( <FREE> )
    {
	if ( /^\s+(.*)/ )
	{
	    @Fields = split( /\s+/, $1 );
	    foreach my $FieldNo ( 0 .. $#Fields )
	    {
		$Offsets{$Fields[$FieldNo]} = $FieldNo;
	    }
	    next;
	}

	# Mem line
	if ( /Mem:\s+(.*)/ )
	{
	    my @Values = split( /\s+/, $1 );
	    for my $Num ( 0 .. $#Values )
	    {
		$Hash->Add( "mem_$Fields[$Num]",
			    HawkeyePublish::TypeNumber,
			    $Values[$Num] );
	    }
	    if ( ( exists $Offsets{total} ) && ( exists $Offsets{used} ) )
	    {
		my $Percent = ( 100 *
				$Values[ $Offsets{used} ] /
				$Values[ $Offsets{total} ] );
		$Hash->Add( "mem_used_pct",
			    HawkeyePublish::TypeNumber,
			    sprintf( "%.2f", $Percent) );
	    }
	}
	# Buffers/cache line
	elsif ( /buffers\/cache:\s+(.*)/ )
	{
	    my @Values = ( 0, split( /\s+/, $1 ) );
	    for my $Num ( 1 .. $#Values )
	    {
		$Hash->Add( "buffers_cache_$Fields[$Num]",
			    HawkeyePublish::TypeNumber, $Values[$Num] );
	    }
	}
	# Swap line
	elsif( /Swap:\s+(.*)/ )
	{
	    my @Values = split( /\s+/, $1 );
	    for my $Num ( 0 .. $#Values )
	    {
		$Hash->Add( "swap_$Fields[$Num]",
			    HawkeyePublish::TypeNumber,
			    $Values[$Num] );
	    }
	    if ( ( exists $Offsets{total} ) && ( exists $Offsets{used} ) )
	    {
		my $Percent = ( 100 *
				$Values[ $Offsets{used} ] /
				$Values[ $Offsets{total} ] );
		$Hash->Add( "swap_used_pct",
			    HawkeyePublish::TypeNumber,
			    sprintf( "%.2f", $Percent) );
	    }
	}
    }

    return 1;
}

# Gather data via the "free" program (Linux)
sub GatherSolaris( $$ )
{
    my $Hash = shift;
    my $Error = shift;
    my $Cmd;

    # Run 'swap -s'

    # Run it, parse it
    my $Program = "/usr/sbin/swap";
    return 0 if ( ! -x $Program );

    my $SwapOk = 0;
    $Cmd = "$Program -s";
    Carp::confess( "Can't run free '$Cmd'" ) if ( ! open ( SWAP, "$Cmd|" ) );
  SWAP:
    while( <SWAP> )
    {
	chomp;
	if ( /total:\s+(.*)/ )
	{
	    my @Strings = split( /\s*[=,+]\s*/, $1 );
	    foreach my $Str ( @Strings )
	    {
	       if ( $Str =~ /^(\d+)([kmg]?)\s+(.*)/ )
		{
		    my $Value = $1;
		    if ( defined $2 )
		    {
			if ( $2 eq "k" )
			{
			    $Value *= 1024;
			}
			elsif ( $2 eq "m" )
			{
			    $Value *= 1024 * 1024;
			}
			elsif ( $2 eq "g" )
			{
			    $Value *= 1024 * 1024 * 1024;
			}
			else
			{
			    print STDERR "swap: can't parse '$Str'\n";
			    next;
			}
		    }
		    my $Label = $3;
		    $Label =~ s/\s+/_/g;
		    $Hash->Add( "swap_" . $Label, HawkeyePublish::TypeNumber, $Value );
		    $SwapOk = 1;
		}
		else
		{
		    print STDERR "swap: can't parse '$Str'\n";
		    next;
		}
		
	    }
	}
	last if ( $SwapOk );
    }

    return $SwapOk;
}

sub GatherError( $$ )
{
    my $Hash = shift;
    my $Error = shift;
    $$Error = "No valid data gathering method found";

    return -1;
}
