Index: /trunk/ippTools/scripts/camtest.sh
===================================================================
--- /trunk/ippTools/scripts/camtest.sh	(revision 14017)
+++ /trunk/ippTools/scripts/camtest.sh	(revision 14018)
@@ -8,4 +8,4 @@
 camtool -pendingimfile || exit 1
 
-camtool -addprocessedexp -cam_id 1 -uri file:///cam -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -sigma_ra 1 -sigma_dec 2 -nastro 42 -path_base file:///foo -zp_mean 1 -zp_stdev 2 || exit 1
-camtool -addprocessedexp -cam_id 2 -uri file:///cam -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -sigma_ra 1 -sigma_dec 2 -nastro 42 -path_base file:///foo -zp_mean 1 -zp_stdev 2 || exit 1
+camtool -addprocessedexp -cam_id 1 -uri file:///cam -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -sigma_ra 1 -sigma_dec 2 -zp_mean 10 -zp_stdev 2 -fwhm 42 -fwhm_range 100 -n_stars 2 -n_extended 0 -n_astrom 42 -n_cr 10000000 -path_base file:///foo || exit 1
+camtool -addprocessedexp -cam_id 2 -uri file:///cam -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -sigma_ra 1 -sigma_dec 2 -zp_mean 10 -zp_stdev 2 -fwhm 42 -fwhm_range 100 -n_stars 2 -n_extended 0 -n_astrom 42 -n_cr 10000000 -path_base file:///foo || exit 1
Index: /trunk/ippTools/scripts/chiptest.sh
===================================================================
--- /trunk/ippTools/scripts/chiptest.sh	(revision 14017)
+++ /trunk/ippTools/scripts/chiptest.sh	(revision 14018)
@@ -8,9 +8,9 @@
 
 for ID in `seq 0 3`; do
-    chiptool -addprocessedimfile -chip_id 1 -class_id $ID -uri file://chipp-t10.$ID -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base file:///foo || exit 1
+    chiptool -addprocessedimfile -chip_id 1 -exp_tag t10.1 -class_id $ID -uri file://chipp-t10.$ID -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base file:///foo || exit 1
 done;
 
 for ID in `seq 0 3`; do
-    chiptool -addprocessedimfile -chip_id 2 -class_id $ID -uri file://chipp-t11.$ID -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base file:///foo || exit 1
+    chiptool -addprocessedimfile -chip_id 2 -exp_tag t11.2 -class_id $ID -uri file://chipp-t11.$ID -bg 1 -bg_stdev 2 -bg_mean_stdev 3 -path_base file:///foo || exit 1
 done;
 
Index: /trunk/ippTools/scripts/difftest.sh
===================================================================
--- /trunk/ippTools/scripts/difftest.sh	(revision 14017)
+++ /trunk/ippTools/scripts/difftest.sh	(revision 14018)
@@ -12,5 +12,5 @@
 difftool -todiffskyfile || exit 1
 difftool -inputskyfile || exit 1
-difftool -adddiffskyfile -diff_id 1 -uri file:///tmp/diff/skyfile -bg 1 -bg_stdev 2 || exit 1
+difftool -adddiffskyfile -diff_id 1 -uri file:///tmp/diff/skyfile -path_base file://lalaland -bg 1 -bg_stdev 2 || exit 1
 difftool -diffskyfile -diff_id 1 || exit 1
 difftool -updaterun -state stop -diff_id 1 || exit 1
Index: /trunk/ippTools/scripts/regtest.sh
===================================================================
--- /trunk/ippTools/scripts/regtest.sh	(revision 14017)
+++ /trunk/ippTools/scripts/regtest.sh	(revision 14018)
@@ -11,12 +11,16 @@
 
 for ID in `seq 0 3`; do
-    $inject -newImfile -exp_tag $exp_tag1 -class OTA -class_id $ID -uri file://$ID || exit 1
+    $inject -newImfile -exp_tag $exp_tag1 -class_id $ID -uri file://$ID || exit 1
 done;
+
+$inject -updatenewExp -exp_tag $exp_tag1 -state run
 
 exp_tag2=`$inject -newExp -exp_id t11 -inst gpc -telescope ps1 -imfiles 4 -workdir file::///some/path -simple` || exit 1
 
 for ID in `seq 0 3`; do
-    $inject -newImfile -exp_tag $exp_tag2 -class OTA -class_id $ID -uri file://$ID || exit 1
+    $inject -newImfile -exp_tag $exp_tag2 -class_id $ID -uri file://$ID || exit 1
 done;
+
+$inject -updatenewExp -exp_tag $exp_tag2 -state run
 
 $regtool -pendingimfile || exit 1
Index: /trunk/ippTools/scripts/warptest.sh
===================================================================
--- /trunk/ippTools/scripts/warptest.sh	(revision 14017)
+++ /trunk/ippTools/scripts/warptest.sh	(revision 14018)
@@ -24,6 +24,6 @@
 warptool -towarped || exit 1
 
-warptool -addwarped -warp_id 1 -skycell_id foo1 -tess_id bar -uri file:///tmp/foo -bg 1 -bg_stdev 2 || exit 1
-warptool -addwarped -warp_id 1 -skycell_id foo2 -tess_id bar -uri file:///tmp/foo -bg 1 -bg_stdev 2 || exit 1
+warptool -addwarped -warp_id 1 -skycell_id foo1 -tess_id bar -uri file:///tmp/foo -path_base file://wonderland -bg 1 -bg_stdev 2 || exit 1
+warptool -addwarped -warp_id 1 -skycell_id foo2 -tess_id bar -uri file:///tmp/foo -path_base file://wonderland -bg 1 -bg_stdev 2 || exit 1
 
 warptool -warped -warp_id 1 || exit 1
Index: /trunk/ippTools/share/camtool_find_chip_id.sql
===================================================================
--- /trunk/ippTools/share/camtool_find_chip_id.sql	(revision 14018)
+++ /trunk/ippTools/share/camtool_find_chip_id.sql	(revision 14018)
@@ -0,0 +1,13 @@
+-- this query is used by both camtool -pendingexp & camtool -addprocessedexp it
+-- does a little more work then is necessary for -addprocessed but it seems
+-- "cleaner" to use the same query for both cases 
+SELECT
+    *
+FROM
+    (SELECT DISTINCT
+        chipRun.*
+    FROM chipRun
+    JOIN chipProcessedExp
+        USING(chip_id)
+    WHERE
+        chipRun.state = 'stop') as Foo
Index: /trunk/ippTools/share/camtool_find_pendingexp.sql
===================================================================
--- /trunk/ippTools/share/camtool_find_pendingexp.sql	(revision 14017)
+++ /trunk/ippTools/share/camtool_find_pendingexp.sql	(revision 14018)
@@ -3,5 +3,5 @@
 -- "cleaner" to use the same query for both cases 
 SELECT
-    camPendingExp.*,
+    camRun.*,
     rawExp.exp_tag,
     rawExp.exp_id,
@@ -9,14 +9,18 @@
     rawExp.telescope,
     rawExp.filelevel
-FROM camPendingExp
-JOIN chipProcessedExp
+FROM camRun
+JOIN chipRun
+    USING(chip_id)
+JOIN chipProcessedImfile
     USING(chip_id)
 JOIN rawExp
-    ON chipProcessedExp.exp_tag = rawExp.exp_tag
+    ON chipProcessedImfile.exp_tag = rawExp.exp_tag
 LEFT JOIN camProcessedExp
-    ON camPendingExp.cam_id = camProcessedExp.cam_id
+    ON camRun.cam_id = camProcessedExp.cam_id
 LEFT JOIN camMask
-    ON camPendingExp.label = camMask.label
+    ON camRun.label = camMask.label
 WHERE
-    camProcessedExp.cam_id IS NULL
+    chipRun.state = 'stop'
+    AND camRun.state = 'run'
     AND camMask.label IS NULL
+    AND camProcessedExp.cam_id IS NULL
Index: /trunk/ippTools/share/camtool_queue_chip_id.sql
===================================================================
--- /trunk/ippTools/share/camtool_queue_chip_id.sql	(revision 14017)
+++ /trunk/ippTools/share/camtool_queue_chip_id.sql	(revision 14018)
@@ -1,14 +1,17 @@
 -- camtool only operates on exposures so we can safely queue more then one at a
 -- time without worrying about losing the track of the generated cam_id
-INSERT INTO camPendingExp
+INSERT INTO camRun
     SElECT
         0,              -- cam_id
         chip_id,        -- chip_id
+        '%s',           -- state
         '%s',           -- workdir
+        '%s',           -- workdir_state
         '%s',           -- label
-        '%s',           -- recipe
+        '%s',           -- reduction
         '%s',           -- expgroup
         '%s'            -- dvodb 
-    FROM chipProcessedExp
+    FROM chipRun
     WHERE
