Index: /trunk/pstamp/scripts/pstamp_finish.pl
===================================================================
--- /trunk/pstamp/scripts/pstamp_finish.pl	(revision 18533)
+++ /trunk/pstamp/scripts/pstamp_finish.pl	(revision 18533)
@@ -0,0 +1,246 @@
+#!/bin/env perl
+
+# pstamp_finish.pl
+
+use warnings;
+use strict;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+use Sys::Hostname;
+use IPC::Cmd 0.36 qw( can_run run );
+use File::Temp qw( tempfile );
+use File::Copy;
+
+use PS::IPP::Metadata::Config;
+use PS::IPP::Metadata::Stats;
+use PS::IPP::Metadata::List qw( parse_md_list );
+
+use PS::IPP::Config qw($PS_EXIT_SUCCESS
+		       $PS_EXIT_UNKNOWN_ERROR
+		       $PS_EXIT_SYS_ERROR
+		       $PS_EXIT_CONFIG_ERROR
+		       $PS_EXIT_PROG_ERROR
+		       $PS_EXIT_DATA_ERROR
+		       $PS_EXIT_TIMEOUT_ERROR
+		       metadataLookupStr
+		       metadataLookupBool
+		       caturi
+		       );
+
+
+my ( $dbname, $limit, $verbose, $save_temps );
+
+# the char to the right of the bar may be used as a single - alias for the longer name
+# for example --input and -i are equivalent
+GetOptions(
+	   'limit=s'    => \$limit,
+	   'dbname=s'   => \$dbname,
+	   'verbose'  => \$verbose,
+	   'save-temps' => \$save_temps,
+) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+
+my $missing_tools;
+
+my $pstamptool  = can_run('pstamptool')  or (warn "Can't find pstamptool"  and $missing_tools = 1);
+my $dsreg  = can_run('dsreg')  or (warn "Can't find dsreg"  and $missing_tools = 1);
+my $pstamp_results = can_run('pstamp_results_file.pl') 
+                            or (warn "Can't find pstamp_results_file.pl" and $missing_tools = 1);
+if ($missing_tools) {
+    warn("Can't find required tools.");
+    exit ($PS_EXIT_CONFIG_ERROR);
+}
+
+my $ipprc = PS::IPP::Config->new(); # IPP Configuration
+
+my $outputDataStoreRoot = metadataLookupStr($ipprc->{_siteConfig}, 'DATA_STORE_ROOT');
+exit ($PS_EXIT_CONFIG_ERROR) unless defined $outputDataStoreRoot; # lookup failure outputs a message
+
+my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
+
+my @requests;
+{
+    my $command = "$pstamptool -completedreq";
+    $command   .= " -limit $limit" if $limit;
+    $command   .= " -dbname $dbname" if $dbname;
+    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+        run(command => $command, verbose => $verbose);
+    unless ($success) {
+        die("Unable to perform $command error code: $error_code");
+    }
+    my $output = join "", @$stdout_buf;
+    if (!$output) {
+        if ($verbose) {
+            print STDERR "no completed requests pending\n"
+        }
+        exit 0;
+    }
+    my $metadata = $mdcParser->parse($output) or die("Unable to parse metdata config doc");
+
+    my $requests = parse_md_list($metadata);
+
+    @requests = @$requests
+}
+
+foreach my $req (@requests) {
+    my $req_id = $req->{req_id};
+
+    my $product = $req->{outProduct};
+    die "outProduct in request is null" if !$product;
+
+    my $req_name = $req->{name};
+    die "request name is null" if !$req_name;
+
+
+    # set the output fileset's name to the request name.
+    my $fileset = $req_name;
+
+    # Here we invoke the assumption that the output for the request is placed in the
+    # fileset directory directly
+    my $out_dir = "$outputDataStoreRoot/$product/$fileset";
+
+    print STDERR "product: $product  REQ_NAME: $req_name $out_dir\n" if $verbose;
+
+    if (!-e $out_dir) {
+        # something must have gone wrong parsing the request
+        print STDERR  "output fileset directory $out_dir does not exist\n";
+
+        # XXX TODO: if this fails fault the request so we pstamp_finish 
+
+        mkdir $out_dir or die "cannot create output directory $out_dir";
+
+    } elsif (! -d $out_dir ) {
+        # XXX TODO: fault the request so we pstamp_finish doesn't keep trying to process the
+        # request
+        die "output fileset directory $out_dir exists but is not a directory";
+    }
+
+
+    # at this point we need to find out what kind of request type it is and
+    # split the processing depending on the request type
+    # the only processing required for a detectabilty query is to build the output fileset.
+
+    # the following is for a postage stamp request
+
+    my ($rlf, $reglist_name) = tempfile ("$out_dir/reglist.XXXX", UNLINK => !$save_temps);
+    print $rlf "results.fits|||table|\n";
+    my $err_file = "$out_dir/parse_error.txt";
+    if (-e $err_file ) {
+        print $rlf "$err_file|||text|\n";
+    }
+
+    my ($tdf, $table_def_name) = tempfile ("$out_dir/tabledef.XXXX", UNLINK => !$save_temps);
+
+
+    # data for the header
+    print $tdf "$req_name|$req_id|\n";
+    my @jobs;
+    {
+        my $command = "$pstamptool -listjob -req_id $req_id";
+        $command   .= " -dbname $dbname" if $dbname;
+        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            run(command => $command, verbose => $verbose);
+        unless ($success) {
+            die("Unable to perform $command error code: $error_code");
+        }
+        my $output = join "", @$stdout_buf;
+        if (!$output) {
+            if ($verbose) {
+                print STDERR "Request $req_id produced no jobs.\n"
+            }
+            # No Jobs. 
+            # XXXX Ouch. We need results for each rownum (each request specification) in the request file 
+            # including those that produced no jobs.
+            # for now add an entry for rownum 1 and a phony error code.
+            #
+            # possible fix: have pstampparse add a dummy job with state=stop and a fault code
+            # we've included parse_results.txt to the fileset if it exists
+            #
+            my $rownum = 1;
+            my $fault = 42; # get a real error code
+            print $tdf "$rownum|$fault|0|0|";
+            print $tdf "0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|\n";
+        } else {
+            my $metadata = $mdcParser->parse($output) or die("Unable to parse metdata config doc");
+
+            my $jobs = parse_md_list($metadata);
+
+            @jobs = @$jobs
+        }
+    }
+
+    foreach my $job (@jobs) {
+        my $job_id = $job->{job_id};
+        my $job_type = $job->{jobType};
+        my $rownum = $job->{rownum};
+        my $fault = $job->{fault};
+        # rownum fault img_name job_id
+        if (($job_type eq "stamp") || ($job_type eq "get_image")) {
+            my $jreglist = "$out_dir/reglist$job_id";
+            if (open JRL, "<$jreglist") {;
+                # process the reglist file to get the list of files produced by this job
+                foreach my $line (<JRL>) {
+                    # add line to the requests's reglist
+                    print $rlf $line;
+
+                    chomp $line;
+                    my ($img_name, undef) = split '\|', $line;
+
+                    # add line to the table definition file
+                    print $tdf "$rownum|$fault|$img_name|$job_id|";
+                    # XXX TODO: need to lookup the rest of this stuff
+                    print $tdf "0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|\n";
+                }
+                close JRL;
+            } else {
+                print STDERR "no reglist file for job $job_id\n" if $verbose;
+                print $tdf "$rownum|$fault|0|$job_id|";
+            }
+        } else {
+            die "Unknown jobType: $job_type";
+        }
+    }
+    close $rlf;
+    close $tdf;
+    my $request_fault = 0;
+    # make the results file
+    {
+        my $command = "$pstamp_results --input $table_def_name --output $out_dir/results.fits";
+        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            run(command => $command, verbose => $verbose);
+        unless ($success) {
+            print STDERR "Unable to perform $command error code: $error_code\n";
+            $request_fault = $error_code >> 8;
+        }
+    }
+    if (!$request_fault) {
+        # register the fileset
+        # Note that we are assuming that the fileset's files are already in the fileset directory.
+        # We could put them somewhere else and copy them in but for now we set the output directory
+        # to the fileset directory at parse time
+        my $command = "$dsreg --list $reglist_name --add $fileset --product $product --type PSRESULTS";
+        $command .= " --dbname $dbname" if $dbname;
+
+        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            run(command => $command, verbose => $verbose);
+        unless ($success) {
+            #die("Unable to perform $command error code: $error_code");
+            print STDERR "Unable to perform $command error code: $error_code\n";
+            $request_fault = $error_code >> 8;
+        }
+    }
+    # set the request's state to stop
+    {
+        
+        my $command = "$pstamptool -processedreq -req_id $req_id -state stop -fault $request_fault";
+        $command   .= " -dbname $dbname" if $dbname;
+        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            run(command => $command, verbose => $verbose);
+        unless ($success) {
+            die("Unable to perform $command error code: $error_code");
+        }
+    }
+}
