Index: trunk/dbconfig/changes.txt
===================================================================
--- trunk/dbconfig/changes.txt	(revision 23911)
+++ trunk/dbconfig/changes.txt	(revision 23912)
@@ -1080,2 +1080,5 @@
     FOREIGN KEY(file_id) REFERENCES receiveFile(file_id)
 ) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+ALTER TABLE rcRun ADD COLUMN fault SMALLINT DEFAULT 0;
+ALTER TABLE rcRun ADD COLUMN status_fs VARCHAR(64) AFTER state;
Index: trunk/dbconfig/rc.md
===================================================================
--- trunk/dbconfig/rc.md	(revision 23911)
+++ trunk/dbconfig/rc.md	(revision 23912)
@@ -37,5 +37,7 @@
     dest_id     S64         0       # Primary Key fkey(dest_id) ref rcDestination(dest_id)
     state       STR         64
+    status_fs_name   STR         64
     registered  UTC         0001-01-01T00:00:00Z
+    fault       S16        0
 END
 
Index: trunk/ippScripts/Build.PL
===================================================================
--- trunk/ippScripts/Build.PL	(revision 23911)
+++ trunk/ippScripts/Build.PL	(revision 23912)
@@ -86,4 +86,5 @@
         scripts/receive_fileset.pl
         scripts/receive_file.pl
+        scripts/rcserver_checkstatus.pl
     )],
     dist_abstract => 'Scripts for running the Pan-STARRS IPP',
Index: trunk/ippScripts/scripts/dist_make_fileset.pl
===================================================================
--- trunk/ippScripts/scripts/dist_make_fileset.pl	(revision 23911)
+++ trunk/ippScripts/scripts/dist_make_fileset.pl	(revision 23912)
@@ -153,5 +153,4 @@
 }
 
-# XXX: disttool -addrcdsfileset
 {
     my $command = "$disttool -addfileset -dist_id $dist_id -prod_id $prod_id -name $fileset_name";
@@ -161,4 +160,6 @@
         run(command => $command, verbose => $verbose);
     unless ($success) {
+        # XXX: if we get here we the fileset has been created but the database update failed
+        # We need to have revertfileset check whether the fileset exists and do dsreg -del if it does
         $error_code = (($error_code >> 8) or $PS_EXIT_PROG_ERROR);
         &my_die("Unable to perform $command error_code: $error_code", $dist_id, $prod_id, $error_code);
Index: trunk/ippScripts/scripts/rcserver_checkstatus.pl
===================================================================
--- trunk/ippScripts/scripts/rcserver_checkstatus.pl	(revision 23912)
+++ trunk/ippScripts/scripts/rcserver_checkstatus.pl	(revision 23912)
@@ -0,0 +1,119 @@
+#!/usr/bin/env perl
+
+use Carp;
+use warnings;
+use strict;
+
+## report the program and machine
+use Sys::Hostname;
+my $host = hostname();
+print "\n\n";
+print "Starting script $0 on $host\n\n";
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use IPC::Cmd 0.36 qw( can_run run );
+use File::Temp qw( tempfile );
+use File::Basename qw( basename );
+use Digest::MD5::File qw( file_md5_hex );
+use PS::IPP::Metadata::Config;
+use PS::IPP::Metadata::List qw( parse_md_list );
+
+use PS::IPP::Config 1.01 qw( :standard );
+
+my $ipprc = PS::IPP::Config->new(); # IPP configuration
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+
+# Look for programs we need
+my $missing_tools;
+my $disttool   = can_run('disttool') or (warn "Can't find disttool" and $missing_tools = 1);
+my $dsproductls = can_run('dsproductls') or (warn "Can't find dsproductls" and $missing_tools = 1);
+my $wget   = can_run('wget') or (warn "Can't find wget" and $missing_tools = 1);
+if ($missing_tools) {
+    warn("Can't find required tools.");
+    exit($PS_EXIT_CONFIG_ERROR);
+}
+
+# Parse the command-line arguments
+my ($dest_id, $prod_id, $status_uri, $last_fileset, $limit);
+my ($dbname, $save_temps, $verbose, $no_update, $logfile);
+
+GetOptions(
+           'dest_id=s'      => \$dest_id,    # destination identifier
+           'prod_id=s'      => \$prod_id,    # product identifier
+           'status_uri=s'   => \$status_uri, # uri for the desination's status data store product
+           'last_fileset=s' => \$last_fileset, # name of last fileset seen on this datastore
+           'limit=i'        => \$limit,      # limit on the number of filesets to process
+           'dbname=s'       => \$dbname,     # Database name
+           'save-temps'     => \$save_temps, # Save temporary files?
+           'verbose'        => \$verbose,    # Print stuff?
+           'no-update'      => \$no_update,  # Don't update the database
+           'logfile=s'      => \$logfile,
+           ) or pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required options: --dest_id --status_uri",
+           -exitval => 3) unless
+    defined $dest_id and
+    defined $status_uri;
+
+$ipprc->redirect_output($logfile) if $logfile;
+
+my $url = "$status_uri/index.txt";
+$url .= "?$last_fileset" if defined($last_fileset) and ($last_fileset ne "NULL");
+
+my @fileset_list;
+{
+    # XXX TODO: use dsproductls once it's been updated to output product type specific columns
+    my $command = "$wget --no-verbose -O - $url";
+    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);
+        &my_die("Unable to perform $command error_code: $error_code", $dest_id, $error_code);
+    }
+
+    @fileset_list = split "\n", join "", @$stdout_buf;
+
+    my $numlines = scalar @fileset_list;
+}
+
+my $numFilesets = 0;
+foreach my $line (@fileset_list) {
+    # skip comment lines
+    next if $line =~ /^#/;
+    $numFilesets++;
+    last if $limit and ($numFilesets > $limit);
+
+    my ($status_fs_name, $time, $type, $fs_name, $fault) = split /\|/, $line;
+
+    my $command = "$disttool -updatercrun -dest_id $dest_id -fs_name $fs_name -status_fs_name $status_fs_name -last_fileset $status_fs_name -fault $fault";
+    if ($fault == 0) {
+        $command .= " -set_state full";
+    }
+    $command .= " -dbname $dbname" if defined $dbname;
+    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);
+        &my_die("Unable to perform $command error_code: $error_code", $dest_id, $error_code);
+    }
+}
+
+
+
+sub my_die {
+    my $msg = shift;
+    my $dest_id = shift;
+    my $fault = shift;
+
+    die "$msg dest_id: $dest_id: $fault";
+
+    exit $fault;
+}
+
+__END__
Index: trunk/ippTasks/rcserver.pro
===================================================================
--- trunk/ippTasks/rcserver.pro	(revision 23911)
+++ trunk/ippTasks/rcserver.pro	(revision 23912)
@@ -9,14 +9,14 @@
 ### Initialise the books containing the tasks to do
 book init rcPendingFS
