#!/usr/bin/perl -sw
#
# Generic program for feeding data from a log into an RRD.
#
# $Cambridge: hermes/src/stats/scripts/rrdfeed,v 1.13 2004/08/31 12:49:33 fanf2 Exp $

use strict;

use RRDp;

use vars qw' $a $d $s $t ';

# avoid rrdtool's localtime braindamage
$ENV{TZ} = 'UTC';
RRDp::start 'rrdtool';

sub rrd (@) {
	RRDp::cmd @_;
	return RRDp::read;
}

sub usage () {
	print STDERR "usage: $0 [-a] [-d] [-s] [-t] file.rrd DSname regexp [DSname regexp ...]\n";
	print STDERR "	-a	guage (average value) mode\n";
	print STDERR "	-d	debug\n";
	print STDERR "	-s	total value mode\n";
	print STDERR "	-t	average time mode\n";
	exit 1;
}

usage if $a and $t;
usage if $a and $s;
usage if $t and $s;

usage if @ARGV < 3;
my $rrdfile = shift;

usage if @ARGV % 2 != 0;
my %argv = @ARGV;
my $argv_ds = join ':', sort keys %argv;
# clear out argv so that <> does the right thing
@ARGV = ();

my $rrdinfo = rrd info => $rrdfile;
my @ds = sort $$rrdinfo =~ m/^ds[[](\w+)[]][.]type/mg;
my $ds = join ':', @ds;
my $template = "--template=$ds";

if ($ds ne $argv_ds) {
	print STDERR "$0: $rrdfile contains data sources '$ds'\n";
	print STDERR "$0: you defined data sources '$argv_ds'\n";
	exit 1;
}

my $pidfile = $rrdfile;
$pidfile =~ s/([.]rrd)?$/.pid/;
open PID, "> $pidfile"
    or die "open $pidfile: $!\n";
print PID "$$\n";
close PID
    or die "write $pidfile: $!\n";

my %regex;
for my $ds (@ds) {
	$regex{$ds} = qr/$argv{$ds}/;
}

my $triggered = 0;
sub trigger () {
	if (/^[A-Z][a-z]{2} [ 123][0-9] [0-9]{2}:[0-9]{2}:00 /) {
		return 0 if $triggered;
		return $triggered = 1;
	} else {
		return $triggered = 0;
	}
}

my %count;
my %total;
sub inc () {
	for my $ds (@ds) {
		if (/$regex{$ds}/) {
			$count{$ds} += 1;
			# if no () then just count
			$total{$ds} += defined $1 ? $1 : 1
			    if $a or $s;
			if ($t) {
				my $time = $1;
				my $secs = 0;
				$secs += $1 * 604800 if $time =~ /(\d+)w/;
				$secs += $1 * 86400 if $time =~ /(\d+)d/;
				$secs += $1 * 3600 if $time =~ /(\d+)h/;
				$secs += $1 * 60 if $time =~ /(\d+)m/;
				$secs += $1 * 1 if $time =~ /(\d+)s/;
				$total{$ds} += $secs;
			}
		}
	}
}
sub zero () {
	for my $ds (@ds) {
		$count{$ds} = 0;
		$total{$ds} = 0;
	}
}

zero;
while (<>) {
	last if trigger;
}
exit 0 unless $triggered;
inc;
while (<>) {
	if (trigger) {
		my $vals = time;
		# paranoia? ensure time is start of minute
		$vals -= $vals % 60;
		for my $ds (@ds) {
			if ($a or $t) {
				$vals .= ":" .
				    ($count{$ds} == 0 ? 'U' :
				     $total{$ds} / $count{$ds});
			} elsif ($s) {
				$vals .= ":" . $total{$ds};
			} else {
				$vals .= ":" . $count{$ds};
			}
		}
		if ($d) {
			print "rrd update $rrdfile $template $vals\n";
		} else {
			rrd update => $rrdfile, $template, $vals;
		}
		zero;
	}
	inc;
}

unlink $pidfile;

exit 0;
