Index: branches/czw_branch/20100519/ippTools/src/addtool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/addtool.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/addtool.c	(revision 28304)
@@ -40,4 +40,15 @@
 static bool maskedMode(pxConfig *config);
 static bool unblockMode(pxConfig *config);
+static bool addminidvodbrunMode(pxConfig *config);
+static bool updateminidvodbrunMode(pxConfig *config);
+static bool listminidvodbrunMode(pxConfig *config);
+static bool flipminidvodbrunMode(pxConfig *config);
+static bool checkminidvodbrunaddrunMode(pxConfig *config);
+static bool addminidvodbprocessedMode(pxConfig *config);
+static bool listminidvodbprocessedMode(pxConfig *config);
+static bool revertminidvodbprocessedMode(pxConfig *config);
+static bool updateminidvodbprocessedMode(pxConfig *config);
+
+
 
 # define MODECASE(caseName, func) \
@@ -69,4 +80,14 @@
         MODECASE(ADDTOOL_MODE_MASKED,               maskedMode);
         MODECASE(ADDTOOL_MODE_UNBLOCK,              unblockMode);
+        MODECASE(ADDTOOL_MODE_ADDMINIDVODBRUN,      addminidvodbrunMode);
+        MODECASE(ADDTOOL_MODE_UPDATEMINIDVODBRUN,   updateminidvodbrunMode);
+        MODECASE(ADDTOOL_MODE_LISTMINIDVODBRUN,     listminidvodbrunMode);
+        MODECASE(ADDTOOL_MODE_FLIPMINIDVODBRUN,     flipminidvodbrunMode);
+        MODECASE(ADDTOOL_MODE_CHECKMINIDVODBRUNADDRUN, checkminidvodbrunaddrunMode);
+        MODECASE(ADDTOOL_MODE_ADDMINIDVODBPROCESSED,addminidvodbprocessedMode);
+        MODECASE(ADDTOOL_MODE_LISTMINIDVODBPROCESSED,listminidvodbprocessedMode);
+        MODECASE(ADDTOOL_MODE_REVERTMINIDVODBPROCESSED,revertminidvodbprocessedMode);
+        MODECASE(ADDTOOL_MODE_UPDATEMINIDVODBPROCESSED,updateminidvodbprocessedMode);
+
         default:
             psAbort("invalid option (this should not happen)");
@@ -102,4 +123,5 @@
     PXOPT_COPY_STR(config->args, where,  "-reduction", "camRun.reduction", "==");
 
+
     if (!psListLength(where->list)) {
         psFree(where);
@@ -114,8 +136,13 @@
     PXOPT_LOOKUP_STR(reduction,   config->args, "-set_reduction", false, false);
     PXOPT_LOOKUP_STR(note,        config->args, "-set_note", false, false);
+    PXOPT_LOOKUP_STR(minidvodb_name,  config->args, "-set_minidvodb_name", false, false);
+    PXOPT_LOOKUP_STR(minidvodb_group, config->args, "-set_minidvodb_group", false, false);
     PXOPT_LOOKUP_BOOL(image_only, config->args, "-image_only", false);
+    PXOPT_LOOKUP_BOOL(minidvodb,  config->args, "-set_minidvodb", false);
     PXOPT_LOOKUP_BOOL(destreaked, config->args, "-destreaked", false);
     PXOPT_LOOKUP_BOOL(pretend,    config->args, "-pretend", false);
     PXOPT_LOOKUP_BOOL(simple,     config->args, "-simple", false);
+
+
 
     // find the cam_id of all the exposures that we want to queue up.
@@ -245,8 +272,11 @@
                                dvodb       ? dvodb     : row->dvodb,
                                note        ? note      : NULL,
-                               image_only
+                               image_only,
+                               minidvodb,
+                               minidvodb_group,
+                               minidvodb_name
         )) {
             if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
+                psError(PS_ERR_UNKNOWN, false, "database error sfg");
             }
             psError(PS_ERR_UNKNOWN, false,
@@ -291,5 +321,5 @@
 
     // pxUpdateRun gets parameters from config->args and runs the update query
-    bool result = pxUpdateRun(config, where, &query, "addRun", "add_id", 
+    bool result = pxUpdateRun(config, where, &query, "addRun", "add_id",
         "addProcessedExp", false);
 
@@ -374,4 +404,6 @@
     PXOPT_LOOKUP_STR(path_base,     config->args, "-path_base", false, false);
     PXOPT_LOOKUP_F32(dtime_addstar, config->args, "-dtime_addstar", false, false);
+    PXOPT_LOOKUP_STR(dvodb_path, config->args, "-dvodb_path", false, false);
+    PXOPT_LOOKUP_STR(minidvodb_name, config->args, "-minidvodb_name", false, false);
     PXOPT_LOOKUP_S16(fault,         config->args, "-fault", false, false);
 
@@ -399,4 +431,5 @@
         return false;
     }
+
     psFree(query);
 
@@ -424,4 +457,5 @@
         dtime_addstar,
         path_base,
+        dvodb_path,
         fault
         );
@@ -437,4 +471,22 @@
         return false;
     }
+
+    //if there is a minidvodb_name, set it in addRun (it's not known until it is processed)
+    if (minidvodb_name) {
+      psString setName = NULL;
+      psStringAppend (&setName, "UPDATE addRun set minidvodb_name = '%s' where add_id = %" PRId64, minidvodb_name, row->add_id);
+      if (!p_psDBRunQuery(config->dbh, setName)) {
+        if (!psDBRollback(config->dbh)) {
+          psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+
+        return false;
+      }
+    }
+
+
+
+
 
     // since there is only one exp per 'new' set addRun.state = 'full'
@@ -522,5 +574,5 @@
 
     if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
+      psError(PS_ERR_UNKNOWN, false, "database error");
         psFree(query);
         return false;
@@ -576,6 +628,10 @@
 
     {
-        psString query = pxDataGet("addtool_reset_faulted_runs.sql");
+        psString query = pxDataGet("addtool_revertprocessedexp.sql");
         if (!query) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
             psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
             psFree(where);
@@ -602,36 +658,4 @@
         psFree(query);
     }
-
-    {
-        psString query = pxDataGet("addtool_revertprocessedexp.sql");
-        if (!query) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
-            psFree(where);
-            return false;
-        }
-
-        // use psDBGenerateWhereConditionalSQL with AND ... because the SQL ends in a WHERE
-        if (where && psListLength(where->list)) {
-            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-            psStringAppend(&query, " AND %s", whereClause);
-            psFree(whereClause);
-        }
-
-        if (!p_psDBRunQuery(config->dbh, query)) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(query);
-            psFree(where);
-            return false;
-        }
-        psFree(query);
-    }
     psFree(where);
 
@@ -733,2 +757,813 @@
     return true;
 }
