Index: trunk/ippTools/src/disttool.c
===================================================================
--- trunk/ippTools/src/disttool.c	(revision 28937)
+++ trunk/ippTools/src/disttool.c	(revision 28938)
@@ -34,4 +34,5 @@
 static bool updaterunMode(pxConfig *config);
 static bool revertrunMode(pxConfig *config);
+static bool rerunMode(pxConfig *config);
 static bool pendingcomponentMode(pxConfig *config);
 static bool addprocessedcomponentMode(pxConfig *config);
@@ -83,4 +84,5 @@
         MODECASE(DISTTOOL_MODE_UPDATERUN, updaterunMode);
         MODECASE(DISTTOOL_MODE_REVERTRUN, revertrunMode);
+        MODECASE(DISTTOOL_MODE_RERUN, rerunMode);
         MODECASE(DISTTOOL_MODE_PENDINGCOMPONENT, pendingcomponentMode);
         MODECASE(DISTTOOL_MODE_ADDPROCESSEDCOMPONENT, addprocessedcomponentMode);
@@ -587,4 +589,132 @@
 }
 
+static bool rerunMode(pxConfig *config)
+{
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-dist_id", "distRun.dist_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_COPY_STR(config->args, where, "-data_group", "data_group", "==");
+
+    // require data_group or dist_id to be supplied
+    PXOPT_LOOKUP_STR(data_group, config->args, "-data_group", true, false);
+    PXOPT_LOOKUP_S64(dist_id, config->args, "-dist_id", false, false);
+    if (!data_group && !dist_id) {
+        psError(PXTOOLS_ERR_CONFIG, true, "data_group or dist_id is required");
+        return false;
+    }
+    PXOPT_LOOKUP_STR(set_label, config->args, "-set_label", false, false);
+
+    psString label_hook = psStringCopy("");
+    if (set_label) {
+        psStringAppend(&label_hook, ", label = '%s'", set_label);
+    }
+
+    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+
+    // It might be useful to be able to query by the parameters of the underlying runs
+
+    if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        return false;
+    }
+
+    psString query = pxDataGet("disttool_rerun_select.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, 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);
+    }
+    psFree(where);
+
+    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);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("disttool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+
+    if (pretend) {
+        if (!ippdbPrintMetadatas(stdout, output, "distRunsToUpdate", true)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+        psFree(output);
+        return true;
+    }
+
+    query = "DELETE FROM distComponent where dist_id = %" PRId64;
+    
+    for (long i=0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+        psS64 dist_id = psMetadataLookupS64(NULL, md, "dist_id");
+
+        if (!psDBTransaction(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+
+        if (!p_psDBRunQueryF(config->dbh, query, dist_id)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(query);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+
+        if (!p_psDBRunQueryF(config->dbh,
+        "UPDATE distRun SET state = 'new', fault=0 %s WHERE dist_id =%" PRId64,
+                label_hook, dist_id)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(query);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+        if (!psDBCommit(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        }
+        printf("re-running distRun %" PRId64 "\n", dist_id);
+    }
+
+    psFree(output);
+
+    return true;
+}
 static bool revertrunMode(pxConfig *config)
 {
Index: trunk/ippTools/src/disttool.h
===================================================================
--- trunk/ippTools/src/disttool.h	(revision 28937)
+++ trunk/ippTools/src/disttool.h	(revision 28938)
@@ -28,4 +28,5 @@
     DISTTOOL_MODE_UPDATERUN,
     DISTTOOL_MODE_REVERTRUN,
+    DISTTOOL_MODE_RERUN,
     DISTTOOL_MODE_PENDINGCOMPONENT,
     DISTTOOL_MODE_ADDPROCESSEDCOMPONENT,
Index: trunk/ippTools/src/disttoolConfig.c
===================================================================
--- trunk/ippTools/src/disttoolConfig.c	(revision 28937)
+++ trunk/ippTools/src/disttoolConfig.c	(revision 28938)
@@ -85,4 +85,16 @@
     psMetadataAddS16(updaterunArgs, PS_LIST_TAIL, "-fault",      0, "define fault code", 0);
 
+    // -rerun
+    psMetadata *rerunArgs = psMetadataAlloc();
+    psMetadataAddStr(rerunArgs, PS_LIST_TAIL, "-data_group",    0, "define data_group (required)", NULL);
+    psMetadataAddS64(rerunArgs, PS_LIST_TAIL, "-dist_id", 0, "search by dist_id", 0);
+    psMetadataAddStr(rerunArgs, PS_LIST_TAIL, "-stage",    0, "search by stage", NULL);
+    psMetadataAddS64(rerunArgs, PS_LIST_TAIL, "-stage_id", 0, "search by stage_id", 0);
+    psMetadataAddStr(rerunArgs, PS_LIST_TAIL, "-label",    0, "search by label", NULL);
+    psMetadataAddStr(rerunArgs, PS_LIST_TAIL, "-set_label",    0, "define new label", NULL);
+    psMetadataAddBool(rerunArgs, PS_LIST_TAIL, "-pretend", 0, "don't queue runs just display what would be selected", false);
+    psMetadataAddU64(rerunArgs, PS_LIST_TAIL, "-limit",  0,  "limit result set to N items", 0);
+    psMetadataAddBool(rerunArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
+
     // -revertrun
     psMetadata *revertrunArgs = psMetadataAlloc();
@@ -327,10 +339,11 @@
     psMetadata *modes = psMetadataAlloc();
 
-    PXOPT_ADD_MODE("-definebyquery",    "", DISTTOOL_MODE_DEFINEBYQUERY, definebyqueryArgs);
-    PXOPT_ADD_MODE("-updaterun",    "", DISTTOOL_MODE_UPDATERUN, updaterunArgs);
-    PXOPT_ADD_MODE("-revertrun",    "", DISTTOOL_MODE_REVERTRUN, revertrunArgs);
+    PXOPT_ADD_MODE("-definebyquery",    "define distribution run", DISTTOOL_MODE_DEFINEBYQUERY, definebyqueryArgs);
+    PXOPT_ADD_MODE("-updaterun",    "update distRun", DISTTOOL_MODE_UPDATERUN, updaterunArgs);
+    PXOPT_ADD_MODE("-rerun",        "reprocess a cleaned distribution run", DISTTOOL_MODE_RERUN, rerunArgs);
+    PXOPT_ADD_MODE("-revertrun",    "revert distRun.faults", DISTTOOL_MODE_REVERTRUN, revertrunArgs);
     PXOPT_ADD_MODE("-pendingcomponent",   "", DISTTOOL_MODE_PENDINGCOMPONENT,    pendingcomponentArgs);
     PXOPT_ADD_MODE("-addprocessedcomponent", "", DISTTOOL_MODE_ADDPROCESSEDCOMPONENT, addprocessedcomponentArgs);
-    PXOPT_ADD_MODE("-revertcomponent",    "", DISTTOOL_MODE_REVERTCOMPONENT, revertcomponentArgs);
+    PXOPT_ADD_MODE("-revertcomponent",    "revert faulted components", DISTTOOL_MODE_REVERTCOMPONENT, revertcomponentArgs);
     PXOPT_ADD_MODE("-processedcomponent", "", DISTTOOL_MODE_PROCESSEDCOMPONENT, processedcomponentArgs);
     PXOPT_ADD_MODE("-toadvance",          "", DISTTOOL_MODE_TOADVANCE, toadvanceArgs);
@@ -340,5 +353,5 @@
     PXOPT_ADD_MODE("-updatefileset",         "", DISTTOOL_MODE_UPDATEFILESET, updatefilesetArgs);
     PXOPT_ADD_MODE("-listfilesets",        "", DISTTOOL_MODE_LISTFILESETS, listfilesetsArgs);
-    PXOPT_ADD_MODE("-revertfileset",      "", DISTTOOL_MODE_REVERTFILESET, revertfilesetArgs);
+    PXOPT_ADD_MODE("-revertfileset",      "revert faulted filesets", DISTTOOL_MODE_REVERTFILESET, revertfilesetArgs);
     PXOPT_ADD_MODE("-queuercrun",         "", DISTTOOL_MODE_QUEUERCRUN, queuercrunArgs);
     PXOPT_ADD_MODE("-updatercrun",        "", DISTTOOL_MODE_UPDATERCRUN, updatercrunArgs);
