package RRD::Amavis;

=head1 NAME

RRD::Amavis - maintains a rrd file with temperature readings

=head1 SYNOPSIS

    use RRD::Amavis qw(create update);

    RRD::Amavis->create( '/var/local/rrd/amavis.rrd', 2 );
    RRD::Amavis->update( '/var/local/rrd/amavis.rrd', '/var/log/mail.log' );

=head1 DESCRIPTION

B<RRD::Amavis::create> creates the initial rrd file
B<RRD::Amavis::update> updates an rrd file with information from the
/sys filesystem.

=head1 METHODS

=over 4

=item create

Performs the initial creation of the rrd file. The first argument is
the path to the rrd file.  The second argument is the interval in 
seconds between which you intend to call update.

=item update

Performs the update of the rrd file. The first argument is the path
to the rrd file. The second argument is the name of the log file.

On failure, throws an error. Return value is not used.

=back

=head1 AUTHOR

(c) 2006 by Luke Heberling, E<lt>lukeh@c-ware.comE<gt>.

All rights reserved. All wrongs reversed. This program is
free software. You can redistribute and/or modify it under
the same terms as Perl itself.

=cut

use strict;
use warnings;
use RRDs;
use File::Tail;

use vars qw(@EXPORT_OK @ISA);
@ISA = qw(Exporter);
# we export nothing by default :)
@EXPORT_OK = qw(update create);

my %counts = ();
my %allids = ();
my $tail;

sub update () {
  shift;
  my $file = shift;
  my $log = shift;

  unless( defined( $tail ) ) {
    $tail = File::Tail->new( name => $log,
                             tail => -1,
                             ignore_nonexistant => 1,
                             nowait => 1,
                             maxbuf => 4096,
                             maxinterval => -1,
                             interval => -1,
    );
    $tail->nowait(1);
  }

  for( my $dummy=0; $dummy < 3; ++$dummy ) {
    while( my $line = $tail->read ) {
      if ( $line =~ /[^:]*amavis\[\d*\]:\s
                     [^,]*((?:(?:Passed)|(?:Blocked))
                     \s(?:(?:CLEAN)|(?:INFECTED)|(?:BANNED)|(?:SPAM(?:MY)?)|(?:BAD-HEADER)))(?:\s\([^\)]*\))?[^,]*,
                     (?:[^,]*)(?:,<[^>]*>)*, # skip this field ( (LOCAL )?[Connection IP] [Received: IP] <sender> -> <recip>(,<recip>)... )
                     (?:\squarantine:\s([^,]*),)?
                     (?:\sMessage-ID:\s(<[^>]*>|[^,]*),)?
                     (?:\sResent-Message-ID:\s(<[^>]*>|[^,]*),)?
                     (?:\smail_id:\s([^,]*),)?
                     (?:\sHits:\s([^,]*),)?
                     (?:\squeued_as:\s([^,]*),)?
                     (?:\s(\d*)\sms)?
                     /x ) {
        my ($status, $quarantine, $message_id, $resent_message_id, $mail_id, $hits, $queued_as, $ms) = ($1,$2,$3,$4,$5,$6,$7,$8);
        ++$counts{$status};
        $allids{$mail_id}=undef;
        if( $mail_id eq "" ) {
          print STDERR "Missed a line: $line";
          print STDERR "$status: Qr: $quarantine Msid: $message_id Rmsid: $resent_message_id Mlid: $mail_id Hits: $hits q: $queued_as ms: $ms\n";
        }
      }
    }
  }

  my @readings = ();
  push @readings, scalar keys %allids;

  foreach my $key ( ("Passed CLEAN", "Passed SPAMMY", "Passed SPAM",  "Passed INFECTED",  "Passed BANNED",  "Passed BAD-HEADER",
                                                     "Blocked SPAM", "Blocked INFECTED", "Blocked BANNED", "Blocked BAD-HEADER" ) ) {
    my $test = $counts{$key};
    push @readings, (defined($test) ? $test : 0 );
    print STDERR "$key:\t". (defined($test) ? $test : 0 ) ."\n";
    #delete $counts{$key}
  }

  #foreach my $key ( keys %counts ) {
  #  print STDERR "Missed $key: $counts{$key} \n";
  #}

  RRDs::update( $file, "N:" . join(':', @readings ) ) ;
  my $error = RRDs::error;
  die "Unable to update $file: $error" if $error;
}

sub create() {
  shift;
  my $file = shift;
  my $inc = shift;
  RRDs::create( $file, 
    '--step', $inc,
    'DS:Checks:DERIVE:660:0:18446744073709551616',
    'DS:Passed_Clean:DERIVE:660:0:18446744073709551616',
    'DS:Passed_Spammy:DERIVE:660:0:18446744073709551616',
    'DS:Passed_Spam:DERIVE:660:0:18446744073709551616',
    'DS:Passed_Virus:DERIVE:660:0:18446744073709551616',
    'DS:Passed_Banned:DERIVE:660:0:18446744073709551616',
    'DS:Passed_BadHeader:DERIVE:660:0:18446744073709551616',
    'DS:Blocked_Spam:DERIVE:660:0:18446744073709551616',
    'DS:Blocked_Virus:DERIVE:660:0:18446744073709551616',
    'DS:Blocked_Banned:DERIVE:660:0:18446744073709551616',
    'DS:Blocked_BadHeader:DERIVE:660:0:18446744073709551616',

    'RRA:AVERAGE:0.5:1:1800',
    'RRA:AVERAGE:0.5:30:1440',
    'RRA:AVERAGE:0.5:150:2016',
    'RRA:AVERAGE:0.5:450:7440',
    'RRA:AVERAGE:0.5:1800:8760'
  );
  my $error = RRDs::error;
  die "Unable to create $file: $error" if $error;
}

1;