+
+static bool addminidvodbrunMode(pxConfig *config)
+{
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  // required
+
+  PXOPT_LOOKUP_STR(minidvodb_group, config->args, "-set_minidvodb_group", true, false);
+  PXOPT_LOOKUP_STR(mergedvodb_path, config->args, "-set_mergedvodb_path", true, false);
+
+  //optional
+  PXOPT_LOOKUP_STR(minidvodb_name, config->args, "-set_minidvodb_name", false, false);
+  PXOPT_LOOKUP_STR(minidvodb_path, config->args, "-set_minidvodb_path", false, false);
+  PXOPT_LOOKUP_STR(state, config->args, "-set_state", false, false);
+
+  if (!psDBTransaction(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  psString minidvodbpath = "NULL";
+
+  // I don't know how to get around the complaints of minidvodb_path can't be null. this 'fixes' it, but someone smarter can fix it properly.
+  if (minidvodb_path) {
+    minidvodbpath = minidvodb_path;
+  }
+
+  if (!minidvodbRunInsert(config->dbh,
+            0, // job_id
+            minidvodb_name,
+            minidvodb_group,
+            minidvodbpath,
+            mergedvodb_path,
+            "new",
+            0
+            )) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  psU64 affected = psDBAffectedRows(config->dbh);
+  if (affected != 1) {
+    psError(PS_ERR_UNKNOWN, false,
+            "should have affected one row but %" PRIu64 " rows were modified",
+            affected);
+    return false;
+  }
+
+  psS64 minidvodb_id = psDBLastInsertID(config->dbh);
+  printf("%" PRId64 "\n", minidvodb_id);
+
+
+  if (!minidvodb_name) {
+    psStringAppend(&minidvodb_name, "%s.%" PRIu64,minidvodb_group,minidvodb_id);
+  }
+
+  if (!minidvodb_path) {
+    psStringAppend(&minidvodb_path,"%s/%s",mergedvodb_path,minidvodb_name);
+  }
+
+  psString query = NULL;
+
+  psStringAppend(&query, "UPDATE minidvodbRun SET minidvodb_path = '%s', minidvodb_name = '%s' where minidvodb_id = %" PRIu64";", minidvodb_path, minidvodb_name, minidvodb_id);
+
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query);
+    return false;
+  }
+
+  if (!psDBCommit(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  return true;
+}
+
+static bool updateminidvodbrunMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-minidvodb_id",     "minidvodb_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-minidvodb_name",     "minidvodb_name", "==");
+    PXOPT_COPY_STR(config->args, where, "-state",     "state", "==");
+    PXOPT_COPY_STR(config->args, where, "-minidvodb_path", "minidvodb_path", "==");
+    PXOPT_COPY_STR(config->args, where, "-mergedvodb_path", "mergedvodb_path", "==");
+    PXOPT_COPY_STR(config->args, where, "-minidvodb_group",     "minidvodb_group", "==");
+
+    PXOPT_LOOKUP_STR(minidvodb_name,  config->args, "-set_minidvodb_name", false, false);
+    PXOPT_LOOKUP_STR(minidvodb_path,  config->args, "-set_minidvodb_path", false, false);
+    PXOPT_LOOKUP_STR(state,  config->args, "-set_state", false, false);
+    PXOPT_LOOKUP_STR(mergedvodb_path,  config->args, "-set_mergedvodb_path", false, false);
+    PXOPT_LOOKUP_STR(minidvodb_group,  config->args, "-set_minidvodb_group", false, false);
+
+
+    if (!psListLength(where->list)) {
+      psFree(where);
+      psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+      return false;
+    }
+
+    psString query = psStringCopy("UPDATE minidvodbRun SET ");
+    int cnt = 0;
+    psString comma = ",";
+    if (minidvodb_name) {
+      psStringAppend(&query, " minidvodb_name = '%s'", minidvodb_name);
+      cnt++;
+    }
+
+    if (minidvodb_path) {
+      if (cnt) {
+          psStringAppend(&query, "%s", comma);
+      }
+
+      psStringAppend(&query, " minidvodb_path = '%s'", minidvodb_path);
+      cnt++;
+    }
+
+    if (state) {
+      if (cnt) {
+        psStringAppend(&query, "%s", comma);
+      }
+      psStringAppend(&query, " state = '%s'", state);
+      cnt++;
+    }
+
+    if (mergedvodb_path) {
+      if (cnt) {
+        psStringAppend(&query, "%s", comma);
+      }
+      psStringAppend(&query, " mergedvodb_path = '%s'", mergedvodb_path);
+      cnt++;
+    }
+
+    if (minidvodb_group) {
+      if (cnt) {
+        psStringAppend(&query, "%s", comma);
+      }
+      psStringAppend(&query, " minidvodb_group = '%s'", minidvodb_group);
+      cnt++;
+    }
+
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " WHERE %s", whereClause);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      return false;
+    }
+
+    psFree(query);
+    psFree(where);
+
+    return true;
+
+}
+
+static bool flipminidvodbrunMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_LOOKUP_STR(minidvodb_group,  config->args, "-minidvodb_group",true, false);
+  PXOPT_COPY_STR(config->args, where, "-minidvodb_group",     "minidvodb_group", "==");
+
+//this flips the new - > active
+// and the active - > waiting in one action
+
+
+// the first query looks to find things that are new and where all the fields are filled (ie, ready to be flipped to active)
+
+// start a transaction eraly so it will contain any row level locks
+  if (!psDBTransaction(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  psString firstquery = psStringCopy("SELECT * from  minidvodbRun where state = 'new' and minidvodb_name is NOT NULL and minidvodb_group IS NOT NULL and minidvodb_path IS NOT NULL and mergedvodb_path IS NOT NULL");
+
+  psString firstwhereClause = psDBGenerateWhereConditionSQL(where, NULL);
+  psStringAppend(&firstquery, " AND %s", firstwhereClause);
+
+
+
+  if (!p_psDBRunQuery(config->dbh, firstquery)) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    return false;
+  }
+  psFree(firstquery);
+
+ //we don't care what the stuff is that is found, just that there is stuff. This is a check to see that there is something in the 'new' state, before flipping (so that if there is nothing in new, it won't flip the active to waiting.  the flipminidvo is just to make it easy to flip from new -> active.
+
+  psArray *output = p_psDBFetchResult(config->dbh);
+  if (!output) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+  if (!psArrayLength(output)) {
+    psTrace("addtool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+
+  //ok, there's something, so flip active -> waiting
+
+  psString query = psStringCopy("UPDATE minidvodbRun SET state = 'waiting' WHERE state = 'active' ");
+
+  psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+  psStringAppend(&query, " AND %s", whereClause);
+
+
+  if (!p_psDBRunQuery(config->dbh, query)) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    return false;
+  }
+
+
+  //now flip new -> active
+  psString query2 = psStringCopy("UPDATE minidvodbRun SET state = 'active' WHERE state = 'new' AND minidvodb_name is NOT NULL and minidvodb_group IS NOT NULL and minidvodb_path IS NOT NULL and mergedvodb_path IS NOT NULL ");
+  psStringAppend(&query2, " AND minidvodb_group = '%s' limit 1;", minidvodb_group);
+  if (!p_psDBRunQuery(config->dbh, query2)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psFree(query);
+    return false;
+  }
+
+
+  if (!psDBCommit(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psFree(query);
+  return false;
+  }
+ psFree(query2);
+ psFree(where);
+
+ return true;
+
+}
+
+
+static bool checkminidvodbrunaddrunMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, false);
+  psMetadata *where = psMetadataAlloc();
+
+  //this checks to see if a minidvod_group/name is has completed addRun processing
+  PXOPT_COPY_STR(config->args, where, "-minidvodb_group", "minidvodbRun.minidvodb_group", "==");
+  PXOPT_COPY_STR(config->args, where, "-minidvodb_name", "minidvodbRun.minidvodb_name", "==");
+  PXOPT_COPY_STR(config->args, where, "-state", "minidvodbRun.state", "==");
+
+
+  PXOPT_LOOKUP_U64(limit,      config->args, "-limit", false, false);
+  PXOPT_LOOKUP_BOOL(all_addrun_states, config->args, "-all_addrun_states", false);
+  //this doesn't care what state the addRun is in (useful for counting addRuns)
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+  if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        return false;
+  }
+
+  psString query = pxDataGet("addtool_checkminidvodbaddrun.sql");
+
+  if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+  }
+
+
+  if (psListLength(where->list)) {
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " WHERE %s", whereClause);
+        psFree(whereClause);
+  }
+
+  if (!all_addrun_states) {
+    psStringAppend(&query, " AND (cnt2 = cnt) ");
+  }
+
+  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("addtool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  if (!ippdbPrintMetadatas(stdout, output, "minidvodbRun", !simple)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to print array");
+    psFree(output);
+    return false;
+  }
+
+  psFree(output);
+
+  return true;
+}
+
+
+
+static bool listminidvodbrunMode(pxConfig *config) {
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_STR(config->args, where, "-minidvodb_name", "minidvodbRun.minidvodb_name", "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-minidvodb_group", "minidvodbRun.minidvodb_group", "==");
+    PXOPT_COPY_S64(config->args, where, "-minidvodb_id", "minidvodbRun.minidvodb_id", "==");
+
+    PXOPT_COPY_STR(config->args, where, "-state", "minidvodbRun.state", "==");
+    PXOPT_LOOKUP_U64(limit,      config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+
+    if (!psListLength(where->list)) {
+      psFree(where);
+      psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+      return false;
+    }
+
+    psString query = pxDataGet("addtool_find_minidvodbrun.sql");
+
+    if (!query) {
+      psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+      return false;
+    }
+
+    if (psListLength(where->list)) {
+      psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+      psStringAppend(&query, " WHERE %s", whereClause);
+      psFree(whereClause);
+    }
+
+    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("addtool", PS_LOG_INFO, "no rows found");
+      psFree(output);
+      return true;
+    }
+
+    if (!ippdbPrintMetadatas(stdout, output, "minidvodbRun",  !simple)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+
+    psFree(output);
+
+return true;
+}
+
+static bool addminidvodbprocessedMode(pxConfig *config) {
+
+  PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+  PXOPT_LOOKUP_U64(minidvodb_id, config->args, "-minidvodb_id", true, false);
+  PXOPT_LOOKUP_STR(mergedvodb_path, config->args, "-mergedvodb_path", true, false);
+  PXOPT_LOOKUP_STR(minidvodb_group, config->args, "-minidvodb_group", true, false);
+
+    // optional
+  PXOPT_LOOKUP_U64(merge_order,     config->args, "-merge_order", false, false);
+  PXOPT_LOOKUP_F32(dtime_relphot, config->args, "-dtime_relphot", false, false);
+  PXOPT_LOOKUP_F32(dtime_resort, config->args, "-dtime_resort", false, false);
+  PXOPT_LOOKUP_F32(dtime_merge, config->args, "-dtime_merge", false, false);
+  PXOPT_LOOKUP_TIME(epoch, config->args, "-epoch", false, false);
+  PXOPT_LOOKUP_S16(fault,         config->args, "-fault", false, false);
+    //generate restrictions
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-minidvodb_id",   "minidvodbRun.minidvodb_id",   "==");
+
+
+  if (!psDBTransaction(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+
+  psString query = pxDataGet("addtool_find_pendingmergeprocess.sql");
+  if (!query) {
+    psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+    return false;
+  }
+  // use psDBGenerateWhereSQL because the SQL yields an intermediate table
+  if (psListLength(where->list)) {
+    psString whereClaus = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, " AND %s", whereClaus);
+    psFree(whereClaus);
+  }
+  psFree(where);
+
+  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("addtool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+
+  minidvodbRunRow *pendingRow = minidvodbRunObjectFromMetadata(output->data[0]);
+  psFree(output);
+  minidvodbProcessedRow *row = minidvodbProcessedRowAlloc(
+               pendingRow->minidvodb_id,
+               merge_order,
+               dtime_resort,
+               dtime_relphot,
+               dtime_merge,
+               epoch,
+               mergedvodb_path,
+               fault
+               );
+
+  if (!minidvodbProcessedInsertObject(config->dbh, row)) {
+    // rollback
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(row);
+    psFree(pendingRow);
+    return false;
+  }
+
+
+
+
+  //this finds the # of merged things (for the merge order)
+  psString query3 = NULL;
+  psStringAppend(&query3, "select count(*) from minidvodbRun join minidvodbProcessed using (minidvodb_id) where state = 'merged' and minidvodb_group = '%s';", minidvodb_group);
+
+  if (!p_psDBRunQuery(config->dbh, query3)) {
+    // rollback
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query3);
+    return false;
+  }
+  psArray *output2 = p_psDBFetchResult(config->dbh);
+  if (!output2) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+  if (!psArrayLength(output2)) {
+    psTrace("addtool", PS_LOG_INFO, "no rows found");
+    psFree(output);
+    return true;
+  }
+  bool status;
+  psS64 m_order = psMetadataLookupS64(&status, output2->data[0], "count(*)");
+  if (!status) {
+
+    psAbort("failed to lookup value for count column");
+    return false;
+  }
+  psString final = NULL;
+  psStringAppend(&final, "%" PRIu64, m_order);
+    //return false;
+  psFree(query3);
+  psFree(output2);
+
+
+
+  //update the merge_order
+
+  psString query4 = NULL;
+  psStringAppend(&query4, "update minidvodbProcessed set merge_order = %"PRIu64,m_order);
+  psStringAppend(&query4," where minidvodb_id = %" PRIu64,  minidvodb_id);
+  printf("%s", query4);
+  if (!p_psDBRunQuery(config->dbh, query4)) {
+    // rollback
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query4);
+    return false;
+  }
+  //
+psFree(query4);
+
+
+
+// since there is only one exp per 'new' set mindvodbRun.state = 'merged'
+
+  psString query2 = NULL ;
+  psStringAppend(&query2, "UPDATE minidvodbRun SET state = 'merged' WHERE minidvodb_id = %'" PRIu64, row->minidvodb_id);
+
+  if (!p_psDBRunQuery(config->dbh, query2)) {
+    // rollback
+    if (!psDBRollback(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+    }
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    psFree(query2);
+    return false;
+  }
+
+
+
+
+
+
+
+
+  psFree(row);
+  psFree(pendingRow);
+
+
+
+
+
+  //commit the changes
+  if (!psDBCommit(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+
+  //print the merge_order (why not!)
+  printf("%s", final);
+  psFree(final);
+
+  return true;
+}
+
+
+
+static bool listminidvodbprocessedMode(pxConfig *config) {
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-minidvodb_id", "minidvodbProcessed.minidvodb_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-minidvodb_name", "minidvodbProcessed.minidvodb_name", "==");
+  PXOPT_COPY_STR(config->args, where, "-minidvodb_group", "minidvodbProcessed.minidvodb_group", "==");
+  PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+  PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+  PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
+  if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        return false;
+    }
+
+  psString query = pxDataGet("addtool_find_minidvodbprocessed.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " WHERE %s", whereClause);
+        psFree(whereClause);
+    }
+
+// we either add AND (condition) or WHERE (condition):
+    if (where->list && faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", " AND minidvodbProcessed.fault != 0");
+    }
+    if (where->list && !faulted) {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", " AND minidvodbProcessed.fault = 0");
+    }
+    if (!where->list && faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", " WHERE minidvodbProcessed.fault != 0");
+    }
+    if (!where->list && !faulted) {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", " WHERE minidvodbProcessed.fault = 0");
+    }
+    psFree(where);
+
+    // order by epoch
+    psStringAppend(&query, " ORDER BY minidvodb_id");
+
+    // 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);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("addtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    // negate simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "minidvodbProcessed", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+return true;
+}
+
+
+
+static bool revertminidvodbprocessedMode(pxConfig *config) {
+  psMetadata *where = psMetadataAlloc();
+  PS_ASSERT_PTR_NON_NULL(config, false);
+  PXOPT_COPY_S64(config->args, where, "-minidvodb_id", "minidvodbProcessed.minidvodb_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-minidvodb_group", "addRun.minidvodb_group", "==");
+
+  if (!psListLength(where->list) && !psMetadataLookupBool(NULL, config->args, "-all")) {
+    psFree(where);
+    psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+    return false;
+  }
+
+  if (!psDBTransaction(config->dbh)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(where);
+      return false;
+  }
+
+  {
+    psString query = pxDataGet("addtool_revertminidvodbprocessed.sql");
+    if (!query) {
+      // rollback
+      if (!psDBRollback(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+      }
+      psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+      psFree(where);
+      return false;
+    }
+
+    // use psDBGenerateWhereConditionalSQL with AND ... because the SQL ends in a WHERE
+    if (where && psListLength(where->list)) {
+      psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+      psStringAppend(&query, " AND %s", whereClause);
+      psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+      // rollback
+      if (!psDBRollback(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+      }
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      psFree(where);
+            return false;
+    }
+    psFree(query);
+  }
+  psFree(where);
+
+  if (!psDBCommit(config->dbh)) {
+    psError(PS_ERR_UNKNOWN, false, "database error");
+    return false;
+  }
+
+  return true;
+}
+
+
+
+static bool updateminidvodbprocessedMode(pxConfig *config) {
+  PS_ASSERT_PTR_NON_NULL(config, false);
+  psMetadata *where = psMetadataAlloc();
+
+  PXOPT_LOOKUP_U64(minidvodb_id,  config->args, "-minidvodb_id", true, false);
+  PXOPT_LOOKUP_U64(merge_order,  config->args, "-set_merge_order", false, false);
+  PXOPT_LOOKUP_S16(fault,  config->args, "-set_fault", false, false);
+  PXOPT_LOOKUP_F32(dtime_relphot,  config->args, "-set_dtime_relphot", false, false);
+  PXOPT_LOOKUP_F32(dtime_resort,  config->args, "-set_dtime_resort", false, false);
+  PXOPT_LOOKUP_F32(dtime_merge,  config->args, "-set_dtime_merge", false, false);
+
+  PXOPT_COPY_S64(config->args, where, "-minidvodb_id",     "minidvodbProcessed.minidvodb_id", "==");
+  PXOPT_COPY_STR(config->args, where, "-minidvodb_name",     "minidvodbRun.minidvodb_name", "==");
+
+
+  if (!psListLength(where->list)) {
+    psFree(where);
+    psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+    return false;
+  }
+
+  psString query = psStringCopy("UPDATE minidvodbProcessed JOIN minidvodbRun USING (minidvodb_id) SET ");
+  int cnt = 0;
+  psString comma = ",";
+  if (fault) {
+    psStringAppend(&query, " fault = %d", fault);
+  cnt++;
+  }
+
+  if (merge_order) {
+    if (cnt) {
+      psStringAppend(&query, "%s", comma);
+    }
+
+    psStringAppend(&query, " merge_order = %" PRId64, merge_order);
+    cnt++;
+  }
+
+  if (dtime_relphot) {
+    if (cnt) {
+      psStringAppend(&query, "%s", comma);
+    }
+    psStringAppend(&query, " dtime_relphot = %f", dtime_relphot);
+    cnt++;
+  }
+
+  if (dtime_resort) {
+    if (cnt) {
+      psStringAppend(&query, "%s", comma);
+    }
+    psStringAppend(&query, " dtime_resort = %f", dtime_resort);
+    cnt++;
+  }
+
+  if (dtime_merge) {
+    if (cnt) {
+      psStringAppend(&query, "%s", comma);
+    }
+    psStringAppend(&query, " dtime_merge = %f", dtime_merge);
+    cnt++;
+ }
+
+  psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+  psStringAppend(&query, " WHERE %s", whereClause);
+
+  if (!p_psDBRunQuery(config->dbh, query)) {
+   psError(PS_ERR_UNKNOWN, false, "database error");
+   psFree(query);
+   return false;
+  }
+
+  psFree(query);
+  psFree(where);
+
+  return true;
+}
+
+
Index: branches/czw_branch/20100519/ippTools/src/addtool.h
===================================================================
--- branches/czw_branch/20100519/ippTools/src/addtool.h	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/addtool.h	(revision 28304)
@@ -39,5 +39,14 @@
     ADDTOOL_MODE_DONECLEANUP,
     ADDTOOL_MODE_EXPORTRUN,
-    ADDTOOL_MODE_IMPORTRUN
+    ADDTOOL_MODE_IMPORTRUN,
+    ADDTOOL_MODE_ADDMINIDVODBRUN,
+    ADDTOOL_MODE_UPDATEMINIDVODBRUN,
+    ADDTOOL_MODE_LISTMINIDVODBRUN,
+    ADDTOOL_MODE_FLIPMINIDVODBRUN,
+    ADDTOOL_MODE_CHECKMINIDVODBRUNADDRUN,
+    ADDTOOL_MODE_ADDMINIDVODBPROCESSED,
+    ADDTOOL_MODE_LISTMINIDVODBPROCESSED,
+    ADDTOOL_MODE_REVERTMINIDVODBPROCESSED,
+    ADDTOOL_MODE_UPDATEMINIDVODBPROCESSED
 } addtoolMode;
 
Index: branches/czw_branch/20100519/ippTools/src/addtoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/addtoolConfig.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/addtoolConfig.c	(revision 28304)
@@ -63,5 +63,7 @@
     psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-pretend",           0, "do not actually modify the database", false);
     psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-simple",            0, "use the simple output format", false);
-
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-set_minidvodb",            0, "use minidvodb", false);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_minidvodb_group", 0,   "define minidvodb_group", NULL);
+    psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_minidvodb_name", 0,   "define minidvodb_bname", NULL);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_data_group", 0,   "define new data_group", NULL);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-set_dist_group", 0,   "define new dist_group", NULL);
@@ -84,4 +86,5 @@
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_dist_group", 0,   "define new dist_group", NULL);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-set_note", 0,         "define new note", NULL);
+
     // -pendingexp
     psMetadata *pendingexpArgs = psMetadataAlloc();
@@ -98,4 +101,6 @@
     psMetadataAddS64(addprocessedexpArgs, PS_LIST_TAIL, "-add_id", 0,            "define addtool ID (required)", 0);
     psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-path_base", 0,            "define base output location", NULL);
+     psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-dvodb_path", 0,            "define base output location", NULL);
+      psMetadataAddStr(addprocessedexpArgs, PS_LIST_TAIL, "-minidvodb_name", 0,            "define minidvodb_name", NULL);
     psMetadataAddF32(addprocessedexpArgs, PS_LIST_TAIL, "-dtime_addstar", 0, "define elapsed time for DVO insertion (seconds)", NAN);
     psMetadataAddS16(addprocessedexpArgs, PS_LIST_TAIL, "-fault",  0,            "set fault code", 0);
@@ -142,4 +147,79 @@
     psMetadataAddStr(unblockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to unmask (required)", NULL);
 
+    // -addminidvodbruns
+    psMetadata *addminidvodbrunArgs = psMetadataAlloc();
+    psMetadataAddStr(addminidvodbrunArgs, PS_LIST_TAIL, "-set_minidvodb_name",        0, "define minidvodb_name", NULL);
+    psMetadataAddStr(addminidvodbrunArgs, PS_LIST_TAIL, "-set_minidvodb_group",        0, "define minidvodb_group (required)", NULL);
+    psMetadataAddStr(addminidvodbrunArgs, PS_LIST_TAIL, "-set_minidvodb_path",        0, "define path for minidvodb", NULL);
+    psMetadataAddStr(addminidvodbrunArgs, PS_LIST_TAIL, "-set_mergedvodb_path",        0, "define path for the merged dvodb (required)", NULL);
+    psMetadataAddStr(addminidvodbrunArgs, PS_LIST_TAIL, "-set_state",        0, "define state", NULL);
+
+    // -updateminidvodbruns
+    psMetadata *updateminidvodbrunArgs = psMetadataAlloc();
+    psMetadataAddU64(updateminidvodbrunArgs, PS_LIST_TAIL, "-minidvodb_id",        0, "search by minidvodb_id ", 0);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-minidvodb_group",        0, "search by minidvodb_name (LIKE)", NULL);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-minidvodb_name",        0, "search by minidvodb_name (LIKE)", NULL);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-minidvodb_path",        0, "search by path for minidvodb", NULL);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-mergedvodb_path",        0, "search by path for the merged dvodb", NULL);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-state",        0, "search by state", NULL);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-set_minidvodb_name",        0, "define minidvodb_name", NULL);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-set_minidvodb_path",        0, "define path for minidvodb", NULL);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-set_mergedvodb_path",        0, "define path for minidvodb", NULL);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-set_minidvodb_group",        0, "define path for the merged dvodb", NULL);
+    psMetadataAddStr(updateminidvodbrunArgs, PS_LIST_TAIL, "-set_state",        0, "define state", NULL);
+    
+    // -listminidvodbrunArgs
+    psMetadata *listminidvodbrunArgs = psMetadataAlloc();
+    psMetadataAddU64(listminidvodbrunArgs, PS_LIST_TAIL, "-minidvodb_id",        0, "search by minidvodb_id", 0);
+    psMetadataAddStr(listminidvodbrunArgs, PS_LIST_TAIL, "-minidvodb_name",        0, "search by minidvodb_name (LIKE)", NULL);
+    psMetadataAddStr(listminidvodbrunArgs, PS_LIST_TAIL, "-minidvodb_group",     0,    "search by minidvodb.minidvodb_group", NULL);
+    psMetadataAddStr(listminidvodbrunArgs, PS_LIST_TAIL, "-state",        0, "search by state", NULL);
+    psMetadataAddU64(listminidvodbrunArgs, PS_LIST_TAIL, "-limit",        0, "limit to N items", 0);
+    psMetadataAddBool(listminidvodbrunArgs, PS_LIST_TAIL, "-simple",        0, "simple output", false);
+    
+    //psMetadataAddBool(listminidvodbrunArgs, PS_LIST_TAIL, "-finished_addrun",        0, "limit to minidvodbs with completed addRuns (none in new state)", false);
+    psMetadata *flipminidvodbrunArgs = psMetadataAlloc();
+    psMetadataAddStr(flipminidvodbrunArgs, PS_LIST_TAIL, "-minidvodb_group",     0,    "for the supplied minidvodb_group (required): flip the current 'new' to 'active', the current 'active' to 'waiting'", NULL);
+    
+    psMetadata *checkminidvodbrunaddrunArgs = psMetadataAlloc();
+    psMetadataAddStr(checkminidvodbrunaddrunArgs, PS_LIST_TAIL, "-minidvodb_group",     0,    "for the supplied minidvodb_group (required): check if the addRun stage is complete (all in addRun.state = full) ", NULL);
+    psMetadataAddStr(checkminidvodbrunaddrunArgs, PS_LIST_TAIL, "-minidvodb_name",     0,    "for the supplied minidvodb_name: check if the addRun stage is complete (all in addRun.state = full) ", NULL);
+    psMetadataAddStr(checkminidvodbrunaddrunArgs, PS_LIST_TAIL, "-state",     0,    "limit by minidvodbRun state ", NULL);
+    psMetadataAddU64(checkminidvodbrunaddrunArgs, PS_LIST_TAIL, "-limit",        0, "limit to N items", 0);
+    psMetadataAddBool(checkminidvodbrunaddrunArgs, PS_LIST_TAIL, "-simple",        0, "simple output", false);
+    psMetadataAddBool(checkminidvodbrunaddrunArgs, PS_LIST_TAIL, "-all_addrun_states",        0, "list all minidvodbRun.minidvodb_names, not just ones that have complete addRuns", false);
+
+    psMetadata *addminidvodbprocessedArgs = psMetadataAlloc();
+    psMetadataAddU64(addminidvodbprocessedArgs, PS_LIST_TAIL, "-minidvodb_id", 0,    "define minidvodb_id (required)", 0);
+    psMetadataAddU64(addminidvodbprocessedArgs, PS_LIST_TAIL, "-merge_order",    0,    "define merge order", 0);
+    psMetadataAddF32(addminidvodbprocessedArgs, PS_LIST_TAIL, "-dtime_relphot",  0,    "define elapsed time for relphot (seconds)", NAN);
+    psMetadataAddF32(addminidvodbprocessedArgs, PS_LIST_TAIL, "-dtime_resort", 0,    "define elapsed time for resort (seconds)", NAN);
+    psMetadataAddF32(addminidvodbprocessedArgs, PS_LIST_TAIL, "-dtime_merge",    0,    "define elapsed time for DVO merge (seconds)", NAN);
+    psMetadataAddTime(addminidvodbprocessedArgs, PS_LIST_TAIL, "-epoch",         0,    "time merge is finished", NULL);
+    psMetadataAddStr(addminidvodbprocessedArgs, PS_LIST_TAIL, "-mergedvodb_path",0,    "path of merged dvodb", NULL);
+    psMetadataAddStr(addminidvodbprocessedArgs, PS_LIST_TAIL, "-minidvodb_group",0,    "minidvodb_group", NULL);
+    psMetadataAddS16(addminidvodbprocessedArgs, PS_LIST_TAIL, "-fault",          0,    "set fault code", 0);
+
+    psMetadata *listminidvodbprocessedArgs = psMetadataAlloc();
+    psMetadataAddU64(listminidvodbprocessedArgs, PS_LIST_TAIL, "-minidvodb_id",        0, "search by minidvodb_id", 0);
+    psMetadataAddStr(listminidvodbprocessedArgs, PS_LIST_TAIL, "-minidvodb_name",        0, "search by minidvodb_name", NULL);
+    psMetadataAddStr(listminidvodbprocessedArgs, PS_LIST_TAIL, "-minidvodb_group",        0, "search by minidvodb.minidvodb_group", NULL);
+    psMetadataAddU64(listminidvodbprocessedArgs, PS_LIST_TAIL, "-limit",        0, "limit to N items", 0);
+    psMetadataAddBool(listminidvodbprocessedArgs, PS_LIST_TAIL, "-simple",        0, "simple output", false);
+    psMetadataAddBool(listminidvodbprocessedArgs, PS_LIST_TAIL, "-faulted",        0, "limit to faulted state", false);
+
+    psMetadata *revertminidvodbprocessedArgs = psMetadataAlloc();
+    psMetadataAddU64(revertminidvodbprocessedArgs, PS_LIST_TAIL, "-minidvodb_id",        0, "search by minidvodb_id", 0);
+    psMetadataAddStr(revertminidvodbprocessedArgs, PS_LIST_TAIL, "-minidvodb_group",        0, "search by addRun.minidvodb_group", NULL);
+
+    psMetadata *updateminidvodbprocessedArgs = psMetadataAlloc();
+    psMetadataAddU64(updateminidvodbprocessedArgs, PS_LIST_TAIL, "-minidvodb_id",        0, "search by minidvodb_id", 0);
+    psMetadataAddStr(updateminidvodbprocessedArgs, PS_LIST_TAIL, "-minidvodb_name",        0, "search by minidvodb_name", NULL);
+    psMetadataAddS16(updateminidvodbprocessedArgs, PS_LIST_TAIL, "-set_fault",  0,            "set fault code", 0);
+    psMetadataAddU64(updateminidvodbprocessedArgs, PS_LIST_TAIL, "-set_merge_order",    0,    "define merge order", 0);
+    psMetadataAddF32(updateminidvodbprocessedArgs, PS_LIST_TAIL, "-set_dtime_relphot",  0,    "define elapsed time for relphot (seconds)", 0);
+    psMetadataAddF32(updateminidvodbprocessedArgs, PS_LIST_TAIL, "-set_dtime_resort", 0,    "define elapsed time for resort (seconds)", 0);
+    psMetadataAddF32(updateminidvodbprocessedArgs, PS_LIST_TAIL, "-set_dtime_merge",    0,    "define elapsed time for DVO merge (seconds)", 0);
+    
     psMetadata *argSets = psMetadataAlloc();
     psMetadata *modes = psMetadataAlloc();
