Index: /trunk/ippTools/src/pztool.c
===================================================================
--- /trunk/ippTools/src/pztool.c	(revision 10055)
+++ /trunk/ippTools/src/pztool.c	(revision 10056)
@@ -25,4 +25,5 @@
 #include <string.h>
 #include <stdlib.h>
+#include <inttypes.h>
 
 #include "pxtools.h"
@@ -33,8 +34,4 @@
 static bool pendingImfileMode(pxConfig *config);
 static bool copydoneMode(pxConfig *config);
-
-//static psArray *pztoolPendingExp(pxConfig *config);
-//static psArray *pztoolPendingImfiles(pxConfig *config);
-//static bool pztoolFlushPendingExp(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -68,4 +65,6 @@
 
 FAIL:
+    psErrorStackPrint(stderr, "\n");
+
     psFree(config);
     pmConfigDone();
@@ -251,11 +250,11 @@
 
     bool status = false;
-    psString filesetid = psMetadataLookupStr(&status, config->args, "-filesetid");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -filesetid");
-        return false;
-    }
-    if (!filesetid) {
-        psError(PS_ERR_UNKNOWN, true, "-filesetid is required");
+    psString exp_id = psMetadataLookupStr(&status, config->args, "-exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -exp_id");
+        return false;
+    }
+    if (!exp_id) {
+        psError(PS_ERR_UNKNOWN, true, "-exp_id is required");
         return false;
     }
@@ -313,154 +312,127 @@
     // need to know exp_id, camera, telescope, class, class_id (to find the
     // pzPendingImfile entry and the URI for the newImfile entry.
+
+    // start a transaction so it's all rows or nothing
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
   
