#!/usr/bin/perl -w

use strict;
use DBI;
use DBD::Oracle;
use POSIX;
use Data::Dumper;

our $conf_db_host = "";
our $conf_db_sid = "ORCL";
our $conf_db_port = 1521;
our $conf_db_username = "";
our $conf_db_password = "";

#
# open master db
#
my $mdbh;
sub open_master_db() {
  # only if closed...
  if($mdbh) { return; }
  $mdbh = DBI->connect("dbi:Oracle:host=$conf_db_host;sid=$conf_db_sid;port=$conf_db_port", "$conf_db_username", "$conf_db_password", { RaiseError => 0, AutoCommit => 1});
  if(!$mdbh) { die "Could not connect to db: $DBI::errstr."; }
  print STDERR "Connected to db\n";
}
open_master_db();

sub close_master_db() {
  if(!$mdbh) { return; }
  $mdbh->disconnect;
  $mdbh = undef;
}

#
# init int signal handler
#
my $mrun = 1;
sub dosigint {
  print STDERR "SIGINT!\n";
  $mrun = 0;
}
$SIG{INT} = \&dosigint;

#
# reaper to clean up dead clients
#
my $children = 0;
sub grimreaper {
  # reset handler, just in case...
  $SIG{CHLD} = \&grimreaper;
  # reap all pending children
  my $kid;
  do {
    $kid = waitpid(-1, WNOHANG);
    if($kid > 0) { 
      my $status = $?;
      print STDERR "Child PID $kid is dead ($status)...\n";
      $children--;
    }
  } while $kid > 0;
}
# set the handler
$SIG{CHLD} = \&grimreaper;

#
# fork and create a child handler for this request
#
sub forkchild($) {
  my ($req) = @_;   
  print STDERR "forkchild\n";
  my $i = fork();
  if(!defined $i) {
    die "fork failed";
  }
  if($i == 0) {
    print STDERR "child started\n";
    # child must not close master dbh on exit
    $mdbh->{InactiveDestroy} = 1;
    # No signal handler for the child?
    $SIG{CHLD} = 'DEFAULT';
    $req->{'child'} = $$;
    # get child db handle
    $req->{'dbh'} = DBI->connect("dbi:Oracle:host=$conf_db_host;sid=$conf_db_sid;port=$conf_db_port", "$conf_db_username", "$conf_db_password", { RaiseError => 0, AutoCommit => 1});
    if(!$req->{'dbh'}) { die "Could not connect child to db (giving up...): $DBI::errstr."; }
    my $ret = $req->{'dbh'}->selectrow_hashref("select SYS_CONTEXT('userenv','sid') from dual");
    print STDERR "RET: " . Dumper($ret);
    sleep(10);
    $req->{'dbh'}->disconnect;
    delete $req->{'dbh'};
    print STDERR "Child done: " . Dumper($req);
    exit 0;
  }
  print STDERR "parent. child is $i";
  $children++;
}

for(my $i = 0; $i < 10; $i++) {
    my $req = {};
    $req->{id} = $i;
    print STDERR "New request(1): " . Dumper($req);
    my $ret = $mdbh->selectrow_hashref("select SYS_CONTEXT('userenv','sid') from dual");
    print STDERR "PRET: " . Dumper($ret);
    forkchild($req);
    sleep(1);
}

while($children > 0) {
  print STDERR "children: $children\n";
  my $ret = $mdbh->selectrow_hashref("select SYS_CONTEXT('userenv','sid') from dual");
  print STDERR "ERET: " . Dumper($ret);
  sleep(1);
}