@@ -154,5 +234,16 @@
     PXOPT_ADD_MODE("-block",                "set a label block",                    ADDTOOL_MODE_BLOCK,         blockArgs);
     PXOPT_ADD_MODE("-masked",               "show blocked labels",                  ADDTOOL_MODE_MASKED,        maskedArgs);
-    PXOPT_ADD_MODE("-unblock",              "remove a label block",                 ADDTOOL_MODE_UNBLOCK,       unblockArgs);
+    PXOPT_ADD_MODE("-addminidvodbrun",      "create minidvodbs ",                   ADDTOOL_MODE_ADDMINIDVODBRUN, addminidvodbrunArgs);
+    PXOPT_ADD_MODE("-updateminidvodbrun",   "change minidvodb properties",          ADDTOOL_MODE_UPDATEMINIDVODBRUN,     updateminidvodbrunArgs);
+    PXOPT_ADD_MODE("-listminidvodbrun",     "list minidvodbs",                      ADDTOOL_MODE_LISTMINIDVODBRUN,       listminidvodbrunArgs);
+    PXOPT_ADD_MODE("-flipminidvodbrun",     "flip minidvodbs",                      ADDTOOL_MODE_FLIPMINIDVODBRUN,       flipminidvodbrunArgs);
+    PXOPT_ADD_MODE("-checkminidvodbrunaddrun", "check minidvodbs to see if addRuns are completed", ADDTOOL_MODE_CHECKMINIDVODBRUNADDRUN,       checkminidvodbrunaddrunArgs);
+    PXOPT_ADD_MODE("-addminidvodbprocessed","add a processed minidvodb",            ADDTOOL_MODE_ADDMINIDVODBPROCESSED,  addminidvodbprocessedArgs);
+    PXOPT_ADD_MODE("-listminidvodbprocessed","list processed minidvodbs",           ADDTOOL_MODE_LISTMINIDVODBPROCESSED, listminidvodbprocessedArgs);
+    PXOPT_ADD_MODE("-revertminidvodbprocessed","revert processed minidvobs",        ADDTOOL_MODE_REVERTMINIDVODBPROCESSED,     revertminidvodbprocessedArgs);
+    PXOPT_ADD_MODE("-updateminidvodbprocessed","change processed minidvodb properties",ADDTOOL_MODE_UPDATEMINIDVODBPROCESSED,  updateminidvodbprocessedArgs);
+ 
+ 
+
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: branches/czw_branch/20100519/ippTools/src/camtool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/camtool.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/camtool.c	(revision 28304)
@@ -503,5 +503,5 @@
 
 /*     psTrace("czw.test",1,"Received versions: pslib %s psmodules %s psphot %s psastro %s ppstats %s ppImage %s streaks %s\n", */
