#! /usr/bin/perl -w

use strict;
use Getopt::Long;

my $mrtg_root = "/var/www/mrtg";
my $device = "sw3-canix2.koumbit.net";
my $maxport = 48;
my $range = "month";
my $maxcount = 1;
my $skip = 0;

sub usage {
  print <<EOF
$0 [-r <root>] [-d <dev>] [-m <port> | -p <ports> ] [ -a <minute|hour|day|month|year> ] [ -c <n> ]
EOF
;
  exit;
}

my @ports = ();
usage() unless GetOptions("root:s" => \$mrtg_root,
                     "dev:s" => \$device,
		     "maxport:i" => \$maxport,
		     "ports:s" => \@ports,
		     "range|a:s" => \$range,
		     "skip:i" => \$skip,
		     "count:i" => \$maxcount);

if (@ports) {
  @ports = split(/,/,join(',', @ports));
} else {
  @ports = ( 1 .. $maxport );
}

$maxcount += $skip;

# map string representation to a position in the localtime array
my %ranges = ( 'minute' => 1,
               'hour' => 2,
	       'day' => 3,
	       'month' => 4,
	       'year' => 5);

if ($ranges{$range}) {
  $range = $ranges{$range};
} else {
  warn("invalid range $range\n");
  usage();
}

# stolen from http://www.perlmonks.org/?node_id=154952 with modif to show mor precision
sub round_it {
  my $num = shift;
  my $gb = (1024 * 1024 * 1024);
  my $mb = (1024 * 1024);
  my $kb = 1024;

   ($num > $gb) ? return sprintf("%0.2fGB", $num/$gb) :
   ($num > $mb) ? return sprintf("%0.2fMB", $num/$mb) :
   ($num > $kb) ? return sprintf("%0.2fKB", $num/$kb) :
   return $num . 'B';
}

sub process_port {

  my (@ot, @dt);
  my $in = 0;
  my $out = 0;
  my $port = shift(@_);
  my $logfile = $mrtg_root . "/" . $device . "_" . $port . ".log";
  my ( $ot, $dt, $lt ); # original, delta and last timestamp
  my $count = 1;
  if (!open(MRTGLOG, $logfile)) {
    warn("cannot open log $logfile, skipping\n");
    return 0;
  }
  while (<MRTGLOG>) {
    # this has been deduced from http://oss.oetiker.ch/mrtg/doc/mrtg-logfile.en.html
    # there may be mistakes here
    if (/^([0-9]*) ([0-9]*) ([0-9]*)$/) { # first line
	$ot = $lt = $1;
        @ot = gmtime($1);
    } elsif (/^([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*)$/) {
        @dt = gmtime($1);
	my $delta = $lt-$1;
        if ($dt[$range] != $ot[$range]) {
	  # next period
	  if (++$count > $maxcount) {
            last;
	  } else {
	    @ot = @dt;
	  }
        }
	if ($count > $skip) {
	  $dt = $lt = $1;
          $in += $delta*$2;
          $out += $delta*$3;
	} else {
	  $ot = $1;
	}
    }
  }
  close(MRTGLOG);
  print "$port\t" . round_it($in) . "\t". round_it($out) . "\t" . scalar gmtime($dt) . "\t" . scalar gmtime($ot) . "\n" if ($out > 0 and $in > 0);

}

print "#port\tin\tout\tstart\tend\n";
foreach (@ports) {
  process_port($_);;
}
