#!/usr/bin/perl
#
# jobscript-to-db -- copy newly spooled job scripts into database
# Copyright 2006 Ohio Supercomputer Center
#
# License:  GNU GPL v2; see ../COPYING for details.
# Revision info:
# $HeadURL$
# $Revision$
# $Date$
#
# Not intended to be invoked directly, but rather by spool-jobscripts
# (which is itself invoked by dnotify or moral equivalent).
use POSIX;
use DBI;

sub keyval_exists
{
    local($key,$val,$dbtable,$dbh) = @_;
    local($sth,$n);

    $sth=$dbh->prepare("SELECT ".$key." FROM ".$dbtable." WHERE ".$key." = \'".$val."\';")
	or die "Could not prepare query:  $dbh->errstr";
    $n=$sth->execute or die "Could not execute query:  $sth->errstr";

    $n;
}

#
# Main program begins here
#

# my spool dir
$spooldir=$ARGV[0];

# my system name in DB
$system=`hostname`;

# figure out pbs server name (we need it later)
if ( ! defined($ENV{"PBS_HOME"}) )
{
    die "\$PBS_HOME undefined!";
} 
$pbsspooldir=$ENV{"PBS_HOME"};
open(SERVERNAME,"<$pbsspooldir/server_name");
$pbsserver=<SERVERNAME>;
close(SERVERNAME);
chop($pbsserver);
# in HA configurations, server_name contains a comma-separated list of
# servers with the primary listed first
# strip off all others
$pbsserver =~ s/,.*$//;
# hack for sloppy admins who don't put the full hostname
# in $PBS_HOME/server_name
# ***WARNING*** you may have to comment out the following code if
# the servername doesn't resolve for whatever reason
if ( $pbsserver =~ /:/ )
  {
    ($host,$port) = split(/:/,$pbsserver);
    @server=gethostbyname($server);
    $pbsserver=$server[0].":".$port;
  }
else
  {
    @server=gethostbyname($pbsserver);
    $pbsserver=$server[0];
    $host=$server[0];
  }

$dbhost="localhost";
$dbuser="pbsacct";
$dbpasswd="pbsRroxor";
$dbname="pbsacct";
$dbtable="Jobs";

$doupdate = 0;

while ( $ARGV[0] =~ /^-.*/ )
  {
    if ( $ARGV[0] eq "-d" )
      {
	$dbname=$ARGV[1];
	shift(@ARGV);
      }
    elsif ( $ARGV[0] eq "-h" )
      {
	$system=$ARGV[1];
	shift(@ARGV);
      }
    elsif ( $ARGV[0] eq "-p" )
      {
	$dbpasswd=$ARGV[1];
	shift(@ARGV);
      }
    elsif ( $ARGV[0] eq "-s" )
      {
	$dbhost=$ARGV[1];
	shift(@ARGV);
      }
    elsif ( $ARGV[0] eq "-t" )
      {
	$dbtable=$ARGV[1];
	shift(@ARGV);
      }
    elsif ( $ARGV[0] eq "-u" )
      {
	$dbuser=$ARGV[1];
	shift(@ARGV);
      }
    elsif ( $ARGV[0] eq "-U" )
      {
        $doupdate = 1;
      }

    shift(@ARGV);
  }

# connect to DB
$dsn = "DBI:mysql:database=$dbname;host=$dbhost;";
$dbh = DBI->connect($dsn,$dbuser,$dbpasswd) ||
  die "$0:  unable to connect to DB!\n";
$insertquery="INSERT INTO $dbtable \(jobid,system,script\) VALUES \(?,?,?\);";
$insert=$dbh->prepare($insertquery) ||
  die "$0:  unable to prepare query -- ".$insert->errstr;
$updatequery="UPDATE $dbtable SET script=? WHERE system=? and jobid=?;";
$update=$dbh->prepare($updatequery) ||
  die "$0:  unable to prepare query -- ".$update->errstr;


foreach $scriptfile (@ARGV)
{
    if ( -e $scriptfile && -r $scriptfile )
    {
	# figure out the full jobid from the truncated version
        # in the script name
	$jobid=$scriptfile;
	$jobid =~ s/^.*\///;
	$jobid =~ s/\..*$//;
	# $jobid should be just digits at this point, otherwise ignore it
	if ( $jobid =~ /^[0-9]+$/ )
	{
	    $jobid .= ".".$pbsserver;

            # suck the script into memory
            open(SCRIPT,"<$scriptfile");
            $script_length=read(SCRIPT,$script,(64*1024));
            close(SCRIPT);
            # may need to massage script contents...?
	    
	    # Check if this jobid key already exists in the DB -- if not,
	    # insert the script
	    if ( &keyval_exists("jobid",$jobid,$dbtable,$dbh)==0 )
	    {
		# do the DB insert
		$insert->execute($jobid,$system,$script) || die "problem executing query -- ".$insert->errstr;;
	    }
            elsif ( $doupdate==1 )
            {
                # do the DB update
                # note that this is turned off by default
                $update->execute($script,$system,$jobid) || die "problem executing query -- ".$update->errstr;;
            }
	}
    }
}

# disconnect from DB
$dbh->disconnect();