-/* 	    ver_pslib,ver_psmodules,ver_psphot,ver_psastro,ver_ppstats,ver_ppimage,ver_streaks); */
+/*          ver_pslib,ver_psmodules,ver_psphot,ver_psastro,ver_ppstats,ver_ppimage,ver_streaks); */
     psString software_ver = NULL;
     if ((ver_pslib)&&(ver_psmodules)) {
@@ -637,16 +637,16 @@
         path_base,
         fault,
-	software_ver,
-	maskfrac_ref_npix,
-	maskfrac_ref_static,
-	maskfrac_ref_dynamic,
-	maskfrac_ref_magic,
-	maskfrac_ref_advisory,
-	maskfrac_max_npix,
-	maskfrac_max_static,
-	maskfrac_max_dynamic,
-	maskfrac_max_magic,
-	maskfrac_max_advisory,
-	quality
+        software_ver,
+        maskfrac_ref_npix,
+        maskfrac_ref_static,
+        maskfrac_ref_dynamic,
+        maskfrac_ref_magic,
+        maskfrac_ref_advisory,
+        maskfrac_max_npix,
+        maskfrac_max_static,
+        maskfrac_max_dynamic,
+        maskfrac_max_magic,
+        maskfrac_max_advisory,
+        quality
         );
 
@@ -677,8 +677,8 @@
     if (!pxSetRunSoftware(config, "camRun", "cam_id", cam_id, software_ver)) {
       if (!psDBRollback(config->dbh)) {
-	psError(PS_ERR_UNKNOWN, false, "database error");
+        psError(PS_ERR_UNKNOWN, false, "database error");
       }
       psError(PS_ERR_UNKNOWN, false, "failed to set camRun.software_ver for cam_id: %" PRId64,
-	      cam_id);
+              cam_id);
       psFree(output);
       return(false);
@@ -687,15 +687,15 @@
     if (maskfrac_ref_npix) {
       if (!pxCamSetRunMaskfrac(config, "camRun", "cam_id",cam_id,
-			       (float) maskfrac_ref_npix, maskfrac_ref_static,
-			       maskfrac_ref_dynamic, maskfrac_ref_magic, maskfrac_ref_advisory,
-			       (float) maskfrac_max_npix, maskfrac_max_static,
-			       maskfrac_max_dynamic, maskfrac_max_magic, maskfrac_max_advisory)) {
-	if (!psDBRollback(config->dbh)) {
-	  psError(PS_ERR_UNKNOWN, false, "database error");
-	}
-	psError(PS_ERR_UNKNOWN, false, "failed to set camRun.maskstats for cam_id: %" PRId64,
-		cam_id);
-	psFree(output);
-	return(false);
+                               (float) maskfrac_ref_npix, maskfrac_ref_static,
+                               maskfrac_ref_dynamic, maskfrac_ref_magic, maskfrac_ref_advisory,
+                               (float) maskfrac_max_npix, maskfrac_max_static,
+                               maskfrac_max_dynamic, maskfrac_max_magic, maskfrac_max_advisory)) {
+        if (!psDBRollback(config->dbh)) {
+          psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "failed to set camRun.maskstats for cam_id: %" PRId64,
+                cam_id);
+        psFree(output);
+        return(false);
       }
     }
@@ -709,10 +709,11 @@
         return false;
     }
-    
+
     psFree(row);
 
     // EAM:  NULL for end_stage means go as far as possible
     // Also, we can run fake even if tess_id is not defined
-    if (pendingRow->end_stage && psStrcasestr(pendingRow->end_stage, "cam")) {
+    // but stop if quality is non-zero.
+    if ((quality > 0) || (pendingRow->end_stage && psStrcasestr(pendingRow->end_stage, "cam"))) {
         psFree(pendingRow);
         if (!psDBCommit(config->dbh)) {
@@ -893,6 +894,10 @@
 
     {
-        psString query = pxDataGet("camtool_reset_faulted_runs.sql");
+        psString query = pxDataGet("camtool_revertprocessedexp.sql");
         if (!query) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
             psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
             psFree(where);
@@ -919,36 +924,4 @@
         psFree(query);
     }
-
-    {
-        psString query = pxDataGet("camtool_revertprocessedexp.sql");
-        if (!query) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
-            psFree(where);
-            return false;
-        }
-
-        // use psDBGenerateWhereConditionalSQL with AND ... because the SQL ends in a WHERE
-        if (where && psListLength(where->list)) {
-            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-            psStringAppend(&query, " AND %s", whereClause);
-            psFree(whereClause);
-        }
-
-        if (!p_psDBRunQuery(config->dbh, query)) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(query);
-            psFree(where);
-            return false;
-        }
-        psFree(query);
-    }
     psFree(where);
 
Index: branches/czw_branch/20100519/ippTools/src/difftool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/difftool.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/difftool.c	(revision 28304)
@@ -2290,5 +2290,5 @@
   if (psListLength(where->list)) {
     psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
-    psStringAppend(&query, " WHERE %s", whereClause);
+    psStringAppend(&query, " AND %s", whereClause);
     psFree(whereClause);
   } else if (!all && !where2) {
@@ -2301,5 +2301,5 @@
       psStringAppend(&query, " %s", where2);
     } else {
-      psStringAppend(&query, " WHERE 1 %s", where2);
+      psStringAppend(&query, " AND 1 %s", where2);
     }
   }
Index: branches/czw_branch/20100519/ippTools/src/disttool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/disttool.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/disttool.c	(revision 28304)
@@ -148,5 +148,5 @@
     PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
 