-book init rcPendingDS
+book init rcPendingDest
 
 ### Database lists
 $rcPendingFS_DB = 0
-$rcPendingDS_DB = 0
+$rcPendingDest_DB = 0
 
 ### Check status of tasks
 macro rcserver.status
   book listbook rcPendingFS
-  book listbook rcPendingDS
+  book listbook rcPendingDest
 end
 
@@ -24,5 +24,5 @@
 macro rcserver.reset
   book init rcPendingFS
-  book init rcPendingDS
+  book init rcPendingDest
 end
 
@@ -35,8 +35,8 @@
     active true
   end
-  task rcserver.checkruns.load
-    active true
-  end
-  task rcserver.checkruns.run
+  task rcserver.checkstatus.load
+    active true
+  end
+  task rcserver.checkstatus.run
     active true
   end
@@ -49,8 +49,8 @@
     active false
   end
-  task rcserver.checkruns.load
-    active false
-  end
-  task rcserver.checkruns.run
+  task rcserver.checkstatus.load
+    active false
+  end
+  task rcserver.checkstatus.run
     active false
   end
@@ -169,5 +169,5 @@
 
 
-task	       rcserver.checkruns.load
+task	       rcserver.checkstatus.load
   host         local
 
@@ -177,19 +177,17 @@
   npending     1
 
-  active false
-
   stdout NULL
-  stderr $LOGDIR/rcserver.checkruns.load.log
-
-  task.exec
-    $run = disttool -pendingdatastores
+  stderr $LOGDIR/rcserver.checkstatus.load.log
+
+  task.exec
+    $run = disttool -pendingdest
     if ($DB:n == 0)
       option DEFAULT
     else
       # save the DB name for the exit tasks
-      option $DB:$rcPendingDS_DB
-      $run = $run -dbname $DB:$rcPendingDS_DB
-      $rcPendingDS_DB ++
-      if ($rcPendingDS_DB >= $DB:n) set rcPendingDS_DB = 0
+      option $DB:$rcPendingDest_DB
+      $run = $run -dbname $DB:$rcPendingDest_DB
+      $rcPendingDest_DB ++
+      if ($rcPendingDest_DB >= $DB:n) set rcPendingDest_DB = 0
     end
     add_poll_args run
@@ -200,11 +198,11 @@
   task.exit    0
     # convert 'stdout' to book format