-#if 0
-    // we don't have to operate on complete frames here as it's ok to start
-    // downloading the imfiles before the exp has been registered
-    psArray *pending = pztoolPendingImfiles(config);
-    if (!pending) {
-        psError(PS_ERR_UNKNOWN, false, "no pzPendingImfiles found");
-        return false;
-    }
-
-    // start a transaction so we don't end up with entries in newImfile that
-    // haven't been removed from pzPendingImfile
-    if (!psDBTransaction(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(pending);
-        return false;
-    }
-
-    for (long i = 0; i < pending->n; i++) {
-        pzPendingImfileRow *pendingImfile = pending->data[i];
-
-        if (!newImfileInsert(
-            config->dbh,
-            pendingImfile->exp_tag,
-            pendingImfile->class,
-            pendingImfile->class_id
-            )
-            // XXX get this from the CLI
-//            pendingImfile->uri
-        ) {
-            psError(PS_ERR_UNKNOWN, false, "dbh access failed");
-            psFree(pending);
-            goto ROLLBACK;
-        }
-    }
-
-    if (pzPendingImfileDeleteRowObjects(config->dbh, pending, MAX_ROWS) < 0) {
-        psError(PS_ERR_UNKNOWN, false, "dbh access failed");
-        psFree(pending);
-        goto ROLLBACK;
-    }
-    psFree(pending);
-
-    // check for completed exps
-    if (!pztoolFlushPendingExp(config)) {
-        psError(PS_ERR_UNKNOWN, false, "pztoolFlushPendingExp() failed");
-        goto ROLLBACK;
+    // insert new imfile into newImfile
+    {
+        char *query =
+            "INSERT INTO newImfile"
+            "   SElECT"
+            "       pzPendingImfile.exp_tag,"
+            "       pzPendingImfile.class,"
+            "       pzPendingImfile.class_id,"
+            "       '%s'" // uri of downloaded file
+            "   FROM pzPendingImfile"
+            "   WHERE"
+            "       pzPendingImfile.exp_id = '%s'"
+            "       AND pzPendingImfile.camera = '%s'"
+            "       AND pzPendingImfile.telescope = '%s'"
+            "       AND pzPendingImfile.class = '%s'"
+            "       AND pzPendingImfile.class_id = '%s'";
+
+        if (!p_psDBRunQuery(config->dbh, query, uri, exp_id, camera, telescope, class, class_id)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        } 
+
+        // sanity check: we should have inserted only one row
+        psU64 affected = psDBAffectedRows(config->dbh);
+        if (psDBAffectedRows(config->dbh) != 1) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "should have affected 1 row but %" PRIu64 " rows were modified", affected);
+            return false;
+        }
+    }
+
+    // cp the imfile into pzDoneImfile
+    {
+        char *query =
+            "INSERT INTO pzDoneImfile"
+            "   SElECT"
+            "       pzPendingImfile.*,"
+            "       '%s'" // uri of downloaded file
+            "   FROM pzPendingImfile"
+            "   WHERE"
+            "       pzPendingImfile.exp_id = '%s'"
+            "       AND pzPendingImfile.camera = '%s'"
+            "       AND pzPendingImfile.telescope = '%s'"
+            "       AND pzPendingImfile.class = '%s'"
+            "       AND pzPendingImfile.class_id = '%s'";
+
+        if (!p_psDBRunQuery(config->dbh, query, uri, exp_id, camera, telescope, class, class_id)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        } 
+
+        // sanity check: we should have inserted only one row
+        psU64 affected = psDBAffectedRows(config->dbh);
+        if (psDBAffectedRows(config->dbh) != 1) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "should have affected 1 row but %" PRIu64 " rows were modified", affected);
+            return false;
+        }
+    }
+
+    // removve the entry from pzPendingImfile
+    {
+        char *query =
+            "DELETE FROM pzPendingImfile"
+            "   WHERE"
+            "       pzPendingImfile.exp_id = '%s'"
+            "       AND pzPendingImfile.camera = '%s'"
+            "       AND pzPendingImfile.telescope = '%s'"
+            "       AND pzPendingImfile.class = '%s'"
+            "       AND pzPendingImfile.class_id = '%s'";
+
+        if (!p_psDBRunQuery(config->dbh, query, exp_id, camera, telescope, class, class_id)) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
+        } 
+
+        // sanity check: we should have removed only one row
+        psU64 affected = psDBAffectedRows(config->dbh);
+        if (psDBAffectedRows(config->dbh) != 1) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            psError(PS_ERR_UNKNOWN, false, "should have affected 1 row but %" PRIu64 " rows were modified", affected);
+            return false;
+        }
     }
 
     // point of no return
     if (!psDBCommit(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        // XXX is this the right thing to do after a commit failure?
-        goto ROLLBACK;
-    }
-
-    return true;
-
-ROLLBACK:
-    // rollback
-    if (!psDBRollback(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-    }
-#endif
-
-    return false;
-}
-
-#if 0
-static psArray *pztoolPendingExp(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, NULL);
-
-    psArray *exps = pzPendingExpSelectRowObjects(config->dbh,
-        config->where, MAX_ROWS);
-    if (!exps) {
-        psError(PS_ERR_UNKNOWN, false, "no pzPendingExp rows found");
-        return NULL;
-    }
-
-    return exps;
-}
-
-static psArray *pztoolPendingImfiles(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, NULL);
-
-    psArray *imfiles = pzPendingImfileSelectRowObjects(config->dbh,
-        config->where, MAX_ROWS);
-    if (!imfiles) {
-        psError(PS_ERR_UNKNOWN, false, "no pzPendingImfile rows found");
-        return NULL;
-    }
-
-    return imfiles;
-}
-
-static bool pztoolFlushPendingExp(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    psArray *pending = pztoolPendingExp(config);
-    if (!pending) {
-        psError(PS_ERR_UNKNOWN, false, "no pzPendingExps found");
-        return false;
-    }
-
-    for (long i = 0; i < pending->n; i++) {
-        pzPendingExpRow *pendingExp = pending->data[i];
-
-        psMetadata *where = psMetadataAlloc();
-        psMetadataAddStr(where, PS_LIST_TAIL, "exp_id", 0, "==",
-            pendingExp->exp_id);
-        psArray *pendingImfiles = pzPendingImfileSelectRowObjects(config->dbh, where, MAX_ROWS);
-        psFree(where);
-
-        if (!pendingImfiles) {
-            // exp has no coresponding imfiles so we need to remove it from
-            // pzPendingExp and add it to newExp
-
-            if (!newExpInsert(
-                    config->dbh,
-                    // XXX exp_tag needs to be generated
-                    "FIXME exp_tag",
-                    pendingExp->exp_id,
-                    pendingExp->camera,
-                    pendingExp->telescope,
-                    pendingExp->exp_type,
-                    pendingExp->imfiles)
-            ) {
-                psError(PS_ERR_UNKNOWN, false, "dbh access failed");
-                psFree(pending);
-                return false;
-            }
-
-            psArray *nukeMe = psArrayAllocEmpty(1);
-            psArrayAdd(nukeMe, 0, pendingExp);
-            bool status = pzPendingExpDeleteRowObjects(config->dbh, nukeMe, MAX_ROWS);
-            psFree(nukeMe);
-            if (!status) {
-                psError(PS_ERR_UNKNOWN, false, "dbh access failed");
-                return false;
-            }
-        }
-
-        psFree(pendingImfiles);
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
     }
 
     return true;
 }
-
-#endif
