Index: /trunk/ippTools/src/Makefile.am
===================================================================
--- /trunk/ippTools/src/Makefile.am	(revision 16276)
+++ /trunk/ippTools/src/Makefile.am	(revision 16277)
@@ -8,4 +8,5 @@
 	flatcorr \
 	magictool \
+        pstamptool \
 	pxadmin \
 	pxinject \
@@ -16,4 +17,5 @@
 	stacktool \
 	warptool
+
 
 bin_SCRIPTS = \
@@ -44,4 +46,5 @@
 	guidetool.h \
 	magictool.h \
+        pstamptool.h \
 	pxinject.h \
 	pzgetexp.h \
@@ -80,4 +83,10 @@
     pztoolConfig.c
 
+pstamptool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS) 
+pstamptool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
+pstamptool_SOURCES = \
+    pstamptool.c \
+    pstamptoolConfig.c
+
 caltool_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS)
 caltool_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) libpxtools.la
Index: /trunk/ippTools/src/pstamptool.c
===================================================================
--- /trunk/ippTools/src/pstamptool.c	(revision 16276)
+++ /trunk/ippTools/src/pstamptool.c	(revision 16277)
@@ -36,14 +36,8 @@
 static bool pendingReqMode(pxConfig *config);
 static bool processedReqMode(pxConfig *config);
-#ifdef notyet
 static bool addJobMode(pxConfig *config);
+static bool listJobMode(pxConfig *config);
 static bool pendingJobMode(pxConfig *config);
-
-static bool copydoneMode(pxConfig *config);
-
-static bool copydoneCompleteExp(pxConfig *config);
-static psArray *pzGetPendingCameras(pxConfig *config);
-static psArray *pzArrayZip(psArray *arraySet, psS64 limit);
-#endif // notyet
+static bool processedJobMode(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -71,4 +65,8 @@
         MODECASE(PSTAMPTOOL_MODE_PENDINGREQ, pendingReqMode);
         MODECASE(PSTAMPTOOL_MODE_PROCESSEDREQ, processedReqMode);
+        MODECASE(PSTAMPTOOL_MODE_ADDJOB, addJobMode);
+        MODECASE(PSTAMPTOOL_MODE_LISTJOB, listJobMode);
+        MODECASE(PSTAMPTOOL_MODE_PENDINGJOB, pendingJobMode);
+        MODECASE(PSTAMPTOOL_MODE_PROCESSEDJOB, processedJobMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -206,5 +204,5 @@
     }
 
-    char *query ="INSERT INTO psRequest"
+    char *query ="INSERT INTO pstampRequest"
                  " (state, uri)"
                  " VALUES( 'new', '%s')";
@@ -224,4 +222,7 @@
     }
 
+    psS64 req_id = psDBLastInsertID(config->dbh);
+    printf("%ld\n", req_id);
+
     return true;
 }
@@ -241,10 +242,10 @@
             "SELECT"
             " *"