-    if (use_alternate) { 
+    if (use_alternate) {
         if (strcmp(stage, "raw")) {
             psError(PXTOOLS_ERR_SYS, true, "alternate inputs only supported for raw stage");
@@ -299,17 +299,17 @@
       query = pxDataGet("disttool_definebyquery_SSdiff.sql");
       if (!query) {
-	psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
-	psFree(where);
-	return(false);
+        psError(PXTOOLS_ERR_SYS, false, "failed to retrieve SQL statement");
+        psFree(where);
+        return(false);
       }
 
       if (label) {
-	psStringAppend(&query, " AND (diffRun.label = '%s') ", label);
+        psStringAppend(&query, " AND (diffRun.label = '%s') ", label);
       }
       if (dist_group) {
-	psStringAppend(&query, " AND (diffRun.dist_group = '%s') ", dist_group);
+        psStringAppend(&query, " AND (diffRun.dist_group = '%s') ", dist_group);
       }
 
-      no_magic = true;    
+      no_magic = true;
     } else {
         psError(PS_ERR_UNKNOWN, true, "unknown value for stage: %s", stage);
@@ -470,5 +470,14 @@
     PXOPT_COPY_STR(config->args, where, "-data_group", "distRun.data_group", "LIKE");
     PXOPT_COPY_STR(config->args, where, "-dist_group", "distTarget.dist_group", "==");
-    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+    PXOPT_COPY_TIME(config->args, where, "-time_stamp_begin", "distRun.time_stamp", ">=");
+    PXOPT_COPY_TIME(config->args, where, "-time_stamp_end", "distRun.time_stamp", "<=");
+
+    PXOPT_LOOKUP_BOOL(clean, config->args, "-clean", false);
+    PXOPT_LOOKUP_BOOL(full, config->args, "-full", false);
+    if (clean && full) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, true, "-clean and -full are contradictory parameters");
+        return false;
+    }
 
     if (!psListLength(where->list)) {
@@ -491,4 +500,5 @@
     }
 
+    psString extraWhere = NULL;
     psString query = psStringCopy("UPDATE distRun join distTarget using(target_id, stage) SET distRun.time_stamp = UTC_TIMESTAMP()");
 
@@ -498,4 +508,8 @@
     if (state) {
         psStringAppend(&query, " , distRun.state = '%s'", state);
+        if (!strcmp(state, "goto_cleaned")) {
+            // don't queue for clean up if run has already already cleaned
+            psStringAppend(&extraWhere, " AND (distRun.state != 'cleaned' AND distRun.state != 'goto_cleaned')");
+        }
     }
 
@@ -521,4 +535,13 @@
     psFree(whereClause);
     psFree(where);
+
+    if (extraWhere) {
+        psStringAppend(&query, "%s", extraWhere);
+    }
+    if (clean) {
+        psStringAppend(&query, " AND (distRun.clean)");
+    } else if (full) {
+        psStringAppend(&query, " AND (!distRun.clean)");
+    }
 
     if (!p_psDBRunQuery(config->dbh, query)) {
@@ -1680,5 +1703,5 @@
         return false;
     }
-        
+
 
     PXOPT_LOOKUP_STR(state, config->args, "-set_state", false, false);
Index: branches/czw_branch/20100519/ippTools/src/disttoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/disttoolConfig.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/disttoolConfig.c	(revision 28304)
@@ -79,5 +79,10 @@
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-data_group",     0, "limit updates to data_group", NULL);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-dist_group",     0, "limit updates to data_group", NULL);
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-time_stamp_begin", 0, "limit updates by time_stamp (>=)", NULL); 
+    psMetadataAddTime(updaterunArgs, PS_LIST_TAIL, "-time_stamp_end", 0, "limit updates by time_stamp (<=)", NULL); 
+    psMetadataAddBool(updaterunArgs, PS_LIST_TAIL,"-clean",     0, "limit updates to clean distRuns", false);
+    psMetadataAddBool(updaterunArgs, PS_LIST_TAIL,"-full",      0, "limit updates to not clean distRuns", false);
     psMetadataAddS16(updaterunArgs, PS_LIST_TAIL, "-fault",      0, "define fault code", 0);
+
     // -revertrun
     psMetadata *revertrunArgs = psMetadataAlloc();
Index: branches/czw_branch/20100519/ippTools/src/flatcorr.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/flatcorr.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/flatcorr.c	(revision 28304)
@@ -671,5 +671,8 @@
                 row->dvodb,
                 NULL,       // note is not propagated
-                0)) {
+                0,
+		0,  //The minidvodb stuff is off
+		NULL,
+		NULL)) {
             if (!psDBRollback(config->dbh)) {
                 psError(PS_ERR_UNKNOWN, false, "database error");
Index: branches/czw_branch/20100519/ippTools/src/magictool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/magictool.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/magictool.c	(revision 28304)
@@ -1367,4 +1367,5 @@
             (strncmp(state, "new", 4) == 0)
             || (strncmp(state, "full", 5) == 0)
+            || (strncmp(state, "drop", 5) == 0)
             || (strncmp(state, "reg", 4) == 0)
         )
Index: branches/czw_branch/20100519/ippTools/src/pstamptool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pstamptool.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/pstamptool.c	(revision 28304)
@@ -30,4 +30,5 @@
 #include "pxdata.h"
 #include "pstamptool.h"
+#include "pstamp.h"
 
 static bool adddatastoreMode(pxConfig *config);
@@ -53,4 +54,5 @@
 static bool updatedependentMode(pxConfig *config);
 static bool revertdependentMode(pxConfig *config);
+static bool getwebrequestnumMode(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -95,4 +97,5 @@
         MODECASE(PSTAMPTOOL_MODE_UPDATEDEPENDENT, updatedependentMode);
         MODECASE(PSTAMPTOOL_MODE_REVERTDEPENDENT, revertdependentMode);
+        MODECASE(PSTAMPTOOL_MODE_GETWEBREQUESTNUM, getwebrequestnumMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -939,10 +942,10 @@
     PXOPT_LOOKUP_S16(fault, config->args, "-fault",  false, false);
 
-    // By default only revert faults < 10 which are our "ipp exit codes"
+    // By default only revert faults < PSTAMP_FIRST_ERROR_CODE which are our "ipp exit codes"
     // codes larger than that are the pstamp request interface.
     // Don't fault those unless -fault waa provided
-    psString faultClause = "";
+    psString faultClause = psStringCopy("");
     if (!fault) {
-        faultClause = " \nAND (pstampJob.fault < 10)";
+        psStringAppend(&faultClause, " \nAND (pstampJob.fault < %d)", PSTAMP_FIRST_ERROR_CODE);
     }
 
@@ -961,7 +964,11 @@
 
     if (!p_psDBRunQueryF(config->dbh, query, faultClause)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
+        psFree(faultClause);
+        psFree(query);
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psFree(faultClause);
 
     return true;
@@ -1133,4 +1140,9 @@
             psFree(output);
             return false;
+        }
+        psS32 fault = psMetadataLookupS64(NULL, dep, "fault");
+        if (fault > 0) {
+            fprintf(stderr, "existing dependent has fault %d\n", fault);
+            exit (fault);
         }
         printf("%" PRId64 "\n", dep_id);
@@ -1315,4 +1327,7 @@
         return false;
     }
+
+    PXOPT_LOOKUP_S16(fault,      config->args, "-fault",          false, false);
+
     psString query = pxDataGet("pstamptool_revertdependent.sql");
     if (!query) {
@@ -1326,10 +1341,32 @@
     psFree(where);
 
-    if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(query);
-        return false;
-    }
-
-    return true;
-}
+    if (!fault) {
+        // unless asked to clear a specific fault value, restrict reverts to fault codes
+        // that are less than the minimum fault in the API
+        psStringAppend(&query, " AND (pstampDependent.fault < %d)", PSTAMP_FIRST_ERROR_CODE);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    return true;
+}
+
+static bool getwebrequestnumMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    if (!pstampWebRequestInsert(config->dbh, 0 )) {
+        psError(PS_ERR_UNKNOWN, false, "failed to insert pstampWebRequest");
+        return false;
+    }
+
+    psS64 req_id = psDBLastInsertID(config->dbh);
+
+    printf("%" PRId64 "\n", req_id);
+
+    return true;
+}
Index: branches/czw_branch/20100519/ippTools/src/pstamptool.h
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pstamptool.h	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/pstamptool.h	(revision 28304)
@@ -48,4 +48,5 @@
     PSTAMPTOOL_MODE_UPDATEDEPENDENT,
     PSTAMPTOOL_MODE_REVERTDEPENDENT,
+    PSTAMPTOOL_MODE_GETWEBREQUESTNUM,
 } pstamptoolMode;
 
Index: branches/czw_branch/20100519/ippTools/src/pstamptoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pstamptoolConfig.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/pstamptoolConfig.c	(revision 28304)
@@ -235,4 +235,7 @@
     psMetadataAddBool(projectArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
 
+    // -getwebrequestnum
+    psMetadata *getwebrequestnumArgs = psMetadataAlloc();
+
     psMetadata *argSets = psMetadataAlloc();
     psMetadata *modes = psMetadataAlloc();
@@ -264,4 +267,5 @@
     PXOPT_ADD_MODE("-modproject",      "", PSTAMPTOOL_MODE_MODPROJECT, modprojectArgs);
     PXOPT_ADD_MODE("-project",         "", PSTAMPTOOL_MODE_PROJECT,    projectArgs);
+    PXOPT_ADD_MODE("-getwebrequestnum","", PSTAMPTOOL_MODE_GETWEBREQUESTNUM,   getwebrequestnumArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: branches/czw_branch/20100519/ippTools/src/pxadd.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pxadd.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/pxadd.c	(revision 28304)
@@ -130,5 +130,8 @@
                        char *dvodb,
                        char *note,
-                       bool image_only)
+                       bool image_only,
+		       bool minidvodb,
+		       char *minidvodb_group,
+		       char *minidvodb_name)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -158,7 +161,10 @@
                          note     ? note     : "NULL",
                          image_only,
+			 minidvodb,
+			 minidvodb_group,
+			 minidvodb_name,
                          (long long) cam_id
     )) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
+      psError(PS_ERR_UNKNOWN, false, "database error %s", query);
         return false;
     }
Index: branches/czw_branch/20100519/ippTools/src/pxadd.h
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pxadd.h	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/pxadd.h	(revision 28304)
@@ -38,5 +38,8 @@
 		       char *dvodb,
 		       char *note,
-		       bool image_only);
+		       bool image_only,
+		       bool minidvodb,
+		       char *minidvodb_group,
+		       char *minidvodb_name);
 
 #endif // PXADD_H
Index: branches/czw_branch/20100519/ippTools/src/pxcam.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pxcam.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/pxcam.c	(revision 28304)
@@ -152,5 +152,5 @@
                     char *tess_id,
                     char *end_stage,
