Index: trunk/ippTools/src/regtool.c
===================================================================
--- trunk/ippTools/src/regtool.c	(revision 8042)
+++ trunk/ippTools/src/regtool.c	(revision 8120)
@@ -12,6 +12,9 @@
 static psArray *newFrameSearchPending(pxConfig *config);
 static p1PendingExpRow *newToP1PendingExp(newExpRow *newExp);
-static p2PendingExpRow *newToP2PendingExp(newExpRow *newExp);
+static p2PendingExpRow *newToP2PendingExp(pxConfig *config, newExpRow *newExp);
 static p2PendingImfileRow *newImfileToP2PendingImfile(newImfileRow *newImfile);
+static rawScienceFrame *newToRawScienceFrame(pxConfig *config, newFrame *newFrame);
+static rawScienceExpRow *newToRawScienceExp(pxConfig *config, newExpRow *exp);
+
 
 # define MODECASE(caseName, func) \
@@ -89,9 +92,18 @@
     // insert 'new' rawScience & detrendframes
     if (psArrayLength(new) > 0) {
+        // start a transaction so we don't end up file raw* frames but no
+        // p2Pending*, etc.
+        if (!psDBTransaction(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(exp);
+            psFree(new);
+            return false;
+        }
+
         for (long i = 0; i < psArrayLength(new); i++) {
             newFrame *newFrame = new->data[i];
             if (detrend) {
                 // it's a detrend frame
-                rawDetrendFrame *frame = newToRawDetrendFrame(newFrame); 
+                rawDetrendFrame *frame = newToRawDetrendFrame(config, newFrame); 
                 if (!frame) {
                     psError(PS_ERR_UNKNOWN, false, "failed to convert new frame into a detrend frame");
@@ -100,4 +112,8 @@
                 }
                 if (!rawDetrendFrameInsert(config, frame)) {
+                    // rollback
+                    if (!psDBRollback(config->dbh)) {
+                        psError(PS_ERR_UNKNOWN, false, "database error");
+                    }
                     psError(PS_ERR_UNKNOWN, false, "failed to insert frame into the database");
                     psFree(frame);
@@ -112,6 +128,10 @@
             // it's a science frame
             // insert into into rawScienceExp
-            rawScienceFrame *frame = newToRawScienceFrame(newFrame); 
+            rawScienceFrame *frame = newToRawScienceFrame(config, newFrame); 
             if (!frame) {
+                // rollback
+                if (!psDBRollback(config->dbh)) {
+                    psError(PS_ERR_UNKNOWN, false, "database error");
+                }
                 psError(PS_ERR_UNKNOWN, false, "failed to convert new frame into a science frame");
                 psFree(new);
@@ -119,4 +139,8 @@
             }
             if (!rawScienceFrameInsert(config, frame)) {
+                // rollback
+                if (!psDBRollback(config->dbh)) {
+                    psError(PS_ERR_UNKNOWN, false, "database error");
+                }
                 psError(PS_ERR_UNKNOWN, false, "failed to insert frame into the database");
                 psFree(frame);
@@ -127,11 +151,22 @@
 
             // insert into into p2PendingExp
-            p2PendingExpRow *exp = newToP2PendingExp(newFrame->exposure);
+            // XXX add a newToP2PendingFrame()
+            // XXX add a p2PendingFrameInsert()
+            p2PendingExpRow *exp = newToP2PendingExp(config, newFrame->exposure);
             if (!exp) {
+                // rollback
+                if (!psDBRollback(config->dbh)) {
+                    psError(PS_ERR_UNKNOWN, false, "database error");
+                }
                 psError(PS_ERR_UNKNOWN, false, "failed to convert newExp into a p2PendingExp");
                 psFree(new);
                 return false;
             }
+
             if (!p2PendingExpInsertObject(config->dbh, exp)) {
+                // rollback
+                if (!psDBRollback(config->dbh)) {
+                    psError(PS_ERR_UNKNOWN, false, "database error");
+                }
                 psError(PS_ERR_UNKNOWN, false, "failed to insert p2PendingExp into the database");
                 psFree(exp);
@@ -145,5 +180,9 @@
                 p2PendingImfileRow *imfile = newImfileToP2PendingImfile(newFrame->images->data[i]);
                 if (!p2PendingImfileInsertObject(config->dbh, imfile)) {
-                psError(PS_ERR_UNKNOWN, false, "failed to insert p2PendingImfile into the database");
+                    // rollback
+                    if (!psDBRollback(config->dbh)) {
+                        psError(PS_ERR_UNKNOWN, false, "database error");
+                    }
+                    psError(PS_ERR_UNKNOWN, false, "failed to insert p2PendingImfile into the database");
                     psFree(imfile);
                     psFree(new);
@@ -152,4 +191,9 @@
                 psFree(imfile);
             }
+        }
+        // point of no return for p2Pending[Exp|Imfile]
+        if (!psDBCommit(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            return false;
         }
     }
@@ -231,8 +275,11 @@
         newExp->telescope,
         newExp->exp_type,
-//        newExp->class,
         newExp->imfiles,
         "my filter",
-        "my stats",
+        0.1, // airmass
+        0.2, // ra
+        0.3, // dec
+        0.4, // exp time
+        0.5, // background
         "my recipe",
         0xff // XXX calc version number
@@ -240,15 +287,77 @@
 }
 
-static p2PendingExpRow *newToP2PendingExp(newExpRow *newExp)
-{
+static p2PendingExpRow *newToP2PendingExp(pxConfig *config, newExpRow *exp)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(exp, NULL);
+
+    bool status = false;
+    psString filter = psMetadataLookupStr(&status, config->args, "-filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -filter");
+        return false;
+    }
+    if (!filter) {
+        psError(PS_ERR_UNKNOWN, true, "-filter is required");
+        return false;
+    }
+    psF32 airmass = psMetadataLookupF32(&status, config->args, "-airmass");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -airmass");
+        return false;
+    }
+    if (isnan(airmass)) {
+        psError(PS_ERR_UNKNOWN, true, "-airmass is required");
+        return false;
+    }
+    psF64 ra = psMetadataLookupF64(&status, config->args, "-ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -ra");
+        return false;
+    }
+    if (isnan(ra)) {
+        psError(PS_ERR_UNKNOWN, true, "-ra is required");
+        return false;
+    }
+    psF64 decl = psMetadataLookupF64(&status, config->args, "-decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -decl");
+        return false;
+    }
+    if (isnan(decl)) {
+        psError(PS_ERR_UNKNOWN, true, "-decl is required");
+        return false;
+    }
+    psF32 exp_time = psMetadataLookupF32(&status, config->args, "-exp_time");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -exp_time");
+        return false;
+    }
+    if (isnan(exp_time)) {
+        psError(PS_ERR_UNKNOWN, true, "-exp_time is required");
+        return false;
+    }
+    psF64 background = psMetadataLookupF64(&status, config->args, "-background");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -background");
+        return false;
+    }
+    if (isnan(background)) {
+        psError(PS_ERR_UNKNOWN, true, "-background is required");
+        return false;
+    }
+
     return p2PendingExpRowAlloc(
-        newExp->exp_id,
-        newExp->camera,
-        newExp->telescope,
-        newExp->exp_type,
-//        newExp->class,
-        newExp->imfiles,
-        "my filter", 
-        "my stats",
+        exp->exp_id,
+        exp->camera,
+        exp->telescope,
+        exp->exp_type,
+        exp->imfiles,
+        filter,
+        airmass,
+        ra,
+        decl,
+        exp_time,
+        background,
         "my recipe",
         0xff, // XXX calc version number
@@ -263,5 +372,4 @@
         newImfile->class_id,
         newImfile->uri,
-        "my stats",
         "my recipe",
         0xff, // XXX calc version number
@@ -269,2 +377,113 @@
     );
 }