-            " FROM psRequest"
+            " FROM pstampRequest"
             " WHERE state = 'new'"
         );
 
     if (config->where) {
-        psString whereClause = psDBGenerateWhereConditionSQL(config->where, "psRequest");
+        psString whereClause = psDBGenerateWhereConditionSQL(config->where, "pstampRequest");
         psStringAppend(&query, " AND %s", whereClause);
         psFree(whereClause);
@@ -288,5 +289,5 @@
 
     // negative simple so the default is true
-    if (!ippdbPrintMetadatas(stdout, output, "pzPendingExp", !simple)) {
+    if (!ippdbPrintMetadatas(stdout, output, "pstampRequest", !simple)) {
         psError(PS_ERR_UNKNOWN, false, "failed to print array");
         psFree(output);
@@ -298,4 +299,5 @@
     return true;
 }
+
 static bool processedReqMode(pxConfig *config)
 {
@@ -325,5 +327,5 @@
     // XXX: check state for a legal value
 
-    char *query ="UPDATE psRequest"
+    char *query ="UPDATE pstampRequest"
                  " SET state = '%s'"
                  " WHERE req_id = '%s'";
@@ -337,9 +339,294 @@
     psU64 affected = psDBAffectedRows(config->dbh);
     if (affected != 1) {
-        psError(PS_ERR_UNKNOWN, false, "should have affected one row but %" PRIu64 " rows were modified",
+        psError(PS_ERR_UNKNOWN, false, "should have affected one row but %" 
+                                        PRIu64 " rows were modified", affected);
+        return false;
+    }
+
+    return true;
+}
+static bool addJobMode(pxConfig *config)
+{
+    bool    status;
+
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psString uri = psMetadataLookupStr(&status, config->args, "-uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -uri");
+        return false;
+    }
+    if (!uri) {
+        psError(PS_ERR_UNKNOWN, true, "-uri is required");
+        return false;
+    }
+
+    psString req_id = psMetadataLookupStr(&status, config->args, "-req_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -req_id");
+        return false;
+    }
+    if (!req_id) {
+        psError(PS_ERR_UNKNOWN, true, "-req_id is required");
+        return false;
+    }
+
+    psString outputBase = psMetadataLookupStr(&status, config->args, "-outputBase");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -outputBase");
+        return false;
+    }
+    if (!outputBase) {
+        psError(PS_ERR_UNKNOWN, true, "-outputBase is required");
+        return false;
+    }
+
+    psString argString = psMetadataLookupStr(&status, config->args, "-args");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -args");
+        return false;
+    }
+    if (!argString) {
+        psError(PS_ERR_UNKNOWN, true, "-args is required");
+        return false;
+    }
+
+    char *query ="INSERT INTO pstampJob"
+                 " (req_id, state, uri, outputBase, args)"
+                 " VALUES( %s, 'new', '%s', '%s', '%s')";
+
+    if (!p_psDBRunQuery(config->dbh, query, req_id, uri, outputBase, argString)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    psU64 affected = psDBAffectedRows(config->dbh);
+    if (affected != 1) {
+        psError(PS_ERR_UNKNOWN, false, 
+            "should have affected one row but %" PRIu64 " rows were modified",
             affected);
         return false;
     }
 
-    return true;
-}
+    psS64 job_id = psDBLastInsertID(config->dbh);
+    printf("%ld\n", job_id);
+
+    return true;
+}
+
+static bool listJobMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    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;
+    }
+
+    psString query = NULL;
+
+    psString req_id = psMetadataLookupStr(&status, config->args, "-req_id");
+    psString job_id = psMetadataLookupStr(&status, config->args, "-job_id");
+    
+    if (req_id) {
+        psStringAppend(&query,
+                "SELECT"
+                " *"
+                " FROM pstampJob"
+                " WHERE req_id = %s", req_id
+            );
+    } else if (job_id) {
+        psStringAppend(&query,
+                "SELECT"
+                " *"
+                " FROM pstampJob"
+                " WHERE job_id = %s", job_id
+            );
+    } else {
+        fprintf(stderr, "either req_id or job_id must be specified\n");
+        exit (1);
+    }
+
+    // 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("pstamptool", 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");
+            psFree(output);
+            return false;
+        }
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pstampJob", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool pendingJobMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    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;
+    }
+
+    psString query = psStringCopy(
+            "SELECT"
+            " *"
+            " FROM pstampJob"
+            " WHERE state = 'new'"
+        );
+
+    if (config->where) {
+        psString whereClause = psDBGenerateWhereConditionSQL(config->where, "pstampJob");
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+
+    // 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("pstamptool", 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");
+            psFree(output);
+            return false;
+        }
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pstampJob", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+static bool processedJobMode(pxConfig *config)
+{
+    bool    status;
+
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psString job_id = psMetadataLookupStr(&status, config->args, "-job_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -job_id");
+        return false;
+    }
+    if (!job_id) {
+        psError(PS_ERR_UNKNOWN, true, "-job_id 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;
+    }
+    psString jobStatus = psMetadataLookupStr(&status, config->args, "-status");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -status");
+        return false;
+    }
+
+    psString statusStr = NULL;
+    if (!jobStatus) {
+        statusStr = psStringCopy("");
+    } else {
+        psStringAppend(&statusStr, ", status = '%s'", jobStatus);
+    }
+        
+
+    // XXX: check state for a legal value
+
+    char *query ="UPDATE pstampJob"
+                 " SET state = '%s' %s"
+                 " WHERE job_id = '%s'";
+
+    if (!p_psDBRunQuery(config->dbh, query, state, statusStr, job_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(statusStr);
+
+    psU64 affected = psDBAffectedRows(config->dbh);
+    if (affected != 1) {
+        psError(PS_ERR_UNKNOWN, false, "should have affected one row but %" 
+                                        PRIu64 " rows were modified", affected);
+        return false;
+    }
+
+    return true;
+}
Index: /trunk/ippTools/src/pstamptool.h
===================================================================
--- /trunk/ippTools/src/pstamptool.h	(revision 16276)
+++ /trunk/ippTools/src/pstamptool.h	(revision 16277)
@@ -31,4 +31,5 @@
     PSTAMPTOOL_MODE_PROCESSEDREQ,
     PSTAMPTOOL_MODE_ADDJOB,
+    PSTAMPTOOL_MODE_LISTJOB,
     PSTAMPTOOL_MODE_PENDINGJOB,
     PSTAMPTOOL_MODE_JOBRESULT,
Index: /trunk/ippTools/src/pstamptoolConfig.c
===================================================================
--- /trunk/ippTools/src/pstamptoolConfig.c	(revision 16276)
+++ /trunk/ippTools/src/pstamptoolConfig.c	(revision 16277)
@@ -74,36 +74,43 @@
             "new state", NULL); 
 