-    ipptool2book stdout rcPendingDS -key fs_id -uniq -setword dbname $options:0 -setword pantaskState INIT
+    ipptool2book stdout rcPendingDest -key dest_id -uniq -setword dbname $options:0 -setword pantaskState INIT
     if ($VERBOSE > 2)
-      book listbook rcPendingDS
+      book listbook rcPendingDest
     end
 
     # delete existing entries in the appropriate pantaskStates
-    process_cleanup rcPendingDS
+    process_cleanup rcPendingDest
   end
 
@@ -220,33 +218,33 @@
 end
 
-task	       rcserver.checkruns.run
+task	       rcserver.checkstatus.run
   periods      -poll $RUNPOLL
   periods      -exec $RUNEXEC
   periods      -timeout 60
 
-  active false
-
-  task.exec
-    book npages rcPendingDS -var N
+  periods      -exec 20
+
+  task.exec
+    book npages rcPendingDest -var N
     if ($N == 0) break
     if ($NETWORK == 0) break
     
     # look for new components to process (pantaskState == INIT)
-    book getpage rcPendingDS 0 -var pageName -key pantaskState INIT
+    book getpage rcPendingDest 0 -var pageName -key pantaskState INIT
     if ("$pageName" == "NULL") break
 
-    book setword rcPendingDS $pageName pantaskState RUN
-    book getword rcPendingDS $pageName dist_id -var DIST_ID
-    book getword rcPendingDS $pageName stage   -var STAGE
-    book getword rcPendingDS $pageName stage_id -var STAGE_ID
-    book getword rcPendingDS $pageName outdir -var OUTDIR
+    stdout NULL
+    stderr $LOGDIR/rcserver.checkstatus.run.log
+
+    book setword rcPendingDest $pageName pantaskState RUN
+    book getword rcPendingDest $pageName dest_id -var DEST_ID
+    book getword rcPendingDest $pageName prod_id -var PROD_ID
+    book getword rcPendingDest $pageName status_uri -var STATUS_URI
+    book getword rcPendingDest $pageName last_fileset -var LAST_FILESET
+    book getword rcPendingDest $pageName dbname -var DBNAME
 
     host anyhost
 
-    sprintf logfile "%s/dist.advance.%s.log" $OUTDIR $DIST_ID
-    stdout $logfile
-    stderr $logfile
-
-    $run = dist_advancerun.pl --dist_id $DIST_ID --stage $STAGE --stage_id $STAGE_ID --outdir $OUTDIR --logfile $logfile
+    $run = rcserver_checkstatus.pl --dest_id $DEST_ID --prod_id $PROD_ID --status_uri $STATUS_URI --last_fileset $LAST_FILESET
     add_standard_args run
 
@@ -263,5 +261,5 @@
   # default exit status
   task.exit    default
-    process_exit rcPendingDS $options:0 $JOB_STATUS
+    process_exit rcPendingDest $options:0 $JOB_STATUS
   end
 
@@ -269,6 +267,6 @@
   task.exit    timeout
     showcommand timeout
-    book setword rcPendingDS $options:0 pantaskState TIMEOUT
-  end
-end
-
+    book setword rcPendingDest $options:0 pantaskState TIMEOUT
+  end
+end
+
Index: trunk/ippTools/share/Makefile.am
===================================================================
--- trunk/ippTools/share/Makefile.am	(revision 23911)
+++ trunk/ippTools/share/Makefile.am	(revision 23912)
@@ -106,9 +106,13 @@
      disttool_pendingcomponent.sql \
      disttool_pendingfileset.sql \
+     disttool_pendingdest.sql \
      disttool_processedcomponent.sql \
+     disttool_queuercrun.sql \
+     disttool_revertrcrun.sql \
      disttool_revertrun_update.sql \
      disttool_revertrun_delete.sql \
      disttool_revertfileset.sql \
      disttool_toadvance.sql \
+     disttool_updatercrun.sql \
      faketool_change_exp_state.sql \
      faketool_change_imfile_data_state.sql \
Index: trunk/ippTools/share/difftool_pendingcleanupskyfile.sql
===================================================================
--- trunk/ippTools/share/difftool_pendingcleanupskyfile.sql	(revision 23911)
+++ trunk/ippTools/share/difftool_pendingcleanupskyfile.sql	(revision 23912)
@@ -10,2 +10,3 @@
 WHERE
     diffRun.state = 'goto_cleaned'
