#!/usr/bin/perl -w -I../lib/
#
# $Id: alert-dispatcher.pl,v 1.13 2002/03/20 13:43:49 fpmip Exp $
#

# Author : Tycho Fruru <tycho@fruru.com>

# Copyright (C) 2001 Tycho Fruru <tycho@fruru.com>
# Copyright (C) 2001 Conostix S.A. Luxembourg - Tycho Fruru <tycho@conostix.com>

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#

use XML::Simple;
use Data::Dumper;	# for debugging those XML data structures
use DBI;

use IPFC::Backend::DB::Interface;
use IPFC::Correlate::Simple;

require "alert-config.pl";
use IPFC::Log;

{
    IPFC::Log::set_verbosity($VERBOSITY);
    
    my $dbh;
    my $sth;
    
    $dbh = DBI->connect($DB_CONNECT_STRING,$DB_USERNAME,$DB_PASSWORD) or
				die "Database connection failed";
    $dbh->{AutoCommit} = 0;
    $sth = $dbh->prepare("select version from ipfc_schema where component = 'db-schema' ".
				    "order by date desc limit 1") or
		die "select version from ipfc_schema failed";
    $sth->execute or die "select version from ipfc_schema execution failed";

    my ($version) = $sth->fetchrow_array;
    $sth->finish;

    if (!defined($version) || ($version lt "20020204-01")) {
	die "Database version incompatible (you have version $version) !";
    }

    my $backend_interface = IPFC::Backend::DB::Interface->new($dbh);
    my $correlator = IPFC::Correlate::Simple->new($backend_interface);
        
    while (1) {
    	$sth = $dbh->prepare("select event_id from $ALERT_QUEUE_NAME as a ".
			"where not exists (select event_id from $ALERT_QUEUE_FINISHED_NAME as b ".
					"where a.event_id = b.event_id) limit 500") or
		die "select event_id from $ALERT_QUEUE_NAME failed";
	$sth->execute or die "select event_id from $ALERT_QUEUE_NAME failed";
	my @event_ids=();

	while (my ($event_id) = $sth->fetchrow_array) {
	    push @event_ids,$event_id;
	}
	$sth->finish;
	$dbh->commit;
	if ($#event_ids+1 == 0) { # length of the @event_ids array
	    IPFC::Log::logger(3,"There are no events, sleeping $POLL_INTERVAL seconds.");
	    sleep $POLL_INTERVAL;
	    next;
	} else {
	    my $number_of_events = $#event_ids + 1;
	    IPFC::Log::logger(4,"There are ".$number_of_events." events to be processed.");
	}
		
	$sth=$dbh->prepare("select agent_id,agent_type_name from agents");
	$sth->execute;
	my %agent_type_name; # $agent_type_name{<agentid>} gives the agent's type name
	while (my ($current_agent_id,$current_agent_type_name) = $sth->fetchrow_array) {
	    $agent_type_name{$current_agent_id}=$current_agent_type_name;	
	}
	
	while ($#event_ids + 1 > 0) {
	  my @current_event_ids = splice @event_ids,0,$ALERT_BLOCKS; # take the $ALERT_BLOCKS first events
	  my $current_event_ids_query = " ('".join("','" , @current_event_ids)."') ";
	  
	  my $current_eventgroup = $backend_interface->get_events(\@current_event_ids);
	  
	  my $finished_sql = ""; # contains inserts to be added to the "treated events" table
	  my @done_event_ids ; #contains all event_ids to be removed from alert_queue
	  
	  my $number_of_events = $current_eventgroup->count_events;
	  
	  foreach my $i (0 .. $number_of_events-1) {
	    my $event = $current_eventgroup->get_event($i) or die "Cannot get events";
	    
	    my $event_id = $event->{'event_id'}->[0];

	    if ($event_id % 100 == 0) {
 	        IPFC::Log::logger(4,"Event id $event_id.");
	    }
	    
	    my ($status,$alert_destinations,$alert_summary,$alert_text);
	    		
	    @search_array = ( 
	    		  "default",
			  "agent_type=$event->{'agent_type_name'}->[0],event_type=$event->{'event_type'}->[0]",
			  "agent_type=$event->{'agent_type_name'}->[0],event_type=$event->{'event_type'}->[0],event_subtype=$event->{'event_subtype'}->[0]",
			  "agent_type=$event->{'agent_type_name'}->[0],event_type=$event->{'event_type'}->[0],event_subtype=$event->{'event_subtype'}->[0],event_version=$event->{'event_version'}->[0]",
			  "agent_id=$event->{'agent_id'}->[0],event_type=$event->{'event_type'}->[0]",
			  "agent_id=$event->{'agent_id'}->[0],event_type=$event->{'event_type'}->[0],event_subtype=$event->{'event_subtype'}->[0]",
			  "agent_id=$event->{'agent_id'}->[0],event_type=$event->{'event_type'}->[0],event_subtype=$event->{'event_subtype'}->[0],event_version=$event->{'event_version'}->[0]"
			    );
	
	    foreach $current_search (@search_array) {
		if (defined($ALERT{$current_search})) {
		    ($status,$alert_destinations,$alert_summary,$alert_text) = 
			&{$ALERT{$current_search}}($event,$alert_destinations,$alert_summary,$alert_text);
		    if ($status == 0) {
			IPFC::Log::logger(1,"There was a problem treating alerts for $event_id");
		    }
		}
	    }
	    
	    
	    if (defined($alert_destinations)) {
	    	IPFC::Log::logger(1,"ALERT :");
	    	IPFC::Log::logger(1,$alert_summary);
		IPFC::Log::logger(1,$alert_text);
	    }
	    
	    $correlator->correlate($event);
	    
	    push @done_event_ids,$event_id;
	  
	  }
	  $dbh->do("delete from alert_queue ".
	           "where event_id in ('".join("','",@done_event_ids)."')");
	  $dbh->commit;
	}
    }	
}
