#!/usr/bin/perl
#
#  Action module for Ant monitoring system
#
#  Writes logs into rrd database
#
#  Arguments - dir, where databases are stored
#            - interval for normal store (in seconds)         [60=def]
#            - timeout (in seconds)                          [600=def]
#            - type of aggreg.:   a(verage),(mi)n,(ma)x,l(ast) [a=def]
#            - type of datastore: g(auge),c(ounter)            [g=def]
#            - number of points for normal store    [1440 (1 day)=def]
#            - number of points to sum for long store          [7=def]
#
#  Databases filenames are $out_name~$addr.rrd
#
#  Template for logging: $time $addr $out_name $value
#
#

use Fcntl;
use RRDs;

open STDERR, ">/tmp/rrderr";

die "Usage: log_packer.pl logdir [interval [tmout [type [datatype [num_to_store [num_to_sum]]]]]]\n" if @ARGV<1;

my $dir=shift @ARGV;
die "No such dir: $dir\n" unless -d $dir;

my ($interval,$timeout,$agg,$type,$total,$tosum)=@ARGV;
my ($time,$addr,$var,$val);
my $ERR;

fcntl(STDIN,F_SETFL,fcntl(STDIN,F_GETFL,0)|O_NONBLOCK);


$interval ||= 60;
$timeout  ||= 600;
$agg      ||= 'a';
$type     ||= 'g';
$total    ||= 1440;
$tosum    ||= 7;

if($agg eq 'a'){
  $agg='AVERAGE';
}
elsif($agg eq 'n'){
  $agg='MIN';
}
elsif($agg eq 'x'){
  $agg='MAX';
}
elsif($agg eq 'l'){
  $agg='LAST';
}
else{
  die "Unknown aggregation: $agg. Only a,n,x,l allowed.\n";
}

if($type eq 'g'){
  $type="GAUGE";
}
elsif($type eq 'c'){
  $type='COUNTER';
}
else{
  die "Unknown type: $type. Only g,c allowed.\n";
}

if($interval<1 or $total<1 or $tosum <1 or $timeout<1){
  die "Invalid parameters. Zeros or negative numbera are not allowed.\n";
}

$|=1;

my $line;

for(;;){
  $line='';
INNER_LOOP:
  for(;;){
    while(read(STDIN,$p,1)>0){
      $line.=$p;
      print STDERR "ZERO!!!\n" if $p eq "\0";
      last INNER_LOOP if $p eq "\n";
    }
    select(undef,undef,undef,0.1);
  }
  action();
}

sub action( $ ){

  unless($line =~ /^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/){
    return;
  }
  if($line =~ tr/\0//sd){
     print STDERR localtime($time)." zeros in '$line'\n";
  }

  ($time,$addr,$var,$val)=($1,$2,$3,$4);

  $var  =~ y{a-zA-Z0-9_}{_}c;
  $addr =~ y{a-zA-Z0-9_}{_}c;
##  $val  =~ y{0-9.+-}{}c;

  # must i create new database?
  unless(-e "$dir/${var}~${addr}.rrd"){
    my ($sec,$min,$hour) = localtime($time);
    $start_time = $time-($sec+60*$min+3600*$hour); # todays midnight.

    RRDs::create("$dir/${var}~${addr}.rrd",
                 "--start=$start_time",
                 "--step=$interval",
                 "DS:data:$type:$timeout:U:U",
                 "RRA:$agg:0.1:1:$total",
                 "RRA:$agg:0.1:$tosum:$total"
                );
    $ERR=RRDs::error;
    print STDERR localtime($time)." ERROR while creating: $ERR\n" if $ERR;
  }
#    print "Updating: '$dir/${var}~${addr}.rrd'\n";
  RRDs::update("$dir/${var}~${addr}.rrd",
               "$time:$val"
              );
  $ERR=RRDs::error;
  print STDERR localtime($time)." ERROR while updating '$dir/${var}~${addr}.rrd with $time:$val: $ERR\n" if $ERR;
}

