Index: trunk/ippTools/src/disttool.c
===================================================================
--- trunk/ippTools/src/disttool.c	(revision 23864)
+++ 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;
+}