+
+static rawScienceFrame *newToRawScienceFrame(pxConfig *config, newFrame *newFrame) 
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(newFrame, NULL);
+
+    newExpRow *newExp = newFrame->exposure;
+    rawScienceExpRow *rawScienceExp = newToRawScienceExp(config, newExp);
+    if (!rawScienceExp) {
+        psError(PS_ERR_UNKNOWN, false, "failed to convert newExp to rawScienceExp");
+        return NULL;
+    }
+
+    psArray *newImages = newFrame->images;
+    psArray *rawImages = psArrayAlloc(psArrayLength(newImages));
+    for (long i = 0; i < psArrayLength(newImages); i++) {
+        newImfileRow *newImfile = newImages->data[i];
+        rawImfileRow *rawImfile = rawImfileRowAlloc(
+            newImfile->exp_id,
+            newImfile->class,
+            newImfile->class_id,
+            newImfile->uri
+        );
+        psArrayAdd(rawImages, 0, rawImfile);
+        psFree(rawImfile);
+    }
+
+    rawScienceFrame *rawScienceFrame = rawScienceFrameAlloc(rawScienceExp, rawImages);
+    psFree(rawScienceExp);
+    psFree(rawImages);
+
+    return rawScienceFrame;
+}
+
+static rawScienceExpRow *newToRawScienceExp(pxConfig *config, newExpRow *exp)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(exp, NULL);
+
+    bool status = false;
+    psString filter = psMetadataLookupStr(&status, config->args, "-filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -filter");
+        return NULL;
+    }
+    if (!filter) {
+        psError(PS_ERR_UNKNOWN, true, "-filter is required");
+        return NULL;
+    }
+    psF32 airmass = psMetadataLookupF32(&status, config->args, "-airmass");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -airmass");
+        return NULL;
+    }
+    if (isnan(airmass)) {
+        psError(PS_ERR_UNKNOWN, true, "-airmass is required");
+        return NULL;
+    }
+    psF64 ra = psMetadataLookupF64(&status, config->args, "-ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -ra");
+        return NULL;
+    }
+    if (isnan(ra)) {
+        psError(PS_ERR_UNKNOWN, true, "-airmass is required");
+        return NULL;
+    }
+    psF64 decl = psMetadataLookupF64(&status, config->args, "-decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -decl");
+        return NULL;
+    }
+    if (isnan(decl)) {
+        psError(PS_ERR_UNKNOWN, true, "-decl is required");
+        return NULL;
+    }
+    psF32 exp_time = psMetadataLookupF32(&status, config->args, "-exp_time");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -exp_time");
+        return NULL;
+    }
+    if (isnan(exp_time)) {
+        psError(PS_ERR_UNKNOWN, true, "-exp_time is required");
+        return NULL;
+    }
+    psF64 background = psMetadataLookupF64(&status, config->args, "-background");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -background");
+        return NULL;
+    }
+    if (isnan(background)) {
+        psError(PS_ERR_UNKNOWN, true, "-background is required");
+        return NULL;
+    }
+
+    return rawScienceExpRowAlloc(
+        exp->exp_id,
+        exp->camera,
+        exp->telescope,
+        exp->exp_type,
+        exp->imfiles,
+        filter,
+        airmass,
+        ra,
+        decl,
+        exp_time,
+        background
+    );
+}
+
+