-        chipProcessedExp.chip_id = %lld
+        chipRun.state = 'stop'
+        AND chipRun.chip_id = %lld
Index: /trunk/ippTools/share/chiptool_completely_processed_exp.sql
===================================================================
--- /trunk/ippTools/share/chiptool_completely_processed_exp.sql	(revision 14017)
+++ /trunk/ippTools/share/chiptool_completely_processed_exp.sql	(revision 14018)
@@ -1,26 +1,31 @@
--- select * from chipPendingExp
--- where exp_tag is not in chipProcessedExp
--- where exp_tag is not in chipPendingImfile
--- where the number of entries in chipProccessedImfile matches the .imfiles
--- entry in rawExp
+-- the output of this query must match the format of chipRun row
 SELECT DISTINCT
-    chipPendingExp.*,
-    rawExp.imfiles,
-    chipProcessedImfile.class_id
-FROM chipPendingExp
-JOIN rawExp
-    ON chipPendingExp.exp_tag = rawExp.exp_tag
-LEFT JOIN chipProcessedExp
-    ON chipPendingExp.chip_id = chipProcessedExp.chip_id
-LEFT JOIN chipPendingImfile
-    ON chipPendingExp.chip_id = chipPendingImfile.chip_id
-LEFT JOIN chipProcessedImfile
-    ON chipPendingExp.chip_id = chipProcessedImfile.chip_id
-WHERE
-    chipProcessedExp.chip_id IS NULL
-    AND chipPendingImfile.chip_id IS NULL
-    AND chipProcessedImfile.chip_id IS NOT NULL
-    AND chipProcessedImfile.fault = 0
-GROUP BY
-    chipPendingExp.chip_id
-HAVING rawExp.imfiles = COUNT(chipProcessedImfile.class_id)
+    chip_id,
+    state,
+    workdir,
+    workdir_state,
+    label,
+    reduction,
+    expgroup,
+    dvodb
+FROM
+    (SELECT 
+        chipRun.*,
+        rawExp.imfiles,
+        chipProcessedImfile.class_id
+    FROM chipRun
+    JOIN chipInputImfile
+        USING(chip_id)
+    JOIN rawExp
+        ON chipInputImfile.exp_tag = rawExp.exp_tag
+    JOIN chipProcessedImfile
+        ON chipInputImfile.chip_id = chipProcessedImfile.chip_id
+        AND chipInputImfile.exp_tag = chipProcessedImfile.exp_tag
+        AND chipInputImfile.class_id = chipProcessedImfile.class_id
+    WHERE
+        chipRun.state = 'run'
+        AND chipProcessedImfile.fault = 0
+    GROUP BY
+        chipInputImfile.chip_id,
+        chipInputImfile.exp_tag
+    HAVING rawExp.imfiles = COUNT(chipProcessedImfile.class_id)) as Foo
Index: /trunk/ippTools/share/chiptool_find_unprocessed_imfile.pl
===================================================================
--- /trunk/ippTools/share/chiptool_find_unprocessed_imfile.pl	(revision 14017)
+++ /trunk/ippTools/share/chiptool_find_unprocessed_imfile.pl	(revision 14018)
@@ -1,5 +1,5 @@
 SELECT DISTINCT
-   chipPendingImfile.*
-FROM chipPendingImfile
+   chipInputImfile.*
+FROM chipInputImfile
 LEFT JOIN chipProcessedImfile
     USING(chip_id, class_id)
Index: /trunk/ippTools/share/chiptool_pendingimfile.sql
===================================================================
--- /trunk/ippTools/share/chiptool_pendingimfile.sql	(revision 14017)
+++ /trunk/ippTools/share/chiptool_pendingimfile.sql	(revision 14018)
@@ -1,17 +1,29 @@
 SELECT
-    chipPendingExp.*,
-    chipPendingImfile.class_id,
-    chipPendingImfile.uri,
+    chipRun.*,
+    chipInputImfile.exp_tag,
+    chipInputImfile.class_id,
+    rawImfile.uri,
     rawExp.exp_id,
     rawExp.camera,
     rawExp.telescope,
     rawExp.filelevel
-FROM chipPendingImfile
-JOIN chipPendingExp
+FROM chipRun
+JOIN chipInputImfile
     USING(chip_id)
+LEFT JOIN chipProcessedImfile
+    ON chipInputImfile.chip_id = chipProcessedImfile.chip_id
+    AND chipInputImfile.exp_tag = chipProcessedImfile.exp_tag
+    AND chipInputImfile.class_id = chipProcessedImfile.class_id
+JOIN rawImfile
+    ON chipInputImfile.exp_tag = rawImfile.exp_tag
+    AND chipInputImfile.class_id = rawImfile.class_id
 JOIN rawExp
-    ON chipPendingExp.exp_tag = rawExp.exp_tag
+    ON rawImfile.exp_tag = rawExp.exp_tag
 LEFT JOIN chipMask
-    ON chipPendingExp.label = chipMask.label
+    ON chipRun.label = chipMask.label
 WHERE
-    chipMask.label IS NULL
+    chipRun.state = 'run'
+    AND chipProcessedImfile.chip_id IS NULL
+    AND chipProcessedImfile.exp_tag IS NULL
+    AND chipProcessedImfile.class_id IS NULL
+    AND chipMask.label IS NULL
Index: unk/ippTools/share/chiptool_queuerawexp.sql
===================================================================
--- /trunk/ippTools/share/chiptool_queuerawexp.sql	(revision 14017)
+++ 	(revision )
@@ -1,16 +1,0 @@
--- we can only enqueue one exp_tag at a time or the generated chip_id of all
--- put the last one inserted will be lost
-INSERT INTO chipPendingExp
-    SElECT
-        0,              -- chip_id
-        exp_tag,        -- exp_tag
-        0xdeadbeef,     -- guide_id
-        '%s',           -- workdir
-        '%s',           -- label
-        '%s',           -- recipe
-        '%s',           -- expgroup
-        '%s'            -- dvodb 
-   FROM rawExp
-   WHERE
-        rawExp.fault = 0
-        AND rawExp.exp_tag = '%s'
Index: /trunk/ippTools/share/chiptool_queuerawimfile.sql
===================================================================
--- /trunk/ippTools/share/chiptool_queuerawimfile.sql	(revision 14017)
+++ /trunk/ippTools/share/chiptool_queuerawimfile.sql	(revision 14018)
@@ -1,11 +1,13 @@
-INSERT INTO chipPendingImfile
+INSERT INTO chipInputImfile
     SELECT
-        chipPendingExp.chip_id,
-        rawImfile.class_id,
-        rawImfile.uri
-    FROM chipPendingExp
-    JOIN rawImfile
+        LAST_INSERT_ID(),
+        rawImfile.exp_tag,
+        rawImfile.class_id
+    FROM rawImfile
+    JOIN newExp
         USING(exp_tag)
     WHERE
         rawImfile.fault = 0
-        AND chipPendingExp.chip_id = LAST_INSERT_ID()
+        AND newExp.state = 'stop'
+        AND rawImfile.exp_tag = '%s'
+
Index: /trunk/ippTools/share/regtool_find_unprocessed_exp.sql
===================================================================
--- /trunk/ippTools/share/regtool_find_unprocessed_exp.sql	(revision 14017)
+++ /trunk/ippTools/share/regtool_find_unprocessed_exp.sql	(revision 14018)
@@ -1,15 +1,16 @@
-SELECT
-   newExp.*
-FROM newExp
-LEFT JOIN newImfile
-   USING(exp_tag)
-LEFT JOIN rawExp
-   USING(exp_tag)
+SELECT DISTINCT * FROM
+    (SELECT
+       newExp.*
+    FROM newExp
+    JOIN newImfile
+       USING(exp_tag)
+    LEFT JOIN rawExp
+       USING(exp_tag)
+    WHERE
+        newExp.state = 'run'
+        AND rawExp.exp_tag IS NULL
+        AND newExp.imfiles =
+        (SELECT COUNT(exp_tag) FROM rawImfile
+            WHERE rawImfile.exp_tag = newExp.exp_tag)) as Foo
 WHERE