-		    psS64 magicked,
+                    psS64 magicked,
                     char *note)
 {
@@ -172,22 +172,28 @@
     // different on 32/64
     if (!p_psDBRunQueryF(config->dbh, query,
-                "new", // state
-                workdir  ? workdir  : "NULL",
-                "dirty", //workdir_state
-                label    ? label    : "NULL",
-                data_group ? data_group : "NULL",
-                dist_group ? dist_group : "NULL",
-                recipe   ? recipe   : "NULL",
-                expgroup ? expgroup : "NULL",
-                dvodb    ? dvodb    : "NULL",
-                tess_id  ? tess_id  : "NULL",
-                end_stage ? end_stage : "NULL",
-                (long long) magicked,
-			 "NULL", // This shouldn't be propagated
-			 "NULL",
-			 "NULL",
-			 "NULL",
-			 "NULL",
-			 "NULL",
+                         "new", // state
+                         workdir  ? workdir  : "NULL",
+                         "dirty", //workdir_state
+                         label    ? label    : "NULL",
+                         data_group ? data_group : "NULL",
+                         dist_group ? dist_group : "NULL",
+                         recipe   ? recipe   : "NULL",
+                         expgroup ? expgroup : "NULL",
+                         dvodb    ? dvodb    : "NULL",
+                         tess_id  ? tess_id  : "NULL",
+                         end_stage ? end_stage : "NULL",
+                         (long long) magicked,
+                         // Here follows the software version and mask statistics which shouldn't be propagated
+                         "NULL",
+                         "NULL",
+                         "NULL",
+                         "NULL",
+                         "NULL",
+                         "NULL",
+                         "NULL",
+                         "NULL",
+                         "NULL",
+                         "NULL",
+                         "NULL",
                 note     ? note     : "NULL",
                 (long long)chip_id
Index: branches/czw_branch/20100519/ippTools/src/pxchip.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pxchip.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/pxchip.c	(revision 28304)
@@ -40,5 +40,5 @@
     psMetadataAddStr(md,  PS_LIST_TAIL, "-telescope",          0, "search for telescope", NULL);
     psMetadataAddTime(md, PS_LIST_TAIL, "-dateobs_begin",      0, "search for exposures by time (>=)", NULL);
-    psMetadataAddTime(md, PS_LIST_TAIL, "-dateobs_end",        0, "search for exposures by time (<)", NULL);
+    psMetadataAddTime(md, PS_LIST_TAIL, "-dateobs_end",        0, "search for exposures by time (<=)", NULL);
     psMetadataAddStr(md,  PS_LIST_TAIL, "-exp_tag",            0, "search by exp_tag", NULL);
     psMetadataAddStr(md,  PS_LIST_TAIL, "-exp_type",           0, "search by exp_type", NULL);
Index: branches/czw_branch/20100519/ippTools/src/pxtools.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/pxtools.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/pxtools.c	(revision 28304)
@@ -48,142 +48,159 @@
 }
 
-psString pxMergeCodeVersions(psString version1, psString version2) {
+psString pxMergeCodeVersions(psString version1, psString version2)
+{
+    if (!version1 && !version2) {
+        return NULL;
+    }
+
+    if (!version1) {
+        return psStringCopy(version2);
+    }
+    if (!version2) {
+        return psStringCopy(version1);
+    }
+
+    bool mod1 = false, mod2 = false;    // Modified versions?
+    if (strchr(version1, 'M')) {
+        psStringSubstitute(&version1, "M", "");
+        mod1 = true;
+    }
+    if (strchr(version2, 'M')) {
+        psStringSubstitute(&version2, "M", "");
+        mod2 = true;
+    }
+
+    int num1 = strtol(version1, NULL, 10);
+    int num2 = strtol(version2, NULL, 10);
+    int numO = PS_MAX(num1, num2);
+
     psString out = NULL;
-
-    bool mod1 = false;
-    bool mod2 = false;
-
-    psS32 num1;
-    psS32 num2;
-    psS32 numO;
-
-    if (!version1) {
-	psStringAppend(&out, "%s", version2);
-	return(out);
-    }
-    if (!version2) {
-	psStringAppend(&out, "%s", version1);
-	return(out);
-    }
-  
-    if (strchr(version1,'M')) {
-	psStringSubstitute(&version1,"M","");
-	mod1 = true;
-    }
-    if (strchr(version2,'M')) {
-	psStringSubstitute(&version2,"M","");
-	mod2 = true;
-    }
-
-    num1 = strtol(version1,NULL,10);
-    num2 = strtol(version2,NULL,10);
-
-    if (num1 >= num2) {
-	numO = num1;
-    }
-    else {
-	numO = num2;
-    }
-  
-    psStringAppend(&out,"%" PRId32,numO);
+    psStringAppend(&out, "%" PRId32, numO);
     if (mod1 || mod2) {
-	psStringAppend(&out,"M");
-    }
-    return(out);
+        psStringAppend(&out, "M");
+    }
+    return out;
 }
 
 bool pxCoalesceRunStatus(pxConfig *config, const psString dbQFile, psS64 stage_id, psString *software_ver,
-			 psS64 *maskfrac_npix, psF32 *maskfrac_static, psF32 *maskfrac_dynamic,
-			 psF32 *maskfrac_magic, psF32 *maskfrac_advisory) {
+                         psS64 *maskfrac_npix, psF32 *maskfrac_static, psF32 *maskfrac_dynamic,
+                         psF32 *maskfrac_magic, psF32 *maskfrac_advisory)
+{
     psString query = pxDataGet(dbQFile);
-/*   psString text_id = NULL; */
-/*   psStringAppend(&text_id," %" PRId64,stage_id); */
-/*   psStringSubstitute(&query,text_id,"@STAGE_ID@"); */
-/*   psFree(text_id); */
+    if (!query) {
+        psError(psErrorCodeLast(), false, "Unable to read query");
+        return false;
+    }
     if (!p_psDBRunQueryF(config->dbh, query, stage_id)) {
-	psError(PS_ERR_UNKNOWN, false, "database error");
-	psFree(query);
-	return(false);
+        psError(psErrorCodeLast(), 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);
-    }
-  
+        psError(psErrorCodeLast(), false, "database error");
+        return false;
+    }
+
+    *maskfrac_npix = 0;
+    *maskfrac_static = 0.0;
+    *maskfrac_dynamic = 0.0;
+    *maskfrac_magic = 0.0;
+    *maskfrac_advisory = 0.0;
+
     for (long i = 0; i < psArrayLength(output); i++) {
-	psMetadata *row = output->data[i];
-
-	psS32 this_npix = psMetadataLookupS32(NULL, row, "maskfrac_npix");
-	psF32 this_static = psMetadataLookupF32(NULL, row, "maskfrac_static");
-	psF32 this_dynamic = psMetadataLookupF32(NULL, row, "maskfrac_dynamic");
-	psF32 this_magic = psMetadataLookupF32(NULL, row, "maskfrac_magic");
-	psF32 this_advisory = psMetadataLookupF32(NULL, row, "maskfrac_advisory");
-	psString this_version = psMetadataLookupStr(NULL, row, "software_ver");
-
-	*software_ver = pxMergeCodeVersions(*software_ver,this_version);
-/*     printf("%ld : %d %f %f %f %f <-> %ld %f %f %f %f\n",i,this_npix,this_static,this_dynamic,this_magic,this_advisory, */
-/* 	   *maskfrac_npix,*maskfrac_static,*maskfrac_dynamic,*maskfrac_magic,*maskfrac_advisory); */
-	if (this_npix > 0) {
-	    *maskfrac_static = ((*maskfrac_static * *maskfrac_npix) + (this_npix * this_static)) / (this_npix + *maskfrac_npix);
-	    *maskfrac_dynamic = ((*maskfrac_dynamic * *maskfrac_npix) + (this_npix * this_dynamic)) / (this_npix + *maskfrac_npix);
-	    *maskfrac_magic = ((*maskfrac_magic * *maskfrac_npix) + (this_npix * this_magic)) / (this_npix + *maskfrac_npix);
-	    *maskfrac_advisory = ((*maskfrac_advisory * *maskfrac_npix) + (this_npix * this_advisory)) / (this_npix + *maskfrac_npix);
-	    *maskfrac_npix += this_npix;
-	}
+        psMetadata *row = output->data[i];
+
+        psS32 this_npix = psMetadataLookupS32(NULL, row, "maskfrac_npix");
+        psF32 this_static = psMetadataLookupF32(NULL, row, "maskfrac_static");
+        psF32 this_dynamic = psMetadataLookupF32(NULL, row, "maskfrac_dynamic");
+        psF32 this_magic = psMetadataLookupF32(NULL, row, "maskfrac_magic");
+        psF32 this_advisory = psMetadataLookupF32(NULL, row, "maskfrac_advisory");
+
+        psTrace("pxtools", 3, "Mask stats: %d %f %f %f %f\n",
+                this_npix, this_static, this_dynamic, this_magic, this_advisory);
+
+        if (this_npix == 0 || this_npix == PS_MAX_S32) {
+            continue;
+        }
+        if (!isfinite(this_static) || !isfinite(this_dynamic) ||
+            !isfinite(this_magic) || !isfinite(this_advisory)) {
+            continue;
+        }
+
+        psString this_version = psMetadataLookupStr(NULL, row, "software_ver");
+        *software_ver = pxMergeCodeVersions(*software_ver,this_version);
+
+        *maskfrac_npix += this_npix;
+        *maskfrac_static += this_npix * this_static;
+        *maskfrac_dynamic += this_npix * this_dynamic;
+        *maskfrac_magic += this_npix * this_magic;
+        *maskfrac_advisory += this_npix * this_advisory;
     }
     psFree(output);
-    return(true);
-}
-
-bool pxSetRunSoftware(pxConfig *config, const psString tableName, const psString stage_id_name, const psS64 stage_id,
-		      psString software_ver) {
+
+    if (*maskfrac_npix > 0) {
+        *maskfrac_static /= *maskfrac_npix;
+        *maskfrac_dynamic /= *maskfrac_npix;
+        *maskfrac_magic /= *maskfrac_npix;
+        *maskfrac_advisory /= *maskfrac_npix;
+    }
+
+    return true;
+}
+
+bool pxSetRunSoftware(pxConfig *config, const psString tableName, const psString stage_id_name,
+                      const psS64 stage_id, psString software_ver)
+{
     char *query = "UPDATE %s SET software_ver = '%s' WHERE %s = %" PRId64;
-/*   printf(query,tableName,software_ver,stage_id_name,stage_id); */
-    if (!p_psDBRunQueryF(config->dbh,query,tableName,software_ver,stage_id_name,stage_id)) {
-	psError(PS_ERR_UNKNOWN, false,
-		"failed to set software version for %s %" PRId64,stage_id_name,stage_id);
-	return(false);
-    }
-  
-    return(true);
-}
-
-bool pxSetRunMaskfrac(pxConfig *config, const psString tableName, const psString stage_id_name, const psS64 stage_id,
-		      psS64 maskfrac_npix, psF32 maskfrac_static, psF32 maskfrac_dynamic,
-		      psF32 maskfrac_magic, psF32 maskfrac_advisory) {
-    char *query = "UPDATE %s SET maskfrac_npix = %f, maskfrac_static = %f, maskfrac_dynamic = %f, maskfrac_magic = %f, maskfrac_advisory = %f WHERE %s = %" PRId64;
-    if (!p_psDBRunQueryF(config->dbh,query,tableName,(float) maskfrac_npix,maskfrac_static,
-			 maskfrac_dynamic, maskfrac_magic,maskfrac_advisory,stage_id_name,stage_id)) {
-	psError(PS_ERR_UNKNOWN, false,
-		"failed to set maskfrac stats for %s %" PRId64,stage_id_name,stage_id);
-	return(false);
-    }
-  
-
-
-    return(true);
-}
-
-bool pxCamSetRunMaskfrac(pxConfig *config, const psString tableName, const psString stage_id_name, const psS64 stage_id,
-			 psS64 maskfrac_ref_npix, psF32 maskfrac_ref_static, psF32 maskfrac_ref_dynamic,
-			 psF32 maskfrac_ref_magic, psF32 maskfrac_ref_advisory,
-			 psS64 maskfrac_max_npix, psF32 maskfrac_max_static, psF32 maskfrac_max_dynamic,
-			 psF32 maskfrac_max_magic, psF32 maskfrac_max_advisory) {
-  char *query = "UPDATE %s SET maskfrac_ref_npix = %f, maskfrac_ref_static = %f, maskfrac_ref_dynamic = %f, maskfrac_ref_magic = %f, maskfrac_ref_advisory = %f, maskfrac_max_npix = %f, maskfrac_max_static = %f, maskfrac_max_dynamic = %f, maskfrac_max_magic = %f, maskfrac_max_advisory = %f WHERE %s = %" PRId64;
-  if (!p_psDBRunQueryF(config->dbh,query,tableName,(float) maskfrac_ref_npix,maskfrac_ref_static,
-		       maskfrac_ref_dynamic, maskfrac_ref_magic,maskfrac_ref_advisory,
-		       (float) maskfrac_max_npix,maskfrac_max_static,
-		       maskfrac_max_dynamic, maskfrac_max_magic,maskfrac_max_advisory,
-		       stage_id_name,stage_id)) {
-    psError(PS_ERR_UNKNOWN, false,
-	    "failed to set maskfrac stats for %s %" PRId64,stage_id_name,stage_id);
-    return(false);
+    if (!p_psDBRunQueryF(config->dbh, query, tableName, software_ver, stage_id_name, stage_id)) {
+        psError(psErrorCodeLast(), false,
+                "failed to set software version for %s %" PRId64, stage_id_name, stage_id);
+        return false;
+    }
+
+    return true;
+}
+
+bool pxSetRunMaskfrac(pxConfig *config, const psString tableName, const psString stage_id_name,
+                      const psS64 stage_id, psS64 maskfrac_npix, psF32 maskfrac_static,
+                      psF32 maskfrac_dynamic, psF32 maskfrac_magic, psF32 maskfrac_advisory)
+{
+    char *query = "UPDATE %s SET maskfrac_npix = %f, maskfrac_static = %f, maskfrac_dynamic = %f, "
+        "maskfrac_magic = %f, maskfrac_advisory = %f WHERE %s = %" PRId64;
+    if (!p_psDBRunQueryF(config->dbh, query, tableName, (float)maskfrac_npix, maskfrac_static,
+                         maskfrac_dynamic, maskfrac_magic, maskfrac_advisory, stage_id_name, stage_id)) {
+        psError(psErrorCodeLast(), false,
+                "failed to set maskfrac stats for %s %" PRId64,stage_id_name,stage_id);
+        return false;
+    }
+
+
+
+    return true;
+}
+
+bool pxCamSetRunMaskfrac(pxConfig *config, const psString tableName,
+                         const psString stage_id_name, const psS64 stage_id,
+                         psS64 maskfrac_ref_npix, psF32 maskfrac_ref_static, psF32 maskfrac_ref_dynamic,
+                         psF32 maskfrac_ref_magic, psF32 maskfrac_ref_advisory,
+                         psS64 maskfrac_max_npix, psF32 maskfrac_max_static, psF32 maskfrac_max_dynamic,
+                         psF32 maskfrac_max_magic, psF32 maskfrac_max_advisory) {
+  char *query = "UPDATE %s SET maskfrac_ref_npix = %f, maskfrac_ref_static = %f, maskfrac_ref_dynamic = %f, "
+      "maskfrac_ref_magic = %f, maskfrac_ref_advisory = %f, maskfrac_max_npix = %f, maskfrac_max_static = %f, "
+      "maskfrac_max_dynamic = %f, maskfrac_max_magic = %f, maskfrac_max_advisory = %f WHERE %s = %" PRId64;
+  if (!p_psDBRunQueryF(config->dbh, query, tableName, (float)maskfrac_ref_npix, maskfrac_ref_static,
+                       maskfrac_ref_dynamic,  maskfrac_ref_magic, maskfrac_ref_advisory,
+                       (float)maskfrac_max_npix, maskfrac_max_static,
+                       maskfrac_max_dynamic,  maskfrac_max_magic, maskfrac_max_advisory,
+                       stage_id_name, stage_id)) {
+      psError(psErrorCodeLast(), false,
+              "failed to set maskfrac stats for %s %" PRId64,stage_id_name,stage_id);
+      return false;
   }
-  
-
-
-  return(true);
+
+  return true;
 }
 
@@ -222,5 +239,5 @@
     psMetadataItem *item = psMetadataLookup(config->args, name);
     if (!item) {
-        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for %s", name);
+        psError(psErrorCodeLast(), false, "failed to lookup value for %s", name);
         return false;
     }
@@ -239,5 +256,5 @@
             item->comment = psStringCopy (op);
             if (!psMetadataAddItem(where, item, PS_LIST_TAIL, PS_META_DUPLICATE_OK)) {
-                psError(PS_ERR_UNKNOWN, false, "failed to add item %s", field);
+                psError(psErrorCodeLast(), false, "failed to add item %s", field);
                 psFree(where);
                 return false;
@@ -272,4 +289,14 @@
     PXOPT_LOOKUP_STR(note, config->args,        "-set_note", false, false);
 
+    if ((state)&&(!strcmp(state, "update"))) {
+        fprintf(stderr, "'-updaterun -set_state update' is not supported.");
+        if (!strcmp(runTable, "chipRun")) {
+            fprintf(stderr, " Use -setimfiletoupdate.\n");
+        } else {
+            fprintf(stderr, " Use -setskyfiletoupdate.\n");
+        }
+        exit(1);
+    }
+
     psString dist_group = NULL;
     if (has_dist_group) {
@@ -293,10 +320,10 @@
     char *comma = ",";
 
-#   define addColumn(_tab, _val)					\
-    do {								\
-	if (_val) {							\
-	    psStringAppend(pQuery, "%s %s.%s = '%s'", separator, _tab, #_val, _val); \
-	    separator = comma;						\
-	}								\
+#   define addColumn(_tab, _val)                                        \
+    do {                                                                \
+        if (_val) {                                                     \
+            psStringAppend(pQuery, "%s %s.%s = '%s'", separator, _tab, #_val, _val); \
+            separator = comma;                                          \
+        }                                                               \
     } while (0)
 
@@ -331,5 +358,5 @@
 
     if (!p_psDBRunQueryF(config->dbh, *pQuery, joinHook)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
+        psError(psErrorCodeLast(), false, "database error");
         return false;
     }
@@ -343,5 +370,5 @@
 
     if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
+        psError(psErrorCodeLast(), false, "database error");
         return false;
     }
@@ -349,14 +376,14 @@
     psArray *output = p_psDBFetchResult(config->dbh);
     if (!output) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
+        psError(psErrorCodeLast(), false, "database error");
         return false;
     }
     if (!psArrayLength(output)) {
         psFree(output);
-        psError(PS_ERR_UNKNOWN, true, "no rows in dbversion");
+        psError(PXTOOLS_ERR_PROG, true, "no rows in dbversion");
         return false;
     }
     if (psArrayLength(output) > 1) {
-        psError(PS_ERR_UNKNOWN, true, "unexpected number of rows found in dbversion: %ld",
+        psError(PXTOOLS_ERR_PROG, true, "unexpected number of rows found in dbversion: %ld",
                 psArrayLength(output));
         return false;
@@ -373,10 +400,10 @@
     psArray *array = NULL;
     if (!pxLookupVersion(config, &array)) {
-        psError(PS_ERR_UNKNOWN, false, "pxLookupVersion failed");
+        psError(psErrorCodeLast(), false, "pxLookupVersion failed");
         return NULL;
     }
     psMetadata *md = array->data[0];
     if (!md) {
-        psError(PS_ERR_UNKNOWN, true, "output of pxLookupVersion is null");
+        psError(PXTOOLS_ERR_PROG, true, "output of pxLookupVersion is null");
         return NULL;
     }
@@ -394,9 +421,9 @@
     psArray *array = NULL;
     if (!pxLookupVersion(config, &array) || !array) {
-        psError(PS_ERR_UNKNOWN, false, "pxLookupVersion failed");
+        psError(psErrorCodeLast(), false, "pxLookupVersion failed");
         return false;
     }
     if (!ippdbPrintMetadatas(file, array, "dbversion", true)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psError(psErrorCodeLast(), false, "failed to print array");
         psFree(array);
         return false;
@@ -414,5 +441,5 @@
     psMetadataItem *multi_item =  psMetadataLookup(input, "dbversion");
     if (!multi_item || (multi_item->type != PS_DATA_METADATA_MULTI)) {
-        psError(PS_ERR_UNKNOWN, true, "dbversion multi not found in input");
+        psError(PXTOOLS_ERR_PROG, true, "dbversion multi not found in input");
         return false;
     }
@@ -420,5 +447,5 @@
     psMetadataItem *dbversion = psListGet(multi_item->data.list, 0);
     if (!dbversion) {
-        psError(PS_ERR_UNKNOWN, true, "dbversion not found in input");
+        psError(PXTOOLS_ERR_PROG, true, "dbversion not found in input");
         return false;
     }
@@ -429,5 +456,5 @@
         psString schema_version = pxGetDBVersion(config);
         if (!schema_version) {
-            psError(PS_ERR_UNKNOWN, false, "pxGetDBVersion failed");
+            psError(psErrorCodeLast(), false, "pxGetDBVersion failed");
             return false;
         }
@@ -435,9 +462,9 @@
         psString import_version = psMetadataLookupStr(NULL, md, "schema_version");
         if (import_version && strcmp(import_version, schema_version)) {
-            psError(PS_ERR_UNKNOWN, true, "input file schema_version: %s does not match data base: %s",
-		    import_version, schema_version);
+            psError(PXTOOLS_ERR_PROG, true, "input file schema_version: %s does not match data base: %s",
+                    import_version, schema_version);
             return false;
         } else if (!import_version) {
-            psError(PS_ERR_UNKNOWN, true, "input file schema_version is NULL");
+            psError(PXTOOLS_ERR_PROG, true, "input file schema_version is NULL");
             return false;
         } else {
@@ -445,8 +472,8 @@
         }
     } else {
-        psError(PS_ERR_UNKNOWN, true, "Unexpected config dump format");
-        return false;
-    }
-
-    return true;
-}
+        psError(PXTOOLS_ERR_PROG, true, "Unexpected config dump format");
+        return false;
+    }
+
+    return true;
+}
Index: branches/czw_branch/20100519/ippTools/src/stacktool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/stacktool.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/stacktool.c	(revision 28304)
@@ -39,4 +39,5 @@
 static bool addsumskyfileMode(pxConfig *config);
 static bool sumskyfileMode(pxConfig *config);
+static bool sassskyfileMode(pxConfig *config);
 static bool revertsumskyfileMode(pxConfig *config);
 static bool tosummaryMode(pxConfig *config);
@@ -77,4 +78,5 @@
         MODECASE(STACKTOOL_MODE_ADDSUMSKYFILE,         addsumskyfileMode);
         MODECASE(STACKTOOL_MODE_SUMSKYFILE,            sumskyfileMode);
+	MODECASE(STACKTOOL_MODE_SASSSKYFILE,            sassskyfileMode);
         MODECASE(STACKTOOL_MODE_REVERTSUMSKYFILE,      revertsumskyfileMode);
 	MODECASE(STACKTOOL_MODE_TOSUMMARY,             tosummaryMode);
@@ -116,5 +118,10 @@
   psString idString = NULL;
   psStringAppend(&idString, "%" PRId64, stack_id);
-  psStringSubstitute(&select,idString, "@STACK_ID@");
+  // Copy string to get around the issue with psStringSubstitute not believing
+  // that select is a psString.
+  psString rep = psStringCopy(select);
+  psFree(select);
+  select = rep;
+  psStringSubstitute(&select, idString, "@STACK_ID@");
   psFree(idString);
 
@@ -143,12 +150,33 @@
     return(NULL);
   }
-  psMetadata *outrow = NULL;
+  psMetadata *outrow = psMetadataAlloc();
   for (long i = 0; i < output->n; i++) {
     psMetadata *row = output->data[i];
-    if (!psMetadataCopy(row,outrow)) {
-      psError(PS_ERR_UNKNOWN, false, "Failed to copy row to return");
-      return(NULL);
-    }
-  }
+
+    printf("%" PRId64 " %s %s %s %s\n",psMetadataLookupS64(NULL,row,"sass_id"),
+	   psMetadataLookupStr(NULL,row,"data_group"),
+	   psMetadataLookupStr(NULL,row,"tess_id"),
+	   psMetadataLookupStr(NULL,row,"filter"),
+	   psMetadataLookupStr(NULL,row,"projection_cell"));
+
+    if (psMetadataLookupS64(NULL,row,"sass_id") == PS_MAX_S64) {
+      psMetadataAddS64(outrow,PS_LIST_TAIL,"sass_id",PS_META_REPLACE,"",0);
+    }
+    else {
+      psMetadataAddS64(outrow,PS_LIST_TAIL,"sass_id",PS_META_REPLACE,"",psMetadataLookupS64(NULL,row,"sass_id"));
+    }
+    psMetadataAddStr(outrow,PS_LIST_TAIL,"data_group",PS_META_REPLACE,"",psMetadataLookupStr(NULL,row,"data_group"));
+    psMetadataAddStr(outrow,PS_LIST_TAIL,"tess_id",PS_META_REPLACE,"",psMetadataLookupStr(NULL,row,"tess_id"));
+    psMetadataAddStr(outrow,PS_LIST_TAIL,"filter",PS_META_REPLACE,"",psMetadataLookupStr(NULL,row,"filter"));
+    psMetadataAddStr(outrow,PS_LIST_TAIL,"projection_cell",PS_META_REPLACE,"",
+		     psMetadataLookupStr(NULL,row,"projection_cell"));
+  }
+  printf("%" PRId64 " %s %s %s %s\n",psMetadataLookupS64(NULL,outrow,"sass_id"),
+	 psMetadataLookupStr(NULL,outrow,"data_group"),
+	 psMetadataLookupStr(NULL,outrow,"tess_id"),
+	 psMetadataLookupStr(NULL,outrow,"filter"),
+	 psMetadataLookupStr(NULL,outrow,"projection_cell"));
+  
+
   psFree(output);
   stackAssociationRow *sassRow = stackAssociationObjectFromMetadata(outrow);
@@ -1063,5 +1091,4 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-stack_id", "stackSumSkyfile.stack_id", "==");
-    PXOPT_COPY_S64(config->args, where, "-sass_id", "stackAssociationMap.sass_id", "==");
     PXOPT_COPY_STR(config->args, where, "-tess_id", "stackRun.tess_id", "==");
     PXOPT_COPY_STR(config->args, where, "-skycell_id", "stackRun.skycell_id", "==");
@@ -1082,4 +1109,89 @@
 
     psString query = pxDataGet("stacktool_sumskyfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " WHERE %s", whereClause);
+        psFree(whereClause);
+    } else if (!all) {
+        psError(PXTOOLS_ERR_CONFIG, true, "search parameters or -all are required");
+        return false;
+    }
+
+    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);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("stacktool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        if (!ippdbPrintMetadatas(stdout, output, "stackSumSkyfile", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool sassskyfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-sass_id", "stackAssociation.sass_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-tess_id", "stackAssociation.tess_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-projection_cell", "stackAssociation.projection_cell", "==");
+    PXOPT_COPY_STR(config->args, where, "-filter", "stackAssociation.filter", "LIKE");
+    PXOPT_COPY_STR(config->args, where, "-data_group", "stackAssociation.data_group", "LIKE");
+
+//  The following three selectors are incompatible with the sql so omit them
+//    PXOPT_COPY_S64(config->args, where, "-warp_id", "warpRun.warp_id", "==");
+//     PXOPT_COPY_S64(config->args, where, "-exp_id", "rawExp.exp_id", "==");
+//    PXOPT_COPY_STR(config->args, where, "-exp_name", "rawExp.exp_name", "==");
+
+    PXOPT_LOOKUP_BOOL(all, config->args, "-all", false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psString query = pxDataGet("stacktool_sassskyfile.sql");
     if (!query) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -1318,5 +1430,5 @@
   PS_ASSERT_PTR_NON_NULL(config, NULL);
 
-  PXOPT_LOOKUP_S64(stack_id, config->args, "-stack_id", true, false);
+  PXOPT_LOOKUP_S64(sass_id, config->args, "-sass_id", true, false);
   PXOPT_LOOKUP_STR(projection_cell, config->args, "-projection_cell", true, false);
   PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", true, false);
@@ -1327,5 +1439,5 @@
     return(false);
   }
-  if (!p_psDBRunQueryF(config->dbh, query, stack_id, projection_cell, path_base)) {
+  if (!p_psDBRunQueryF(config->dbh, query, sass_id, projection_cell, path_base)) {
     psError(PS_ERR_UNKNOWN, false, "database error");
     psFree(query);
Index: branches/czw_branch/20100519/ippTools/src/stacktool.h
===================================================================
--- branches/czw_branch/20100519/ippTools/src/stacktool.h	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/stacktool.h	(revision 28304)
@@ -33,4 +33,5 @@
     STACKTOOL_MODE_ADDSUMSKYFILE,
     STACKTOOL_MODE_SUMSKYFILE,
+    STACKTOOL_MODE_SASSSKYFILE,
     STACKTOOL_MODE_REVERTSUMSKYFILE,
     STACKTOOL_MODE_TOSUMMARY,
Index: branches/czw_branch/20100519/ippTools/src/stacktoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/stacktoolConfig.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/stacktoolConfig.c	(revision 28304)
@@ -197,4 +197,16 @@
     psMetadataAddBool(sumskyfileArgs, PS_LIST_TAIL, "-all",  0,            "enable search without arguments", false);
 
+    // -sassskyfile
+    psMetadata *sassskyfileArgs = psMetadataAlloc();
+    psMetadataAddS64(sassskyfileArgs, PS_LIST_TAIL, "-sass_id", 0,           "search by stack association ID", 0);
+    psMetadataAddStr(sassskyfileArgs, PS_LIST_TAIL, "-tess_id", 0,            "search by tess ID", 0);
+    psMetadataAddStr(sassskyfileArgs, PS_LIST_TAIL, "-projection_cell", 0,         "search by projection cell", 0);
+
+    psMetadataAddStr(sassskyfileArgs, PS_LIST_TAIL, "-data_group", 0,        "search by stackAssociation.data_group (LIKE comparison)", NULL);
+    psMetadataAddStr(sassskyfileArgs, PS_LIST_TAIL, "-filter", 0,            "search by filter (LIKE comparison)", NULL);
+    psMetadataAddU64(sassskyfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddBool(sassskyfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddBool(sassskyfileArgs, PS_LIST_TAIL, "-all",  0,            "enable search without arguments", false);
+
     // -revertsumskyfile
     psMetadata *revertsumskyfileArgs= psMetadataAlloc();
@@ -221,5 +233,5 @@
     // -addsummary
     psMetadata *addsummaryArgs = psMetadataAlloc();
-    psMetadataAddS64(addsummaryArgs, PS_LIST_TAIL, "-stack_id", 0,      "set stack ID", 0);
+    psMetadataAddS64(addsummaryArgs, PS_LIST_TAIL, "-sass_id", 0,      "set stack Association ID", 0);
     psMetadataAddStr(addsummaryArgs, PS_LIST_TAIL, "-projection_cell", 0, "set projection cell", NULL);
     psMetadataAddStr(addsummaryArgs, PS_LIST_TAIL, "-path_base", 0,     "set summary path base", NULL);		     
@@ -273,4 +285,5 @@
     PXOPT_ADD_MODE("-addsumskyfile",   "", STACKTOOL_MODE_ADDSUMSKYFILE,   addsumskyfileArgs);
     PXOPT_ADD_MODE("-sumskyfile",      "list results of stackRun", STACKTOOL_MODE_SUMSKYFILE,      sumskyfileArgs);
+    PXOPT_ADD_MODE("-sassskyfile",      "list results of stackAssociation", STACKTOOL_MODE_SASSSKYFILE,      sassskyfileArgs);
     PXOPT_ADD_MODE("-revertsumskyfile","", STACKTOOL_MODE_REVERTSUMSKYFILE,      revertsumskyfileArgs);
     PXOPT_ADD_MODE("-pendingcleanuprun",     "show runs that need to be cleaned up", STACKTOOL_MODE_PENDINGCLEANUPRUN,    pendingcleanuprunArgs);
Index: branches/czw_branch/20100519/ippTools/src/staticskytool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/staticskytool.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/staticskytool.c	(revision 28304)
@@ -42,4 +42,6 @@
 static bool importrunMode(pxConfig *config);
 
+static bool setstaticskyRunState(pxConfig *config, psS64 sky_id, const char *state);
+
 # define MODECASE(caseName, func) \
     case caseName: \
@@ -129,4 +131,5 @@
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
+    PXOPT_LOOKUP_BOOL(check_inputs, config->args, "-check_inputs", false);
 
     psString select = pxDataGet("staticskytool_definebyquery_select.sql");
@@ -255,4 +258,16 @@
 	    psWarning("staticskytool ERROR: no rows found for known tess_id, skycell_id?");
 	    continue;
+	}
+
+	if (check_inputs) {
+	  // negative simple so the default is true
+	  if (!ippdbPrintMetadatas(stdout, inputs, "staticskyInput", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            psFree(where);
+            return false;
+	  }
+	  psFree(inputs);
+	  continue;
 	}
 
@@ -550,4 +565,14 @@
     }
 
+    if (!fault) {
+        if (!setstaticskyRunState(config, sky_id, "full")) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to change staticskyRun state");
+            return false;
+        }
+    }
+
     // point of no return
     if (!psDBCommit(config->dbh)) {
@@ -643,9 +668,8 @@
     PS_ASSERT_PTR_NON_NULL(config, false);
 
-# if (0)
     psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-stack_id", "stackSumSkyfile.stack_id", "==");
-    pxAddLabelSearchArgs(config, where, "-label", "stackRun.label", "==");
-    PXOPT_COPY_S16(config->args, where, "-fault", "stackSumSkyfile.fault", "==");
+    PXOPT_COPY_S64(config->args, where, "-sky_id", "staticskyResult.sky_id", "==");
+    pxAddLabelSearchArgs(config, where, "-label", "staticskyRun.label", "==");
+    PXOPT_COPY_S16(config->args, where, "-fault", "staticskyResult.fault", "==");
 
     if (!psListLength(where->list) && !psMetadataLookupBool(NULL, config->args, "-all")) {
@@ -656,5 +680,5 @@
 
     // Delete product
-    psString delete = pxDataGet("staticskytool_revertsumskyfile_delete.sql");
+    psString delete = pxDataGet("staticskytool_revert.sql");
     if (!delete) {
         psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
@@ -680,39 +704,17 @@
 
     psFree(where);
-# endif
-
     return true;
 }
 
-# if (0)
-static bool updateresultState(pxConfig *config)
-{
-    // check that state is a valid string value
-    if (!pxIsValidState(state)) {
-        psError(PS_ERR_UNKNOWN, false, "invalid stackRun state: %s", state);
-        return false;
-    }
-
-    char *query = "UPDATE stackRun SET state = '%s' WHERE stack_id = %"PRId64;
-    if (!p_psDBRunQueryF(config->dbh, query, state, stack_id)) {
-        psError(PS_ERR_UNKNOWN, false,
-                "failed to change state for stack_id %"PRId64, stack_id);
-        return false;
-    }
-    return true;
-}
-# endif
-
 static bool updateresult(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
 
-# if (0)
     PXOPT_LOOKUP_S16(fault, config->args, "-fault", true, false);
 
     psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-stack_id",   "stack_id",   "==");
-
-    if (!pxSetFaultCode(config->dbh, "stackSumSkyfile", where, fault)) {
+    PXOPT_COPY_S64(config->args, where, "-sky_id",   "sky_id",   "==");
+
+    if (!pxSetFaultCode(config->dbh, "staticskyResult", where, fault)) {
         psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
         psFree (where);
@@ -720,6 +722,4 @@
     }
     psFree (where);
-
-# endif
     return true;
 }
@@ -898,4 +898,23 @@
 # endif
   return true;
+}
+
+static bool setstaticskyRunState(pxConfig *config, psS64 sky_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!pxIsValidState(state)) {
+        psError(PS_ERR_UNKNOWN, false, "invalid staticskyRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE staticskyRun SET state = '%s' WHERE sky_id = %"PRId64;
+    if (!p_psDBRunQueryF(config->dbh, query, state, sky_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to change state for sky_id %"PRId64, sky_id);
+        return false;
+    }
+    return true;
+
 }
 
Index: branches/czw_branch/20100519/ippTools/src/staticskytoolConfig.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/staticskytoolConfig.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/staticskytoolConfig.c	(revision 28304)
@@ -61,4 +61,5 @@
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-set_registered", 0, "time detrend run was registered", now);
     psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-pretend",  0, "do not actually modify the database", false);
+    psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-check_inputs",  0, "list inputs, do not modify database", false);
     psMetadataAddBool(definebyqueryArgs, PS_LIST_TAIL, "-simple", 0, "use the simple output format", false);
 
Index: branches/czw_branch/20100519/ippTools/src/warptool.c
===================================================================
--- branches/czw_branch/20100519/ippTools/src/warptool.c	(revision 28245)
+++ branches/czw_branch/20100519/ippTools/src/warptool.c	(revision 28304)
@@ -430,5 +430,5 @@
     }
 
-    psString query = psStringCopy("UPDATE warpRun JOIN warpSkyfile USING(warp_id) JOIN fakeRun USING(fake_id) JOIN camRun USING(cam_id) JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)");
+    psString query = psStringCopy("UPDATE warpRun");
 
     // pxUpdateRun gets parameters from config->args and updates
