#!/usr/bin/perl

use strict;
use Mysql;
use POSIX ":sys_wait_h";
use Socket;

my $opt_user="satis";
my $opt_password="satis";
my $database="satis";
my $socket="/tmp/mysql.sock"; 
 
$ENV{"3306"}="$socket";
my $dbh = Mysql->connect("", "$database", "$opt_user", "$opt_password") ||
    	die "Can't connect\n";

#--- Create tables ---
my $query = "CREATE TABLE IF NOT EXISTS lastspectrum".
            "(bandid INT NOT NULL,".
            "freq INT NOT NULL,".
            "sign FLOAT NOT NULL)";
my $sth = Query $dbh $query or die "$Mysql::db_errstr";
undef $sth;

#--- Start polling ---
my @nodes;

$query = "DELETE FROM SystemConf WHERE name='LockID';";
Query $dbh $query or die "$Mysql::db_errstr";

$query = "DELETE FROM SystemConf WHERE name like 'locking%';";
Query $dbh $query or die "$Mysql::db_errstr";

$query = "SELECT NodeID FROM Nodes WHERE Type IN ('WinRadio', 'HP', 'SatSpec', 'FS300', 'Decimator');";
$sth = Query $dbh $query or die "$Mysql::db_errstr";
my $line;
my $ni = 0;
while ($line = $sth->fetchrow_arrayref)
{
    $nodes[$ni++]="$$line[0]";
    print "START> Analizer id = $$line[0]\n";
}
if($ni==0)
{
    print "START> No analizers available. Exiting...\n";
	sleep(3);
	exit(-1);
}

#open(PIDFILE,"> pidfile") or die "Can't open pidfile: $!";
#print PIDFILE "$$";
#close(PIDFILE);

my %hashpid;
my $i;
for($i=0; $i<$ni; $i++)
{   
    my $server_pid = server_fork($nodes[$i]);
    $hashpid{$server_pid}=-$nodes[$i] if $server_pid > 0;
    
    my $monitor_pid = monitor_fork($nodes[$i]);
    $hashpid{$monitor_pid}=$nodes[$i] if $monitor_pid > 0;

    sleep(3);
}

undef $sth;
undef $dbh;  

my $kid;
while() {
    $kid = wait();
    my $tempnode=$hashpid{$kid};
    delete $hashpid{$kid};
    
    if($tempnode>=0)
    {
		my $pid = monitor_fork($tempnode); 
		$hashpid{$pid}=$tempnode;
    }
    else
    {
		my $pid = server_fork(-$tempnode);
		$hashpid{$pid}=$tempnode;
    }    
}


####################
# Function section #
####################

sub server_fork
{
    my $nodeid = shift;
    
    my $hiport = 1650;
    my $port  = 1549;
    my $addr  = inet_aton("localhost");
    my $paddr;
    my $isPortFree = 0;
    
    socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'))
	    or die "Couldn't create socket! Error message:!$\n";
#    setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR,
#	    pack("l", 1)) || die "setsockopt: $!";
    while($isPortFree!=1)
    {	
		$isPortFree = 1;
		$port++;
		$paddr = sockaddr_in($port, $addr);
        bind(SOCK, $paddr) or $isPortFree=0;
		$port<$hiport || die "Socket port can't be greater than 1650!";
    }
    close(SOCK);
    print "START> Socket Port = $port for SAID=$nodeid\n";
    
    #--- Save socket port
    if( $nodeid ne "")
    {
		$query = "DELETE FROM SystemConf WHERE NodeID='$nodeid' AND Name='SocketPort'";
		$sth = Query $dbh $query or die "$Mysql::db_errstr";
		undef $sth;
    }
    
    $query = "INSERT INTO SystemConf(NodeID,Name,Value,Type) VALUES('$nodeid','SocketPort','$port','Integer');";
    $sth = Query $dbh $query or die "$Mysql::db_errstr";
    undef $sth;
    
    my $pid;
	while(){
		$pid = fork();
		if(defined($pid) && $pid >= 0) { last; }
		sleep(3);
	}
    if($pid == 0)
    {
		print "Child (Spectrum Server): SAID = $nodeid.\n";
		exec "../SpectrumServer/SpectrumServer", "-p", "$port";
		print STDERR "Couldn't start Spectrum Server for SAID = $nodeid: $!\n";
		exit 0;
    }
    
    return $pid;
}

sub monitor_fork
{   
    my $nodeid=shift;
    
    my $pid;
	while(){
		$pid = fork();
		if(defined($pid) && $pid >= 0) { 
			last; 
		}
		sleep(3);
	}
    if ($pid == 0)
    {	
        print "START> Child. SAID = $nodeid.\n";
        exec "./monitoring.pl", "$nodeid";
		print STDERR "START> Couldn't start Spectrum Monitoring for SAID = $nodeid: $!\n";
		exit 0;
    }
    
    return $pid;
}