-    newExp.exp_tag IS NOT NULL
-    AND newImfile.exp_tag IS NULL
-    AND rawExp.exp_tag IS NULL
-    AND newExp.imfiles =
-    (SELECT COUNT(exp_tag) FROM rawImfile
-        WHERE rawImfile.exp_tag = newExp.exp_tag)
-    AND newExp.exp_tag = '%s'
+    exp_tag = '%s'
Index: /trunk/ippTools/share/regtool_find_unprocessed_imfile.sql
===================================================================
--- /trunk/ippTools/share/regtool_find_unprocessed_imfile.sql	(revision 14017)
+++ /trunk/ippTools/share/regtool_find_unprocessed_imfile.sql	(revision 14018)
@@ -1,8 +1,11 @@
-SELECT
-    *
-FROM
-    (SELECT newImfile.* FROM newImfile
-        LEFT JOIN newExp USING(exp_tag)
-        LEFT JOIN rawExp USING(exp_tag)
-        WHERE newExp.exp_tag IS NOT NULL
+SELECT DISTINCT * FROM
+    (SELECT
+        newImfile.*
+    FROM newImfile
+    JOIN newExp
+        USING(exp_tag)
+    LEFT JOIN rawExp
+        USING(exp_tag)
+    WHERE
+        newExp.state = 'run'
         AND rawExp.exp_tag IS NULL) as Foo
Index: /trunk/ippTools/share/regtool_pendingexp.sql
===================================================================
--- /trunk/ippTools/share/regtool_pendingexp.sql	(revision 14017)
+++ /trunk/ippTools/share/regtool_pendingexp.sql	(revision 14018)
@@ -2,10 +2,10 @@
     newExp.*
 FROM newExp
-LEFT JOIN newImfile
+JOIN newImfile
     USING(exp_tag)
 LEFT JOIN rawExp
     USING(exp_tag)
 WHERE
-    newImfile.exp_tag IS NULL
+    newExp.state = 'run'
     AND rawExp.exp_tag IS NULL
     AND newExp.imfiles =
Index: /trunk/ippTools/src/Makefile.am
===================================================================
--- /trunk/ippTools/src/Makefile.am	(revision 14017)
+++ /trunk/ippTools/src/Makefile.am	(revision 14018)
@@ -15,6 +15,14 @@
 	pztool 
 
-include_HEADERS = \
+pkginclude_HEADERS = \
 	pxtoolsErrorCodes.h \
+	pxadmin.h \
+	pxdata.h \
+	pxio.h \
+	pxtag.h \
+	pxregister.h \
+	pxchip.h \
+	pxcam.h \
+	pxconfig.h \
 	pxtools.h
 
@@ -29,9 +37,5 @@
 	difftool.h \
 	stacktool.h \
-	pxadmin.h \
 	pxinject.h \
-	pxdata.h \
-	pxio.h \
-	pxtag.h \
 	pzgetexp.h \
 	pzgetimfiles.h \
@@ -51,6 +55,7 @@
 	pxio.c \
 	pxtag.c \
-	chipqueue.c \
-	camqueue.c
+	pxregister.c \
+	pxchip.c \
+	pxcam.c
 
 # for pxtools.h
Index: unk/ippTools/src/camqueue.c
===================================================================
--- /trunk/ippTools/src/camqueue.c	(revision 14017)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * camqueue.c
- *
- * Copyright (C) 2007  Joshua Hoblitt
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "pxtools.h"
-#include "pxdata.h"
-#include "camtool.h"
-
-bool camQueueChipID(pxConfig *config,
-                    psS64 chip_id,
-                    psString workdir,
-                    psString label,
-                    psString recipe,
-                    psString expgroup,
-                    psString dvodb)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    // load the SQL to enqueue our exp_tags from disk once
-    static psString query = NULL;
-    if (!query) {
-        query = pxDataGet("camtool_queue_chip_id.sql");
-        psMemSetPersistent(query, true);
-        if (!query) {
-            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-            return false;
-        }
-    }
-
-    // queue the exp
-    // XXX chip_id is being cast here work around psS64 have a different type
-    // different on 32/64
-    if (!p_psDBRunQuery(config->dbh, query,
-                workdir  ? workdir  : "NULL",
-                label    ? label    : "NULL",
-                recipe   ? recipe   : "NULL",
-                expgroup ? expgroup : "NULL",
-                dvodb    ? dvodb    : "NULL",
-                (long long)chip_id
-    )) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
-    // just to be safe, we should have changed at least one row
-    if (psDBAffectedRows(config->dbh) < 1) {
-        psError(PS_ERR_UNKNOWN, false,
-                "no rows affected - should have changed at least one row");
-        return false;
-    }
-
-    return true;
-}
Index: /trunk/ippTools/src/camtool.c
===================================================================
--- /trunk/ippTools/src/camtool.c	(revision 14017)
+++ /trunk/ippTools/src/camtool.c	(revision 14018)
@@ -203,8 +203,13 @@
 
     // find the chipProcessedExp exposures that we want to queue up.