+    AND diffSkyfile.data_state = 'full'
Index: trunk/ippTools/share/disttool_pendingdest.sql
===================================================================
--- trunk/ippTools/share/disttool_pendingdest.sql	(revision 23912)
+++ trunk/ippTools/share/disttool_pendingdest.sql	(revision 23912)
@@ -0,0 +1,12 @@
+SELECT DISTINCT
+    rcDestination.*,
+    count(fs_id) as pending_fs
+FROM rcDestination
+JOIN rcRun using(dest_id)
+WHERE rcRun.state = 'new'
+    AND rcDestination.state = 'enabled'
+    AND status_uri IS NOT NULL
+    -- where hook %s
+GROUP BY dest_id
+HAVING count(fs_id) > 0
+
Index: trunk/ippTools/share/disttool_queuercrun.sql
===================================================================
--- trunk/ippTools/share/disttool_queuercrun.sql	(revision 23912)
+++ trunk/ippTools/share/disttool_queuercrun.sql	(revision 23912)
@@ -0,0 +1,21 @@
+-- create rcRun's for all destinations that have filesets that they are interested in available
+INSERT INTO rcRun
+SELECT                  -- rows in this select must match rcRun
+    0,                  -- rc_id (auto-increment)
+    fs_id,
+    dest_id,
+    'new',
+    NULL,                -- status_fs
+    NULL,                -- registered (database sets this to CURRENT_TIMESTAMP)
+    0                    -- fault
+
+FROM rcDestination 
+JOIN rcInterest USING(dest_id) 
+JOIN distTarget USING(target_id) 
+JOIN rcDSProduct USING(prod_id)
+JOIN distRun USING(target_id, stage) 
+JOIN rcDSFileset USING(prod_id, dist_id)
+LEFT JOIN rcRun using(fs_id, dest_id)
+WHERE rcRun.rc_id IS NULL
+    AND rcDSFileset.state = 'full'
+    AND rcDSFileset.fault = 0
Index: trunk/ippTools/share/disttool_revertrcrun.sql
===================================================================
--- trunk/ippTools/share/disttool_revertrcrun.sql	(revision 23912)
+++ trunk/ippTools/share/disttool_revertrcrun.sql	(revision 23912)
@@ -0,0 +1,3 @@
+UPDATE rcRun SET fault = 0
+WHERE fault != 0
+
Index: trunk/ippTools/share/disttool_updatercrun.sql
===================================================================
--- trunk/ippTools/share/disttool_updatercrun.sql	(revision 23912)
+++ trunk/ippTools/share/disttool_updatercrun.sql	(revision 23912)
@@ -0,0 +1,9 @@
+UPDATE rcRun
+JOIN rcDestination USING(dest_id)
+JOIN rcDSProduct USING(prod_id) 
+JOIN rcDSFileset using(prod_id, fs_id)
+SET
+    -- set hook %s
+WHERE
+    rcRun.state = 'new'
+
Index: trunk/ippTools/share/pxadmin_create_tables.sql
===================================================================
--- trunk/ippTools/share/pxadmin_create_tables.sql	(revision 23911)
+++ trunk/ippTools/share/pxadmin_create_tables.sql	(revision 23912)
@@ -1297,5 +1297,7 @@
     dest_id     BIGINT,
     state       VARCHAR(64),
+    status_fs_name   VARCHAR(64),
     registered  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    fault       SMALLINT DEFAULT 0,
     PRIMARY KEY(rc_id),
     FOREIGN KEY(fs_id) REFERENCES rcDSFileset(fs_id),
Index: trunk/ippTools/share/rcserver_updatercrun.sql
===================================================================
--- trunk/ippTools/share/rcserver_updatercrun.sql	(revision 23912)
+++ trunk/ippTools/share/rcserver_updatercrun.sql	(revision 23912)
@@ -0,0 +1,9 @@
+UPDATE rcRun
+JOIN rcDestination USING(dest_id)
+JOIN rcDSProduct USING(prod_id) 
+JOIN rcDSFileset using(prod_id, fs_id)
+SET
+rcRun.fault= 42, rcDestination.last_fileset = 'o4741g0236o.chip.14519.33.1'
+
+
+
Index: trunk/ippTools/src/disttool.c
===================================================================
--- trunk/ippTools/src/disttool.c	(revision 23911)
+++ trunk/ippTools/src/disttool.c	(revision 23912)
@@ -45,5 +45,5 @@
 static bool updatercrunMode(pxConfig *config);
 static bool revertrcrunMode(pxConfig *config);