-#ifdef notdef
-    // -pendingimfile
-    psMetadata *pendingimfileArgs = psMetadataAlloc();
-    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-exp_name", 0,
-            "define exposure ID", NULL); 
-    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-inst", 0,
-            "define camera ID", NULL); 
-    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-telescope", 0,
-            "define telescope ID", NULL); 
-    psMetadataAddStr(pendingimfileArgs, PS_LIST_TAIL, "-exp_type", 0,
-            "define exposure type", NULL); 
-    psMetadataAddU64(pendingimfileArgs, PS_LIST_TAIL, "-limit",  0,
+    // -addjob
+    psMetadata *addjobArgs = psMetadataAlloc();
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-uri", 0,
+            "define job file uri", NULL); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-req_id", 0,
+            "define job req_id", NULL); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-outputBase", 0,
+            "define job outputBase", NULL); 
+    psMetadataAddStr(addjobArgs, PS_LIST_TAIL, "-args", 0,
+            "define job args", NULL); 
+
+    // -listjob
+    psMetadata *listjobArgs = psMetadataAlloc();
+    psMetadataAddStr(listjobArgs, PS_LIST_TAIL, "-req_id", 0,
+            "define request", NULL); 
+    psMetadataAddStr(listjobArgs, PS_LIST_TAIL, "-job_id", 0,
+            "define job", NULL); 
+    psMetadataAddU64(listjobArgs, PS_LIST_TAIL, "-limit",  0,
             "limit result set to N items", 0);
-    psMetadataAddBool(pendingimfileArgs, PS_LIST_TAIL, "-simple", 0,
-            "use the simple output format", false);
-
-    // -copydone
-    psMetadata *copydoneArgs = psMetadataAlloc();
-    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-exp_name", 0,
-            "define exposure ID (required)", NULL); 
-    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-inst", 0,
-            "define camera ID (required)", NULL); 
-    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-telescope", 0,
-            "define telescope ID (required)", NULL); 
-    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-class", 0,
-            "define class", NULL);
-    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-class_id", 0,
-            "define class_id", NULL);
-    psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-uri", 0,
-            "define storage uri", NULL);
-
-#endif // notyet
+    psMetadataAddBool(listjobArgs, PS_LIST_TAIL, "-simple", 0,
+            "use the simple output format", false);
+
+    // -pendingjob
+    psMetadata *pendingjobArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingjobArgs, PS_LIST_TAIL, "-job_id", 0,
+            "define job", NULL); 
+    psMetadataAddU64(pendingjobArgs, PS_LIST_TAIL, "-limit",  0,
+            "limit result set to N items", 0);
+    psMetadataAddBool(pendingjobArgs, PS_LIST_TAIL, "-simple", 0,
+            "use the simple output format", false);
+
+    // -processedjob
+    psMetadata *processedjobArgs = psMetadataAlloc();
+    psMetadataAddStr(processedjobArgs, PS_LIST_TAIL, "-job_id", 0,
+            "req_id for which to change state", NULL); 
+    psMetadataAddStr(processedjobArgs, PS_LIST_TAIL, "-state", 0,
+            "new state", NULL); 
+    psMetadataAddStr(processedjobArgs, PS_LIST_TAIL, "-status", 0,
+            "new status", NULL); 
 
 #define PXTOOL_MODE(option, modeval, argset) \
