#! /usr/bin/env perl
use Cwd;
use Getopt::Long;
use strict;
use warnings;

$ENV{PATH} = "/usr/local/bin:/usr/kerberos/bin:/usr/bin:/bin";

# Some defines for our returns
my $ALLSWELL = 0;
my $FAILEDCURLWRAPPER = 1;
my $FAILEDCURLRUNTIME = 2;
my $CHECKSUMFAILED = 3;
my $NORUNTIME = 4;
my $UNTARRUNTIME = 5;
my $UNTARJOBDATA = 6;
my $FAILEDRLIBUNTAR = 7;
my $FAILEDRUN = 8;
my $MISSINGOUTPUT = 9;
my $BADUSAGE = 10;
my $NOCHECKSUM = 11;
my $FAILEDCURLCHECKSUM = 12;

my $stampfilename = "CURLTIME_$$";

system("printenv");

#print "Starting to run <$cmdtorun> <$unique> <@ARGV>\n";
#print "Using <$type> <$tarball> <$installfrom>\n";

my $wrapper = "runR_MatlabTest.pl";
my $curlres = 0;

$curlres = FetchViaCurl($wrapper,"http://submit.chtc.wisc.edu/SQUID/","$stampfilename");

if($curlres != 0) {
    print "Fetch of runtime <$wrapper> failed via curl\n";
	exit($FAILEDCURLWRAPPER);
}

if($ARGV[0] eq "--help") {
	system("./$wrapper --help");
	exit(0);
}


system("chmod 755 $wrapper");
my $res = system("./$wrapper @ARGV");
print "Done Running $wrapper Result was <$res>\n";
ExplainFailure($res);

sub ExplainFailure
{
	my $result = shift;

	#system puts error code in upper 8 bits
	if($result & 0xff00) {
		$result >>= 8;
	} 

	if($result == $ALLSWELL) {
		print "All went well!\n";
		exit($result);
	} elsif($result == $FAILEDCURLWRAPPER) {
		print "Failed to curl fetch real wrapper\n";
	} elsif($result == $FAILEDCURLRUNTIME) {
		print "Failed to curl runtime\n";
	} elsif($result == $CHECKSUMFAILED) {
		print "Checksum for runtime failed\n";
	} elsif($result == $NORUNTIME) {
		print "There is no runtime!\n";
	} elsif($result == $UNTARRUNTIME) {
		print "Untar of runtime failed\n";
	} elsif($result == $UNTARJOBDATA) {
		print "Untar of job data failed\n";
	} elsif($result == $FAILEDRLIBUNTAR) {
		print "Failed to extract R packages\n";
	} elsif($result == $FAILEDRUN) {
		print "Run failed\n";
	} elsif($result == $MISSINGOUTPUT) {
		print "Failed to find expected output\n";
	} elsif($result == $BADUSAGE) {
		print "run rungeneric.pl --help for full usage help\n";
	} elsif($result = $NOCHECKSUM) {
		print "Could not find checksum file\n";
	} elsif($result = $FAILEDCURLCHECKSUM) {
		print "Could not CURL checksum file\n";
	} else {
		print "Unexpected result from job\n";
	}

	system("touch CODEBLOWUP");
	exit($result);
}

sub FetchViaCurl
{
	my $target = shift;
	my $url = shift;
	my $unique = shift;

	my $tries = 30;
	my $trycount = 0;
	my $sleeptime = 6;
	my $starttime = time();
	
	while($trycount < $tries) {
		$curlres = system("curl -H \"Pragma:\" -o $target $url$target");
		# trace data per attempt
		my $stoptime = time();
		my $elapsed = $stoptime - $starttime;
		my $fetchfile = "$url$target";
		my $result = $curlres >>=8;
		my $signal = $curlres & 255;
		write_audit_message("CURL",(url=>$fetchfile,time=>$elapsed,signal=>$signal,result=>$result));
		if($curlres != 0) {
			$trycount += 1;
			sleep($sleeptime);
		} else {
			last;
		}
	}
	print "Curl error <$curlres>\n";
	return($curlres);
}

#	I don't care strongly about the filename, but as a straw man:
#	"AuditLog.$unique"?

#	I propose the following for the records:

#	TIMESTAMP TYPE key=value key=value key=value

#	- TIMESTAMP can be anything easy to parse.
#	- TYPE is unique identified for that type of record
#	- keys and values are forbidden from having spaces in them (to
#	  simplify parsing).  We'll probably want some sort of simple
#	  escaping mechanism.  Perhaps s/\\/\\\\/g; s/_/\\_/g; s/ /_/g;
#	- Might want to sort keys within a given record.

#	so for example
#	2011-04-18 14:35 CURL duration=32 url=http://www.example.com/foo/bar result=1
#	2011-04-17 15:22 EXIT cmd=R return=0 signal=7


#	proposed API:

#	sub write_audit_message {
#	my($type, %keys) = @_;
#	# Write log here.
#	}


sub write_audit_message {
	open(STAMP,">>$stampfilename");
	my($type, %classad) = @_;
	print STAMP ( timestamp(), " $type ");
	foreach my $key (sort keys (%classad)) {
		my $filter = $classad{$key};
		$filter =~ s/>/GT/g;
		print STAMP "$key=<$filter> ";
	}
	print STAMP "\n";
	close(STAMP);
}

sub timestamp {
    return scalar localtime();
}