-    psString query = psStringCopy("SELECT * FROM chipProcessedExp");
+//    psString query = psStringCopy("SELECT * FROM chipRun WHERE chipRun.state = 'stop'");
+    psString query = pxDataGet("camtool_find_chip_id.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
 
     if (where) {
-        psString whereClause = psDBGenerateWhereSQL(where, "chipProcessedExp");
+        psString whereClause = psDBGenerateWhereSQL(where, "");
         psFree(where);
         psStringAppend(&query, " %s", whereClause);
@@ -245,7 +250,7 @@
         psMetadata *md = output->data[i];
 
-        chipProcessedExpRow *row = chipProcessedExpObjectFromMetadata(md);
+        chipRunRow *row = chipRunObjectFromMetadata(md);
         if (!row) {
-            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into chipProcessedExp");
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into chipRun");
             psFree(output);
             return false;
@@ -253,5 +258,5 @@
 
         // queue the exp
-        if (!camQueueChipID(config,
+        if (!pxcamQueueByChipID(config,
                     row->chip_id,
                     workdir     ? workdir   : row->workdir,
@@ -601,6 +606,4 @@
     }
 
-    // start a transaction so we don't end up with an exp_tag is both
-    // camPendingExp & camProcessedExp
     if (!psDBTransaction(config->dbh)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
@@ -609,5 +612,5 @@
     }
 
-    camPendingExpRow *pendingRow = camPendingExpObjectFromMetadata(output->data[0]);
+    camRunRow *pendingRow = camRunObjectFromMetadata(output->data[0]);
     psFree(output);
     // create a new camProcessedImfile object
@@ -615,9 +618,4 @@
         pendingRow->cam_id,
         pendingRow->chip_id,
-        pendingRow->workdir,
-        pendingRow->label,
-        pendingRow->reduction,
-        pendingRow->expgroup,
-        pendingRow->dvodb,
         uri,
         bg,
@@ -637,4 +635,5 @@
         code
     );
+    psFree(pendingRow);
 
     // insert the new row into the camProcessedImfile table
@@ -646,23 +645,16 @@
         psError(PS_ERR_UNKNOWN, false, "database error");
         psFree(row);
-        psFree(pendingRow);
-        return false;
-    }
+        return false;
+    }
+
+    // since there is only one exp per 'run' set camRun.state = 'stop'
+    if (!pxcamRunSetState(config, row->cam_id, "stop")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to change camRun.state for cam_id: %" PRId64, row->cam_id);
+        psFree(row);
+        return false;
+    }
+
     psFree(row);
 
-    // delete the camPendingExp row from the database
-    if (!camPendingExpDeleteObject(config->dbh, pendingRow)) {
-        // rollback
-        if (!psDBRollback(config->dbh)) {
-            psError(PS_ERR_UNKNOWN, false, "database error");
-        }
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(pendingRow);
-        return false;
-    }
-
-    psFree(pendingRow);
-
-    // point of no return for camPendingExp -> camProcessedExp
     if (!psDBCommit(config->dbh)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
Index: /trunk/ippTools/src/camtool.h
===================================================================
--- /trunk/ippTools/src/camtool.h	(revision 14017)
+++ /trunk/ippTools/src/camtool.h	(revision 14018)
@@ -38,11 +38,3 @@
 pxConfig *camtoolConfig(pxConfig *config, int argc, char **argv);
 
-bool camQueueChipID(pxConfig *config,
-                    psS64 chip_id,
-                    psString workdir,
-                    psString label,
-                    psString recipe,
-                    psString expgroup,
-                    psString dvodb);
-
 #endif // CAMTOOL_H
Index: unk/ippTools/src/chipqueue.c
===================================================================
--- /trunk/ippTools/src/chipqueue.c	(revision 14017)
+++ 	(revision )
@@ -1,93 +1,0 @@
-/*
- * chipqueue.c
- *
- * Copyright (C) 2007  Joshua Hoblitt
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * program; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "pxtools.h"
-#include "pxdata.h"
-#include "chiptool.h"
-
-bool chipQueueExpTag(pxConfig *config,
-                     psString exp_tag,
-                     psString workdir,
-                     psString label,
-                     psString recipe,
-                     psString expgroup,
-                     psString dvodb)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    // load the SQL to enqueue our exp_tags from disk once
-    static psString queuerawexp_query = NULL;
-    if (!queuerawexp_query) {
-        queuerawexp_query = pxDataGet("chiptool_queuerawexp.sql");
-        psMemSetPersistent(queuerawexp_query, true);
-        if (!queuerawexp_query) {
-            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-            return false;
-        }
-    }
-
-    static psString queuerawimfile_query = NULL;
-    if (!queuerawimfile_query) {
-        queuerawimfile_query = pxDataGet("chiptool_queuerawimfile.sql");
-        psMemSetPersistent(queuerawimfile_query, true);
-        if (!queuerawexp_query) {
-            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-            return false;
-        }
-    }
-
-    // queue the exp
-    if (!p_psDBRunQuery(config->dbh, queuerawexp_query,
-                workdir  ? workdir  : "NULL",
-                label    ? label    : "NULL",
-                recipe   ? recipe   : "NULL",
-                expgroup ? expgroup : "NULL",
-                dvodb    ? dvodb    : "NULL",
-                exp_tag
-    )) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
-    // just to be safe, we should have changed at least one row
-    if (psDBAffectedRows(config->dbh) < 1) {
-        psError(PS_ERR_UNKNOWN, false,
-                "no rows affected - should have changed at least one row");
-        return false;
-    }
-
-    // queue the imfiles for the exp we just queued
-    if (!p_psDBRunQuery(config->dbh, queuerawimfile_query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
-    // just to be safe, we should have changed at least one row
-    if (psDBAffectedRows(config->dbh) < 1) {
-        psError(PS_ERR_UNKNOWN, false,
-                "no rows affected - should have changed at least one row");
-        return false;
-    }
-
-    return true;
-}
Index: /trunk/ippTools/src/chiptool.c
===================================================================
--- /trunk/ippTools/src/chiptool.c	(revision 14017)
+++ /trunk/ippTools/src/chiptool.c	(revision 14018)
@@ -30,4 +30,5 @@
 #include "pxtools.h"
 #include "pxdata.h"
+
 #include "chiptool.h"
 #include "camtool.h"
@@ -42,6 +43,4 @@
 static bool unblockMode(pxConfig *config);
 
-static chipProcessedImfileRow *chipPendingToProcessedImfile(pxConfig *config, chipPendingImfileRow *imfile);
-static chipProcessedExpRow *chipPendingToProcessedExp(pxConfig *config, chipPendingExpRow *pendingExp);
 static bool chipProcessedCompleteExp(pxConfig *config);
 
@@ -243,5 +242,5 @@
 
         // queue the exp
-        if (!chipQueueExpTag(config, exp_tag, workdir, label, reduction, expgroup, dvodb)) {
+        if (!pxchipQueueByExpTag(config, exp_tag, workdir, label, reduction, expgroup, dvodb)) {
             if (!psDBRollback(config->dbh)) {
                 psError(PS_ERR_UNKNOWN, false, "database error");
@@ -283,5 +282,5 @@
 
     if (config->where) {
-        psString whereClause = psDBGenerateWhereConditionSQL(config->where, "chipPendingImfile");
+        psString whereClause = psDBGenerateWhereConditionSQL(config->where, "chipInputImfile");
         psStringAppend(&query, " AND %s", whereClause);
         psFree(whereClause);
@@ -330,5 +329,5 @@
 
     // negative simple so the default is true
-    if (!ippdbPrintMetadatas(stdout, output, "chipPendingImfile", !simple)) {
+    if (!ippdbPrintMetadatas(stdout, output, "chipInputImfile", !simple)) {
         psError(PS_ERR_UNKNOWN, false, "failed to print array");
         psFree(output);
@@ -346,491 +345,36 @@
     PS_ASSERT_PTR_NON_NULL(config, false);
 
-    // select * from chipProcessedImfiles
-    // where
-    // exp_tag & class_id are not in chipPendingImfile
-
-    // add the completed imfile to
-    // the chipProcessedeImfile tables
-    // remove corresponding entries from the
-    // chipPendingImfile table
-    // check to see if any chipPendingExps have no
-    // associated chipPendingImfiles
-    // if so move the chipPendingExp(s) to chipProcessedExp
-
-    psString query = pxDataGet("chiptool_find_unprocessed_imfile.pl");
-    if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
-    {
-        psMetadata *where = psMetadataAlloc();
-        bool status = false;
-        psString chip_id = psMetadataLookupStr(&status, config->args, "-chip_id");        if (!status) {
-            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -chip_id");
-            psFree(query);
-            return false;
-        }
-        if (chip_id) {
-            if (!psMetadataAddStr(where, PS_LIST_TAIL, "chip_id", 0, "==", chip_id)) {
-                psError(PS_ERR_UNKNOWN, false, "failed to add item chip_id");
-                psFree(where);
-                psFree(query);
-                return false;
-            }
-        }
-
-        psString class_id = psMetadataLookupStr(&status, config->args, "-class_id");
-        if (!status) {
-            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -class_id");
-            psFree(query);
-            return false;
-        }
-        if (class_id) {
-            if (!psMetadataAddStr(where, PS_LIST_TAIL, "class_id", 0, "==", class_id)) {
-                psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
-                psFree(where);
-                psFree(query);
-                return false;
-            }
-        }
-
-        psString whereClause = psDBGenerateWhereConditionSQL(config->where, "chipPendingImfile");
-        psFree(where);
-        if (whereClause) {
-            psStringAppend(&query, " AND %s", whereClause);
-            psFree(whereClause);
-        }
-    }
-
-    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)) {
-        // XXX check psError here
-        psError(PS_ERR_UNKNOWN, false, "no chipPendingImfile rows found");
-        psFree(output);
-        return false;
-    }
-
-    // start a transaction so we don't end up with an incremented iteration
-    // count but no detInputExps
-    if (!psDBTransaction(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(output);
-        return false;
-    }
-
-    // insert into chipProcessedImfile
-    // remove chipPendingImfile entry
-    for (long i = 0; i < psArrayLength(output); i++) {
-        psMetadata *row = output->data[i];
-        // convert metadata into a chipPendingImfile object
-        chipPendingImfileRow *object = chipPendingImfileObjectFromMetadata(row);
-        // convert chipPendingImfile object into a chipProcessedImfile object
-        chipProcessedImfileRow *imfile = chipPendingToProcessedImfile(config, object);
-        if (!imfile) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "failed to convert chipPendingImfile to chipProcessedImfile");
-            psFree(object);
-            psFree(output);
-            return false;
-        }
-        // insert chipProccessedImfile object into the database
-        if (!chipProcessedImfileInsertObject(config->dbh, imfile)) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(imfile);
-            psFree(object);
-            psFree(output);
-            return false;
-        }
-        psFree(imfile);
-        // delete the chipPendingImfile object from the database
-        if (!chipPendingImfileDeleteObject(config->dbh, object)) {
-            // there must be atleast 1 Imfile to get this far
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(object);
-            psFree(output);
-            return false;
-        }
-        psFree(object);
-    }
-
-    psFree(output);
-
-    // XXX I've decided to make the transaction cover the Exp migration as
-    // well.  Otherwise, if the last imfile in an exp is moved and the exp
-    // migration fails then the data base is left in a satuation where the exp
-    // migration can't happen.
-
-    if (!chipProcessedCompleteExp(config)) {
-        // rollback
-        if (!psDBRollback(config->dbh)) {
-            psError(PS_ERR_UNKNOWN, false, "database error");
-        }
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
-    // point of no return for chipPendingImfile -> chipProcessedImfile
-    // point of no return for chipPendingExp -> chipProcessedExp
-    if (!psDBCommit(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
-    return true;
-}
-
-
-static bool processedimfileMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, NULL);
-
     bool status = false;
-    psU64 limit = psMetadataLookupU64(&status, config->args, "-limit");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -limit");
-        return false;
-    }
-
-    bool faulted = psMetadataLookupU64(&status, config->args, "-faulted");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -faulted");
-        return false;
-    }
-
-    // XXX does this need to be constrained so that it won't return any results
-    // if a match chipPendingExp hasn't been registered?
-    psString query = pxDataGet("chiptool_processedimfile.sql");
-    if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
-    if (config->where) {
-        psString whereClause = psDBGenerateWhereConditionSQL(config->where, "chipProcessedImfile");
-        psStringAppend(&query, " AND %s", whereClause);
-        psFree(whereClause);
-    }
-
-    if (faulted) {
-        // list only faulted rows
-        psStringAppend(&query, " %s", "AND chipProcessedImfile.fault != 0");
-    } else {
-        // don't list faulted rows
-        psStringAppend(&query, " %s", "AND chipProcessedImfile.fault = 0");
-    }
-
-    // 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("chiptool", PS_LOG_INFO, "no rows found");
-        psFree(output);
-        return true;
-    }
-
-    bool simple = false;
-    {
-        bool status = false;
-        simple = psMetadataLookupBool(&status, config->args, "-simple");
-        if (!status) {
-            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -simple");
-            return false;
-        }
-    }
-
-    if (!convertIdToStr(output)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to convert id fields into a strings");
-        psFree(output);
-        return false;
-    }
-
-    // negative simple so the default is true
-    if (!ippdbPrintMetadatas(stdout, output, "chipProcessedImfile", !simple)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to print array");
-        psFree(output);
-        return false;
-    }
-
-    psFree(output);
-
-    return true;
-}
-
-
-static bool updateprocessedimfileMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    bool status = false;
-    psS16 code = psMetadataLookupS16(&status, config->args, "-code");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -code");
-        return false;
-    }
-    if (code == INT16_MAX) {
-        psError(PS_ERR_UNKNOWN, true, "-code is required");
-        return false;
-    }
-
-    if (!pxSetFaultCode(config->dbh, "chipProcessedImfile", config->where, code)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
-        return false;
-    }
-
-    return true;
-}
-
-
-static bool blockMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    bool status = false;
-    psString label = psMetadataLookupStr(&status, config->args, "-label");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -label");
-        return false;
-    }
-    if (!label) {
-        psError(PS_ERR_UNKNOWN, true, "-label is required");
-        return false;
-    }
-
-    if (!chipMaskInsert(config->dbh, label)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
-    return true;
-}
-
-
-static bool maskedMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    psString query = psStringCopy("SELECT * FROM chipMask");
-
-    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("chiptool", PS_LOG_INFO, "no rows found");
-        psFree(output);
-        return true;
-    }
-
-    bool simple = false;
-    {
-        bool status = false;
-        simple = psMetadataLookupBool(&status, config->args, "-simple");
-        if (!status) {
-            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -simple");
-            return false;
-        }
-    }
-
-    if (!convertIdToStr(output)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to convert id fields into a strings");
-        psFree(output);
-        return false;
-    }
-
-    // negative simple so the default is true
-    if (!ippdbPrintMetadatas(stdout, output, "chipMask", !simple)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to print array");
-        psFree(output);
-        return false;
-    }
-
-    psFree(output);
-
-    return true;
-}
-
-
-static bool unblockMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    bool status = false;
-    psString label = psMetadataLookupStr(&status, config->args, "-label");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -label");
-        return false;
-    }
-    if (!label) {
-        psError(PS_ERR_UNKNOWN, true, "-label is required");
-        return false;
-    }
-
-    char *query = "DELETE FROM chipMask WHERE label = '%s'";
-
-    if (!p_psDBRunQuery(config->dbh, query, label)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(query);
-        return false;
-    }
-
-    return true;
-}
-
-
-static bool chipProcessedCompleteExp(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    // look for completed chipPendingExp
-    // migrate them to chipProccessedExp & camPendingExp
-    psString query = pxDataGet("chiptool_completely_processed_exp.sql");
-    if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
-    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("chiptool", PS_LOG_INFO, "no rows found");
-        psFree(output);
-        return true;
-    }
-
-    // insert into chipProcessedExp
-    // insert into camPendingExp
-    // remove chipPendingExp entry
-    for (long i = 0; i < psArrayLength(output); i++) {
-        psMetadata *row = output->data[i];
-
-        // convert metadata into a chipPendingExp object
-        chipPendingExpRow *pendingExp = chipPendingExpObjectFromMetadata(row);
-        if (!pendingExp) {
-            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into chipPendingExp");
-            psFree(output);
-            return false;
-        }
-
-        // convert chipPendingExp object into a chipProcesseExp object
-        chipProcessedExpRow *processedExp = chipPendingToProcessedExp(config, pendingExp);
-        if (!processedExp) {
-            psError(PS_ERR_UNKNOWN, false, "failed to convert chipPendingExp to chipProcessedExp");
-            psFree(pendingExp);
-            psFree(output);
-            return false;
-        }
-
-        // delete the chipPendingExp object from the database
-        if (!chipPendingExpDeleteObject(config->dbh, pendingExp)) {
-            // there must be atleast 1 Imfile to get this far
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(processedExp);
-            psFree(pendingExp);
-            psFree(output);
-            return false;
-        }
-        psFree(pendingExp);
-
-        // insert chipProccessedExp object into the database
-        if (!chipProcessedExpInsertObject(config->dbh, processedExp)) {
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(processedExp);
-            psFree(output);
-            return false;
-        }
-
-        // camQueueChipID() can only be run after the chipProcessedExp entry
-        // has been inserted.
-        // queue the chip_id in the camPendingExp table
-        if (!camQueueChipID(config,
-                    processedExp->chip_id,
-                    processedExp->workdir,
-                    processedExp->label,
-                    processedExp->reduction,
-                    processedExp->expgroup,
-                    processedExp->dvodb
-        )) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "failed to queue camPendingExp");
-            psFree(processedExp);
-            psFree(output);
-            return false;
-        }
-
-        psFree(processedExp);
-    }
-
-    psFree(output);
-
-    return true;
-}
-
-
-static chipProcessedImfileRow *chipPendingToProcessedImfile(pxConfig *config, chipPendingImfileRow *imfile)
-{
-    PS_ASSERT_PTR_NON_NULL(config, NULL);
-    PS_ASSERT_PTR_NON_NULL(imfile, NULL);
-
-    bool status = false;
+    // chip_id, ext_tag, class_id are required
+    psString chip_id = psMetadataLookupStr(&status, config->args, "-chip_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -chip_id");
+        return false;
+    }
+    if (!chip_id) {
+        psError(PS_ERR_UNKNOWN, true, "-chip_id is required");
+        return false;
+    }
+
+    psString exp_tag = psMetadataLookupStr(&status, config->args, "-exp_tag");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -exp_tag");
+        return false;
+    }
+    if (!exp_tag) {
+        psError(PS_ERR_UNKNOWN, true, "-exp_tag is required");
+        return false;
+    }
+
+    psString class_id = psMetadataLookupStr(&status, config->args, "-class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -class_id");
+        return false;
+    }
+    if (!class_id) {
+        psError(PS_ERR_UNKNOWN, true, "-class_id is required");
+        return false;
+    }
+
     psString uri = psMetadataLookupStr(&status, config->args, "-uri");
     if (!status) {
@@ -961,7 +505,13 @@
     }
 
-    return chipProcessedImfileRowAlloc(
-        imfile->chip_id,
-        imfile->class_id,
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    chipProcessedImfileRow *imfile = chipProcessedImfileRowAlloc(
+        (psU64)atoll(chip_id),
+        exp_tag,
+        class_id,
         uri,
         bg,
@@ -985,21 +535,335 @@
         path_base,
         code
-        );
-}
-
-
-static chipProcessedExpRow *chipPendingToProcessedExp(pxConfig *config, chipPendingExpRow *pendingExp)
+    );
+    if (!imfile) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "failed to alloc chipProcessedImfileRow object");
+        return false;
+    }
+    if (!chipProcessedImfileInsertObject(config->dbh, imfile)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(imfile);
+        return false;
+    }
+
+
+
+    // XXX I've decided to make the transaction cover the Exp migration as
+    // well.  Otherwise, if the last imfile in an exp is moved and the exp
+    // migration fails then the data base is left in a satuation where the exp
+    // migration can't happen.
+
+    if (!chipProcessedCompleteExp(config)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool processedimfileMode(pxConfig *config)
 {
-    PS_ASSERT_PTR_NON_NULL(pendingExp, NULL);
-
-    return chipProcessedExpRowAlloc(
-        pendingExp->chip_id,
-        pendingExp->exp_tag,
-        pendingExp->guide_id,
-        pendingExp->workdir,
-        pendingExp->label,
-        pendingExp->reduction,
-        pendingExp->expgroup,
-        pendingExp->dvodb
-    );
-}
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    bool status = false;
+    psU64 limit = psMetadataLookupU64(&status, config->args, "-limit");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -limit");
+        return false;
+    }
+
+    bool faulted = psMetadataLookupU64(&status, config->args, "-faulted");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -faulted");
+        return false;
+    }
+
+    // XXX does this need to be constrained so that it won't return any results
+    // if a match chipPendingExp hasn't been registered?
+    psString query = pxDataGet("chiptool_processedimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (config->where) {
+        psString whereClause = psDBGenerateWhereConditionSQL(config->where, "chipProcessedImfile");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (faulted) {
+        // list only faulted rows
+        psStringAppend(&query, " %s", "AND chipProcessedImfile.fault != 0");
+    } else {
+        // don't list faulted rows
+        psStringAppend(&query, " %s", "AND chipProcessedImfile.fault = 0");
+    }
+
+    // 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("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    bool simple = false;
+    {
+        bool status = false;
+        simple = psMetadataLookupBool(&status, config->args, "-simple");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -simple");
+            return false;
+        }
+    }
+
+    if (!convertIdToStr(output)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to convert id fields into a strings");
+        psFree(output);
+        return false;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipProcessedImfile", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool updateprocessedimfileMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    bool status = false;
+    psS16 code = psMetadataLookupS16(&status, config->args, "-code");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -code");
+        return false;
+    }
+    if (code == INT16_MAX) {
+        psError(PS_ERR_UNKNOWN, true, "-code is required");
+        return false;
+    }
+
+    if (!pxSetFaultCode(config->dbh, "chipProcessedImfile", config->where, code)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool blockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    bool status = false;
+    psString label = psMetadataLookupStr(&status, config->args, "-label");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -label");
+        return false;
+    }
+    if (!label) {
+        psError(PS_ERR_UNKNOWN, true, "-label is required");
+        return false;
+    }
+
+    if (!chipMaskInsert(config->dbh, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool maskedMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psString query = psStringCopy("SELECT * FROM chipMask");
+
+    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("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    bool simple = false;
+    {
+        bool status = false;
+        simple = psMetadataLookupBool(&status, config->args, "-simple");
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -simple");
+            return false;
+        }
+    }
+
+    if (!convertIdToStr(output)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to convert id fields into a strings");
+        psFree(output);
+        return false;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipMask", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool unblockMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    bool status = false;
+    psString label = psMetadataLookupStr(&status, config->args, "-label");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -label");
+        return false;
+    }
+    if (!label) {
+        psError(PS_ERR_UNKNOWN, true, "-label is required");
+        return false;
+    }
+
+    char *query = "DELETE FROM chipMask WHERE label = '%s'";
+
+    if (!p_psDBRunQuery(config->dbh, query, label)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool chipProcessedCompleteExp(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // look for completed chipPendingExp
+    // migrate them to chipProccessedExp & camPendingExp
+    psString query = pxDataGet("chiptool_completely_processed_exp.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    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("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *row = output->data[i];
+
+        chipRunRow *chipRun = chipRunObjectFromMetadata(row);
+        // set chipRun.state to 'stop'
+        if (!pxchipRunSetState(config, chipRun->chip_id, "stop")) {
+            psError(PS_ERR_UNKNOWN, false, "failed to change chipRun.state for chip_id: %" PRId64, chipRun->chip_id);
+            psFree(chipRun);
+            psFree(output);
+            return false;
+        }
+
+        // camQueueChipID() can only be run after chipRun.state has been set to
+        // stop
+        if (!pxcamQueueByChipID(config,
+                    chipRun->chip_id,
+                    chipRun->workdir,
+                    chipRun->label,
+                    chipRun->reduction,
+                    chipRun->expgroup,
+                    chipRun->dvodb
+        )) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "failed to queue camPendingExp");
+            psFree(chipRun);
+            psFree(output);
+            return false;
+        }
+        psFree(chipRun);
+    }
+
+    psFree(output);
+
+    return true;
+}
Index: /trunk/ippTools/src/chiptool.h
===================================================================
--- /trunk/ippTools/src/chiptool.h	(revision 14017)
+++ /trunk/ippTools/src/chiptool.h	(revision 14018)
@@ -38,11 +38,3 @@
 pxConfig *chiptoolConfig(pxConfig *config, int argc, char **argv);
 
-bool chipQueueExpTag(pxConfig *config,
-                     psString exp_tag,
-                     psString workdir,
-                     psString label,
-                     psString recipe,
-                     psString expgroup,
-                     psString dvodb);
-
 #endif // CHIPTOOL_H
Index: /trunk/ippTools/src/chiptoolConfig.c
===================================================================
--- /trunk/ippTools/src/chiptoolConfig.c	(revision 14017)
+++ /trunk/ippTools/src/chiptoolConfig.c	(revision 14018)
@@ -127,4 +127,6 @@
     psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-chip_id",  0,
             "define chip ID (required)", NULL);
+    psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-exp_tag",  0,
+            "define exposure ID", NULL);
     psMetadataAddStr(addprocessedimfileArgs, PS_LIST_TAIL, "-class_id",  0,
             "define class ID (requied)", NULL);
Index: /trunk/ippTools/src/pxcam.c
===================================================================
--- /trunk/ippTools/src/pxcam.c	(revision 14018)
+++ /trunk/ippTools/src/pxcam.c	(revision 14018)
@@ -0,0 +1,104 @@
+/*
+ * pxcam.c
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxcam.h"
+
+bool pxcamRunSetState(pxConfig *config, psS64 cam_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(state, "run", 4) == 0)
+            || (strncmp(state, "stop", 5) == 0)
+            || (strncmp(state, "reg", 4) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid camRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE camRun SET state = '%s' WHERE cam_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, cam_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for cam_id %" PRId64, cam_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pxcamQueueByChipID(pxConfig *config,
+                    psS64 chip_id,
+                    psString workdir,
+                    psString label,
+                    psString recipe,
+                    psString expgroup,
+                    psString dvodb)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // load the SQL to enqueue our exp_tags from disk once
+    static psString query = NULL;
+    if (!query) {
+        query = pxDataGet("camtool_queue_chip_id.sql");
+        psMemSetPersistent(query, true);
+        if (!query) {
+            psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+            return false;
+        }
+    }
+
+    // queue the exp
+    // XXX chip_id is being cast here work around psS64 have a different type
+    // different on 32/64
+    if (!p_psDBRunQuery(config->dbh, query,
+                "run", // state
+                workdir  ? workdir  : "NULL",
+                "dirty", //workdir_state
+                label    ? label    : "NULL",
+                recipe   ? recipe   : "NULL",
+                expgroup ? expgroup : "NULL",
+                dvodb    ? dvodb    : "NULL",
+                (long long)chip_id
+    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // just to be safe, we should have changed at least one row
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "no rows affected - should have changed at least one row");
+        return false;
+    }
+
+    return true;
+}
Index: /trunk/ippTools/src/pxcam.h
===================================================================
--- /trunk/ippTools/src/pxcam.h	(revision 14018)
+++ /trunk/ippTools/src/pxcam.h	(revision 14018)
@@ -0,0 +1,37 @@
+/*
+ * pxcam.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXCAM_H
+#define PXCAM_H 1
+
+#include <pslib.h>
+
+#include "pxtools.h"
+
+bool pxcamRunSetState(pxConfig *config, psS64 cam_id, const char *state);
+
+bool pxcamQueueByChipID(pxConfig *config,
+                        psS64 chip_id,
+                        psString workdir,
+                        psString label,
+                        psString recipe,
+                        psString expgroup,
+                        psString dvodb);
+
+#endif // PXCAM_H
Index: /trunk/ippTools/src/pxchip.c
===================================================================
--- /trunk/ippTools/src/pxchip.c	(revision 14018)
+++ /trunk/ippTools/src/pxchip.c	(revision 14018)
@@ -0,0 +1,126 @@
+/*
+ * pxchip.c
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxchip.h"
+
+bool pxchipRunSetState(pxConfig *config, psS64 chip_id, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(state, "run", 4) == 0)
+            || (strncmp(state, "stop", 5) == 0)
+            || (strncmp(state, "reg", 4) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid chipRun state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE chipRun SET state = '%s' WHERE chip_id = %" PRId64;
+    if (!p_psDBRunQuery(config->dbh, query, state, chip_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for chip_id %" PRId64, chip_id);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool pxchipQueueByExpTag(pxConfig *config,
+                         psString exp_tag,
+                         psString workdir,
+                         psString label,
+                         psString reduction,
+                         psString expgroup,
+                         psString dvodb)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // start a transaction
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    
+    // create a chipRun
+    if (!chipRunInsert(config->dbh,
+            0x0,
+            "run",      // state                
+            workdir,
+            "dirty",    // workdir_state
+            label,
+            reduction,
+            expgroup,
+            dvodb)
+    ) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+#if 0
+    // get the chip_id
+    long chip_id = psDBLastInsertID(config->dbh);
+#endif
+
+    // populate the chipInputImfile table from rawImfile based on exp_tag,
+    // where the coresponding newExp.state entry is set to stop
+    psString query = pxDataGetCached("chiptool_queuerawimfile.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // queue the imfiles for the exp_tag
+    if (!p_psDBRunQuery(config->dbh, query, exp_tag)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // just to be safe, we should have changed at least one row
+    if (psDBAffectedRows(config->dbh) < 1) {
+        psError(PS_ERR_UNKNOWN, false,
+                "no rows affected - should have changed at least one row");
+        return false;
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
Index: /trunk/ippTools/src/pxchip.h
===================================================================
--- /trunk/ippTools/src/pxchip.h	(revision 14018)
+++ /trunk/ippTools/src/pxchip.h	(revision 14018)
@@ -0,0 +1,37 @@
+/*
+ * pxchip.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXCHIP_H
+#define PXCHIP_H 1
+
+#include <pslib.h>
+
+#include "pxtools.h"
+
+bool pxchipRunSetState(pxConfig *config, psS64 chip_id, const char *state);
+
+bool pxchipQueueByExpTag(pxConfig *config,
+                         psString exp_tag,
+                         psString workdir,
+                         psString label,
+                         psString recipe,
+                         psString expgroup,
+                         psString dvodb);
+
+#endif // PXCHIP_H
Index: /trunk/ippTools/src/pxconfig.h
===================================================================
--- /trunk/ippTools/src/pxconfig.h	(revision 14018)
+++ /trunk/ippTools/src/pxconfig.h	(revision 14018)
@@ -0,0 +1,39 @@
+/*
+ * pxconfig.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXCONFIG_H
+#define PXCONFIG_H 1
+
+#include "pslib.h"
+#include "psmodules.h"
+
+typedef struct {
+    char *modeName;
+    int mode;
+    pmConfig *modules;
+    psDB *dbh;
+    psMetadata *args;
+    psMetadata *where;
+    int argc;
+    char **argv;
+} pxConfig;
+
+pxConfig *pxConfigAlloc(void);
+
+#endif // PXCONFIG_H
Index: /trunk/ippTools/src/pxdata.h
===================================================================
--- /trunk/ippTools/src/pxdata.h	(revision 14017)
+++ /trunk/ippTools/src/pxdata.h	(revision 14018)
@@ -24,4 +24,5 @@
 
 psString pxDataGet(const char *filename);
+psString pxDataGetCached(const char *filename);
 
 #endif // PXDATA_H
Index: /trunk/ippTools/src/pxinject.c
===================================================================
--- /trunk/ippTools/src/pxinject.c	(revision 14017)
+++ /trunk/ippTools/src/pxinject.c	(revision 14018)
@@ -24,11 +24,12 @@
 #include <stdlib.h>
 #include <ippdb.h>
+#include <string.h>
 
 #include "pxtools.h"
-#include "pxtag.h"
 #include "pxinject.h"
 
 static bool newExpMode(pxConfig *config);
 static bool newImfileMode(pxConfig *config);
+static bool updatenewExpMode(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -52,4 +53,5 @@
         MODECASE(PXINJECT_MODE_NEWEXP, newExpMode);
         MODECASE(PXINJECT_MODE_NEWIMFILE, newImfileMode);
+        MODECASE(PXINJECT_MODE_UPDATENEWEXP, updatenewExpMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -134,8 +136,10 @@
                 exp_tag,
                 exp_id,
+                "reg", // state
                 camera,
                 telescope,
                 imfiles,
-                workdir
+                workdir,
+                "dirty"
             )
         ) {
@@ -191,4 +195,5 @@
         return false;
     }
+#if 0
     psString class = psMetadataLookupStr(&status, config->args, "-class");
     if (!status) {
@@ -200,4 +205,5 @@
         return false;
     }
+#endif
     psString class_id = psMetadataLookupStr(&status, config->args, "-class_id");
     if (!status) {
@@ -220,5 +226,5 @@
 
     // insert with error flag state set to 0 (no errors)
-    if (!newImfileInsert(config->dbh, exp_tag, class, class_id, uri)) {
+    if (!newImfileInsert(config->dbh, exp_tag, class_id, uri)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
         return false;
@@ -227,2 +233,36 @@
     return true;
 }
+
+
+static bool updatenewExpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    bool status = false;
+    psString exp_tag = psMetadataLookupStr(&status, config->args, "-exp_tag");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -exp_tag");
+        return false;
+    }
+    if (!exp_tag) {
+        psError(PS_ERR_UNKNOWN, true, "-exp_tag is required");
+        return false;
+    }
+
+    psString state = psMetadataLookupStr(&status, config->args, "-state");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -state");
+        return false;
+    }
+    if (!state) {
+        psError(PS_ERR_UNKNOWN, true, "-state is required");
+        return false;
+    }
+
+    if (state) {
+        // set detRun.state to state
+        return pxnewExpSetState(config, exp_tag, state);
+    }
+
+    return true;
+}
Index: /trunk/ippTools/src/pxinject.h
===================================================================
--- /trunk/ippTools/src/pxinject.h	(revision 14017)
+++ /trunk/ippTools/src/pxinject.h	(revision 14018)
@@ -26,5 +26,6 @@
     PXINJECT_MODE_NONE           = 0x0,
     PXINJECT_MODE_NEWEXP,
-    PXINJECT_MODE_NEWIMFILE
+    PXINJECT_MODE_NEWIMFILE,
+    PXINJECT_MODE_UPDATENEWEXP
 } pxinjectMode;
 
Index: /trunk/ippTools/src/pxinjectConfig.c
===================================================================
--- /trunk/ippTools/src/pxinjectConfig.c	(revision 14017)
+++ /trunk/ippTools/src/pxinjectConfig.c	(revision 14018)
@@ -46,26 +46,36 @@
     psMetadata *newExpArgs = psMetadataAlloc();
     psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-exp_id",  0,
-        "define the exp_id (required)", NULL);
+            "define the exp_id (required)", NULL);
     psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-inst",  0,
-        "define the camera name (required)", NULL);
+            "define the camera name (required)", NULL);
     psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-telescope",  0,
-        "define the telescope name (required)", NULL);
+            "define the telescope name (required)", NULL);
     psMetadataAddS32(newExpArgs, PS_LIST_TAIL, "-imfiles",  0,
-        "define the number of imfiles in this exp (required)", 0);
+            "define the number of imfiles in this exp (required)", 0);
     psMetadataAddStr(newExpArgs, PS_LIST_TAIL, "-workdir",  0,
-        "define workdir (required)", 0);
+            "define workdir (required)", 0);
     psMetadataAddBool(newExpArgs, PS_LIST_TAIL, "-simple",  0,
-        "use the simple output format", false);
+            "use the simple output format", false);
 
     // -newImfile
     psMetadata *newImfileArgs = psMetadataAlloc();
     psMetadataAddStr(newImfileArgs, PS_LIST_TAIL, "-exp_tag",  0,
-        "define the exp_tag (required)", NULL);
+            "define the exp_tag (required)", NULL);
+#if 0
     psMetadataAddStr(newImfileArgs, PS_LIST_TAIL, "-class",  0,
-        "define the class (required)", NULL);
+            "define the class (required)", NULL);
+#endif
     psMetadataAddStr(newImfileArgs, PS_LIST_TAIL, "-class_id",  0,
-        "define the class ID (required)", NULL);
+            "define the class ID (required)", NULL);
     psMetadataAddStr(newImfileArgs, PS_LIST_TAIL, "-uri",  0,
-        "define the URI (required)", NULL);
+            "define the URI (required)", NULL);
+
+    // -updatenewExp
+    psMetadata *updatenewExpArgs = psMetadataAlloc();
+    psMetadataAddStr(updatenewExpArgs, PS_LIST_TAIL, "-exp_tag",  0,
+            "define the exp_tag (required)", NULL);
+    psMetadataAddStr(updatenewExpArgs, PS_LIST_TAIL, "-state", 0,
+            "set state (required)", NULL);
+
 
     psMetadata *argSets = psMetadataAlloc();
@@ -74,4 +84,5 @@
     PXTOOL_ADD_MODE("-newExp",      "", PXINJECT_MODE_NEWEXP,       newExpArgs);
     PXTOOL_ADD_MODE("-newImfile",   "", PXINJECT_MODE_NEWIMFILE,    newImfileArgs);
+    PXTOOL_ADD_MODE("-updatenewExp",   "", PXINJECT_MODE_UPDATENEWEXP,    updatenewExpArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: /trunk/ippTools/src/pxregister.c
===================================================================
--- /trunk/ippTools/src/pxregister.c	(revision 14018)
+++ /trunk/ippTools/src/pxregister.c	(revision 14018)
@@ -0,0 +1,56 @@
+/*
+ * register.c
+ *
+ * Copyright (C) 2006  Joshua Hoblitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+#include <string.h>
+
+#include "pxtools.h"
+#include "pxregister.h"
+
+bool pxnewExpSetState(pxConfig *config, const char *exp_tag, const char *state)
+{
+    PS_ASSERT_PTR_NON_NULL(exp_tag, false);
+    PS_ASSERT_PTR_NON_NULL(state, false);
+
+    // check that state is a valid string value
+    if (!(
+            (strncmp(state, "run", 4) == 0)
+            || (strncmp(state, "stop", 5) == 0)
+            || (strncmp(state, "reg", 4) == 0)
+        )
+    ) {
+        psError(PS_ERR_UNKNOWN, false,
+                "invalid newExp state: %s", state);
+        return false;
+    }
+
+    char *query = "UPDATE newExp SET state = '%s' WHERE exp_tag = '%s'";
+    if (!p_psDBRunQuery(config->dbh, query, state, exp_tag)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to change state for exp_tag %s", exp_tag);
+        return false;
+    }
+
+    return true;
+}
Index: /trunk/ippTools/src/pxregister.h
===================================================================
--- /trunk/ippTools/src/pxregister.h	(revision 14018)
+++ /trunk/ippTools/src/pxregister.h	(revision 14018)
@@ -0,0 +1,29 @@
+/*
+ * pxregister.h
+ *
+ * Copyright (C) 2007  Joshua Hoblitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * program; see the file COPYING. If not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PXREGISTER_H
+#define PXREGISTER_H 1
+
+#include <pslib.h>
+
+#include "pxtools.h"
+
+bool pxnewExpSetState(pxConfig *config, const char *exp_tag, const char *state);
+
+#endif // PXREGISTER_H
Index: /trunk/ippTools/src/pxtables.c
===================================================================
--- /trunk/ippTools/src/pxtables.c	(revision 14017)
+++ /trunk/ippTools/src/pxtables.c	(revision 14018)
@@ -60,10 +60,9 @@
     CREATE_TABLE(rawImfileCreateTable);
     CREATE_TABLE(guidePendingExpCreateTable);
-    CREATE_TABLE(chipPendingExpCreateTable);
-    CREATE_TABLE(chipPendingImfileCreateTable);
-    CREATE_TABLE(chipProcessedExpCreateTable);
+    CREATE_TABLE(chipRunCreateTable);
+    CREATE_TABLE(chipInputImfileCreateTable);
     CREATE_TABLE(chipProcessedImfileCreateTable);
     CREATE_TABLE(chipMaskCreateTable);
-    CREATE_TABLE(camPendingExpCreateTable);
+    CREATE_TABLE(camRunCreateTable);
     CREATE_TABLE(camProcessedExpCreateTable);
     CREATE_TABLE(camMaskCreateTable);
@@ -142,10 +141,9 @@
     DROP_TABLE(rawImfileDropTable);
     DROP_TABLE(guidePendingExpDropTable);
-    DROP_TABLE(chipPendingExpDropTable);
-    DROP_TABLE(chipPendingImfileDropTable);
-    DROP_TABLE(chipProcessedExpDropTable);
+    DROP_TABLE(chipRunDropTable);
+    DROP_TABLE(chipInputImfileDropTable);
     DROP_TABLE(chipProcessedImfileDropTable);
     DROP_TABLE(chipMaskDropTable);
-    DROP_TABLE(camPendingExpDropTable);
+    DROP_TABLE(camRunDropTable);
     DROP_TABLE(camProcessedExpDropTable);
     DROP_TABLE(camMaskDropTable);
Index: /trunk/ippTools/src/pxtag.h
===================================================================
--- /trunk/ippTools/src/pxtag.h	(revision 14017)
+++ /trunk/ippTools/src/pxtag.h	(revision 14018)
@@ -21,5 +21,7 @@
 #define PXTAG_H 1
 
-#include "pxtools.h"
+#include <pslib.h>
+
+#include "pxconfig.h"
 
 psString pxGenExpTag(pxConfig *config, const char *exp_id);
Index: /trunk/ippTools/src/pxtools.h
===================================================================
--- /trunk/ippTools/src/pxtools.h	(revision 14017)
+++ /trunk/ippTools/src/pxtools.h	(revision 14018)
@@ -21,30 +21,23 @@
 #define PXTOOLS_H 1
 
-# include <stdio.h>
-# include <strings.h>  // for strcasecmp
-# include <unistd.h>   // for unlink
-# include <pslib.h>
-# include <psmodules.h>
-# include <ippdb.h>
+#include <stdio.h>
+#include <strings.h>  // for strcasecmp
+#include <unistd.h>   // for unlink
+#include <pslib.h>
+#include <psmodules.h>
+#include <ippdb.h>
 
-# include "pxtoolsErrorCodes.h"
-# include "pxio.h"
-# include "pxdata.h"
+#include "pxtoolsErrorCodes.h"
+#include "pxio.h"
+#include "pxdata.h"
+#include "pxtag.h"
+#include "pxregister.h"
+#include "pxchip.h"
+#include "pxcam.h"
+#include "pxconfig.h"
 
 # define MAX_ROWS 10e9
 # define PXTOOL_MODE_NONE 0x0
 
-typedef struct {
-    char *modeName;
-    int mode;
-    pmConfig *modules;
-    psDB *dbh;
-    psMetadata *args;
-    psMetadata *where;
-    int argc;
-    char **argv;
-} pxConfig;
-
-pxConfig *pxConfigAlloc(void);
 bool pxCreateTables (pxConfig *config);
 bool pxDeleteTables (pxConfig *config);
Index: /trunk/ippTools/src/regtool.c
===================================================================
--- /trunk/ippTools/src/regtool.c	(revision 14017)
+++ /trunk/ippTools/src/regtool.c	(revision 14018)
@@ -44,5 +44,5 @@
 // static guidePendingExpRow *newToP1PendingExp(newExpRow *newExp);
 //static chipPendingExpRow *newTochipPendingExp(pxConfig *config, newExpRow *newExp);
-//static chipPendingImfileRow *rawImfileTochipPendingImfile(pxConfig *config, psS64 chip_id, rawImfileRow *rawImfile);
+//static chipInputImfileRow *rawImfileTochipInputImfile(pxConfig *config, psS64 chip_id, rawImfileRow *rawImfile);
 
 static rawExpRow *newToRawExp(pxConfig *config, newExpRow *exp);
@@ -282,4 +282,5 @@
                 return false;
             }
+            psFree(object);
             // insert the rawImfile object into the database
             if (!rawImfileInsertObject(config->dbh, imfile)) {
@@ -290,21 +291,8 @@
                 psError(PS_ERR_UNKNOWN, false, "failed to insert row into the database");
                 psFree(imfile);
-                psFree(object);
                 psFree(output);
                 return false;
             }
             psFree(imfile);
-            // remove the neImfile object from the database
-            if (!newImfileDeleteObject(config->dbh, object)) {
-                // rollback
-                if (!psDBRollback(config->dbh)) {
-                    psError(PS_ERR_UNKNOWN, false, "database error");
-                }
-                psError(PS_ERR_UNKNOWN, false, "failed to delete row from the database");
-                psFree(object);
-                psFree(output);
-                return false;
-            }
-            psFree(object);
         }
 
@@ -573,11 +561,9 @@
     }
     if (!psArrayLength(output)) {
-        psTrace("regtool", PS_LOG_INFO, "no rows found");
+        psError(PS_ERR_UNKNOWN, false, "no pending newExp rows found");
         psFree(output);
-        return true;
-    }
-
-    // start a transaction so we don't end up with an exp in both rawExp &
-    // newExp
+        return false;
+    }
+
     if (!psDBTransaction(config->dbh)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
@@ -603,4 +589,5 @@
             return false;
         }
+        psFree(newExp);
 
         // insert the rawExp object into the database
@@ -612,5 +599,4 @@
             psError(PS_ERR_UNKNOWN, false, "database error");
             psFree(rawExp);
-            psFree(newExp);
             psFree(output);
             return false;
@@ -618,26 +604,35 @@
         psFree(rawExp);
 
-        // delete the newExp object from the database
-        if (!newExpDeleteObject(config->dbh, newExp)) {
+        // if this is a detrend image don't put it in the chip queue (and we're
+        // done)
+        if (detrend) {
+            // set the state for the newExp to stop 
+            if (!pxnewExpSetState(config, exp_tag, "stop")) {
+                // rollback
+                if (!psDBRollback(config->dbh)) {
+                    psError(PS_ERR_UNKNOWN, false, "database error");
+                }
+                psError(PS_ERR_UNKNOWN, false, "failed to change newExp.state for exp_tag: %s", exp_tag);
+                psFree(output);
+                return false;
+            }
+            continue;
+        }
+
+
+        // set the state for the newExp to stop
+        if (!pxnewExpSetState(config, exp_tag, "stop")) {
             // rollback
             if (!psDBRollback(config->dbh)) {
                 psError(PS_ERR_UNKNOWN, false, "database error");
             }
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(newExp);
+            psError(PS_ERR_UNKNOWN, false, "failed to change newExp.state for exp_tag: %s", exp_tag);
             psFree(output);
             return false;
         }
 
-        psFree(newExp);
-
-        // if this is a detrend image don't put it in the chip queue (and we're
-        // done)
-        if (detrend) {
-            continue;
-        }
-
         // insert an entry into the chipPendingExp table
-        if (!chipQueueExpTag(config, exp_tag, NULL, NULL, NULL, NULL, NULL)) {
+        // this can only be run as the newExp's state has been set to stop
+        if (!pxchipQueueByExpTag(config, exp_tag, NULL, NULL, NULL, NULL, NULL)) {
             // rollback
             if (!psDBRollback(config->dbh)) {
@@ -649,5 +644,4 @@
         }
     }
-
     psFree(output);
 
@@ -828,7 +822,7 @@
 
 
-static chipPendingImfileRow *rawImfileTochipPendingImfile(pxConfig *config, psS64 chip_id, rawImfileRow *rawImfile)
-{
-    return chipPendingImfileRowAlloc(
+static chipInputImfileRow *rawImfileTochipInputImfile(pxConfig *config, psS64 chip_id, rawImfileRow *rawImfile)
+{
+    return chipInputImfileRowAlloc(
             chip_id,
             rawImfile->class_id,
