#!/usr/bin/perl -w

# original version by Nélio Alves Pereira Filho
# modification by Dobrica Pavlinusic

use strict;
use Pg;
use Getopt::Long;
use POSIX ":sys_wait_h";


$| = 1;
my $control = 0;

my ($numprocs,$numstmts) = (4,100);
my ($debug,$verbose) = (0,0);
my ($help,$host,$port,$user,$password);

my $result = GetOptions(
	"debug!" => \$debug, "verbose!" => \$verbose, "help" => \$help,
	"host=s" => \$host, "port=i" => \$port,
	"user=s" => \$user, "password=s" => \$password,
	"numprocs=i" => \$numprocs, "numstmts=i" => \$numstmts,
	);

if (defined($help) || (scalar(@ARGV) < 3)) {
    print "Usage: $0 [options] db table column
Options:
	--host=hostname --port=port
	--user=username --password=string
	--numprocs=4 --numstmts=100
";
    exit ((scalar(@ARGV) < 3)? 1:0);
}

print STDERR "Running $numprocs threads, $numstmts inserts each\n";

my $db = $ARGV[0] || "master";
my $table = $ARGV[1];
my $col = $ARGV[2];

my $info = "dbname=$db";
$info = "$info host=$host" if (defined($host));
$info = "$info port=$port" if (defined($port));
$info = "$info user=$user" if (defined($user));
$info = "$info password=$password" if (defined($password));

my @pids = ();
my $q;

for (my $i=0; $i < $numprocs; $i++) {
    my $pid = fork();
    if (! defined($pid)) {
    	print "Can't fork...\n";
	exit;
    } elsif ($pid == 0) {
	doInserts($i+1);
	exit;
    } elsif ($pid) {
	push @pids, $pid;
    }
}

foreach my $pid (@pids) {
    my $x = -1;
    do {
	sleep(1);
	$x = waitpid($pid, 0);
    } until $x == $pid;
}


#########################

sub doInserts {
    my ($pid) = @_;
    print "<$pid> Running...\n";

    my $conn = Pg::connectdb($info);
    if ($conn->status != PGRES_CONNECTION_OK) {
	print "<$pid> Failed opening $info\n";
	print "<$pid> Abort!\n";
	last;
    }
 
    $result = $conn->exec("BEGIN");
    if ($result->resultStatus ne PGRES_COMMAND_OK) {
	print "<$pid> Error in query '$q': ". $conn->errorMessage."\n";
	print "<$pid> Abort!\n";
	last;
    }
    
    print "<$pid> Inserting $numstmts records...\n";
    my $sql = "INSERT INTO $table ($col) VALUES";
    for (my $i = 0; $i < $numstmts; $i++) {
	my $time = time;
	$q = "$sql ('test_${pid}_${i}_$time')";
	$result = $conn->exec($q);
	if ($result->resultStatus ne PGRES_COMMAND_OK) {
	    print "<$pid> Error in query '$q': ". $conn->errorMessage."\n";
	    $conn->exec("ROLLBACK");
	    print "<$pid> Abort!\n";
	    last;
	}
    }
    print "<$pid> done!\n";

    $result = $conn->exec("COMMIT");
    if ($result->resultStatus ne PGRES_COMMAND_OK) {
	print "<$pid> Error in query '$q': ". $conn->errorMessage."\n";
	$conn->exec("ROLLBACK");
	print "<$pid> Abort!\n";
	last;
    }
    
    print "<$pid> Finished.\n";
    $control++;
}
