#!/usr/bin/perl -w
#
#  $Id: spreaddata,v 1.1 2006/03/04 07:22:30 dgregor Exp $
# 
# Copyright (c) 2004-2006 Daniel J. Gregor, Jr.
# 
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject
# to the following conditions:
# 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

use Time::Local;

%months = (
	'Jan' => 0,
	'Feb' => 1,
	'Mar' => 2,
	'Apr' => 3,
	'May' => 4,
	'Jun' => 5,
	'Jul' => 6,
	'Aug' => 7,
	'Sep' => 8,
	'Oct' => 9,
	'Nov' => 10,
	'Dec' => 11
);

my $previous;

my $begin;
my $end;

use Getopt::Std;

my %opts;
getopts('ce:r:d:', \%opts);

my $expression = $opts{'e'} || '^(.*)$';
my $rrdoutput = $opts{'r'};
my $dsname = $opts{'d'};
my $rrdcreate = defined($opts{'c'});

while (<>) {
    chomp();

    if (!defined($previous)) {
	if (!defined($begin)) {
	    $begin = parsedate($_);
	} else {
	    $previous = $_;
	}
    } else {
	parsedata($previous, $expression);
	$previous = $_;
    }
}

if (!defined($previous)) {
    die("what!!! too few lines!\n");
}

$end = parsedate($previous);

my $data_points = scalar(@data);
$period = ($end - $begin) / $data_points;

if ($rrdcreate) {
    my $step = ($period >= 1) ? int($period) : 1;
    my @rras;

    my $i = 1;
    while ($i == 1 || ($data_points / $i) >= 4000) {
	my $steps = int($i);
	my $rows = int($data_points / $i);
        push(@rras, sprintf("RRA:AVERAGE:0.25:%d:%d", $steps, $rows));
        push(@rras, sprintf("RRA:MAX:0.25:%d:%d", $steps, $rows));
	$i *= 10;
    }

    print("create $rrdoutput --start '$begin - 10s' --step $step ",
          "DS:$dsname:GAUGE:" . (5 * $step) . ":U:U ",
 	  join(" ", @rras),
          "\n");
}

for $a (0 .. $#data) {
    $time = int($begin + ($period * $a));
    if (defined($rrdoutput)) {
        print("update $rrdoutput --template $dsname $time:$data[$a]\n");
    } else {
        print($time, " ", $data[$a], "\n");
    }
}

sub parsedate {
    my $date = shift(@_);

    #                     month   day     hour   min  sec           year
    #                      $1      $2      $3    $4    $5            $6
    if ($date !~ m/^\S+\s+(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+\S+\s+(\d+)$/){
	die("could not parse date \"$date\" on line $.\n");
    }

    if (!exists($months{$1})) {
	die("month \"$1\" is not valid in date string \"$date\" on line $.\n");
    }

    return Time::Local::timelocal($5, $4, $3, $2, $months{$1}, $6 - 1900);
}

# e.g. for sar data:  -e '^\s*([0-9.]+)\s'

sub parsedata {
    my $data = shift(@_);
    my $expression = shift(@_);

    if ($data =~ m/$expression/) {
	push(@data, $1);
    }
}
