Index: trunk/pstamp/scripts/Makefile.am
===================================================================
--- trunk/pstamp/scripts/Makefile.am	(revision 25808)
+++ trunk/pstamp/scripts/Makefile.am	(revision 25957)
@@ -15,6 +15,8 @@
 	pstamp_revert_request.pl \
 	pstamp_runcommand.sh \
+	pstamp_server_status \
 	pstamp_webrequest.pl \
         pstamp_get_image_job.pl \
+	pstamp_check_dependents.pl \
 	request_finish.pl \
 	detect_query_read \
Index: trunk/pstamp/scripts/pstamp_check_dependents.pl
===================================================================
--- trunk/pstamp/scripts/pstamp_check_dependents.pl	(revision 25957)
+++ trunk/pstamp/scripts/pstamp_check_dependents.pl	(revision 25957)
@@ -0,0 +1,231 @@
+#!/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 Carp;
+
+use Time::Local;
+use Sys::Hostname;
+use IPC::Cmd 0.36 qw( can_run run );
+use File::Temp qw( tempfile );
+use File::Copy;
+use File::Basename qw(dirname);
+
+use PS::IPP::Metadata::Config;
+use PS::IPP::Metadata::Stats;
+use PS::IPP::Metadata::List qw( parse_md_list );
+
+use PS::IPP::Config qw( :standard );
+use PS::IPP::PStamp::RequestFile qw( :standard );
+use PS::IPP::PStamp::Job qw( :standard );
+
+my ( $dep_id, $dep_state, $stage, $stage_id, $imagedb, $rlabel, $no_magic, $dbname, $dbserver);
+my ( $no_update, $verbose, $save_temps, $logfile);
+
+GetOptions(
+           'dep_id=s'       => \$dep_id,
+           'state=s'        => \$dep_state,
+           'stage=s'        => \$stage,
+           'stage_id=s'     => \$stage_id,
+	   'imagedb=s'      => \$imagedb,
+	   'rlabel=s'       => \$rlabel,
+	   'no-magic=s'     => \$no_magic,
+	   'dbname=s'       => \$dbname,
+	   'dbserver=s'     => \$dbserver,
+	   'verbose'        => \$verbose,
+	   'no-update'      => \$no_update,
+	   'save-temps'     => \$save_temps,
+	   'logfile'        => \$logfile,
+) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+
+die "--dep_id --state --stage --stage_id --imagedb and --rlabel are requried \n"
+    if !$dep_id or !$dep_state or !$stage or !$stage_id or !$imagedb or !$rlabel;
+
+my $ipprc = PS::IPP::Config->new(); # IPP Configuration
+if ($logfile) {
+    $ipprc->redirect_output($logfile);
+}
+
+if (!$dbname) {
+    $dbname =  metadataLookupStr($ipprc->{_siteConfig}, 'PS_DBNAME');
+}
+if (!$dbserver) {
+    $dbserver =  metadataLookupStr($ipprc->{_siteConfig}, 'PS_DBSERVER');
+}
+
+# XXX: for testing
+$no_update = 1;
+
+my $missing_tools;
+
+my $pstamptool  = can_run('pstamptool')  or (warn "Can't find pstamptool"  and $missing_tools = 1);
+my $chiptool  = can_run('chiptool')  or (warn "Can't find chiptool"  and $missing_tools = 1);
+my $warptool  = can_run('warptool')  or (warn "Can't find warptool"  and $missing_tools = 1);
+my $difftool  = can_run('difftool')  or (warn "Can't find difftool"  and $missing_tools = 1);
+my $stacktool  = can_run('stacktool')  or (warn "Can't find stacktool"  and $missing_tools = 1);
+my $magicdstool  = can_run('magicdstool')  or (warn "Can't find magicdstool"  and $missing_tools = 1);
+if ($missing_tools) {
+    warn("Can't find required tools.");
+    exit ($PS_EXIT_CONFIG_ERROR);
+}
+
+$pstamptool .= " -dbname $dbname -dbserver $dbserver";
+
+my $mdcParser = PS::IPP::Metadata::Config->new; # Parser for metadata config files
+
+my $done = 0;
+if ($stage eq "chip") {
+    my $checkcmd = "$chiptool -runstatus -chip_id $stage_id -dbname $imagedb";
+
+    my $run_state = get_state($checkcmd);
+
+    my $state = $run_state->{state};
+    my $magic_ds_state = $run_state->{magic_ds_state};
+    if ($state eq "full") {
+        print STDERR "chipRun $stage_id is full\n" if $verbose;
+        if ($no_magic or ($run_state->{magicked} > 0)) {
+            # It's all done set the jobs free
+            $done = 1;
+        }
+    } elsif (($state eq "purged") or ($state eq "goto_purged") 
+          or ($magic_ds_state eq "censored") or ($magic_ds_state eq "goto_censored")) {
+
+        # Can't update the run. fault all pstampJobs depending on this
+        runcommand("$pstamptool -updatejob -set_state stop -dep_id $dep_id -fault $PSTAMP_GONE");
+
+    } else {
+
+        # XXX: TODO set label to the "standard" update value
+
+        # don't update if in runs are in state goto_cleaned, wait for clean to finish
+        if ($state eq "cleaned") {
+            runcommand("$chiptool -dbname $imagedb -chip_id $stage_id -updaterun -set_state update");
+        }
+
+        # don't update yet if magicDSRuns are in state goto_purged, wait for purge to finish
+        if ($magic_ds_state eq "purged") {
+            my $magic_ds_id = $run_state->{magic_ds_id};
+            runcommand("$magicdstool -dbname $imagedb -magic_ds_id $magic_ds_id -updaterun -set_state new");
+        }
+    }
+    
+} elsif ($stage eq "warp") {
+    # perhaps -runstatus is a better name for this mode
+    my $checkcmd = "$warptool -runstate -dbname $imagedb -warp_id $stage_id";
+
+    my $run_state = get_state($checkcmd);
+
+    my_die("unable to get run_state for $stage $stage_id", $dep_id, $PS_EXIT_CONFIG_ERROR) if !$run_state;
+
+    my $state = $run_state->{'state'};
+    my $chip_state = $run_state->{chip_state};
+    my $magic_ds_state = $run_state->{magic_ds_state};
+
+#    $state = 'purged';
+    if ($state eq 'full') {
+        print STDERR "warpRun $stage_id is full\n" if $verbose;
+        if ($no_magic or ($run_state->{magicked} > 0)) {
+            # It's all done set the jobs free
+            $done = 1;
+        }
+    } elsif (($state eq 'purged') or ($state eq 'goto_purged') 
+             or ($chip_state eq 'purged') or ($chip_state eq 'goto_purged')
+             or ($magic_ds_state eq 'censored') or ($magic_ds_state eq 'goto_censored')) {
+
+        # Can't update the run. fault all pstampJobs depending on this
+        runcommand("$pstamptool -updatejob -set_state stop -dep_id $dep_id -fault $PSTAMP_GONE");
+
+    } else {
+
+        # XXX: TODO set label to the "standard" update value
+
+        # don't update if in runs are in state goto_cleaned, wait for clean to finish
+        if ($state eq 'cleaned') {
+            runcommand("$warptool -dbname $imagedb -warp_id $stage_id -updaterun -set_state update");
+        }
+
+        if ($chip_state eq 'cleaned') {
+            my $chip_id = $run_state->{chip_id};
+            runcommand("$chiptool -dbname $imagedb -chip_id $chip_id -updaterun -set_state update");
+        }
+
+        # don't update yet if magicDSRuns are in state goto_purged, wait for purge to finish
+        if ($magic_ds_state eq 'purged') {
+            my $magic_ds_id = $run_state->{magic_ds_id};
+            runcommand("$magicdstool -dbname $imagedb -magic_ds_id $magic_ds_id -updaterun -set_state new");
+        }
+    }
+    
+} elsif ($stage eq "diff") {
+    my $checkcmd = "$difftool -runstate -diff_id $stage_id -dbname $imagedb";
+    my $run_state = get_state($checkcmd);
+    
+} elsif ($stage eq "stack") {
+    my $checkcmd = "$stacktool -runstate -stack_id $stage_id -dbname $imagedb";
+    my $run_state = get_state($checkcmd);
+} else {
+    my_die("Invalid stage value found: $stage", $dep_id, $PS_EXIT_CONFIG_ERROR);
+}
+
+if ($done) {
+    runcommand("$pstamptool -updatedependent -dep_id $dep_id -set_state full");
+}
+
+sub runcommand
+{
+    my $command = shift;
+    my $command_does_not_update = shift;
+    if ($command_does_not_update or !$no_update) {
+        my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+            run(command => $command, verbose => $verbose);
+        unless ($success) {
+            my_die("Unable to perform $command error code: $error_code", $dep_id, $PS_EXIT_UNKNOWN_ERROR);
+        }
+        return join "", @$stdout_buf if defined wantarray();
+    } else {
+        print STDERR "skipping $command\n";
+    }
+}
+
+sub get_state
+{
+    my $command = shift;
+    my $output = runcommand($command, 1);
+
+    if ($output) {
+        my $metadata = $mdcParser->parse($output) or die("Unable to parse metdata config doc");
+
+        my $files = parse_md_list($metadata);
+        if (scalar @$files eq 1) {
+            return $files->[0];
+        }
+    }
+    return undef;
+}
+
+
+sub my_die {
+    my $msg = shift;
+    my $req_id = shift;
+    my $fault = shift;
+
+    carp($msg);
+
+    exit $fault;
+
+    # XXX TODO: add a fault column
+    my $command = "$pstamptool -updatedependent -dep_id $dep_id  -set_state fault_$fault";
+    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");
+    }
+    exit $fault;
+}
Index: trunk/pstamp/scripts/pstamp_server_status
===================================================================
--- trunk/pstamp/scripts/pstamp_server_status	(revision 25957)
+++ trunk/pstamp/scripts/pstamp_server_status	(revision 25957)
@@ -0,0 +1,137 @@
+#!/bin/env perl
+
+use strict;
+use warnings;
+
+use File::Temp qw( tempfile );
+
+#use DBI;
+use IPC::Cmd 0.36 qw( can_run run );
+#use PS::IPP::Metadata::Config;
+use PS::IPP::Config 1.01 qw( :standard );
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+
+my ($rundir, $verbose, $save_temps);
+
+GetOptions(
+    'rundir=s'      => \$rundir,
+    'verbose'       => \$verbose,
+    'save-temps'    => \$save_temps,
+) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+#pod2usage( -msg => "Required options: --first --stage",
+#	   -exitval => 3) unless
+#    defined $first and
+#    defined $stage;
+
+# Look for programs we need
+my $missing_tools;
+my $pantasks_client   = can_run('pantasks_client') 
+    or (warn "Can't find pantasks_client" and $missing_tools = 1);
+if ($missing_tools) {
+    warn("Can't find required tools.");
+    exit($PS_EXIT_CONFIG_ERROR);
+}
+
+my $ipphome = "/home/panstarrs/ipp";
+$rundir = "$ipphome/pstamp" if !$rundir;
+
+chdir $rundir or die "failed to cd to $rundir";
+
+
+my ($pts, $pantasks_script) = tempfile ('/tmp/pts.XXXX', UNLINK => !$save_temps);
+
+print $pts "status\n";
+print $pts "quit\n";
+close $pts;
+
+my $command = "$pantasks_client < $pantasks_script";
+my  ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+    run(command => $command, verbose => $verbose);
+unless ($success) {
+    $error_code = (($error_code >> 8) or 1);
+    if ($error_code == 12) {
+        print "Postage Stamp Server is not running\n";
+        exit 0;
+    }
+    warn("$command failed. exit status: $error_code");
+    exit $error_code;
+}
+
+my $output = join "", @$stdout_buf;
+
+print "$output" if $verbose;
+
+my @lines = split "\n", $output;
+
+my ($scheduler_state, $controller_state);
+my $got_state = 0;
+my %tasks;
+foreach my $line (@lines) {
+    chomp $line;
+    next if !$line;
+    my ($first, $second, $third);
+
+    if ($line =~ /Scheduler is/) {
+        ($first, $second, $scheduler_state) = split " ", $line;
+        $got_state = 1;
+#        print "$first $second $third $scheduler_state\n";
+    } elsif ($line =~ /Controller is/) {
+        ($first, $second, $controller_state) = split " ", $line;
+#        print "$first $second $third $controller_state\n";
+    } elsif ($got_state == 1 and $line =~ /\+|\-/) {
+#        print "$line\n";
+        my ($task_state, $task, $njobs, $ngood, $nfail, $ntime, $cmd) = split " ", $line;
+#        print "$task $task_state\n";
+        my %this_task = ( name => $task, njobs => $njobs, ngood => $ngood, nfail => $nfail, ntime => $ntime, cmd => $cmd ); 
+
+        # change '.' in task name to '_' so we have a valid hash key
+        $task =~ s/\./\_/g;
+        $tasks{$task} =  \%this_task;
+    }
+}
+
+if ($scheduler_state) {
+    print "Pantasks Scheduler $scheduler_state.\n";
+    if ($controller_state) {
+        print "Pantasks Controller $controller_state.\n";
+    } else {
+        print STDERR "Controller state not found";
+        exit 1;
+    }
+    print "\n";
+} else {
+    print STDERR "Scheduler state not found";
+    exit 1;
+}
+
+my $request_run = $tasks{'pstamp_request_run'};
+my $request_fin = $tasks{'request_finish_run'};
+my $job_run = $tasks{'pstamp_job_run'};
+
+
+if ($request_run) {
+    print "$request_run->{ngood} of $request_run->{njobs} Requests parsed successfully.";
+    if ($request_fin) {
+        print "  $request_fin->{ngood} Requests finished.";
+    } else {
+        print "Task request.finish.run not found.\n";
+    }
+    print "\n";
+    print "\n";
+    if ($job_run) {
+        print "$job_run->{ngood} of $job_run->{njobs} Jobs run successfully.";
+        print "\n";
+    } else {
+        print "Task pstamp.job.run not found.\n";
+    }
+} else {
+    print "Task pstamp.request.run not found.\n";
+}
+
+
+exit 0;