-static bool pendingdatastoresMode(pxConfig *config);
+static bool pendingdestMode(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -80,5 +80,5 @@
         MODECASE(DISTTOOL_MODE_UPDATERCRUN, updatercrunMode);
         MODECASE(DISTTOOL_MODE_REVERTRCRUN, revertrcrunMode);
-        MODECASE(DISTTOOL_MODE_PENDINGDATASTORES, pendingdatastoresMode);
+        MODECASE(DISTTOOL_MODE_PENDINGDEST, pendingdestMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -952,12 +952,11 @@
 }
 
-static bool pendingdatastoresMode(pxConfig *config)
+static bool pendingdestMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
-#ifdef notyet
 
     psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-dist_id", "dist_id", "==");
-    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+    PXOPT_COPY_S64(config->args, where, "-dest_id", "dist_id", "==");
+//     PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
 
     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
@@ -965,5 +964,5 @@
 
     // look for "inputs" that need to processed
-    psString query = pxDataGet("disttool_pendingfileset.sql");
+    psString query = pxDataGet("disttool_pendingdest.sql");
     if (!query) {
         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
@@ -971,7 +970,9 @@
     }
 
+    psString whereString = NULL;
     if (psListLength(where->list)) {
         psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-        psStringAppend(&query, " AND %s", whereClause);
+        // where string gets added by hook, not at the end of the query
+        psStringAppend(&whereString, "\n AND %s", whereClause);
         psFree(whereClause);
     }
@@ -985,6 +986,7 @@
     }
 
-    if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
+    if (!p_psDBRunQueryF(config->dbh, query, whereString ? whereString : "")) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(whereString);
         psFree(query);
         return false;
@@ -1022,5 +1024,5 @@
 
     psFree(output);
-# endif // notdef
+
     return true;
 }
@@ -1029,14 +1031,184 @@
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
-    return true;
-}
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_S64(config->args, where, "-dist_id",  "dist_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-dest_id",  "dest_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-prod_id",  "prod_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-target_id","target_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-fs_id",    "fs_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-stage",    "stage", "==");;
+    PXOPT_COPY_S64(config->args, where, "-stage_id", "stage_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-label",    "label", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+    psString query = pxDataGet("disttool_queuercrun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    long numUpdated = psDBAffectedRows(config->dbh);
+
+    psLogMsg("disttool", PS_LOG_INFO, "Inserted %ld rcRuns", numUpdated);
+
+    return true;
+}
+
+
 static bool updatercrunMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
-    return true;
-}
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_LOOKUP_S64(rc_id, config->args, "-rc_id", false, false);
+    PXOPT_LOOKUP_STR(fs_name, config->args, "-fs_name", false, false);
+    PXOPT_LOOKUP_STR(status_fs_name, config->args, "-status_fs_name", false, false);
+    PXOPT_LOOKUP_S64(dest_id, config->args, "-dest_id", false, false);
+
+    // We either need rc_id or (dest_id and fs_name) to identifiy the rcRun
+    if ((!rc_id) && !(dest_id && fs_name)) {
+        psError(PXTOOLS_ERR_DATA, true, "either -rc_id or (-fs_name and -dest_id) are required");
+        return false;
+    }
+
+    // now that we have done the argument checking
+    PXOPT_COPY_S64(config->args, where, "-rc_id", "rc_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-fs_name", "rcDSFileset.name", "==");
+    PXOPT_COPY_S64(config->args, where, "-dest_id", "rcRun.dest_id", "==");
+
+    if (!psListLength(where->list)) {
+        // this can't happen because we checked above
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+
+    PXOPT_LOOKUP_STR(last_fileset, config->args, "-last_fileset", false, false);
+    PXOPT_LOOKUP_STR(state, config->args, "-set_state", false, false);
+    PXOPT_LOOKUP_S16(fault, config->args, "-fault", false, false);
+
+    if (!state && (fault < 0)) {
+        psError(PXTOOLS_ERR_DATA, false, "parameters (-fault or -set_state) are required");
+        psFree(where);
+        return false;
+    }
+
+    psString query = pxDataGet("disttool_updatercrun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    psString setString = psStringCopy("\n");
+    psString separator = "";
+    if (state) {
+        psStringAppend(&setString, " rcRun.state = '%s'", state);
+        separator = ",";
+    }
+
+    // default for fault is -1, so set it if it's zero or higher. This allows clearing fault
+    // without forcing revert first
+    if (fault >= 0) {
+        psStringAppend(&setString, "%s rcRun.fault = %d", separator, fault);
+    }
+
+    if (status_fs_name) {
+        psStringAppend(&setString, ", rcRun.status_fs_name = '%s'", status_fs_name);
+    }
+
+    if (last_fileset) {
+        psStringAppend(&setString, ", rcDestination.last_fileset = '%s'", last_fileset);
+    }
+
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " AND %s", whereClause);
+    psFree(whereClause);
+    psFree(where);
+
+    if (!p_psDBRunQueryF(config->dbh, query, setString)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(setString);
+        psFree(query);
+        return false;
+    }
+    psFree(setString);
+    psFree(query);
+
+    long numUpdated = psDBAffectedRows(config->dbh);
+
+    psLogMsg("disttool", PS_LOG_INFO, "Updated %ld rows", numUpdated);
+
+    return true;
+}
+
 static bool revertrcrunMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
