Index: /trunk/ippTools/src/chiptool.c
===================================================================
--- /trunk/ippTools/src/chiptool.c	(revision 8050)
+++ /trunk/ippTools/src/chiptool.c	(revision 8051)
@@ -173,8 +173,20 @@
     }
 
+    // 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(valid_exp_ids);
+        return false;
+    }
+
     // insert into done
     for (long i = 0; i < psArrayLength(pendingImfiles); i++) {
         p2DoneImfileRow *imfile = p2pendingToDoneImfile(config, pendingImfiles->data[0]);
         if (!imfile) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
             psError(PS_ERR_UNKNOWN, false, "failed to convert p2PendingImfile to p2DoneImfile");
             psFree(pendingImfiles);
@@ -182,4 +194,8 @@
         }
         if (!p2DoneImfileInsertObject(config->dbh, imfile)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
             psError(PS_ERR_UNKNOWN, false, "dbh access failed");
             psFree(imfile);
@@ -193,7 +209,19 @@
     if (p2PendingImfileDeleteRowObjects(config->dbh, pendingImfiles, MAX_ROWS) < 0) {
         // 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, "dbh access failed");
         return false;
     }
+
+    // point of no return for p2PendingImfile -> p2DoneImfile 
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // XXX make exposure state transition transactional
 
     // look for pending exposures
