Index: trunk/PS-IPP-PStamp/lib/PS/IPP/PStamp/Job.pm
===================================================================
--- trunk/PS-IPP-PStamp/lib/PS/IPP/PStamp/Job.pm	(revision 27349)
+++ trunk/PS-IPP-PStamp/lib/PS/IPP/PStamp/Job.pm	(revision 27354)
@@ -16,4 +16,5 @@
                     locate_images
                     resolve_project
+                    getCamRunByCamID
                     );
 our %EXPORT_TAGS = (standard => [@EXPORT_OK]);
@@ -26,4 +27,10 @@
 use PS::IPP::Config qw( :standard );
 use Carp;
+
+# caches of camProcessedExp objects. 
+# Key is $exp_id
+my %camRunByExpIDCache;
+# Key is $cam_id
+my %camRunByCamIDCache;
 
 ### my @images = locate_images($image_db, $req_type, $img_type, $id, $component,
@@ -665,4 +672,8 @@
     my $runs;
     foreach my $camRun (@$camruns) {
+        my $cam_id = $camRun->{cam_id};
+
+        updateCamRunCache($camRun);
+
         next if $camRun->{quality};
         next if $camRun->{fault};
@@ -809,4 +820,6 @@
     my $verbose = shift;
 
+    my $mdcParser;
+
     my $exp_id = $image->{exp_id};
     if (($exp_id eq $last_exp_id) and $lastAstromFile) {
@@ -825,52 +838,63 @@
     }
 
-    my $command = "$camtool -dbname $image_db -processedexp -exp_id $exp_id";
-    # run the tool and parse the output
-    my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
-                run(command => $command, verbose => $verbose);
-    unless ($success) {
-        print STDERR @$stderr_buf;
-        return undef;
-    }
-
-    my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
-
-    my $output = join "", @$stdout_buf;
-    if (!$output) {
-        print STDERR "no output returned from $command\n" if $verbose;
-        return undef;
-    }
-    my $camruns = parse_md_fast($mdcParser, $output);
-    if (!$camruns) {
-        return undef;
-    }
-
-    # If there are multiple cam runs for this exposure, take the last completed one
-    # on the assumption that it has the best astrometry.
-    my $camdata;
-    while ($camdata = pop @$camruns) {
-        last if (($camdata->{quality} eq 0) and ($camdata->{fault} eq 0));
-    }
-    if (!$camdata) {
-        # no cam runs for this exposure id therefore best astrometry is whatever is in the header
-        return undef;
-    }
-    my $camRoot = $camdata->{path_base};
+    my $camRun = getCamRunByExpID($exp_id);
+    if (!$camRun) {
+        my $command = "$camtool -dbname $image_db -processedexp -exp_id $exp_id";
+        # run the tool and parse the output
+        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+                    run(command => $command, verbose => $verbose);
+        unless ($success) {
+            print STDERR @$stderr_buf;
+            return undef;
+        }
+
+        $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
+
+        my $output = join "", @$stdout_buf;
+        if (!$output) {
+            print STDERR "no output returned from $command\n" if $verbose;
+            return undef;
+        }
+        my $camruns = parse_md_fast($mdcParser, $output);
+        if (!$camruns) {
+            return undef;
+        }
+
+        # If there are multiple cam runs for this exposure, take the last completed one with good quality
+        # on the assumption that it has the best astrometry.
+        while ($camRun = pop @$camruns) {
+            last if (($camRun->{quality} eq 0) and ($camRun->{fault} eq 0));
+        }
+        # XXX: this looks like a bug at least if ASTROM.SOURCE eq PSASTRO.OUTPUT
+        if (!$camRun) {
+            # no cam runs for this exposure id therefore best astrometry is whatever is in the header
+            return undef;
+        }
+        updateCamRunCache($camRun);
+    }
+    my $camRoot = $camRun->{path_base};
     my $camera = $image->{camera};
     my $astromSource = $astromSources{$camera};
     if (!$astromSource) {
-       my $command = "$ppConfigDump -camera $camera -dump-recipe PSWARP -";
-        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
-            run(command => $command, verbose => $verbose);
-        unless ($success) {
-            $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
-            die("Unable to perform ppConfigDump: $error_code");
-        }
-        my $metadata = $mdcParser->parse(join "", @$stdout_buf) or
-            die("Unable to parse metadata config doc");
-        $astromSource = metadataLookupStr($metadata, 'ASTROM.SOURCE');
+        if ($camera eq "GPC1") {
+            # CHEATER !
+            $astromSource = "PSASTRO.OUTPUT";
+        } else {
+            my $command = "$ppConfigDump -camera $camera -dump-recipe PSWARP -";
+            my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+                run(command => $command, verbose => $verbose);
+            unless ($success) {
+                $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
+                die("Unable to perform ppConfigDump: $error_code");
+            }
+            $mdcParser = PS::IPP::Metadata::Config->new if !$mdcParser; # Parser for metadata config files
+            my $metadata = $mdcParser->parse(join "", @$stdout_buf) or
+                die("Unable to parse metadata config doc");
+            $astromSource = metadataLookupStr($metadata, 'ASTROM.SOURCE');
+        }
         $astromSources{$camera} = $astromSource;
     }
 
+    # XXX: Is this code correct if ASTROM.SOURCE ne "PSASTRO.OUTPUT"
     my $astromFile = $ipprc->filename($astromSource, $camRoot);
     if ($astromFile) {
@@ -984,3 +1008,39 @@
     return $last_project;
 }
+
+sub updateCamRunCache {
+    my $camRun = shift;
+    die "updateCamRunCache: camRun is nil" if !$camRun;
+
+    my $exp_id = $camRun->{exp_id};
+    die "updateCamRunCache: exp_id is nil" if !$exp_id;
+
+    my $cam_id = $camRun->{cam_id};
+    die "updateCamRunCache: cam_id is nil" if !$cam_id;
+
+    $camRunByCamIDCache{$cam_id} = $camRun;
+
+    # if this camRun is newer than previous update the cache.
+    # This assumes that the newest has the "best" astrometry
+    my $previous = $camRunByExpIDCache{$exp_id};
+    if ($previous) {
+        my $previous_cam_id = $previous->{cam_id};
+        return if $cam_id < $previous_cam_id;
+    }
+
+    $camRunByExpIDCache{$exp_id} = $camRun;
+}
+
+sub getCamRunByExpID {
+    my $exp_id = shift;
+    die "getCamRun: exp_id is nil" if !$exp_id;
+
+    return $camRunByExpIDCache{$exp_id};
+}
+sub getCamRunByCamID {
+    my $cam_id = shift;
+    die "getCamRun: cam_id is nil" if !$cam_id;
+
+    return $camRunByCamIDCache{$cam_id};
+}
 1;