-    return true;
-}
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-rc_id", "rc_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-fs_id", "fs_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-dest_id", "dest_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-fault", "fault", "==");
+
+    if (!psListLength(where->list) && !psMetadataLookupBool(NULL, config->args, "-all")) {
+        psFree(where);
+        psError(PXTOOLS_ERR_DATA, false, "search parameters are required");
+        return false;
+    }
+
+    psString query = pxDataGet("disttool_revertrcrun.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        return false;
+    }
+    psFree(query);
+
+    long numUpdated = psDBAffectedRows(config->dbh);
+
+    psLogMsg("disttool", PS_LOG_INFO, "Updated %ld rcRuns", numUpdated);
+
+    return true;
+}
Index: trunk/ippTools/src/disttool.h
===================================================================
--- trunk/ippTools/src/disttool.h	(revision 23911)
+++ trunk/ippTools/src/disttool.h	(revision 23912)
@@ -39,5 +39,5 @@
     DISTTOOL_MODE_UPDATERCRUN,
     DISTTOOL_MODE_REVERTRCRUN,
-    DISTTOOL_MODE_PENDINGDATASTORES,
+    DISTTOOL_MODE_PENDINGDEST,
 } disttoolMode;
 
Index: trunk/ippTools/src/disttoolConfig.c
===================================================================
--- trunk/ippTools/src/disttoolConfig.c	(revision 23911)
+++ trunk/ippTools/src/disttoolConfig.c	(revision 23912)
@@ -120,6 +120,6 @@
     psMetadata *toadvanceArgs = psMetadataAlloc();
     psMetadataAddS64(toadvanceArgs, PS_LIST_TAIL, "-dist_id", 0, "define dist_id", 0);
