IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Aug 16, 2008, 1:27:58 PM (18 years ago)
Author:
eugene
Message:

extensive changes from eam_branch_20080719:

  • added the 'cleanup' options to camtool, faketool, warptool, difftool, stacktool
  • added corresponding sql code
  • changed the states for camera, fake, warp, diff, and stack to the new set of states: new, full, goto_cleaned, cleaned, update, goto_purged, and purged
  • added 'data_state' entries to the detrend tables and the detRunSummary
  • added 'cleanup' options to dettool using the detRunSummary data_state as the control
  • moved dettool supporting code to dettool_STAGE, where stage is processedimfile, processedexp, etc.
  • converted dettool to use S64 for det_id and exp_id entries
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ippTools/src/dettool.c

    r18561 r19092  
    2828static bool inputMode(pxConfig *config);
    2929static bool rawMode(pxConfig *config);
    30 // processedimfile
    31 static bool toprocessedimfileMode(pxConfig *config);
    32 static bool addprocessedimfileMode(pxConfig *config);
    33 static bool processedimfileMode(pxConfig *config);
    34 static bool revertprocessedimfileMode(pxConfig *config);
    35 // processedexp
    36 static bool toprocessedexpMode(pxConfig *config);
    37 static bool addprocessedexpMode(pxConfig *config);
    38 static bool processedexpMode(pxConfig *config);
    39 static bool revertprocessedexpMode(pxConfig *config);
    40 // stackedimfile
    41 static bool tostackedMode(pxConfig *config);
    42 static bool addstackedMode(pxConfig *config);
    43 static bool stackedMode(pxConfig *config);
    44 static bool revertstackedMode(pxConfig *config);
    45 // normalizedstat
    46 static bool tonormalizedstatMode(pxConfig *config);
    47 static bool addnormalizedstatMode(pxConfig *config);
    48 static bool normalizedstatMode(pxConfig *config);
    49 static bool revertnormalizedstatMode(pxConfig *config);
    50 // normalizedimfile
    51 static bool tonormalizeMode(pxConfig *config);
    52 static bool addnormalizedimfileMode(pxConfig *config);
    53 static bool normalizedimfileMode(pxConfig *config);
    54 static bool revertnormalizedimfileMode(pxConfig *config);
    55 // normalizedexp
    56 static bool tonormalizedexpMode(pxConfig *config);
    57 static bool addnormalizedexpMode(pxConfig *config);
    58 static bool normalizedexpMode(pxConfig *config);
    59 static bool revertnormalizedexpMode(pxConfig *config);
    60 // residimfile
    61 static bool toresidimfileMode(pxConfig *config);
    62 static bool addresidimfileMode(pxConfig *config);
    63 static bool residimfileMode(pxConfig *config);
    64 static bool revertresidimfileMode(pxConfig *config);
    65 // residexp
    66 static bool toresidexpMode(pxConfig *config);
    67 static bool addresidexpMode(pxConfig *config);
    68 static bool residexpMode(pxConfig *config);
    69 static bool revertresidexpMode(pxConfig *config);
    70 static bool updateresidexpMode(pxConfig *config);
    71 // detrunsummary
    72 static bool todetrunsummaryMode(pxConfig *config);
    73 static bool adddetrunsummaryMode(pxConfig *config);
    74 static bool detrunsummaryMode(pxConfig *config);
    75 static bool revertdetrunsummaryMode(pxConfig *config);
    76 static bool updatedetrunsummaryMode(pxConfig *config);
     30
    7731// run
    7832static bool updatedetrunMode(pxConfig *config);
     
    8135static bool register_detrendMode(pxConfig *config);
    8236
    83 static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row);
    8437//static psArray *validDetInputClassIds(pxConfig *config, const char *det_id);
    8538//static psArray *searchInputImfiles(pxConfig *config, const char *det_id);
    8639static detInputExpRow *rawDetrenTodetInputExpRow(rawExpRow *rawExp, psS64 det_id, psS32 iteration);
    87 static psArray *searchRawImfiles(pxConfig *config);
    88 static bool startNewIteration(pxConfig *config, psS64 det_id);
    8940static psS32 incrementIteration(pxConfig *config, psS64 det_id);
    90 static bool setDetRunState(pxConfig *config, psS64 det_id, const char *state);
    91 static bool isValidMode(pxConfig *config, const char *mode);
    9241
    9342# define MODECASE(caseName, func) \
     
    12776        MODECASE(DETTOOL_MODE_PROCESSEDIMFILE,  processedimfileMode);
    12877        MODECASE(DETTOOL_MODE_REVERTPROCESSEDIMFILE, revertprocessedimfileMode);
     78        MODECASE(DETTOOL_MODE_UPDATEPROCESSEDIMFILE, updateprocessedimfileMode);
     79        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_PROCESSEDIMFILE, pendingcleanup_processedimfileMode);
     80        MODECASE(DETTOOL_MODE_DONECLEANUP_PROCESSEDIMFILE, donecleanup_processedimfileMode);
    12981        // exp
    13082        MODECASE(DETTOOL_MODE_TOPROCESSEDEXP,   toprocessedexpMode);
     
    13284        MODECASE(DETTOOL_MODE_PROCESSEDEXP,     processedexpMode);
    13385        MODECASE(DETTOOL_MODE_REVERTPROCESSEDEXP, revertprocessedexpMode);
     86        MODECASE(DETTOOL_MODE_UPDATEPROCESSEDEXP, updateprocessedexpMode);
     87        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_PROCESSEDEXP, pendingcleanup_processedexpMode);
     88        MODECASE(DETTOOL_MODE_DONECLEANUP_PROCESSEDEXP, donecleanup_processedexpMode);
    13489        // stacked
    13590        MODECASE(DETTOOL_MODE_TOSTACKED,        tostackedMode);
     
    13792        MODECASE(DETTOOL_MODE_STACKED,          stackedMode);
    13893        MODECASE(DETTOOL_MODE_REVERTSTACKED,    revertstackedMode);
     94        MODECASE(DETTOOL_MODE_UPDATESTACKED,    updatestackedMode);
     95        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_STACKED, pendingcleanup_stackedMode);
     96        MODECASE(DETTOOL_MODE_DONECLEANUP_STACKED, donecleanup_stackedMode);
    13997        // normalizedstat
    14098        MODECASE(DETTOOL_MODE_TONORMALIZEDSTAT, tonormalizedstatMode);
     
    142100        MODECASE(DETTOOL_MODE_NORMALIZEDSTAT,   normalizedstatMode);
    143101        MODECASE(DETTOOL_MODE_REVERTNORMALIZEDSTAT, revertnormalizedstatMode);
     102        MODECASE(DETTOOL_MODE_UPDATENORMALIZEDSTAT, updatenormalizedstatMode);
     103        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDSTAT, pendingcleanup_normalizedstatMode);
     104        MODECASE(DETTOOL_MODE_DONECLEANUP_NORMALIZEDSTAT, donecleanup_normalizedstatMode);
    144105        // normalizedimfile
    145106        MODECASE(DETTOOL_MODE_TONORMALIZE,      tonormalizeMode);
     
    147108        MODECASE(DETTOOL_MODE_NORMALIZEDIMFILE, normalizedimfileMode);
    148109        MODECASE(DETTOOL_MODE_REVERTNORMALIZEDIMFILE, revertnormalizedimfileMode);
     110        MODECASE(DETTOOL_MODE_UPDATENORMALIZEDIMFILE, updatenormalizedimfileMode);
     111        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDIMFILE, pendingcleanup_normalizedimfileMode);
     112        MODECASE(DETTOOL_MODE_DONECLEANUP_NORMALIZEDIMFILE, donecleanup_normalizedimfileMode);
    149113        // normalizedexp
    150114        MODECASE(DETTOOL_MODE_TONORMALIZEDEXP,  tonormalizedexpMode);
     
    152116        MODECASE(DETTOOL_MODE_NORMALIZEDEXP,    normalizedexpMode);
    153117        MODECASE(DETTOOL_MODE_REVERTNORMALIZEDEXP, revertnormalizedexpMode);
     118        MODECASE(DETTOOL_MODE_UPDATENORMALIZEDEXP, updatenormalizedexpMode);
     119        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_NORMALIZEDEXP, pendingcleanup_normalizedexpMode);
     120        MODECASE(DETTOOL_MODE_DONECLEANUP_NORMALIZEDEXP, donecleanup_normalizedexpMode);
    154121        // residimfile
    155122        MODECASE(DETTOOL_MODE_TORESIDIMFILE,    toresidimfileMode);
     
    157124        MODECASE(DETTOOL_MODE_RESIDIMFILE,      residimfileMode);
    158125        MODECASE(DETTOOL_MODE_REVERTRESIDIMFILE,revertresidimfileMode);
     126        MODECASE(DETTOOL_MODE_UPDATERESIDIMFILE, updateresidimfileMode);
     127        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_RESIDIMFILE, pendingcleanup_residimfileMode);
     128        MODECASE(DETTOOL_MODE_DONECLEANUP_RESIDIMFILE, donecleanup_residimfileMode);
    159129        // residexp
    160130        MODECASE(DETTOOL_MODE_TORESIDEXP,       toresidexpMode);
     
    163133        MODECASE(DETTOOL_MODE_REVERTRESIDEXP,   revertresidexpMode);
    164134        MODECASE(DETTOOL_MODE_UPDATERESIDEXP,   updateresidexpMode);
     135        MODECASE(DETTOOL_MODE_PENDINGCLEANUP_RESIDEXP, pendingcleanup_residexpMode);
     136        MODECASE(DETTOOL_MODE_DONECLEANUP_RESIDEXP, donecleanup_residexpMode);
    165137        // detrunsummary
    166138        MODECASE(DETTOOL_MODE_TODETRUNSUMMARY,  todetrunsummaryMode);
     
    208180   
    209181    psMetadata *where = psMetadataAlloc();
    210     PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
     182    PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
    211183    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
    212184    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
     
    722694
    723695   
    724     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
     696    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
    725697    PXOPT_LOOKUP_STR(det_type, config->args, "-set_det_type", false, false); // optional
    726698    PXOPT_LOOKUP_STR(mode, config->args, "-set_mode", false, false); // optional
     
    758730    {
    759731        psMetadata *where = psMetadataAlloc();
    760         psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", (psS64)atoll(det_id));
     732        psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", det_id);
    761733        detRuns = detRunSelectRowObjects(config->dbh, where, 0);
    762734        psFree(where);
     
    768740    // sanity check the result... we should have only found one det_id
    769741    if (psArrayLength(detRuns) != 1) {
    770         psAbort("found more then one detRun matching det_id %" PRId64 " (this should not happen)", (psS64)atoll(det_id));
     742        psAbort("found more then one detRun matching det_id %" PRId64 " (this should not happen)", det_id);
    771743        return false;                   // unreachable
    772744    }
     
    939911    psFree(time_filter);
    940912
    941     if (!p_psDBRunQuery(config->dbh, query, (psS64)newDet_id, (psS64)atoll(det_id))) {
     913    if (!p_psDBRunQuery(config->dbh, query, (long long) newDet_id, (long long) det_id)) {
    942914        psError(PS_ERR_UNKNOWN, false, "database error");
    943915        psFree(query);
     
    987959    psMetadata *where = psMetadataAlloc();
    988960    PXOPT_COPY_STR(config->args, where, "-det_type", "det_type", "==");
    989     PXOPT_COPY_STR(config->args, where, "-det_id",   "det_id", "==");
     961    PXOPT_COPY_S64(config->args, where, "-det_id",   "det_id", "==");
    990962
    991963    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
     
    11521124
    11531125    psMetadata *where = psMetadataAlloc();
    1154     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     1126    PXOPT_COPY_S64(config->args, where, "-det_id",    "det_id", "==");
    11551127    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    11561128    PXOPT_COPY_S64(config->args, where, "-exp_id",    "exp_id", "==");
     
    12511223}
    12521224
    1253 static bool toprocessedimfileMode(pxConfig *config)
    1254 {
    1255     PS_ASSERT_PTR_NON_NULL(config, false);
    1256 
    1257     psMetadata *where = psMetadataAlloc();
    1258     PXOPT_COPY_STR(config->args, where, "-det_id",   "det_id", "==");
    1259     PXOPT_COPY_STR(config->args, where, "-exp_id",   "exp_id", "==");
    1260     PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
    1261 
    1262     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    1263     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    1264 
    1265     psString query = pxDataGet("dettool_toprocessedimfile.sql");
    1266     if (!query) {
    1267         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    1268         return false;
    1269     }
    1270 
    1271     if (psListLength(where->list)) {
    1272         psString whereClause = psDBGenerateWhereConditionSQL(where, "rawImfile");
    1273         psStringAppend(&query, " AND %s", whereClause);
    1274         psFree(whereClause);
    1275     }
    1276     psFree (where);
    1277 
    1278     // treat limit == 0 as "no limit"
    1279     if (limit) {
    1280         psString limitString = psDBGenerateLimitSQL(limit);
    1281         psStringAppend(&query, " %s", limitString);
    1282         psFree(limitString);
    1283     }
    1284 
    1285     if (!p_psDBRunQuery(config->dbh, query)) {
    1286         psError(PS_ERR_UNKNOWN, false, "database error");
    1287         psFree(query);
    1288         return false;
    1289     }
    1290     psFree(query);
    1291 
    1292     psArray *output = p_psDBFetchResult(config->dbh);
    1293     if (!output) {
    1294         psError(PS_ERR_UNKNOWN, false, "database error");
    1295         return false;
    1296     }
    1297     if (!psArrayLength(output)) {
    1298         psTrace("dettool", PS_LOG_INFO, "no rows found");
    1299         psFree(output);
    1300         return true;
    1301     }
    1302 
    1303     // negative simple so the default is true
    1304     if (!ippdbPrintMetadatas(stdout, output, "detPendingProcessedImfile", !simple)) {
    1305         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    1306         psFree(output);
    1307         return false;
    1308     }
    1309 
    1310     psFree(output);
    1311 
    1312     return true;
    1313 }
    1314 
    1315 static bool addprocessedimfileMode(pxConfig *config)
    1316 {
    1317     PS_ASSERT_PTR_NON_NULL(config, false);
    1318 
    1319     // det_id, exp_id, class_id, uri, recipe, -bg, -bg_stdev are required
    1320     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    1321     PXOPT_LOOKUP_STR(exp_id, config->args, "-exp_id", true, false);
    1322     PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
    1323 
    1324     // default values
    1325     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    1326 
    1327     // Required if code == 0
    1328     PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false);
    1329     PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false);
    1330 
    1331     // optional
    1332     PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    1333     PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
    1334     PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
    1335     PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
    1336     PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
    1337     PXOPT_LOOKUP_F64(fringe_2, config->args, "-fringe_2", false, false);
    1338     PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
    1339     PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
    1340     PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
    1341     PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
    1342     PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    1343     PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    1344 
    1345     // find the matching rawImfile by exp_id/class_id
    1346     psMetadata *where = psMetadataAlloc();
    1347     PXOPT_COPY_STR(config->args, where, "-exp_id",   "exp_id", "==");
    1348     PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
    1349 
    1350     psArray *rawImfiles = rawImfileSelectRowObjects(config->dbh, where, 0);
    1351     psFree(where);
    1352 
    1353     if (!rawImfiles) {
    1354         psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found ");
    1355         return false;
    1356     }
    1357 
    1358     // create a new detProcessedImfile object
    1359     detProcessedImfileRow *detRow = detProcessedImfileRowAlloc(
    1360         (psS64)atoll(det_id),
    1361         (psS64)atoll(exp_id),
    1362         class_id,
    1363         uri,
    1364         recipe,
    1365         bg,
    1366         bg_stdev,
    1367         bg_mean_stdev,
    1368         fringe_0,
    1369         fringe_1,
    1370         fringe_2,
    1371         user_1,
    1372         user_2,
    1373         user_3,
    1374         user_4,
    1375         user_5,
    1376         path_base,
    1377         code
    1378     );
    1379     psFree(rawImfiles);
    1380 
    1381     // insert the new row into the detProcessedImfile table
    1382     if (!detProcessedImfileInsertObject(config->dbh, detRow)) {
    1383         psError(PS_ERR_UNKNOWN, false, "database error");
    1384         psFree(detRow);
    1385         return false;
    1386     }
    1387 
    1388     psFree(detRow);
    1389 
    1390     return true;
    1391 }
    1392 
    1393 static bool processedimfileMode(pxConfig *config)
    1394 {
    1395     PS_ASSERT_PTR_NON_NULL(config, false);
    1396 
    1397     char *value = NULL;
    1398 
    1399     PXOPT_LOOKUP_BOOL(included, config->args, "-included", false);
    1400     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    1401     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    1402     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    1403 
    1404     psMetadata *where = psMetadataAlloc();
    1405     PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    1406     PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
    1407     PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
    1408 
    1409     psString query = pxDataGet("dettool_processedimfile.sql");
    1410     if (!query) {
    1411         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    1412         psFree(where);
    1413         return false;
    1414     }
    1415 
    1416     // add the two required restrictions: detRun.state and detRun.mode
    1417     // NOTE the above query requires one of the following two WHERE statements
    1418     {
    1419         bool status;
    1420         if ((value = psMetadataLookupStr(&status, config->args, "-select_state"))) {
    1421             psStringAppend(&query, " WHERE detRun.state = '%s'", value);
    1422         } else {
    1423             psStringAppend(&query, " WHERE detRun.state = 'run'");
    1424         }
    1425         if ((value = psMetadataLookupStr(&status, config->args, "-select_mode"))) {
    1426             psStringAppend(&query, " AND detRun.mode = '%s'", value);
    1427         } else {
    1428             psStringAppend(&query, " AND detRun.mode = 'master'");
    1429         }
    1430     }
    1431 
    1432     if (psListLength(where->list)) {
    1433         psString whereClause = psDBGenerateWhereConditionSQL(where, "detProcessedImfile");
    1434         psStringAppend(&query, " AND %s", whereClause);
    1435         psFree(whereClause);
    1436     }
    1437     psFree (where);
    1438 
    1439     // restrict search to included imfiles
    1440     if (included) {
    1441         psStringAppend(&query, " AND detInputExp.include = 1");
    1442     }
    1443 
    1444     if (faulted) {
    1445         // list only faulted rows
    1446         psStringAppend(&query, " %s", "AND detProcessedImfile.fault != 0");
    1447     } else {
    1448         // don't list faulted rows
    1449         psStringAppend(&query, " %s", "AND detProcessedImfile.fault = 0");
    1450     }
    1451 
    1452     // treat limit == 0 as "no limit"
    1453     if (limit) {
    1454         psString limitString = psDBGenerateLimitSQL(limit);
    1455         psStringAppend(&query, " %s", limitString);
    1456         psFree(limitString);
    1457     }
    1458 
    1459     if (!p_psDBRunQuery(config->dbh, query)) {
    1460         psError(PS_ERR_UNKNOWN, false, "database error");
    1461         psFree(query);
    1462         return false;
    1463     }
    1464     psFree(query);
    1465 
    1466     psArray *output = p_psDBFetchResult(config->dbh);
    1467     if (!output) {
    1468         psError(PS_ERR_UNKNOWN, false, "database error");
    1469         return false;
    1470     }
    1471     if (!psArrayLength(output)) {
    1472         psTrace("dettool", PS_LOG_INFO, "no rows found");
    1473         psFree(output);
    1474         return true;
    1475     }
    1476 
    1477     // negative simple so the default is true
    1478     if (!ippdbPrintMetadatas(stdout, output, "rawImfile", !simple)) {
    1479         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    1480         psFree(output);
    1481         return false;
    1482     }
    1483 
    1484     psFree(output);
    1485 
    1486     return true;
    1487 }
    1488 
    1489 static bool revertprocessedimfileMode(pxConfig *config)
    1490 {
    1491     PS_ASSERT_PTR_NON_NULL(config, false);
    1492 
    1493     psMetadata *where = psMetadataAlloc();
    1494     PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    1495     PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
    1496     PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
    1497     PXOPT_COPY_S16(config->args, where, "-code", "fault", "==");
    1498 
    1499     psString query = pxDataGet("dettool_revertprocessedimfile.sql");
    1500     if (!query) {
    1501         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    1502         return false;
    1503     }
    1504 
    1505     if (psListLength(where->list)) {
    1506         psString whereClause = psDBGenerateWhereConditionSQL(where, "detProcessedImfile");
    1507         psStringAppend(&query, " AND %s", whereClause);
    1508         psFree(whereClause);
    1509     }
    1510     psFree(where);
    1511 
    1512     if (!p_psDBRunQuery(config->dbh, query)) {
    1513         psError(PS_ERR_UNKNOWN, false, "database error");
    1514         psFree(query);
    1515         return false;
    1516     }
    1517     psFree(query);
    1518 
    1519     if (psDBAffectedRows(config->dbh) < 1) {
    1520         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    1521         return false;
    1522     }
    1523 
    1524     return true;
    1525 }
    1526 
    1527 static bool toprocessedexpMode(pxConfig *config)
    1528 {
    1529     PS_ASSERT_PTR_NON_NULL(config, false);
    1530 
    1531     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    1532     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    1533 
    1534     psString query = pxDataGet("dettool_toprocessedexp.sql");
    1535     if (!query) {
    1536         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    1537         return false;
    1538     }
    1539 
    1540     // treat limit == 0 as "no limit"
    1541     if (limit) {
    1542         psString limitString = psDBGenerateLimitSQL(limit);
    1543         psStringAppend(&query, " %s", limitString);
    1544         psFree(limitString);
    1545     }
    1546 
    1547     if (!p_psDBRunQuery(config->dbh, query)) {
    1548         psError(PS_ERR_UNKNOWN, false, "database error");
    1549         psFree(query);
    1550         return false;
    1551     }
    1552     psFree(query);
    1553 
    1554     psArray *output = p_psDBFetchResult(config->dbh);
    1555     if (!output) {
    1556         psError(PS_ERR_UNKNOWN, false, "database error");
    1557         return false;
    1558     }
    1559     if (!psArrayLength(output)) {
    1560         psTrace("dettool", PS_LOG_INFO, "no rows found");
    1561         psFree(output);
    1562         return true;
    1563     }
    1564 
    1565     // negative simple so the default is true
    1566     if (!ippdbPrintMetadatas(stdout, output, "detPendingProcessedExp", !simple)) {
    1567         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    1568         psFree(output);
    1569         return false;
    1570     }
    1571 
    1572     psFree(output);
    1573 
    1574     return true;
    1575 }
    1576 
    1577 static bool addprocessedexpMode(pxConfig *config)
    1578 {
    1579     PS_ASSERT_PTR_NON_NULL(config, false);
    1580 
    1581     // det_id, exp_id, recip, -bg, -bg_stdev
    1582     // are required
    1583     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    1584     PXOPT_LOOKUP_STR(exp_id, config->args, "-exp_id", true, false);
    1585 
    1586     // default values
    1587     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    1588 
    1589     // Required if code == 0
    1590     PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false);
    1591 
    1592     // optional
    1593     PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    1594     PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
    1595     PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
    1596     PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
    1597     PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
    1598     PXOPT_LOOKUP_F64(fringe_2, config->args, "-fringe_2", false, false);
    1599     PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
    1600     PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
    1601     PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
    1602     PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
    1603     PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    1604     PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", true, false);
    1605 
    1606     psString query = pxDataGet("dettool_addprocessedexp.sql");
    1607     if (!query) {
    1608         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    1609         return false;
    1610     }
    1611 
    1612     if (!p_psDBRunQuery(config->dbh, query, det_id, exp_id)) {
    1613         psError(PS_ERR_UNKNOWN, false, "database error");
    1614         psFree(query);
    1615         return false;
    1616     }
    1617     psFree(query);
    1618 
    1619     psArray *output = p_psDBFetchResult(config->dbh);
    1620     if (!output) {
    1621         psError(PS_ERR_UNKNOWN, false, "database error");
    1622         return false;
    1623     }
    1624     if (!psArrayLength(output)) {
    1625         psTrace("dettool", PS_LOG_INFO, "no rows found");
    1626         psFree(output);
    1627         return true;
    1628     }
    1629     psFree(output);
    1630 
    1631     // create a new detProcessedImfile object
    1632     detProcessedExpRow *detRow = detProcessedExpRowAlloc(
    1633         (psS64)atoll(det_id),
    1634         (psS64)atoll(exp_id),
    1635         recipe,
    1636         bg,
    1637         bg_stdev,
    1638         bg_mean_stdev,
    1639         fringe_0,
    1640         fringe_1,
    1641         fringe_2,
    1642         user_1,
    1643         user_2,
    1644         user_3,
    1645         user_4,
    1646         user_5,
    1647         path_base,
    1648         code
    1649     );
    1650 
    1651     // insert the new row into the detProcessedImfile table
    1652     if (!detProcessedExpInsertObject(config->dbh, detRow)) {
    1653         psError(PS_ERR_UNKNOWN, false, "database error");
    1654         psFree(detRow);
    1655         return false;
    1656     }
    1657 
    1658     psFree(detRow);
    1659 
    1660     return true;
    1661 }
    1662 
    1663 static bool processedexpMode(pxConfig *config)
    1664 {
    1665     PS_ASSERT_PTR_NON_NULL(config, false);
    1666 
    1667     psMetadata *where = psMetadataAlloc();
    1668     PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    1669     PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
    1670 
    1671     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    1672     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    1673     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    1674 
    1675     psString query = psStringCopy("SELECT * FROM detProcessedExp");
    1676 
    1677     if (psListLength(where->list)) {
    1678         psString whereClause = psDBGenerateWhereSQL(where, NULL);
    1679         psStringAppend(&query, " %s", whereClause);
    1680         psFree(whereClause);
    1681     }
    1682     psFree(where);
    1683 
    1684     if (faulted) {
    1685         // list only faulted rows
    1686         psStringAppend(&query, " %s", "AND detProcessedExp.fault != 0");
    1687     } else {
    1688         // don't list faulted rows
    1689         psStringAppend(&query, " %s", "AND detProcessedExp.fault = 0");
    1690     }
    1691 
    1692     // treat limit == 0 as "no limit"
    1693     if (limit) {
    1694         psString limitString = psDBGenerateLimitSQL(limit);
    1695         psStringAppend(&query, " %s", limitString);
    1696         psFree(limitString);
    1697     }
    1698 
    1699     if (!p_psDBRunQuery(config->dbh, query)) {
    1700         psError(PS_ERR_UNKNOWN, false, "database error");
    1701         psFree(query);
    1702         return false;
    1703     }
    1704     psFree(query);
    1705 
    1706     psArray *output = p_psDBFetchResult(config->dbh);
    1707     if (!output) {
    1708         psError(PS_ERR_UNKNOWN, false, "database error");
    1709         return false;
    1710     }
    1711     if (!psArrayLength(output)) {
    1712         psTrace("dettool", PS_LOG_INFO, "no rows found");
    1713         psFree(output);
    1714         return true;
    1715     }
    1716 
    1717     // negative simple so the default is true
    1718     if (!ippdbPrintMetadatas(stdout, output, "detProcessedExp", !simple)) {
    1719         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    1720         psFree(output);
    1721         return false;
    1722     }
    1723 
    1724     psFree(output);
    1725 
    1726     return true;
    1727 }
    1728 
    1729 
    1730 static bool revertprocessedexpMode(pxConfig *config)
    1731 {
    1732     PS_ASSERT_PTR_NON_NULL(config, false);
    1733 
    1734     psMetadata *where = psMetadataAlloc();
    1735     PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    1736     PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
    1737     PXOPT_COPY_S16(config->args, where, "-code",   "fault", "==");
    1738 
    1739     psString query = pxDataGet("dettool_revertprocessedexp.sql");
    1740     if (!query) {
    1741         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    1742         return false;
    1743     }
    1744 
    1745     if (psListLength(where->list)) {
    1746         psString whereClause = psDBGenerateWhereConditionSQL(where, "detProcessedExp");
    1747         psStringAppend(&query, " AND %s", whereClause);
    1748         psFree(whereClause);
    1749     }
    1750     psFree(where);
    1751 
    1752     if (!p_psDBRunQuery(config->dbh, query)) {
    1753         psError(PS_ERR_UNKNOWN, false, "database error");
    1754         psFree(query);
    1755         return false;
    1756     }
    1757     psFree(query);
    1758 
    1759     if (psDBAffectedRows(config->dbh) < 1) {
    1760         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    1761         return false;
    1762     }
    1763 
    1764     return true;
    1765 }
    1766 
    1767 
    1768 static bool tostackedMode(pxConfig *config)
    1769 {
    1770     PS_ASSERT_PTR_NON_NULL(config, false);
    1771 
    1772     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    1773     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    1774 
    1775     psString query = pxDataGet("dettool_tostacked.sql");
    1776     if (!query) {
    1777         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    1778         return false;
    1779     }
    1780 
    1781     // treat limit == 0 as "no limit"
    1782     if (limit) {
    1783         psString limitString = psDBGenerateLimitSQL(limit);
    1784         psStringAppend(&query, " %s", limitString);
    1785         psFree(limitString);
    1786     }
    1787 
    1788     if (!p_psDBRunQuery(config->dbh, query)) {
    1789         psError(PS_ERR_UNKNOWN, false, "database error");
    1790         psFree(query);
    1791         return false;
    1792     }
    1793     psFree(query);
    1794 
    1795     psArray *output = p_psDBFetchResult(config->dbh);
    1796     if (!output) {
    1797         psError(PS_ERR_UNKNOWN, false, "database error");
    1798         return false;
    1799     }
    1800     if (!psArrayLength(output)) {
    1801         psTrace("dettool", PS_LOG_INFO, "no rows found");
    1802         psFree(output);
    1803         return true;
    1804     }
    1805 
    1806     // negative simple so the default is true
    1807     if (!ippdbPrintMetadatas(stdout, output, "detPendingStackedImfile", !simple)) {
    1808         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    1809         psFree(output);
    1810         return false;
    1811     }
    1812 
    1813     psFree(output);
    1814 
    1815     return true;
    1816 }
    1817 
    1818 // this is NOT a command-line mode : it is used by 'addstackedMode'
    1819 static psArray *searchRawImfiles(pxConfig *config)
    1820 {
    1821     PS_ASSERT_PTR_NON_NULL(config, NULL);
    1822 
    1823     psMetadata *where = psMetadataAlloc();
    1824     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    1825     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    1826 
    1827     // select exp_ids from detInputExp matching det_id & iteration
    1828     // where query should be pre-generated
    1829     psArray *detInputExp = detInputExpSelectRowObjects(config->dbh, where, 0);
    1830     psFree (where);
    1831 
    1832     if (!detInputExp) {
    1833         psError(PS_ERR_UNKNOWN, false, "no rawExp rows found");
    1834         return NULL;
    1835     }
    1836 
    1837     // generate where query with just the exp_ids
    1838     psMetadata *where_exp_ids = psMetadataAlloc();
    1839     for (long i = 0; i < psArrayLength(detInputExp); i++) {
    1840         detInputExpRow *row = detInputExp->data[i];
    1841         if (!psMetadataAddS64(where_exp_ids, PS_LIST_TAIL, "exp_id",
    1842                 PS_META_DUPLICATE_OK, "==", row->exp_id)
    1843         ) {
    1844             psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1845             psFree(detInputExp);
    1846             psFree(where_exp_ids);
    1847             return NULL;
    1848         }
    1849     }
    1850     psFree(detInputExp);
    1851 
    1852     // select rawImfiles with matching exp_ids
    1853     psArray *rawImfiles =
    1854         rawImfileSelectRowObjects(config->dbh, where_exp_ids, 0);
    1855     psFree(where_exp_ids);
    1856     if (!rawImfiles) {
    1857         psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found");
    1858         return NULL;
    1859     }
    1860 
    1861     return rawImfiles;
    1862 }
    1863 
    1864 static bool addstackedMode(pxConfig *config)
    1865 {
    1866     PS_ASSERT_PTR_NON_NULL(config, false);
    1867 
    1868     // det_id, iteration, class_id, uri, & recipe are required
    1869     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    1870     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", true, false);
    1871     PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
    1872 
    1873     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    1874 
    1875     // Required if code == 0
    1876     PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false);
    1877     PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false);
    1878 
    1879     // optional
    1880     PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    1881     PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
    1882     PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
    1883     PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
    1884     PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
    1885     PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
    1886     PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
    1887     PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    1888 
    1889     // correlate the class_id against the input exposure(s)
    1890     // searchRawImfiles defines a where clause to search by det_id and iteration
    1891     psArray *rawImfiles = searchRawImfiles(config);
    1892 
    1893     if (!rawImfiles) {
    1894         psError(PS_ERR_UNKNOWN, false, "failed to get rawImfiles from db");
    1895         return false;
    1896     }
    1897 
    1898     bool valid_class_id = false;
    1899     if (rawImfiles) {
    1900         for (long i = 0; i < psArrayLength(rawImfiles); i++) {
    1901             if (!rawImfiles->data[i]) {
    1902                 fprintf (stderr, "*");
    1903                 continue;
    1904             }
    1905             if (strcmp(class_id, ((rawImfileRow *)rawImfiles->data[i])->class_id) == 0) {
    1906                 valid_class_id = true;
    1907                 break;
    1908             }
    1909         }
    1910         psFree(rawImfiles);
    1911     }
    1912 
    1913     if (!valid_class_id) {
    1914         psError(PS_ERR_UNKNOWN, true,
    1915             "class_id can not be correlated with the input exposures");
    1916         return false;
    1917     }
    1918 
    1919     // create a new detStackedImfile object
    1920     detStackedImfileRow *stackedImfile = detStackedImfileRowAlloc(
    1921             (psS64)atoll(det_id),
    1922             iteration,
    1923             class_id,
    1924             uri,
    1925             recipe,
    1926             bg,
    1927             bg_stdev,
    1928             bg_mean_stdev,
    1929             user_1,
    1930             user_2,
    1931             user_3,
    1932             user_4,
    1933             user_5,
    1934             code
    1935         );
    1936 
    1937     // insert the new row into the detProcessedImfile table
    1938     if (!detStackedImfileInsertObject(config->dbh, stackedImfile)) {
    1939         psError(PS_ERR_UNKNOWN, false, "database error");
    1940         psFree(stackedImfile);
    1941         return false;
    1942     }
    1943 
    1944     psFree(stackedImfile);
    1945 
    1946     return true;
    1947 }
    1948 
    1949 static bool stackedMode(pxConfig *config)
    1950 {
    1951     PS_ASSERT_PTR_NON_NULL(config, false);
    1952 
    1953     psMetadata *where = psMetadataAlloc();
    1954     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    1955     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    1956     PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
    1957     PXOPT_COPY_STR(config->args, where, "-recip",     "recipe", "==");
    1958 
    1959     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    1960     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    1961     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    1962 
    1963     psString query = pxDataGet("dettool_stacked.sql");
    1964     if (!query) {
    1965         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    1966         psFree(where);
    1967         return false;
    1968     }
    1969 
    1970     if (psListLength(where->list)) {
    1971         psString whereClause = psDBGenerateWhereConditionSQL(where, "detStackedImfile");
    1972         psStringAppend(&query, " AND %s", whereClause);
    1973         psFree(whereClause);
    1974     }
    1975     psFree(where);
    1976 
    1977     if (faulted) {
    1978         // list only faulted rows
    1979         psStringAppend(&query, " %s", "AND detStackedImfile.fault != 0");
    1980     } else {
    1981         // don't list faulted rows
    1982         psStringAppend(&query, " %s", "AND detStackedImfile.fault = 0");
    1983     }
    1984 
    1985     // treat limit == 0 as "no limit"
    1986     if (limit) {
    1987         psString limitString = psDBGenerateLimitSQL(limit);
    1988         psStringAppend(&query, " %s", limitString);
    1989         psFree(limitString);
    1990     }
    1991 
    1992     if (!p_psDBRunQuery(config->dbh, query)) {
    1993         psError(PS_ERR_UNKNOWN, false, "database error");
    1994         psFree(query);
    1995         return false;
    1996     }
    1997     psFree(query);
    1998 
    1999     psArray *output = p_psDBFetchResult(config->dbh);
    2000     if (!output) {
    2001         psError(PS_ERR_UNKNOWN, false, "database error");
    2002         return false;
    2003     }
    2004     if (!psArrayLength(output)) {
    2005         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2006         psFree(output);
    2007         return true;
    2008     }
    2009 
    2010     // negative simple so the default is true
    2011     if (!ippdbPrintMetadatas(stdout, output, "rawImfile", !simple)) {
    2012         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2013         psFree(output);
    2014         return false;
    2015     }
    2016 
    2017     psFree(output);
    2018 
    2019     return true;
    2020 }
    2021 
    2022 
    2023 static bool revertstackedMode(pxConfig *config)
    2024 {
    2025     PS_ASSERT_PTR_NON_NULL(config, false);
    2026 
    2027     psMetadata *where = psMetadataAlloc();
    2028     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    2029     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    2030     PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
    2031     PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
    2032 
    2033     psString query = pxDataGet("dettool_revertstacked.sql");
    2034     if (!query) {
    2035         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2036         return false;
    2037     }
    2038 
    2039     if (psListLength(where->list)) {
    2040         psString whereClause = psDBGenerateWhereConditionSQL(where, "detStackedImfile");
    2041         psStringAppend(&query, " AND %s", whereClause);
    2042         psFree(whereClause);
    2043     }
    2044     psFree(where);
    2045 
    2046     if (!p_psDBRunQuery(config->dbh, query)) {
    2047         psError(PS_ERR_UNKNOWN, false, "database error");
    2048         psFree(query);
    2049         return false;
    2050     }
    2051     psFree(query);
    2052 
    2053     if (psDBAffectedRows(config->dbh) < 1) {
    2054         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    2055         return false;
    2056     }
    2057 
    2058     return true;
    2059 }
    2060 
    2061 static bool tonormalizedstatMode(pxConfig *config)
    2062 {
    2063     PS_ASSERT_PTR_NON_NULL(config, false);
    2064 
    2065     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    2066     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2067 
    2068     psString query = pxDataGet("dettool_tonormalizedstat.sql");
    2069     if (!query) {
    2070         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2071         return false;
    2072     }
    2073 
    2074     // treat limit == 0 as "no limit"
    2075     if (limit) {
    2076         psString limitString = psDBGenerateLimitSQL(limit);
    2077         psStringAppend(&query, " %s", limitString);
    2078         psFree(limitString);
    2079     }
    2080 
    2081     if (!p_psDBRunQuery(config->dbh, query)) {
    2082         psError(PS_ERR_UNKNOWN, false, "database error");
    2083         psFree(query);
    2084         return false;
    2085     }
    2086     psFree(query);
    2087 
    2088     psArray *output = p_psDBFetchResult(config->dbh);
    2089     if (!output) {
    2090         psError(PS_ERR_UNKNOWN, false, "database error");
    2091         return false;
    2092     }
    2093     if (!psArrayLength(output)) {
    2094         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2095         psFree(output);
    2096         return true;
    2097     }
    2098 
    2099     // negative simple so the default is true
    2100     if (!ippdbPrintMetadatas(stdout, output, "detPendingNormStatImfile", !simple)) {
    2101         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2102         psFree(output);
    2103         return false;
    2104     }
    2105 
    2106     psFree(output);
    2107 
    2108     return true;
    2109 }
    2110 
    2111 static bool addnormalizedstatMode(pxConfig *config)
    2112 {
    2113     PS_ASSERT_PTR_NON_NULL(config, NULL);
    2114 
    2115     // required
    2116     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    2117     PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
    2118 
    2119     // optional
    2120     PXOPT_LOOKUP_F32(norm, config->args, "-norm", false, false);
    2121 
    2122     // default
    2123     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    2124     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    2125 
    2126     if (!detNormalizedStatImfileInsert(config->dbh,
    2127         (psS64)atoll(det_id),
    2128         iteration,
    2129         class_id,
    2130         norm,
    2131         code
    2132     )) {
    2133         psError(PS_ERR_UNKNOWN, false, "database error");
    2134         return false;
    2135     }
    2136 
    2137     return true;
    2138 }
    2139 
    2140 
    2141 static bool normalizedstatMode(pxConfig *config)
    2142 {
    2143     PS_ASSERT_PTR_NON_NULL(config, false);
    2144 
    2145     psMetadata *where = psMetadataAlloc();
    2146     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    2147     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    2148     PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
    2149 
    2150     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    2151     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    2152     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2153 
    2154     psString query = pxDataGet("dettool_normalizedstat.sql");
    2155     if (!query) {
    2156         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2157         return false;
    2158     }
    2159 
    2160     if (faulted) {
    2161         // list only faulted rows
    2162         psStringAppend(&query, " %s", "WHERE fault != 0");
    2163     } else {
    2164         // don't list faulted rows
    2165         psStringAppend(&query, " %s", "WHERE fault = 0");
    2166     }
    2167 
    2168     if (psListLength(where->list)) {
    2169         psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    2170         psStringAppend(&query, " AND %s", whereClause);
    2171         psFree(whereClause);
    2172     }
    2173     psFree(where);
    2174 
    2175     // treat limit == 0 as "no limit"
    2176     if (limit) {
    2177         psString limitString = psDBGenerateLimitSQL(limit);
    2178         psStringAppend(&query, " %s", limitString);
    2179         psFree(limitString);
    2180     }
    2181 
    2182     if (!p_psDBRunQuery(config->dbh, query)) {
    2183         psError(PS_ERR_UNKNOWN, false, "database error");
    2184         psFree(query);
    2185         return false;
    2186     }
    2187     psFree(query);
    2188 
    2189     psArray *output = p_psDBFetchResult(config->dbh);
    2190     if (!output) {
    2191         psError(PS_ERR_UNKNOWN, false, "database error");
    2192         return false;
    2193     }
    2194     if (!psArrayLength(output)) {
    2195         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2196         psFree(output);
    2197         return true;
    2198     }
    2199 
    2200     // negative simple so the default is true
    2201     if (!ippdbPrintMetadatas(stdout, output, "detNormalizedStatImfile", !simple)) {
    2202         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2203         psFree(output);
    2204         return false;
    2205     }
    2206 
    2207     psFree(output);
    2208 
    2209     return true;
    2210 }
    2211 
    2212 static bool revertnormalizedstatMode(pxConfig *config)
    2213 {
    2214     PS_ASSERT_PTR_NON_NULL(config, false);
    2215 
    2216     psMetadata *where = psMetadataAlloc();
    2217     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    2218     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    2219     PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
    2220     PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
    2221 
    2222     psString query = pxDataGet("dettool_revertnormalizedstat.sql");
    2223     if (!query) {
    2224         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2225         return false;
    2226     }
    2227 
    2228     if (psListLength(where->list)) {
    2229         psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedStatImfile");
    2230         psStringAppend(&query, " AND %s", whereClause);
    2231         psFree(whereClause);
    2232     }
    2233     psFree(where);
    2234 
    2235     if (!p_psDBRunQuery(config->dbh, query)) {
    2236         psError(PS_ERR_UNKNOWN, false, "database error");
    2237         psFree(query);
    2238         return false;
    2239     }
    2240     psFree(query);
    2241 
    2242     if (psDBAffectedRows(config->dbh) < 1) {
    2243         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    2244         return false;
    2245     }
    2246 
    2247     return true;
    2248 }
    2249 
    2250 static bool tonormalizeMode(pxConfig *config)
    2251 {
    2252     PS_ASSERT_PTR_NON_NULL(config, false);
    2253 
    2254     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    2255     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2256 
    2257     psString query = pxDataGet("dettool_tonormalize.sql");
    2258     if (!query) {
    2259         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2260         return false;
    2261     }
    2262 
    2263     // treat limit == 0 as "no limit"
    2264     if (limit) {
    2265         psString limitString = psDBGenerateLimitSQL(limit);
    2266         psStringAppend(&query, " %s", limitString);
    2267         psFree(limitString);
    2268     }
    2269 
    2270     if (!p_psDBRunQuery(config->dbh, query)) {
    2271         psError(PS_ERR_UNKNOWN, false, "database error");
    2272         psFree(query);
    2273         return false;
    2274     }
    2275     psFree(query);
    2276 
    2277     psArray *output = p_psDBFetchResult(config->dbh);
    2278     if (!output) {
    2279         psError(PS_ERR_UNKNOWN, false, "database error");
    2280         return false;
    2281     }
    2282     if (!psArrayLength(output)) {
    2283         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2284         psFree(output);
    2285         return true;
    2286     }
    2287 
    2288     // negative simple so the default is true
    2289     if (!ippdbPrintMetadatas(stdout, output, "detPendingNormImfile", !simple)) {
    2290         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2291         psFree(output);
    2292         return false;
    2293     }
    2294 
    2295     psFree(output);
    2296 
    2297     return true;
    2298 }
    2299 
    2300 static bool addnormalizedimfileMode(pxConfig *config)
    2301 {
    2302     PS_ASSERT_PTR_NON_NULL(config, false);
    2303 
    2304     // required
    2305     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    2306     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    2307     PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
    2308 
    2309     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    2310 
    2311     // Required if code == 0
    2312     PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false);
    2313 
    2314     // optional
    2315     PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    2316     PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
    2317     PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
    2318     PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
    2319     PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
    2320     PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
    2321     PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
    2322     PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    2323     PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    2324 
    2325     if (!detNormalizedImfileInsert(config->dbh,
    2326         (psS64)atoll(det_id),
    2327         iteration,
    2328         class_id,
    2329         uri,
    2330         bg,
    2331         bg_stdev,
    2332         bg_mean_stdev,
    2333         user_1,
    2334         user_2,
    2335         user_3,
    2336         user_4,
    2337         user_5,
    2338         path_base,
    2339         code
    2340     )) {
    2341         psError(PS_ERR_UNKNOWN, false, "database error");
    2342         return false;
    2343     }
    2344 
    2345     return true;
    2346 }
    2347 
    2348 static bool normalizedimfileMode(pxConfig *config)
    2349 {
    2350     PS_ASSERT_PTR_NON_NULL(config, false);
    2351 
    2352     psMetadata *where = psMetadataAlloc();
    2353     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    2354     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    2355     PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
    2356     PXOPT_COPY_STR(config->args, where, "-recip",     "recipe", "==");
    2357 
    2358     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    2359     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2360     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    2361 
    2362     psString query = pxDataGet("dettool_normalizedimfile.sql");
    2363     if (!query) {
    2364         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2365         return false;
    2366     }
    2367 
    2368     if (psListLength(where->list)) {
    2369         psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedImfile");
    2370         psStringAppend(&query, " AND %s", whereClause);
    2371         psFree(whereClause);
    2372     }
    2373     psFree(where);
    2374 
    2375     if (faulted) {
    2376         // list only faulted rows
    2377         psStringAppend(&query, " %s", "AND detNormalizedImfile.fault != 0");
    2378     } else {
    2379         // don't list faulted rows
    2380         psStringAppend(&query, " %s", "AND detNormalizedImfile.fault = 0");
    2381     }
    2382 
    2383     // treat limit == 0 as "no limit"
    2384     if (limit) {
    2385         psString limitString = psDBGenerateLimitSQL(limit);
    2386         psStringAppend(&query, " %s", limitString);
    2387         psFree(limitString);
    2388     }
    2389 
    2390     if (!p_psDBRunQuery(config->dbh, query)) {
    2391         psError(PS_ERR_UNKNOWN, false, "database error");
    2392         psFree(query);
    2393         return false;
    2394     }
    2395     psFree(query);
    2396 
    2397     psArray *output = p_psDBFetchResult(config->dbh);
    2398     if (!output) {
    2399         psError(PS_ERR_UNKNOWN, false, "database error");
    2400         return false;
    2401     }
    2402     if (!psArrayLength(output)) {
    2403         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2404         psFree(output);
    2405         return true;
    2406     }
    2407 
    2408     // negative simple so the default is true
    2409     if (!ippdbPrintMetadatas(stdout, output, "detNormalizedImfile", !simple)) {
    2410         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2411         psFree(output);
    2412         return false;
    2413     }
    2414 
    2415     psFree(output);
    2416 
    2417     return true;
    2418 }
    2419 
    2420 
    2421 static bool revertnormalizedimfileMode(pxConfig *config)
    2422 {
    2423     PS_ASSERT_PTR_NON_NULL(config, false);
    2424 
    2425     psMetadata *where = psMetadataAlloc();
    2426     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    2427     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    2428     PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
    2429     PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
    2430 
    2431     psString query = pxDataGet("dettool_revertnormalizedimfile.sql");
    2432     if (!query) {
    2433         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2434         return false;
    2435     }
    2436 
    2437     if (psListLength(where->list)) {
    2438         psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedImfile");
    2439         psStringAppend(&query, " AND %s", whereClause);
    2440         psFree(whereClause);
    2441     }
    2442     psFree(where);
    2443 
    2444     if (!p_psDBRunQuery(config->dbh, query)) {
    2445         psError(PS_ERR_UNKNOWN, false, "database error");
    2446         psFree(query);
    2447         return false;
    2448     }
    2449     psFree(query);
    2450 
    2451     if (psDBAffectedRows(config->dbh) < 1) {
    2452         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    2453         return false;
    2454     }
    2455 
    2456     return true;
    2457 }
    2458 
    2459 static bool tonormalizedexpMode(pxConfig *config)
    2460 {
    2461     PS_ASSERT_PTR_NON_NULL(config, false);
    2462 
    2463     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    2464     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2465 
    2466     psString query = pxDataGet("dettool_tonormalizedexp.sql");
    2467     if (!query) {
    2468         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2469         return false;
    2470     }
    2471 
    2472     // treat limit == 0 as "no limit"
    2473     if (limit) {
    2474         psString limitString = psDBGenerateLimitSQL(limit);
    2475         psStringAppend(&query, " %s", limitString);
    2476         psFree(limitString);
    2477     }
    2478 
    2479     if (!p_psDBRunQuery(config->dbh, query)) {
    2480         psError(PS_ERR_UNKNOWN, false, "database error");
    2481         psFree(query);
    2482         return false;
    2483     }
    2484     psFree(query);
    2485 
    2486     psArray *output = p_psDBFetchResult(config->dbh);
    2487     if (!output) {
    2488         psError(PS_ERR_UNKNOWN, false, "database error");
    2489         return false;
    2490     }
    2491     if (!psArrayLength(output)) {
    2492         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2493         psFree(output);
    2494         return true;
    2495     }
    2496 
    2497     // negative simple so the default is true
    2498     if (!ippdbPrintMetadatas(stdout, output, "detPendingNormExp", !simple)) {
    2499         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2500         psFree(output);
    2501         return false;
    2502     }
    2503 
    2504     psFree(output);
    2505 
    2506     return true;
    2507 }
    2508 
    2509 static bool addnormalizedexpMode(pxConfig *config)
    2510 {
    2511     PS_ASSERT_PTR_NON_NULL(config, false);
    2512    
    2513     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
    2514     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    2515     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    2516     PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false); // Required if code == 0
    2517     PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    2518     PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
    2519     PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
    2520     PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
    2521     PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
    2522     PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
    2523     PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
    2524     PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    2525     PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    2526 
    2527     psString query = pxDataGet("dettool_tonormalizedexp.sql");
    2528     if (!query) {
    2529         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2530         return false;
    2531     }
    2532 
    2533     // XXX in some other places, we put the arguments in the .sql and supply them to RunQuery
    2534     psStringAppend(&query, " WHERE det_id = %s AND iteration = %d", det_id, iteration);
    2535 
    2536     if (!p_psDBRunQuery(config->dbh, query)) {
    2537         psError(PS_ERR_UNKNOWN, false, "database error");
    2538         psFree(query);
    2539         return false;
    2540     }
    2541     psFree(query);
    2542 
    2543     psArray *output = p_psDBFetchResult(config->dbh);
    2544     if (!output) {
    2545         psError(PS_ERR_UNKNOWN, false, "database error");
    2546         return false;
    2547     }
    2548     if (!psArrayLength(output)) {
    2549         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2550         psFree(output);
    2551         return true;
    2552     }
    2553     psFree(output);
    2554 
    2555     // insert the new row into the detProcessedImfile table
    2556     if (!detNormalizedExpInsert(config->dbh,
    2557         (psS64)atoll(det_id),
    2558         iteration,
    2559         recipe,
    2560         bg,
    2561         bg_stdev,
    2562         bg_mean_stdev,
    2563         user_1,
    2564         user_2,
    2565         user_3,
    2566         user_4,
    2567         user_5,
    2568         path_base,
    2569         code
    2570     )) {
    2571         psError(PS_ERR_UNKNOWN, false, "database error");
    2572         return false;
    2573     }
    2574 
    2575     return true;
    2576 }
    2577 
    2578 
    2579 static bool normalizedexpMode(pxConfig *config)
    2580 {
    2581     PS_ASSERT_PTR_NON_NULL(config, false);
    2582 
    2583     psMetadata *where = psMetadataAlloc();
    2584     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    2585     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    2586     PXOPT_COPY_STR(config->args, where, "-recip",  "recipe", "==");
    2587 
    2588     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    2589     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2590     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    2591 
    2592     psString query = pxDataGet("dettool_normalizedexp.sql");
    2593     if (!query) {
    2594         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2595         return false;
    2596     }
    2597 
    2598     if (psListLength(where->list)) {
    2599         psString whereClause = psDBGenerateWhereSQL(where, NULL);
    2600         psStringAppend(&query, " %s", whereClause);
    2601         psFree(whereClause);
    2602     }
    2603     psFree(where);
    2604 
    2605     if (faulted) {
    2606         // list only faulted rows
    2607         psStringAppend(&query, " %s", "AND detNormalizedExp.fault != 0");
    2608     } else {
    2609         // don't list faulted rows
    2610         psStringAppend(&query, " %s", "AND detNormalizedExp.fault = 0");
    2611     }
    2612 
    2613     // treat limit == 0 as "no limit"
    2614     if (limit) {
    2615         psString limitString = psDBGenerateLimitSQL(limit);
    2616         psStringAppend(&query, " %s", limitString);
    2617         psFree(limitString);
    2618     }
    2619 
    2620     if (!p_psDBRunQuery(config->dbh, query)) {
    2621         psError(PS_ERR_UNKNOWN, false, "database error");
    2622         psFree(query);
    2623         return false;
    2624     }
    2625     psFree(query);
    2626 
    2627     psArray *output = p_psDBFetchResult(config->dbh);
    2628     if (!output) {
    2629         psError(PS_ERR_UNKNOWN, false, "database error");
    2630         return false;
    2631     }
    2632     if (!psArrayLength(output)) {
    2633         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2634         psFree(output);
    2635         return true;
    2636     }
    2637 
    2638     // negative simple so the default is true
    2639     if (!ippdbPrintMetadatas(stdout, output, "detNormalizedExp", !simple)) {
    2640         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2641         psFree(output);
    2642         return false;
    2643     }
    2644 
    2645     psFree(output);
    2646 
    2647     return true;
    2648 }
    2649 
    2650 
    2651 
    2652 static bool revertnormalizedexpMode(pxConfig *config)
    2653 {
    2654     PS_ASSERT_PTR_NON_NULL(config, false);
    2655 
    2656     psMetadata *where = psMetadataAlloc();
    2657     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    2658     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    2659     PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
    2660 
    2661     psString query = pxDataGet("dettool_revertnormalizedexp.sql");
    2662     if (!query) {
    2663         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2664         return false;
    2665     }
    2666 
    2667     if (psListLength(where->list)) {
    2668         psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedExp");
    2669         psStringAppend(&query, " AND %s", whereClause);
    2670         psFree(whereClause);
    2671     }
    2672     psFree(where);
    2673 
    2674     if (!p_psDBRunQuery(config->dbh, query)) {
    2675         psError(PS_ERR_UNKNOWN, false, "database error");
    2676         psFree(query);
    2677         return false;
    2678     }
    2679     psFree(query);
    2680 
    2681     if (psDBAffectedRows(config->dbh) < 1) {
    2682         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    2683         return false;
    2684     }
    2685 
    2686     return true;
    2687 }
    2688 
    2689 
    2690 static bool toresidimfileMode(pxConfig *config)
    2691 {
    2692     PS_ASSERT_PTR_NON_NULL(config, false);
    2693 
    2694     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    2695     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2696 
    2697     psString query = pxDataGet("dettool_toresidimfile.sql");
    2698     if (!query) {
    2699         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2700         return false;
    2701     }
    2702 
    2703     // treat limit == 0 as "no limit"
    2704     if (limit) {
    2705         psString limitString = psDBGenerateLimitSQL(limit);
    2706         psStringAppend(&query, " %s", limitString);
    2707         psFree(limitString);
    2708     }
    2709 
    2710     if (!p_psDBRunQuery(config->dbh, query)) {
    2711         psError(PS_ERR_UNKNOWN, false, "database error");
    2712         psFree(query);
    2713         return false;
    2714     }
    2715     psFree(query);
    2716 
    2717     psArray *output = p_psDBFetchResult(config->dbh);
    2718     if (!output) {
    2719         psError(PS_ERR_UNKNOWN, false, "database error");
    2720         return false;
    2721     }
    2722     if (!psArrayLength(output)) {
    2723         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2724         psFree(output);
    2725         return true;
    2726     }
    2727 
    2728     // negative simple so the default is true
    2729     if (!ippdbPrintMetadatas(stdout, output, "detPendingResidImfile", !simple)) {
    2730         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2731         psFree(output);
    2732         return false;
    2733     }
    2734 
    2735     psFree(output);
    2736 
    2737     return true;
    2738 }
    2739 
    2740 
    2741 static bool addresidimfileMode(pxConfig *config)
    2742 {
    2743     PS_ASSERT_PTR_NON_NULL(config, false);
    2744 
    2745    
    2746     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
    2747     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    2748     PXOPT_LOOKUP_STR(exp_id, config->args, "-exp_id", true, false); // required
    2749     PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false); // required
    2750     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    2751     PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false); // Required if code == 0
    2752     PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false); // Required if code == 0
    2753     PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    2754     PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
    2755     PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
    2756     PXOPT_LOOKUP_F64(bg_skewness, config->args, "-bg_skewness", false, false);
    2757     PXOPT_LOOKUP_F64(bg_kurtosis, config->args, "-bg_kurtosis", false, false);
    2758     PXOPT_LOOKUP_F64(bin_stdev, config->args, "-bin_stdev", false, false);
    2759     PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
    2760     PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
    2761     PXOPT_LOOKUP_F64(fringe_2, config->args, "-fringe_2", false, false);
    2762     PXOPT_LOOKUP_F64(fringe_resid_0, config->args, "-fringe_resid_0", false, false);
    2763     PXOPT_LOOKUP_F64(fringe_resid_1, config->args, "-fringe_resid_1", false, false);
    2764     PXOPT_LOOKUP_F64(fringe_resid_2, config->args, "-fringe_resid_2", false, false);
    2765     PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
    2766     PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
    2767     PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
    2768     PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
    2769     PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    2770     PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    2771 
    2772     if (!detResidImfileInsert(config->dbh,
    2773             (psS64)atoll(det_id),
    2774             iteration,
    2775             (psS64)atoll(exp_id),
    2776             class_id,
    2777             uri,
    2778             recipe,
    2779             bg,
    2780             bg_stdev,
    2781             bg_mean_stdev,
    2782             bg_skewness,
    2783             bg_kurtosis,
    2784             bin_stdev,
    2785             fringe_0,
    2786             fringe_1,
    2787             fringe_2,
    2788             fringe_resid_0,
    2789             fringe_resid_1,
    2790             fringe_resid_2,
    2791             user_1,
    2792             user_2,
    2793             user_3,
    2794             user_4,
    2795             user_5,
    2796             path_base,
    2797             code
    2798     )) {
    2799         psError(PS_ERR_UNKNOWN, false, "database error");
    2800         return false;
    2801     }
    2802 
    2803     return true;
    2804 }
    2805 
    2806 
    2807 static bool residimfileMode(pxConfig *config)
    2808 {
    2809     PS_ASSERT_PTR_NON_NULL(config, false);
    2810 
    2811     psMetadata *where = psMetadataAlloc();
    2812     PXOPT_COPY_STR(config->args, where, "-det_id",     "det_id", "==");
    2813     PXOPT_COPY_S32(config->args, where, "-iteration",  "iteration", "==");
    2814     PXOPT_COPY_STR(config->args, where, "-exp_id",     "exp_id", "==");
    2815     PXOPT_COPY_STR(config->args, where, "-class_id",   "class_id", "==");
    2816     PXOPT_COPY_STR(config->args, where, "-recip",      "recipe", "==");
    2817 
    2818     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    2819     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2820     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    2821 
    2822     psString query = pxDataGet("dettool_residimfile.sql");
    2823     if (!query) {
    2824         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2825         return false;
    2826     }
    2827 
    2828     // NOTE: the query ends in a WHERE, add the required restriction on detRun.state
    2829     char *value = NULL;
    2830     bool status;
    2831     if ((value = psMetadataLookupStr(&status, config->args, "-select_state"))) {
    2832         psStringAppend(&query, " detRun.state = '%s'", value);
    2833     } else {
    2834         psStringAppend(&query, " detRun.state = 'run'");
    2835     }
    2836 
    2837     if (psListLength(where->list)) {
    2838         psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidImfile");
    2839         psStringAppend(&query, " AND %s", whereClause);
    2840         psFree(whereClause);
    2841     }
    2842     psFree(where);
    2843 
    2844     if (faulted) {
    2845         // list only faulted rows
    2846         psStringAppend(&query, " %s", "AND detResidImfile.fault != 0");
    2847     } else {
    2848         // don't list faulted rows
    2849         psStringAppend(&query, " %s", "AND detResidImfile.fault = 0");
    2850     }
    2851 
    2852     // treat limit == 0 as "no limit"
    2853     if (limit) {
    2854         psString limitString = psDBGenerateLimitSQL(limit);
    2855         psStringAppend(&query, " %s", limitString);
    2856         psFree(limitString);
    2857     }
    2858 
    2859     if (!p_psDBRunQuery(config->dbh, query)) {
    2860         psError(PS_ERR_UNKNOWN, false, "database error");
    2861         psFree(query);
    2862         return false;
    2863     }
    2864     psFree(query);
    2865 
    2866     psArray *output = p_psDBFetchResult(config->dbh);
    2867     if (!output) {
    2868         psError(PS_ERR_UNKNOWN, false, "database error");
    2869         return false;
    2870     }
    2871     if (!psArrayLength(output)) {
    2872         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2873         psFree(output);
    2874         return true;
    2875     }
    2876 
    2877     // negative simple so the default is true
    2878     if (!ippdbPrintMetadatas(stdout, output, "rawResidImfile", !simple)) {
    2879         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2880         psFree(output);
    2881         return false;
    2882     }
    2883 
    2884     psFree(output);
    2885 
    2886     return true;
    2887 }
    2888 
    2889 
    2890 static bool revertresidimfileMode(pxConfig *config)
    2891 {
    2892     PS_ASSERT_PTR_NON_NULL(config, false);
    2893 
    2894     psMetadata *where = psMetadataAlloc();
    2895     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    2896     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    2897     PXOPT_COPY_STR(config->args, where, "-exp_id",  "exp_id", "==");
    2898     PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
    2899     PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
    2900 
    2901     psString query = pxDataGet("dettool_revertresidimfile.sql");
    2902     if (!query) {
    2903         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2904         return false;
    2905     }
    2906 
    2907     if (psListLength(where->list)) {
    2908         psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidImfile");
    2909         psStringAppend(&query, " AND %s", whereClause);
    2910         psFree(whereClause);
    2911     }
    2912     psFree(where);
    2913 
    2914     if (!p_psDBRunQuery(config->dbh, query)) {
    2915         psError(PS_ERR_UNKNOWN, false, "database error");
    2916         psFree(query);
    2917         return false;
    2918     }
    2919     psFree(query);
    2920 
    2921     if (psDBAffectedRows(config->dbh) < 1) {
    2922         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    2923         return false;
    2924     }
    2925 
    2926     return true;
    2927 }
    2928 
    2929 
    2930 /*
    2931   The SQL returns a list of exposures for which all component class ids have had residuals
    2932   created.  This list includes the detrend id, iteration, exposure id, detrend type, and
    2933   whether the exposure was included in the stack for this iteration.
    2934 */
    2935 
    2936 static bool toresidexpMode(pxConfig *config)
    2937 {
    2938     PS_ASSERT_PTR_NON_NULL(config, false);
    2939 
    2940     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    2941     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2942 
    2943     psString query = pxDataGet("dettool_toresidexp.sql");
    2944     if (!query) {
    2945         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    2946         return false;
    2947     }
    2948 
    2949     // treat limit == 0 as "no limit"
    2950     if (limit) {
    2951         psString limitString = psDBGenerateLimitSQL(limit);
    2952         psStringAppend(&query, " %s", limitString);
    2953         psFree(limitString);
    2954     }
    2955 
    2956     if (!p_psDBRunQuery(config->dbh, query)) {
    2957         psError(PS_ERR_UNKNOWN, false, "database error");
    2958         psFree(query);
    2959         return false;
    2960     }
    2961     psFree(query);
    2962 
    2963     psArray *output = p_psDBFetchResult(config->dbh);
    2964     if (!output) {
    2965         psError(PS_ERR_UNKNOWN, false, "database error");
    2966         return false;
    2967     }
    2968     if (!psArrayLength(output)) {
    2969         psTrace("dettool", PS_LOG_INFO, "no rows found");
    2970         psFree(output);
    2971         return true;
    2972     }
    2973 
    2974     // negative simple so the default is true
    2975     if (!ippdbPrintMetadatas(stdout, output, "detPendingResidExp", !simple)) {
    2976         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    2977         psFree(output);
    2978         return false;
    2979     }
    2980 
    2981     psFree(output);
    2982 
    2983     return true;
    2984 }
    2985 
    2986 /*
    2987   The SQL returns a list of exposures for which all component class ids have had residuals
    2988   created.  This list includes the detrend id, iteration, exposure id, detrend type, and
    2989   whether the exposure was included in the stack for this iteration.
    2990 */
    2991 
    2992 static bool addresidexpMode(pxConfig *config)
    2993 {
    2994     PS_ASSERT_PTR_NON_NULL(config, false);
    2995 
    2996     // limit search by det_id, iteration, exp_id
    2997     psMetadata *where = psMetadataAlloc();
    2998     PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    2999     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3000     PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
    3001 
    3002     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
    3003     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    3004     PXOPT_LOOKUP_STR(exp_id, config->args, "-exp_id", true, false); // required
    3005     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    3006     PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false); // Required if code == 0
    3007     PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    3008     PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
    3009     PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
    3010     PXOPT_LOOKUP_F64(bg_skewness, config->args, "-bg_skewness", false, false);
    3011     PXOPT_LOOKUP_F64(bg_kurtosis, config->args, "-bg_kurtosis", false, false);
    3012     PXOPT_LOOKUP_F64(bin_stdev, config->args, "-bin_stdev", false, false);
    3013     PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
    3014     PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
    3015     PXOPT_LOOKUP_F64(fringe_2, config->args, "-fringe_2", false, false);
    3016     PXOPT_LOOKUP_F64(fringe_resid_0, config->args, "-fringe_resid_0", false, false);
    3017     PXOPT_LOOKUP_F64(fringe_resid_1, config->args, "-fringe_resid_1", false, false);
    3018     PXOPT_LOOKUP_F64(fringe_resid_2, config->args, "-fringe_resid_2", false, false);
    3019     PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
    3020     PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
    3021     PXOPT_LOOKUP_F64(user_3, config->args, "-user_3", false, false);
    3022     PXOPT_LOOKUP_F64(user_4, config->args, "-user_4", false, false);
    3023     PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    3024     PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    3025     PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
    3026 
    3027     psString query = pxDataGet("dettool_toresidexp.sql");
    3028     if (!query) {
    3029         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    3030         return false;
    3031     }
    3032 
    3033     if (psListLength(where->list)) {
    3034         psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    3035         psStringAppend(&query, " WHERE %s", whereClause);
    3036         psFree(whereClause);
    3037     }
    3038     psFree(where);
    3039 
    3040     if (!p_psDBRunQuery(config->dbh, query)) {
    3041         psError(PS_ERR_UNKNOWN, false, "database error");
    3042         psFree(query);
    3043         return false;
    3044     }
    3045     psFree(query);
    3046 
    3047     psArray *output = p_psDBFetchResult(config->dbh);
    3048     if (!output) {
    3049         psError(PS_ERR_UNKNOWN, false, "database error");
    3050         return false;
    3051     }
    3052     if (!psArrayLength(output)) {
    3053         // XXX check psError here
    3054         psError(PS_ERR_UNKNOWN, false, "no detResidImfile rows found");
    3055         psFree(output);
    3056         return false;
    3057     }
    3058     psFree(output);
    3059 
    3060     if (!detResidExpInsert(config->dbh,
    3061             (psS64)atoll(det_id),
    3062             iteration,
    3063             (psS64)atoll(exp_id),
    3064             recipe,
    3065             bg,
    3066             bg_stdev,
    3067             bg_mean_stdev,
    3068             bg_skewness,
    3069             bg_kurtosis,
    3070             bin_stdev,
    3071             fringe_0,
    3072             fringe_1,
    3073             fringe_2,
    3074             fringe_resid_0,
    3075             fringe_resid_1,
    3076             fringe_resid_2,
    3077             user_1,
    3078             user_2,
    3079             user_3,
    3080             user_4,
    3081             user_5,
    3082             path_base,
    3083             !reject,
    3084             code
    3085         )) {
    3086         psError(PS_ERR_UNKNOWN, false, "database error");
    3087         return false;
    3088     }
    3089 
    3090     return true;
    3091 }
    3092 
    3093 static bool residexpMode(pxConfig *config)
    3094 {
    3095     PS_ASSERT_PTR_NON_NULL(config, false);
    3096 
    3097     psMetadata *where = psMetadataAlloc();
    3098     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    3099     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3100     PXOPT_COPY_STR(config->args, where, "-exp_id",    "exp_id", "==");
    3101     PXOPT_COPY_STR(config->args, where, "-recip",     "recipe", "==");
    3102 
    3103     PXOPT_LOOKUP_U64(limit,    config->args, "-limit", false, false);
    3104     PXOPT_LOOKUP_BOOL(simple,  config->args, "-simple", false);
    3105     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    3106     PXOPT_LOOKUP_BOOL(reject,  config->args, "-reject", false);
    3107 
    3108     psString query = pxDataGet("dettool_residexp.sql");
    3109     if (!query) {
    3110         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    3111         return false;
    3112     }
    3113 
    3114     if (psListLength(where->list)) {
    3115         psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidExp");
    3116         psStringAppend(&query, " AND %s", whereClause);
    3117         psFree(whereClause);
    3118     }
    3119     psFree(where);
    3120 
    3121     if (faulted) {
    3122         // list only faulted rows
    3123         psStringAppend(&query, " %s", "AND detResidExp.fault != 0");
    3124     } else {
    3125         // don't list faulted rows
    3126         psStringAppend(&query, " %s", "AND detResidExp.fault = 0");
    3127     }
    3128 
    3129     // list only accepted rows
    3130     // XXX the usage of this flag is unclear : -reject means "accepted"?
    3131     if (reject) {
    3132         psStringAppend(&query, " %s", "AND detResidExp.accept != 0");
    3133     }
    3134 
    3135     // treat limit == 0 as "no limit"
    3136     if (limit) {
    3137         psString limitString = psDBGenerateLimitSQL(limit);
    3138         psStringAppend(&query, " %s", limitString);
    3139         psFree(limitString);
    3140     }
    3141 
    3142     if (!p_psDBRunQuery(config->dbh, query)) {
    3143         psError(PS_ERR_UNKNOWN, false, "database error");
    3144         psFree(query);
    3145         return false;
    3146     }
    3147     psFree(query);
    3148 
    3149     psArray *output = p_psDBFetchResult(config->dbh);
    3150     if (!output) {
    3151         psError(PS_ERR_UNKNOWN, false, "database error");
    3152         return false;
    3153     }
    3154     if (!psArrayLength(output)) {
    3155         psTrace("dettool", PS_LOG_INFO, "no rows found");
    3156         psFree(output);
    3157         return true;
    3158     }
    3159 
    3160     // negative simple so the default is true
    3161     if (!ippdbPrintMetadatas(stdout, output, "detResidExp", !simple)) {
    3162         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    3163         psFree(output);
    3164         return false;
    3165     }
    3166 
    3167     psFree(output);
    3168 
    3169     return true;
    3170 }
    3171 
    3172 
    3173 static bool revertresidexpMode(pxConfig *config)
    3174 {
    3175     PS_ASSERT_PTR_NON_NULL(config, false);
    3176 
    3177     psMetadata *where = psMetadataAlloc();
    3178     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    3179     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3180     PXOPT_COPY_STR(config->args, where, "-exp_id",    "exp_id", "==");
    3181     PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
    3182 
    3183     psString query = pxDataGet("dettool_revertresidexp.sql");
    3184     if (!query) {
    3185         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    3186         return false;
    3187     }
    3188 
    3189     if (psListLength(where->list)) {
    3190         psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidExp");
    3191         psStringAppend(&query, " AND %s", whereClause);
    3192         psFree(whereClause);
    3193     }
    3194     psFree(where);
    3195 
    3196     if (!p_psDBRunQuery(config->dbh, query)) {
    3197         psError(PS_ERR_UNKNOWN, false, "database error");
    3198         psFree(query);
    3199         return false;
    3200     }
    3201     psFree(query);
    3202 
    3203     if (psDBAffectedRows(config->dbh) < 1) {
    3204         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    3205         return false;
    3206     }
    3207 
    3208     return true;
    3209 }
    3210 
    3211 
    3212 static bool updateresidexpMode(pxConfig *config)
    3213 {
    3214     PS_ASSERT_PTR_NON_NULL(config, false);
    3215 
    3216     PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
    3217 
    3218     // build a query to search by det_id, iteration, exp_id
    3219     psMetadata *where = psMetadataAlloc();
    3220     PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    3221     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3222     PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
    3223 
    3224     // find the values we're going to set
    3225     // copy everything but det_id, iteration, & exp_id from the args and
    3226     // remove the '-' prefix
    3227     psMetadata *set = psMetadataAlloc();
    3228     PXOPT_COPY_STR(config->args, set, "-recip", "recipe", "==");
    3229     PXOPT_COPY_F64(config->args, set, "-bg", "bg", "==");
    3230     PXOPT_COPY_F64(config->args, set, "-bg_stdev", "bg_stdev", "==");
    3231     PXOPT_COPY_F64(config->args, set, "-bg_mean_stdev", "bg_mean_stdev", "==");
    3232     PXOPT_COPY_STR(config->args, set, "-path_base", "path_base", "==");
    3233 
    3234     // this can't be PXOPT_ macro-ized as reject is !'d
    3235     if (!psMetadataAddBool(set, PS_LIST_TAIL, "accept", 0, "==", !reject)) {
    3236         psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
    3237         psFree(set);
    3238         psFree(where);
    3239         return false;
    3240     }
    3241 
    3242     long changed = psDBUpdateRows(config->dbh, "detResidExp", where, set);
    3243     psFree(set);
    3244     psFree(where);
    3245 
    3246     if (changed < 0) {
    3247         psError(PS_ERR_UNKNOWN, false, "no rows were updated");
    3248         return false;
    3249     }
    3250 
    3251     return true;
    3252 }
    3253 
    3254 /* The SQL returns a list of detrend runs (with detrend id, iteration and detrend type) which
    3255  * have completed all residexps.
    3256  */
    3257 
    3258 static bool todetrunsummaryMode(pxConfig *config)
    3259 {
    3260     PS_ASSERT_PTR_NON_NULL(config, false);
    3261 
    3262     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    3263     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    3264 
    3265     psString query = pxDataGet("dettool_todetrunsummary.sql");
    3266     if (!query) {
    3267         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    3268         return false;
    3269     }
    3270 
    3271     // treat limit == 0 as "no limit"
    3272     if (limit) {
    3273         psString limitString = psDBGenerateLimitSQL(limit);
    3274         psStringAppend(&query, " %s", limitString);
    3275         psFree(limitString);
    3276     }
    3277 
    3278     if (!p_psDBRunQuery(config->dbh, query)) {
    3279         psError(PS_ERR_UNKNOWN, false, "database error");
    3280         psFree(query);
    3281         return false;
    3282     }
    3283     psFree(query);
    3284 
    3285     psArray *output = p_psDBFetchResult(config->dbh);
    3286     if (!output) {
    3287         psError(PS_ERR_UNKNOWN, false, "database error");
    3288         return false;
    3289     }
    3290     if (!psArrayLength(output)) {
    3291         psTrace("dettool", PS_LOG_INFO, "no rows found");
    3292         psFree(output);
    3293         return true;
    3294     }
    3295 
    3296     // negative simple so the default is true
    3297     if (!ippdbPrintMetadatas(stdout, output, "detRejectExp", !simple)) {
    3298         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    3299         psFree(output);
    3300         return false;
    3301     }
    3302 
    3303     psFree(output);
    3304 
    3305     return true;
    3306 }
    3307 
    3308 // this function is used to generate the detrunSummary entries used below
    3309 // XXX why is this a separate function?  roll it back into adddetrunsummary?
    3310 static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row)
    3311 {
    3312     PS_ASSERT_PTR_NON_NULL(config, false);
    3313 
    3314     bool status = false;
    3315     // from row
    3316     psS64 det_id = psMetadataLookupS64(&status, row, "det_id");
    3317     if (!status) {
    3318         psError(PS_ERR_UNKNOWN, false, "failed to lookup value for det_id");
    3319         return false;
    3320     }
    3321     psS32 iteration = psMetadataLookupS32(&status, row, "iteration");
    3322     if (!status) {
    3323         psError(PS_ERR_UNKNOWN, false, "failed to lookup value for iteration");
    3324         return false;
    3325     }
    3326 
    3327     // optional
    3328     PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    3329     PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
    3330     PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
    3331 
    3332     // default values
    3333     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    3334     PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
    3335 
    3336     return detRunSummaryRowAlloc(
    3337             det_id,
    3338             iteration,
    3339             bg,
    3340             bg_stdev,
    3341             bg_mean_stdev,
    3342             accept,
    3343             code
    3344         );
    3345 }
    3346 
    3347 static bool adddetrunsummaryMode(pxConfig *config)
    3348 {
    3349     PS_ASSERT_PTR_NON_NULL(config, false);
    3350    
    3351     // build a query to search by det_id, iteration, exp_id
    3352     psMetadata *where = psMetadataAlloc();
    3353     PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    3354     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3355 
    3356     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
    3357     PXOPT_LOOKUP_BOOL(again, config->args, "-again", false);
    3358 
    3359     // The values supplied as arguments on the command (eg, -bg) are parsed
    3360     // by mdToDetRunSummary below.
    3361     // XXX why is there ever more than one?
    3362 
    3363     psString query = pxDataGet("dettool_find_completed_runs.sql");
    3364     if (!query) {
    3365         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    3366         return false;
    3367     }
    3368 
    3369     if (psListLength(where->list)) {
    3370         psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    3371         psStringAppend(&query, " WHERE %s", whereClause);
    3372         psFree(whereClause);
    3373     }
    3374     psFree(where);
    3375 
    3376     if (!p_psDBRunQuery(config->dbh, query)) {
    3377         psError(PS_ERR_UNKNOWN, false, "database error");
    3378         psFree(query);
    3379         return false;
    3380     }
    3381     psFree(query);
    3382 
    3383     psArray *output = p_psDBFetchResult(config->dbh);
    3384     if (!output) {
    3385         psError(PS_ERR_UNKNOWN, false, "database error");
    3386         return false;
    3387     }
    3388     if (!psArrayLength(output)) {
    3389         psTrace("dettool", PS_LOG_INFO, "no rows found");
    3390         psFree(output);
    3391         return true;
    3392     }
    3393 
    3394     // start a transaction so it's all rows or nothing
    3395     if (!psDBTransaction(config->dbh)) {
    3396         psError(PS_ERR_UNKNOWN, false, "database error");
    3397         psFree(output);
    3398         return false;
    3399     }
    3400 
    3401     // XXX why is there ever more than one result here?
    3402     for (long i = 0; i < psArrayLength(output); i++) {
    3403         psMetadata *row = output->data[i];
    3404         // convert metadata into a detResidExp object
    3405         detRunSummaryRow *runSummary = mdToDetRunSummary(config, row);
    3406         if (!runSummary) {
    3407             if (!psDBRollback(config->dbh)) {
    3408                 psError(PS_ERR_UNKNOWN, false, "database error");
    3409             }
    3410             psError(PS_ERR_UNKNOWN, false, "failed to convert metadata to detResidExp");
    3411             psFree(output);
    3412             return false;
    3413         }
    3414         // insert detResidExp object into the database
    3415         if (!detRunSummaryInsertObject(config->dbh, runSummary)) {
    3416             if (!psDBRollback(config->dbh)) {
    3417                 psError(PS_ERR_UNKNOWN, false, "database error");
    3418             }
    3419             psError(PS_ERR_UNKNOWN, false, "database error");
    3420             psFree(runSummary);
    3421             psFree(output);
    3422             return false;
    3423         }
    3424         psFree(runSummary);
    3425     }
    3426 
    3427     psFree(output);
    3428 
    3429     // XXX this logic does not deal with the case of -code being set
    3430     // XXX it should be an error for -again and -code to both be set
    3431     if (again) {
    3432         if (!startNewIteration(config, (psS64)atoll(det_id))) {
    3433             if (!psDBRollback(config->dbh)) {
    3434                 psError(PS_ERR_UNKNOWN, false, "database error");
    3435             }
    3436             psError(PS_ERR_UNKNOWN, false, "failed to start new iteration");
    3437             return false;
    3438         }
    3439     } else {
    3440         // set detRun.state to stop
    3441         if (!setDetRunState(config, (psS64)atoll(det_id), "stop")) {
    3442             if (!psDBRollback(config->dbh)) {
    3443                 psError(PS_ERR_UNKNOWN, false, "database error");
    3444             }
    3445             psError(PS_ERR_UNKNOWN, false, "failed to set detRun.state");
    3446             return false;
    3447         }
    3448     }
    3449 
    3450     if (!psDBCommit(config->dbh)) {
    3451         psError(PS_ERR_UNKNOWN, false, "database error");
    3452         return false;
    3453     }
    3454     return true;
    3455 }
    3456 
    3457 static bool detrunsummaryMode(pxConfig *config)
    3458 {
    3459     PS_ASSERT_PTR_NON_NULL(config, false);
    3460 
    3461     psMetadata *where = psMetadataAlloc();
    3462     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    3463     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3464 
    3465     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    3466     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    3467     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    3468 
    3469     psString query = pxDataGet("dettool_detrunsummary.sql");
    3470     if (!query) {
    3471         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    3472         psFree(where);
    3473         return false;
    3474     }
    3475 
    3476     if (psListLength(where->list)) {
    3477         psString whereClause = psDBGenerateWhereConditionSQL(where, "NULL");
    3478         psStringAppend(&query, " AND %s", whereClause);
    3479         psFree(whereClause);
    3480     }
    3481     psFree(where);
    3482 
    3483     if (faulted) {
    3484         // list only faulted rows
    3485         psStringAppend(&query, " %s", "AND detRunSummary.fault != 0");
    3486     } else {
    3487         // don't list faulted rows
    3488         psStringAppend(&query, " %s", "AND detRunSummary.fault = 0");
    3489     }
    3490 
    3491     // treat limit == 0 as "no limit"
    3492     if (limit) {
    3493         psString limitString = psDBGenerateLimitSQL(limit);
    3494         psStringAppend(&query, " %s", limitString);
    3495         psFree(limitString);
    3496     }
    3497 
    3498     if (!p_psDBRunQuery(config->dbh, query)) {
    3499         psError(PS_ERR_UNKNOWN, false, "database error");
    3500         psFree(query);
    3501         return false;
    3502     }
    3503     psFree(query);
    3504 
    3505     psArray *output = p_psDBFetchResult(config->dbh);
    3506     if (!output) {
    3507         psError(PS_ERR_UNKNOWN, false, "database error");
    3508         return false;
    3509     }
    3510     if (!psArrayLength(output)) {
    3511         psTrace("dettool", PS_LOG_INFO, "no rows found");
    3512         psFree(output);
    3513         return true;
    3514     }
    3515 
    3516     // negative simple so the default is true
    3517     if (!ippdbPrintMetadatas(stdout, output, "rawDetrendImfile", !simple)) {
    3518         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    3519         psFree(output);
    3520         return false;
    3521     }
    3522 
    3523     psFree(output);
    3524 
    3525     return true;
    3526 }
    3527 
    3528 
    3529 static bool revertdetrunsummaryMode(pxConfig *config)
    3530 {
    3531     PS_ASSERT_PTR_NON_NULL(config, false);
    3532 
    3533     psMetadata *where = psMetadataAlloc();
    3534     PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
    3535     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3536     PXOPT_COPY_STR(config->args, where, "-code",      "fault", "==");
    3537 
    3538     psString query = pxDataGet("dettool_revertdetrunsummary.sql");
    3539     if (!query) {
    3540         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    3541         return false;
    3542     }
    3543 
    3544     if (psListLength(where->list)) {
    3545         psString whereClause = psDBGenerateWhereConditionSQL(where, "detRunSummary");
    3546         psStringAppend(&query, " AND %s", whereClause);
    3547         psFree(whereClause);
    3548     }
    3549     psFree(where);
    3550 
    3551     if (!p_psDBRunQuery(config->dbh, query)) {
    3552         psError(PS_ERR_UNKNOWN, false, "database error");
    3553         psFree(query);
    3554         return false;
    3555     }
    3556     psFree(query);
    3557 
    3558     if (psDBAffectedRows(config->dbh) < 1) {
    3559         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    3560         return false;
    3561     }
    3562 
    3563     return true;
    3564 }
    3565 
    3566 
    3567 static bool updatedetrunsummaryMode(pxConfig *config)
    3568 {
    3569     PS_ASSERT_PTR_NON_NULL(config, false);
    3570    
    3571     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
    3572     PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
    3573     PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
    3574 
    3575     if (accept && reject) {
    3576         psError(PS_ERR_UNKNOWN, true, "-accept and -reject are exclusive");
    3577         return false;
    3578     }
    3579 
    3580     if (!(accept || reject)) {
    3581         psError(PS_ERR_UNKNOWN, true, "either -accept or -reject is required");
    3582         return false;
    3583     }
    3584 
    3585     char *query = "UPDATE detRunSummary SET accept = %d WHERE det_id = %"PRId64;
    3586     if (!p_psDBRunQuery(config->dbh, query, accept, (psS64)atoll(det_id))) {
    3587         psError(PS_ERR_UNKNOWN, false, "database error");
    3588         return false;
    3589     }
    3590 
    3591     return true;
    3592 }
    3593 
    3594 
    35951225static bool updatedetrunMode(pxConfig *config)
    35961226{
    35971227    PS_ASSERT_PTR_NON_NULL(config, false);
    35981228
    3599     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
     1229    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
    36001230    PXOPT_LOOKUP_BOOL(again, config->args, "-again", false);
    36011231    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
     
    36131243    if (state) {
    36141244        // set detRun.state to state
    3615         return setDetRunState(config, (psS64)atoll(det_id), state);
     1245        return setDetRunState(config, det_id, state);
    36161246    }
    36171247
    36181248    // else
    36191249    // -again
    3620     if (!startNewIteration(config, (psS64)atoll(det_id))) {
     1250    if (!startNewIteration(config, det_id)) {
    36211251        psError(PS_ERR_UNKNOWN, false, "failed to start new iteration");
    36221252        return false;
     
    36271257
    36281258// used by updatedetrunMode
    3629 static bool startNewIteration(pxConfig *config, psS64 det_id)
     1259bool startNewIteration(pxConfig *config, psS64 det_id)
    36301260{
    36311261    PS_ASSERT_PTR_NON_NULL(config, false);
     
    37391369
    37401370    // det_id is required
    3741     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
     1371    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false);
    37421372
    37431373    // we have to support multipe exp_ids
     
    37841414
    37851415    // add the det_id & iteration == 0 to the where clause
    3786     if (!psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==",
    3787                 (psS64)atoll(det_id))) {
     1416    if (!psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==", det_id)) {
    37881417        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    37891418        psFree(where);
     
    38221451
    38231452    // up the detRuns iteration count
    3824     psS32 newIteration = incrementIteration(config, (psS64)atoll(det_id));
     1453    psS32 newIteration = incrementIteration(config, det_id);
    38251454    if (!newIteration) {
    38261455        // rollback
     
    38461475            }
    38471476            // invalid exp_id
    3848             psError(PS_ERR_UNKNOWN, false, "exp_id %s is invalid for det_id %s",
     1477            psError(PS_ERR_UNKNOWN, false, "exp_id %s is invalid for det_id %" PRId64,
    38491478                    (char *)mItem->data.V, det_id);
    38501479            psFree(iter);
     
    38531482        }
    38541483        detInputExpRow *newInputExp = detInputExpRowAlloc(
    3855             (psS64)atoll(det_id),
     1484            det_id,
    38561485            newIteration,
    38571486            inputExp->exp_id,
     
    39121541    PXOPT_LOOKUP_TIME(use_begin, config->args, "-use_begin", false, false);
    39131542    PXOPT_LOOKUP_TIME(use_end, config->args, "-use_end", false, false);
    3914     PXOPT_LOOKUP_STR(parent, config->args, "-parent", false, false);
     1543    PXOPT_LOOKUP_S64(parent, config->args, "-parent", false, false);
    39151544    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
    39161545    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     
    39501579                      solang_max,
    39511580                      label,      // label
    3952                       parent ? (psS64)atoll(parent) : 0
     1581                      parent
    39531582            )) {
    39541583        psError(PS_ERR_UNKNOWN, false, "database error");
     
    40011630    PS_ASSERT_PTR_NON_NULL(config, false);
    40021631   
    4003     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
     1632    PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true, false); // required
    40041633    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false); // required
    40051634    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false); // required
     
    40151644
    40161645    if (!detRegisteredImfileInsert(config->dbh,
    4017         (psS64)atoll(det_id),
    4018         0,  // the iteration is fixed at 0
    4019         class_id,
    4020         uri,
    4021         bg,
    4022         bg_stdev,
    4023         bg_mean_stdev,
    4024         user_1,
    4025         user_2,
    4026         user_3,
    4027         user_4,
    4028         user_5,
    4029         path_base,
    4030         0       // fault code
    4031     )) {
     1646                                   det_id,
     1647                                   0,  // the iteration is fixed at 0
     1648                                   class_id,
     1649                                   uri,
     1650                                   bg,
     1651                                   bg_stdev,
     1652                                   bg_mean_stdev,
     1653                                   user_1,
     1654                                   user_2,
     1655                                   user_3,
     1656                                   user_4,
     1657                                   user_5,
     1658                                   path_base,
     1659                                   "full",                                 
     1660                                   0       // fault code
     1661            )) {
    40321662        psError(PS_ERR_UNKNOWN, false, "database error");
    40331663        return false;
     
    40751705}
    40761706
    4077 static bool setDetRunState(pxConfig *config, psS64 det_id, const char *state)
     1707bool setDetRunState(pxConfig *config, psS64 det_id, const char *state)
    40781708{
    40791709    PS_ASSERT_PTR_NON_NULL(config, false);
     
    41031733}
    41041734
    4105 static bool isValidMode(pxConfig *config, const char *mode)
     1735bool isValidDataState (const char *data_state) {
     1736
     1737    // check that state is a valid string value
     1738    if (!strncmp(data_state, "run", 4)) return true;
     1739    if (!strncmp(data_state, "stop", 5)) return true;
     1740    if (!strncmp(data_state, "drop", 5)) return true;
     1741    if (!strncmp(data_state, "register", 4)) return true;
     1742
     1743    psError(PS_ERR_UNKNOWN, true, "invalid data state: %s", data_state);
     1744    return false;
     1745}
     1746
     1747bool isValidMode(pxConfig *config, const char *mode)
    41061748{
    41071749    PS_ASSERT_PTR_NON_NULL(config, false);
     
    41221764}
    41231765
     1766
     1767bool setProcessedImfileDataState(pxConfig *config, psS64 det_id, psS64 exp_id, const char *class_id, const char *data_state)
     1768{
     1769    PS_ASSERT_PTR_NON_NULL(config, false);
     1770    PS_ASSERT_PTR_NON_NULL(data_state, false);
     1771    PS_ASSERT_PTR_NON_NULL(class_id, false);
     1772
     1773    if (!isValidDataState (data_state)) return false;
     1774
     1775    char *query = "UPDATE detProcessedImfile SET data_state = '%s'"
     1776        " WHERE det_id = %" PRId64
     1777        " AND exp_id = %" PRId64
     1778        " AND class_id = '%s'";
     1779    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, exp_id, class_id)) {
     1780        psError(PS_ERR_UNKNOWN, false,
     1781                "failed to change state for det_id %" PRId64 ", exp_id %" PRId64 ", class_id %s",
     1782                det_id, exp_id, class_id);
     1783        return false;
     1784    }
     1785
     1786    return true;
     1787}
     1788
     1789bool setProcessedExpDataState(pxConfig *config, psS64 det_id, psS64 exp_id, const char *data_state)
     1790{
     1791    PS_ASSERT_PTR_NON_NULL(config, false);
     1792    PS_ASSERT_PTR_NON_NULL(data_state, false);
     1793
     1794    if (!isValidDataState (data_state)) return false;
     1795
     1796    char *query = "UPDATE detProcessedExp SET data_state = '%s'"
     1797        " WHERE det_id = %" PRId64
     1798        " AND exp_id = %" PRId64;
     1799    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, exp_id)) {
     1800        psError(PS_ERR_UNKNOWN, false,
     1801                "failed to change state for det_id %" PRId64 ", exp_id %" PRId64,
     1802                det_id, exp_id);
     1803        return false;
     1804    }
     1805
     1806    return true;
     1807}
     1808
     1809
     1810bool setStackedImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *class_id, const char *data_state)
     1811{
     1812    PS_ASSERT_PTR_NON_NULL(config, false);
     1813    PS_ASSERT_PTR_NON_NULL(class_id, false);
     1814    PS_ASSERT_PTR_NON_NULL(data_state, false);
     1815
     1816    if (!isValidDataState (data_state)) return false;
     1817
     1818    char *query = "UPDATE detStackedImfile SET data_state = '%s'"
     1819        " WHERE det_id = %" PRId64
     1820        " AND iteration = %" PRId32
     1821        " AND class_id = %s";
     1822    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration, class_id)) {
     1823        psError(PS_ERR_UNKNOWN, false,
     1824                "failed to change state for det_id %" PRId64 ", iteration %" PRId32 "class_id %s",
     1825                det_id, iteration, class_id);
     1826        return false;
     1827    }
     1828
     1829    return true;
     1830}
     1831
     1832bool setNormStatImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *class_id, const char *data_state)
     1833{
     1834    PS_ASSERT_PTR_NON_NULL(config, false);
     1835    PS_ASSERT_PTR_NON_NULL(class_id, false);
     1836    PS_ASSERT_PTR_NON_NULL(data_state, false);
     1837
     1838    if (!isValidDataState (data_state)) return false;
     1839
     1840    char *query = "UPDATE detNormalizedStatImfile SET data_state = '%s'"
     1841        " WHERE det_id = %" PRId64
     1842        " AND iteration = %" PRId32
     1843        " AND class_id = %s";
     1844    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration)) {
     1845        psError(PS_ERR_UNKNOWN, false,
     1846                "failed to change state for det_id %" PRId64 ", iteration %" PRId32,
     1847                det_id, iteration);
     1848        return false;
     1849    }
     1850
     1851    return true;
     1852}
     1853
     1854bool setNormImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *class_id, const char *data_state)
     1855{
     1856    PS_ASSERT_PTR_NON_NULL(config, false);
     1857    PS_ASSERT_PTR_NON_NULL(class_id, false);
     1858    PS_ASSERT_PTR_NON_NULL(data_state, false);
     1859
     1860    if (!isValidDataState (data_state)) return false;
     1861
     1862    char *query = "UPDATE detNormalizedImfile SET data_state = '%s'"
     1863        " WHERE det_id = %" PRId64
     1864        " AND iteration = %" PRId32
     1865        " AND class_id = %s";
     1866    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration, class_id)) {
     1867        psError(PS_ERR_UNKNOWN, false,
     1868                "failed to change state for det_id %" PRId64 ", iteration %" PRId32 " class %s",
     1869                det_id, iteration, class_id);
     1870        return false;
     1871    }
     1872
     1873    return true;
     1874}
     1875
     1876bool setNormExpDataState(pxConfig *config, psS64 det_id, psS32 iteration, const char *data_state)
     1877{
     1878    PS_ASSERT_PTR_NON_NULL(config, false);
     1879    PS_ASSERT_PTR_NON_NULL(data_state, false);
     1880
     1881    if (!isValidDataState (data_state)) return false;
     1882
     1883    char *query = "UPDATE detNormalizedExp SET data_state = '%s'"
     1884        " WHERE det_id = %" PRId64
     1885        " AND iteration = %" PRId32;
     1886    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration)) {
     1887        psError(PS_ERR_UNKNOWN, false,
     1888                "failed to change state for det_id %" PRId64 ", iteration %" PRId32,
     1889                det_id, iteration);
     1890        return false;
     1891    }
     1892
     1893    return true;
     1894}
     1895
     1896bool setResidImfileDataState(pxConfig *config, psS64 det_id, psS32 iteration, psS64 exp_id, const char *class_id, const char *data_state)
     1897{
     1898    PS_ASSERT_PTR_NON_NULL(config, false);
     1899    PS_ASSERT_PTR_NON_NULL(data_state, false);
     1900    PS_ASSERT_PTR_NON_NULL(class_id, false);
     1901
     1902    if (!isValidDataState (data_state)) return false;
     1903
     1904    char *query = "UPDATE detResidImfile SET data_state = '%s'"
     1905        " WHERE det_id = %" PRId64
     1906        " AND iteration = %" PRId32
     1907        " AND exp_id = %" PRId64
     1908        " AND class_id = '%s'";
     1909    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration, exp_id, class_id)) {
     1910        psError(PS_ERR_UNKNOWN, false,
     1911                "failed to change state for det_id %" PRId64 ", iteration %" PRId32 ", exp_id %" PRId64 ", class_id %s",
     1912                det_id, iteration, exp_id, class_id);
     1913        return false;
     1914    }
     1915
     1916    return true;
     1917}
     1918
     1919bool setResidExpDataState(pxConfig *config, psS64 det_id, psS32 iteration, psS64 exp_id, const char *data_state)
     1920{
     1921    PS_ASSERT_PTR_NON_NULL(config, false);
     1922    PS_ASSERT_PTR_NON_NULL(data_state, false);
     1923
     1924    if (!isValidDataState (data_state)) return false;
     1925
     1926    char *query = "UPDATE detResidExp SET data_state = '%s'"
     1927        " WHERE det_id = %" PRId64
     1928        " AND iteration = %" PRId32
     1929        " AND exp_id = %" PRId64;
     1930    if (!p_psDBRunQuery(config->dbh, query, data_state, det_id, iteration, exp_id)) {
     1931        psError(PS_ERR_UNKNOWN, false,
     1932                "failed to change state for det_id %" PRId64 ", iteration %" PRId32 ", exp_id %" PRId64,
     1933                det_id, iteration, exp_id);
     1934        return false;
     1935    }
     1936
     1937    return true;
     1938}
    41241939
    41251940#if 0
Note: See TracChangeset for help on using the changeset viewer.