@@ -129,16 +136,18 @@
     psMetadata *modes = psMetadataAlloc();
 
-    PXTOOL_ADD_MODE("-adddatastore",    "", PSTAMPTOOL_MODE_ADDDATASTORE, adddatastoreArgs);
-    PXTOOL_ADD_MODE("-datastore",       "", PSTAMPTOOL_MODE_DATASTORE,    datastoreArgs);
-
-    PXTOOL_ADD_MODE("-addreq",          "", PSTAMPTOOL_MODE_ADDREQ,       addreqArgs);
-    PXTOOL_ADD_MODE("-pendingreq",      "", PSTAMPTOOL_MODE_PENDINGREQ,   pendingreqArgs);
-    PXTOOL_ADD_MODE("-processedreq",    "", PSTAMPTOOL_MODE_PROCESSEDREQ, processedreqArgs);
+    PXOPT_ADD_MODE("-adddatastore",    "", PSTAMPTOOL_MODE_ADDDATASTORE, adddatastoreArgs);
+    PXOPT_ADD_MODE("-datastore",       "", PSTAMPTOOL_MODE_DATASTORE,    datastoreArgs);
+
+    PXOPT_ADD_MODE("-addreq",          "", PSTAMPTOOL_MODE_ADDREQ,       addreqArgs);
+    PXOPT_ADD_MODE("-pendingreq",      "", PSTAMPTOOL_MODE_PENDINGREQ,   pendingreqArgs);
+    PXOPT_ADD_MODE("-processedreq",    "", PSTAMPTOOL_MODE_PROCESSEDREQ, processedreqArgs);
+
+    PXOPT_ADD_MODE("-addjob",          "", PSTAMPTOOL_MODE_ADDJOB,       addjobArgs);
+    PXOPT_ADD_MODE("-listjob",         "", PSTAMPTOOL_MODE_LISTJOB,      listjobArgs);
+    PXOPT_ADD_MODE("-pendingjob",      "", PSTAMPTOOL_MODE_PENDINGJOB,   pendingjobArgs);
+    PXOPT_ADD_MODE("-processedjob",    "", PSTAMPTOOL_MODE_PROCESSEDJOB, processedjobArgs);
 
 #ifdef notyet
-    PXTOOL_ADD_MODE("-addjob",          "", PSTAMPTOOL_MODE_ADDJOB,       addjobArgs);
-    PXTOOL_ADD_MODE("-pendingjob",      "", PSTAMPTOOL_MODE_PENDINGJOB,   pendingjobArgs);
-    PXTOOL_ADD_MODE("-processedjob"     "", PSTAMPTOOL_MODE_PROCESSEDJOB, processedjobArgs);
-    PXTOOL_ADD_MODE("-jobresult",       "", PSTAMPTOOL_MODE_JOBRESULT,    jobresultArgs);
+    PXOPT_ADD_MODE("-jobresult",       "", PSTAMPTOOL_MODE_JOBRESULT,    jobresultArgs);
 #endif
 
@@ -174,24 +183,4 @@
     addWhereStr(job_id); 
 
-#ifdef notdef
-    addWhereStr(exp_name); 
-    addWhereStr(telescope); 
-    // convert '-inst' to 'camera'
-    {
-        psString str = NULL;
-        bool status = false;
-        if ((str = psMetadataLookupStr(&status, config->args, "-inst"))) {
-            if (!psMetadataAddStr(config->where, PS_LIST_TAIL, "camera", 0, "==", str)) {
-                psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
-                psFree(config);
-                return NULL;
-            }
-        }
-    }
-    addWhereStr(exp_type); 
-    addWhereStr(class); 
-    addWhereStr(class_id); 
-#endif
-
     if (config->where->list->n < 1) {
         psFree(config->where);
