use strict;
use re 'taint';
use Time::HiRes ();
use BerkeleyDB;
use vars qw($VERSION); $VERSION = 1.02;
use vars qw(%keys %virus %types %history $avg_int $uptime);
$avg_int = 5*60;
sub p1($$@) {
my($k,$avg,@tot_k) = @_;
printf("%-23s %6d %6.0f/h", $k, $keys{$k}, $avg*3600);
for my $tot_k (@tot_k) {
if ($keys{$tot_k} <= 0) {
printf(" --- %%")
} else {
printf(" %6.1f %%", 100*$keys{$k}/$keys{$tot_k})
}
print " ($tot_k)";
}
print "\n";
}
sub p2($$$) {
my($k,$avg,$tot_k) = @_;
printf("%-23s %6d %6.0f/h %6.1f %% (%s)\n",
$k, $virus{$k}, $avg*3600, 100*$virus{$k}/$keys{$tot_k}, $tot_k);
}
sub enqueue($$$$) {
my($name,$now,$val,$hold_time) = @_;
if (ref $history{$name} ne 'ARRAY') { $history{$name} = [] }
my($oldest_useful);
for my $j (0..$ if ($history{$name}->[$j][0] + $hold_time >= $now)
{ $oldest_useful = $j; last }
}
if (defined $oldest_useful) {
@{$history{$name}} =
@{$history{$name}}[$oldest_useful..$ }
push(@{$history{$name}}, [$now,$val]);
my($average,$dv,$dt); my($n) = scalar(@{$history{$name}});
my($oldest) = $history{$name}->[0];
my($latest) = $history{$name}->[$n-1];
$dt = $latest->[0] - $oldest->[0]; $dv = $latest->[1] - $oldest->[1];
if ($n < 2 || $dt < $hold_time/2) {
$dt = $uptime; $dv = $val; }
if ($dt > 0) { $average = $dv/$dt }
($average, $dv, $dt, $n);
}
sub fmt_ticks($) {
my($t) = @_;
my($hh)= $t % 100; $t = int($t/100);
my($s) = $t % 60; $t = int($t/60);
my($m) = $t % 60; $t = int($t/60);
my($h) = $t % 24; $t = int($t/24);
my($d) = $t;
sprintf("%d days, %d:%02d:%02d.%02d", $d,$h,$m,$s,$hh);
};
$SIG{INT} = sub { die "\n" }; my($env) = BerkeleyDB::Env->new(
'-Home'=>'/var/amavis/db', '-Flags'=> DB_INIT_CDB | DB_INIT_MPOOL);
defined $env or die "BDB no env: $BerkeleyDB::Error $!";
my($db) = BerkeleyDB::Hash->new(
'-Filename'=>'snmp.db', '-Flags'=>DB_RDONLY, '-Env'=>$env );
defined $db or die "BDB no dbS 1: $BerkeleyDB::Error $!";
my($cursor);
$| = 1;
my($stat,$key,$val);
for (;;) {
%keys = (); %virus = (); %types = ();
my($now); my($eval_stat,$interrupt); $interrupt = '';
print "\n";
{ my($h1) = sub { $interrupt = $_[0] };
local(@SIG{qw(INT HUP TERM TSTP QUIT ALRM USR1 USR2)}) = ($h1) x 8;
eval {
$cursor = $db->db_cursor; defined $cursor or die "db_cursor error: $BerkeleyDB::Error";
$now = Time::HiRes::time;
while ( ($stat=$cursor->c_get($key,$val,DB_NEXT)) == 0 ) {
if ($key =~ /^virus\.byname\.(.*)\z/s) { $virus{$1} = $val }
else { $keys{$key} = $val }
}
$stat==DB_NOTFOUND or die "c_get: $BerkeleyDB::Error $!";
$cursor->c_close==0 or die "c_close error: $BerkeleyDB::Error";
$cursor = undef;
};
$eval_stat = $@;
if (defined $db) {
$cursor->c_close if defined $cursor; $cursor = undef;
}
}
if ($interrupt ne '') { kill($interrupt,$$) } elsif ($eval_stat ne '') { chomp($eval_stat); die "BDB $eval_stat\n" }
for my $k (sort keys %keys) {
if ($keys{$k} =~ /^C32 (.*)\z/) {
$keys{$k} = $1;
} elsif ($k eq 'sysUpTime' && $keys{$k} =~ /^INT (.*)\z/) {
$uptime = $now - $1; my($ticks) = int($uptime*100);
printf("%-15s %s %s (%s)\n",
$k,'Timeticks', $ticks, fmt_ticks($ticks));
delete($keys{$k});
} else {
printf("%-15s %s\n", $k,$keys{$k});
delete($keys{$k});
}
}
for (sort keys %keys) {
my($avg,$dv,$dt,$n) = enqueue($_, $now, $keys{$_}, $avg_int);
if (/^OpsDecTyp/) {} elsif (/^CacheHitsVirusMsgs$/) { p1($_,$avg,'ContentVirusMsgs') }
elsif (/^CacheHitsBannedMsgs$/) { p1($_,$avg,'ContentBannedMsgs') }
elsif (/^CacheHitsSpamMsgs$/) { p1($_,$avg,'ContentSpamMsgs') }
elsif (/^Cache/) { p1($_,$avg,'CacheAttempts') }
elsif (/^Content/) { p1($_,$avg,'InMsgs') }
elsif (/^Quar/) { p1($_,$avg,'QuarMsgs') }
elsif (/^OpsSql/) { p1($_,$avg,'InMsgsRecips') }
elsif (/^(InMsgs|Ops)/) { p1($_,$avg,'InMsgs') }
elsif (/^Out/) { p1($_,$avg,'OutMsgs') }
else { p1($_,$avg,undef) }
}
for (sort { $keys{$b} <=> $keys{$a} } grep {/^OpsDecTyp/} keys %keys) {
my($avg,$dv,$dt,$n) = enqueue($_, $now, $keys{$_}, $avg_int);
p1($_,$avg,'InMsgs');
}
for (keys %virus) { $virus{$_} = $1 if $virus{$_} =~ /^C32 (.*)\z/ }
for (sort { $virus{$b} <=> $virus{$a} } keys %virus) {
my($avg,$dv,$dt,$n) = enqueue($_, $now, $virus{$_}, $avg_int);
p2($_,$avg,'ContentVirusMsgs');
}
sleep 10;
}
END {
if (defined $db) {
$cursor->c_close if defined $cursor; $db->db_close==0 or die "BDB db_close error: $BerkeleyDB::Error $!";
}
print STDERR "exited\n";
}