#!/usr/bin/perl

# get-statinfo
# SunZhenyu, 8/26/04
# sunzhenyu@world2.cn

use strict;
use FileHandle;
use Time::Local 'timelocal_nocheck';

	my $g_interval = '5min';
	my $g_statinfo_filename = '/export/logs/statinfom';
	my $g_hostname = 'any';
	my $g_progname = 'any';
	my %g_statinfos;

	process();

sub process
{
	if( $ARGV[0] eq 'hour' ){	$g_interval = 'hour';	$g_statinfo_filename = '/export/logs/statinfoh';	}
	if( $ARGV[0] eq 'day' )	{	$g_interval = 'day';	$g_statinfo_filename = '/export/logs/statinfod';	}
	if( not -f $g_statinfo_filename or -s $g_statinfo_filename <= 0 )
	{
		$g_statinfo_filename    =       '/export/logs/old/statinfom.1';
		if( @ARGV[0] eq 'hour' ) { $g_statinfo_filename = '/export/logs/old/statinfoh.1'; }
		if( @ARGV[0] eq 'day' ) { $g_statinfo_filename = '/export/logs/statinfod.1'; }
	}

	$g_hostname = $ARGV[1] if( @ARGV > 1 );
	$g_progname = $ARGV[2] if( @ARGV > 2 );
	%g_statinfos = ();
	
	my @value_names;
	my @value_orders;
	my $i;
	for( $i=3; $i+1<@ARGV; $i=$i+2 )
	{
		push( @value_names, $ARGV[$i] );
		push( @value_orders, $ARGV[$i+1] );
		$g_statinfos{$ARGV[$i]} = $ARGV[$i+1];
	}

	if( keys(%g_statinfos) > 0 )
	{
		read_statinfo( $g_interval, $g_statinfo_filename, $g_hostname, $g_progname, \%g_statinfos );

		foreach( @value_names )
		{
			print $g_statinfos{$_} . "\n";
		}
	}

	for( $i=0; $i<30; $i++ )
	{
		print "0\n";
	}
}

#################################################################################
# The following is common subroutines

sub read_statinfo
{
	my ($interval, $filename, $hostname, $progname, $statinfos) = @_;
	$hostname = ".+" if( $hostname eq 'any');
	$progname = "" if( $progname eq 'any');
	my %read_values;
	my $read_lines_count;

	my $time_now = time;
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time_now);

	my $fh = new FileHandle;
	if( $fh->open("< $filename") )
	{
		$fh->seek( 0, 2 );

		my @lines;
		while( @lines = getprevlines( $fh ) )
		{
			last if( 0 == @lines );
			foreach( @lines )
			{
				my @content;
				@content = $_ =~ /^(.+)\s$hostname\s$progname.+STAT:(.+)/;
				next if( @content != 2 );

				my $time_line = get_timelocal( $content[0], $year );
				$time_line = get_timelocal( $content[0], $year-1 ) if( $time_line > $time_now+864000 );
				my $timespan = $time_now - $time_line;
				last if( ($interval eq 'hour' and $timespan > 21600) or ($interval eq 'day' and $timespan > 604800) or ($interval ne 'hour' and $interval ne 'day' and $timespan > 1800) );

				my @values;
				@values = $content[1] =~ /(.+)=(\d+):(\d+):(\d+):(\d+):(\d+)/g;
				next if( @values < 2 or defined $read_values{$values[0]} );

				my $value_no = $statinfos->{$values[0]};
				if( defined $value_no )
				{
					$statinfos->{$values[0]} = $values[$value_no];
					$read_values{$values[0]} = 1;
					if( keys(%$statinfos) == keys(%read_values) )
					{
						$fh->close();
						return;
					}
				}
			}
			$read_lines_count += @lines;
			last if( $read_lines_count > 2048 );
		}

		$fh->close();
	}

	foreach( keys(%$statinfos) )
	{	$statinfos->{$_} = 0 if( not defined $read_values{$_} );	}
}

sub getprevlines
{
	my $fh = shift;

	my $buffer;
	my $buffersize = 4096;
	my @lines;

	# read_bytes and pos
	my $read_bytes = $buffersize;
	my $pos = $fh->tell();
	return @lines if( 0 == $pos );
	my $pos = $pos-$buffersize;
	if( $pos < 0 )
	{
		$read_bytes = $read_bytes + $pos;
		$pos = 0;
	}

	# read
	$fh->seek( $pos, 0 );
	$read_bytes = $fh->read( $buffer, $read_bytes );

	# process lines
	my $last_line_pos = $read_bytes;
	my $i;
	for( $i=$read_bytes-1; $i>=0; $i-- )
	{
		if( "\n" eq substr( $buffer, $i, 1 ) )
		{
			my $line;
			$line = substr( $buffer, $i+1, $last_line_pos-$i-1 ) if( $last_line_pos-$i-1 > 0 );

			push @lines, $line if( defined $line and length($line) > 0 );
			$last_line_pos = $i;
		}
	}

	if( 0 == $pos )
	{
		my $line;
		$line = substr( $buffer, 0, $last_line_pos ) if( $last_line_pos > 0 );

		push @lines, $line if( defined $line and length($line) > 0 );
		$last_line_pos = 0;
	}

	# seek
	$pos = $pos+$last_line_pos;
	$fh->seek( $pos, 0 );

	return @lines;
}

sub get_timelocal
{
	my ($content,$year) = @_;
	my @t = $content =~ /(\w+)\s+(\d+)\s+(\d+):(\d+):(\d)/;

	if( @t == 5 )
	{
		my $mon = $t[0];
		if( $mon eq 'Jan' )		{	$mon = 0;	}
		elsif( $mon eq 'Feb' )	{	$mon = 1;	}
		elsif( $mon eq 'Mar' )	{	$mon = 2;	}
		elsif( $mon eq 'Apr' )	{	$mon = 3;	}
		elsif( $mon eq 'May' )	{	$mon = 4;	}
		elsif( $mon eq 'Jun' )	{	$mon = 5;	}
		elsif( $mon eq 'Jul' )	{	$mon = 6;	}
		elsif( $mon eq 'Aug' )	{	$mon = 7;	}
		elsif( $mon eq 'Sep' )	{	$mon = 8;	}
		elsif( $mon eq 'Oct' )	{	$mon = 9;	}
		elsif( $mon eq 'Nov' )	{	$mon = 10;	}
		elsif( $mon eq 'Dec' )	{	$mon = 11;	}
		else	{	$mon = 0;	}

		my $time = timelocal_nocheck($t[4],$t[3],$t[2],$t[1],$mon,$year);
		return $time;
	}
	else
	{
		@t = ();
		@t = $content =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;

		my $time = timelocal_nocheck($t[5],$t[4],$t[3],$t[2],$t[1],$t[0]);
		return $time;
	}
}

