Index: /trunk/ippTools/src/pztool.c
===================================================================
--- /trunk/ippTools/src/pztool.c	(revision 20172)
+++ /trunk/ippTools/src/pztool.c	(revision 20173)
@@ -46,5 +46,5 @@
 static bool advanceMode(pxConfig *config);
 
-static bool copydoneCompleteExp(pxConfig *config, const char *exp_name, const char *camera, const char *telescope, bool rowLock);
+static bool copydoneCompleteExp(pxConfig *config);
 static psArray *pzGetPendingCameras(pxConfig *config);
 static psArray *pzArrayZip(psArray *arraySet, psS64 limit);
@@ -404,4 +404,38 @@
     // NOTE : the rest of the command-line args are parsed in copydoneCompleteExp
 
+    // start a transaction early so it will contain any row level locks
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    
+    // query to get an excluse lock on this exposure in
+    // pzDownloadExp
+    psString lock_query = NULL;
+    if (row_lock) {
+        lock_query = psStringCopy("SELECT * FROM pzDownloadExp");
+
+        psMetadata *where = psMetadataAlloc();
+        PXOPT_COPY_STR(config->args, where,  "-exp_name", "exp_name", "==");
+        PXOPT_COPY_STR(config->args, where,  "-inst", "camera", "==");
+        PXOPT_COPY_STR(config->args, where,  "-telescope", "telescope", "==");
+        
+        if (psListLength(where->list)) {
+            psString whereClause = psDBGenerateWhereSQL(where, NULL);
+            psStringAppend(&lock_query, " %s FOR UPDATE", whereClause);
+            psFree(whereClause);
+        }
+        psFree(where);
+
+        // aquire a lock on the pzDownloadExp record
+        // lock persists until the transaction is committed
+        if (!p_psDBRunQuery(config->dbh, lock_query)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(lock_query);
+            return false;
+        }
+        psFree(lock_query);
+    }
+
     if (!pzDownloadImfileInsert(config->dbh,
             exp_name,
@@ -418,11 +452,5 @@
     }
 
-    // start a transaction so it's all rows or nothing
-    if (!psDBTransaction(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
-    if (!copydoneCompleteExp(config, exp_name, camera, telescope, row_lock)) {
+    if (!copydoneCompleteExp(config)) {
         // rollback
         if (!psDBRollback(config->dbh)) {
@@ -446,5 +474,5 @@
 }
 
-static bool copydoneCompleteExp(pxConfig *config, const char *exp_name, const char *camera, const char *telescope, bool row_lock)
+static bool copydoneCompleteExp(pxConfig *config)
 {
     // THIS FUNCTION MUST BE INVOKED FROM INSIDE A TRANSACTION!!!
@@ -464,5 +492,4 @@
     PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
 
-
     // find all exposures that have had all of their imfiles downloaded but do
     // not appear in newExp
@@ -473,59 +500,15 @@
     }
 
-    // XXX this is a bit ugly : could just use the PXOPT_COPY_* methods 
-    // and not pass exp_name, camera, or telescope as additional args
     psMetadata *where = psMetadataAlloc();
-    if (exp_name) {
-        if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_name", 0, "==", exp_name)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_name");
-            psFree(where);
-            return false;
-        }
-    }
-
-    if (camera) {
-        if (!psMetadataAddStr(where, PS_LIST_TAIL, "camera", 0, "==", camera)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
-            psFree(where);
-            return false;
-        }
-    }
-
-    if (telescope) {
-        if (!psMetadataAddStr(where, PS_LIST_TAIL, "telescope", 0, "==", telescope)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
-            psFree(where);
-            return false;
-        }
-    }
-
-    // query to get an excluse lock on all rows for this exposure in
-    // pzDownloadImfile
-    psString lock_query = NULL;
-    if (row_lock) {
-        lock_query = psStringCopy("SELECT * FROM pzDownloadImfile");
-    }
+    PXOPT_COPY_STR(config->args, where,  "-exp_name", "exp_name", "==");
+    PXOPT_COPY_STR(config->args, where,  "-inst", "camera", "==");
+    PXOPT_COPY_STR(config->args, where,  "-telescope", "telescope", "==");
 
     if (psListLength(where->list)) {
         psString whereClause = psDBGenerateWhereSQL(where, NULL);
         psStringAppend(&query, " %s", whereClause);
-        if (row_lock) {
-            psStringAppend(&lock_query, " %s FOR UPDATE", whereClause);
-        }
         psFree(whereClause);
     }
     psFree(where);
-
-    // aquire lock on pzDownloadImfile rows
-    // lock persists until a transaction is committed
-    if (row_lock) {
-        if (!p_psDBRunQuery(config->dbh, lock_query)) {
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            psFree(lock_query);
-            psFree(query);
-            return false;
-        }
-        psFree(lock_query);
-    }
 
     // find completed exps
@@ -880,5 +863,5 @@
     }
 
-    if (!copydoneCompleteExp(config, NULL, NULL, NULL, true)) {
+    if (!copydoneCompleteExp(config)) {
         // rollback
         if (!psDBRollback(config->dbh)) {
