#!/usr/bin/perl -w

=head1 NAME

octo_dispatcher - Octopussy Dispatcher program

=head1 DESCRIPTION

octo_dispatcher is the program that receive syslog lines and dispatch into device directories

(syslog --> device/year/month/day/Unknown)

=cut

use strict;

use File::Copy;
use Octopussy;

my $PROG_NAME = "octo_dispatcher";
my $dir_pid = Octopussy::Directory("running");

my %device_dir;
my %device_type;

=head1 FUNCTIONS

=head2 Init()

=cut

sub Init()
{
	%device_dir = ();
	%device_type = ();
	AAT::Syslog($PROG_NAME, "Load Devices Configuration");
	foreach my $d (Octopussy::Device::Configurations("name"))
	{
  	my $type = $d->{type};
  	$type =~ s/ /_/g;
		my $status = (defined $d->{status} ? $d->{status} : "Paused");
		$device_type{$d->{name}} = ($status ne "Stopped" ? $type : "");
		$device_dir{$d->{name}} = 
			Octopussy::Storage::Directory_Incoming($d->{name});
	}		
	Octopussy::RRDTool::Syslog_By_DeviceType_Init();
}

=head2 Handle_Dir($device, $day, $month, $year)

=cut

sub Handle_Dir($$$$)
{
	my ($device, $day, $month, $year) = @_;

	if (!defined $device_dir{$device})
	{
  	if (!-f Octopussy::Device::Filename($device))
  	{
    	Octopussy::Device::New({ name => $device, address => $device,
      	description => "New Device !" });
    	$device_dir{$device} = Octopussy::Storage::Directory_Incoming($device);
  	}
	}
	my $type = (AAT::NOT_NULL($device_type{$device})
    ? $device_type{$device} : "Unknown");
  my $dir_incoming = "$device_dir{$device}/$device/Incoming/$year/$month/$day";
	Octopussy::Create_Directory($dir_incoming);

	return ($dir_incoming);
}

#
# MAIN
#

my %logs;
my $device = undef;
my $line = undef;

my ($year, $month, $mday, $hour, $min) = AAT::Datetime::Now();
my ($n_year, $n_month, $n_mday, $n_hour, $n_min) = AAT::Datetime::Now();

$SIG{HUP} = \&Init;
Octopussy::PID_File($PROG_NAME);
AAT::Syslog($PROG_NAME, "Started !");
Init();
while (<>)
{
	$line = $_;
	chomp($line);
	$line =~ s/^<\d+>//;
	if ($line =~ /^\w{3} \s?\d{1,2} \d\d:\d\d:\d\d (\S+)/)
	{
		$device = $1;
		($n_year, $n_month, $n_mday, $n_hour, $n_min) = AAT::Datetime::Now();
		if (($n_min != $min) || ($n_hour != $hour) || ($n_mday != $mday) 
			|| ($n_month != $month))
		{
			open(STATS, "> $dir_pid/$PROG_NAME.stats.tmp");
			print STATS "[$year$month$mday$hour$min]\n";
			my $total = 0;
			my %dtype_stats = ();
			foreach my $device (keys %logs)
      {
				my $dir = Handle_Dir($device, $mday, $month, $year);
				my $file = "$dir/msg_$hour" . "h$min.log";
				my $i = 0;
				if (defined open(FILE, ">> $file"))
				{
					foreach my $l (@{$logs{$device}})
						{ print FILE "$l\n"; $i++; }
					close(FILE);
				}
				else
      	{
        	print "Unable to open file '$file'\n";
        	AAT::Syslog("octo_dispatcher", "UNABLE_OPEN_FILE", $file);
      	}
				AAT::Syslog($PROG_NAME, "Device: $device - Events: $i");
				$dtype_stats{$device_type{$device}} += $i;
				print STATS "$device: $i\n";
				Octopussy::Chown($file);
				delete $logs{$device};
				$total += $i;
			}
			close(STATS);
			my @dt_stats = ();
			my @dtypes = Octopussy::Device::Types();
			foreach my $dt (@dtypes)
			{ 
				$dt =~ s/ /_/;
				push(@dt_stats, $dtype_stats{$dt} + 0); 
			}
			Octopussy::RRDTool::Syslog_By_DeviceType_Update(\@dt_stats);
			copy("$dir_pid/$PROG_NAME.stats.tmp", "$dir_pid/$PROG_NAME.stats");
			($year, $month, $mday, $hour, $min) = 
				($n_year, $n_month, $n_mday, $n_hour, $n_min);
		}
		push(@{$logs{$device}}, $line)	
			if ((!defined $device_type{$device}) || ($device_type{$device} ne ""));
	}
}

=head1 AUTHOR

Sebastien Thebert <octo.devel@gmail.com>

=head1 SEE ALSO

octo_extractor, octo_parser, octo_uparser, octo_reporter, octo_scheduler

=cut