-    psMetadataAddStr(toadvanceArgs, PS_LIST_TAIL, "-label",     0, "limit updates to label", NULL);
-    psMetadataAddU64(toadvanceArgs, PS_LIST_TAIL, "-limit",  0,  "limit result set to N items", 0);
+    psMetadataAddStr(toadvanceArgs, PS_LIST_TAIL, "-label",   0, "limit updates to label", NULL);
+    psMetadataAddU64(toadvanceArgs, PS_LIST_TAIL, "-limit",   0,  "limit result set to N items", 0);
     psMetadataAddBool(toadvanceArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
 
@@ -127,7 +127,7 @@
     psMetadata *pendingfilesetArgs = psMetadataAlloc();
     psMetadataAddS64(pendingfilesetArgs, PS_LIST_TAIL, "-dist_id", 0, "define dist_id", 0);
-    psMetadataAddStr(pendingfilesetArgs, PS_LIST_TAIL, "-label",    0, "limit results to label", NULL);
-    psMetadataAddStr(pendingfilesetArgs, PS_LIST_TAIL, "-stage",    0, "limit results to runs for stage", NULL);
-    psMetadataAddU64(pendingfilesetArgs, PS_LIST_TAIL, "-limit",  0,  "limit result set to N items", 0);
+    psMetadataAddStr(pendingfilesetArgs, PS_LIST_TAIL, "-label",   0, "limit results to label", NULL);
+    psMetadataAddStr(pendingfilesetArgs, PS_LIST_TAIL, "-stage",   0, "limit results to runs for stage", NULL);
+    psMetadataAddU64(pendingfilesetArgs, PS_LIST_TAIL, "-limit",   0,  "limit result set to N items", 0);
     psMetadataAddBool(pendingfilesetArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
 
@@ -136,26 +136,56 @@
     psMetadataAddS64(addfilesetArgs, PS_LIST_TAIL, "-dist_id", 0, "define dist_id", 0);
     psMetadataAddS64(addfilesetArgs, PS_LIST_TAIL, "-prod_id", 0, "define prod_id", 0);
-    psMetadataAddStr(addfilesetArgs, PS_LIST_TAIL, "-name", 0, "define file name", NULL);
-    psMetadataAddS32(addfilesetArgs, PS_LIST_TAIL, "-fault", 0, "define fault code", 0);
-    //
-    // -pendingfileset
-    psMetadata *pendingdatastoresArgs = psMetadataAlloc();
-    psMetadataAddS64(pendingdatastoresArgs, PS_LIST_TAIL, "-dist_id", 0, "define dist_id", 0);
-    psMetadataAddStr(pendingdatastoresArgs, PS_LIST_TAIL, "-label",    0, "limit results to label", NULL);
-    psMetadataAddStr(pendingdatastoresArgs, PS_LIST_TAIL, "-stage",    0, "limit results to runs for stage", NULL);
-    psMetadataAddU64(pendingdatastoresArgs, PS_LIST_TAIL, "-limit",  0,  "limit result set to N items", 0);
-    psMetadataAddBool(pendingdatastoresArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+    psMetadataAddStr(addfilesetArgs, PS_LIST_TAIL, "-name",    0, "define file name", NULL);
+    psMetadataAddS32(addfilesetArgs, PS_LIST_TAIL, "-fault",   0, "define fault code", 0);
+
+    // -pendingdest
+    psMetadata *pendingdestArgs = psMetadataAlloc();
+    psMetadataAddS64(pendingdestArgs, PS_LIST_TAIL, "-dest_id", 0, "define dest_id", 0);
+    psMetadataAddU64(pendingdestArgs, PS_LIST_TAIL, "-limit",   0,  "limit result set to N items", 0);
+    psMetadataAddBool(pendingdestArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+    psMetadataAddStr(pendingdestArgs, PS_LIST_TAIL, "-label",   0, "limit results to label", NULL);
 
     // -revertfileset
     psMetadata *revertfilesetArgs = psMetadataAlloc();
-    psMetadataAddS64(revertfilesetArgs, PS_LIST_TAIL, "-fs_id", 0, "define fs_id", 0);
+    psMetadataAddS64(revertfilesetArgs, PS_LIST_TAIL, "-fs_id",   0, "define fs_id", 0);
     psMetadataAddS64(revertfilesetArgs, PS_LIST_TAIL, "-dist_id", 0, "define dist_id", 0);
     psMetadataAddS64(revertfilesetArgs, PS_LIST_TAIL, "-prod_id", 0, "define dist_id", 0);
-    psMetadataAddStr(revertfilesetArgs, PS_LIST_TAIL, "-stage",    0, "define stage", NULL);
-    psMetadataAddS64(revertfilesetArgs, PS_LIST_TAIL, "-stage_id", 0, "define stage_id", 0);
-    psMetadataAddStr(revertfilesetArgs, PS_LIST_TAIL, "-state",    0, "define state", NULL);
-    psMetadataAddStr(revertfilesetArgs, PS_LIST_TAIL, "-label",    0, "define label", NULL);
-    psMetadataAddS16(revertfilesetArgs, PS_LIST_TAIL, "-fault", 0, "define fault code", 0);
+    psMetadataAddStr(revertfilesetArgs, PS_LIST_TAIL, "-stage",   0, "define stage", NULL);
+    psMetadataAddS64(revertfilesetArgs, PS_LIST_TAIL, "-stage_id",0, "define stage_id", 0);
+    psMetadataAddStr(revertfilesetArgs, PS_LIST_TAIL, "-state",   0, "define state", NULL);
+    psMetadataAddStr(revertfilesetArgs, PS_LIST_TAIL, "-label",   0, "define label", NULL);
+    psMetadataAddS16(revertfilesetArgs, PS_LIST_TAIL, "-fault",   0, "define fault code", 0);
     psMetadataAddBool(revertfilesetArgs, PS_LIST_TAIL, "-all",    0, "revert all faulted runs", NULL);
+
+    // -queuercrun
+    psMetadata *queuercrunArgs = psMetadataAlloc();
+    psMetadataAddS64(queuercrunArgs, PS_LIST_TAIL, "-dist_id",   0, "define dist_id", 0);
+    psMetadataAddS64(queuercrunArgs, PS_LIST_TAIL, "-dest_id",   0, "define dest_id", 0);
+    psMetadataAddS64(queuercrunArgs, PS_LIST_TAIL, "-prod_id",   0, "define prod_id", 0);
+    psMetadataAddS64(queuercrunArgs, PS_LIST_TAIL, "-target_id", 0, "define target_id", 0);
+    psMetadataAddS64(queuercrunArgs, PS_LIST_TAIL, "-fs_id",     0, "define fs_id", 0);
+    psMetadataAddStr(queuercrunArgs, PS_LIST_TAIL, "-stage",     0, "define stage", NULL);
+    psMetadataAddS64(queuercrunArgs, PS_LIST_TAIL, "-stage_id",  0, "define stage_id", 0);
+    psMetadataAddStr(queuercrunArgs, PS_LIST_TAIL, "-state",     0, "define state", NULL);
+    psMetadataAddStr(queuercrunArgs, PS_LIST_TAIL, "-label",     0, "define label", NULL);
+    psMetadataAddU64(queuercrunArgs, PS_LIST_TAIL, "-limit",     0, "limit number of runs queued to N", 0);
+
+    // -updatercrun
+    psMetadata *updatercrunArgs = psMetadataAlloc();
+    psMetadataAddS64(updatercrunArgs, PS_LIST_TAIL, "-rc_id",    0, "define rc_id", 0);
+    psMetadataAddS64(updatercrunArgs, PS_LIST_TAIL, "-dest_id",  0, "define dest_id", 0);
+    psMetadataAddStr(updatercrunArgs, PS_LIST_TAIL, "-fs_name",  0, "define fileset name", NULL);
+    psMetadataAddStr(updatercrunArgs, PS_LIST_TAIL, "-status_fs_name",  0, "define status fileset name", NULL);
+    psMetadataAddStr(updatercrunArgs, PS_LIST_TAIL, "-set_state",0, "new value for state", NULL);
+    psMetadataAddStr(updatercrunArgs, PS_LIST_TAIL, "-last_fileset",0, "new value for last_fileset", NULL);
+    psMetadataAddS16(updatercrunArgs, PS_LIST_TAIL, "-fault",    0, "define fault code", -1);
+
+    // -revertrcrun
+    psMetadata *revertrcrunArgs = psMetadataAlloc();
+    psMetadataAddS64(revertrcrunArgs, PS_LIST_TAIL,  "-rc_id",   0, "define rc_id", 0);
+    psMetadataAddS64(revertrcrunArgs, PS_LIST_TAIL,  "-fs_id",   0, "define fs_id", 0);
+    psMetadataAddS64(revertrcrunArgs, PS_LIST_TAIL,  "-dest_id", 0, "define dest_id", 0);
+    psMetadataAddS16(revertrcrunArgs, PS_LIST_TAIL,  "-fault",   0, "define fault code", 0);
+    psMetadataAddBool(revertrcrunArgs, PS_LIST_TAIL, "-all",     0, "revert all faulted runs", NULL);
 
     psMetadata *argSets = psMetadataAlloc();
@@ -168,10 +198,13 @@
     PXOPT_ADD_MODE("-pendingcomponent",       "", DISTTOOL_MODE_PENDINGCOMPONENT,    pendingcomponentArgs);
     PXOPT_ADD_MODE("-addprocessedcomponent",      "", DISTTOOL_MODE_ADDPROCESSEDCOMPONENT, addprocessedcomponentArgs);
-    PXOPT_ADD_MODE("-processedcomponent",      "", DISTTOOL_MODE_PROCESSEDCOMPONENT, processedcomponentArgs);
-    PXOPT_ADD_MODE("-toadvance",      "", DISTTOOL_MODE_TOADVANCE, toadvanceArgs);
-    PXOPT_ADD_MODE("-pendingfileset",      "", DISTTOOL_MODE_PENDINGFILESET, pendingfilesetArgs);
-    PXOPT_ADD_MODE("-addfileset",      "", DISTTOOL_MODE_ADDFILESET, addfilesetArgs);
+    PXOPT_ADD_MODE("-processedcomponent", "", DISTTOOL_MODE_PROCESSEDCOMPONENT, processedcomponentArgs);
+    PXOPT_ADD_MODE("-toadvance",          "", DISTTOOL_MODE_TOADVANCE, toadvanceArgs);
+    PXOPT_ADD_MODE("-pendingfileset",     "", DISTTOOL_MODE_PENDINGFILESET, pendingfilesetArgs);
+    PXOPT_ADD_MODE("-addfileset",         "", DISTTOOL_MODE_ADDFILESET, addfilesetArgs);
     PXOPT_ADD_MODE("-revertfileset",      "", DISTTOOL_MODE_REVERTFILESET, revertfilesetArgs);
-    PXOPT_ADD_MODE("-pendingdatastores",      "", DISTTOOL_MODE_PENDINGDATASTORES, pendingdatastoresArgs);
+    PXOPT_ADD_MODE("-queuercrun",         "", DISTTOOL_MODE_QUEUERCRUN, queuercrunArgs);
+    PXOPT_ADD_MODE("-updatercrun",        "", DISTTOOL_MODE_UPDATERCRUN, updatercrunArgs);
+    PXOPT_ADD_MODE("-revertrcrun",        "", DISTTOOL_MODE_REVERTRCRUN, revertrcrunArgs);
+    PXOPT_ADD_MODE("-pendingdest",        "", DISTTOOL_MODE_PENDINGDEST, pendingdestArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
