IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 3, 2010, 8:45:22 AM (16 years ago)
Author:
eugene
Message:

updates from trunk

Location:
branches/simmosaic_branches
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/simmosaic_branches

  • branches/simmosaic_branches/ippTools/src

    • Property svn:ignore
      •  

        old new  
         1*.la
         2*.lo
        13.deps
        24.gdb_history
         
        46Makefile
        57Makefile.in
         8addtool
         9caltool
         10camtool
         11chiptool
        612config.h
        713config.h.in
        8 stamp-h1
        9 *.la
        10 *.lo
         14detselect
         15dettool
         16difftool
         17disttool
         18dqstatstool
         19faketool
         20flatcorr
         21guidetool
         22magicdstool
         23magictool
         24pstamptool
         25pubtool
         26pxadmin
         27pxdata.c
         28pxinject
        1129pxtoolsErrorCodes.c
        1230pxtoolsErrorCodes.h
        13 pxadmin
        14 pxinject
        15 pztool
        1631pzgetexp
        1732pzgetimfiles
         33pztool
         34receivetool
        1835regtool
        19 guidetool
        20 chiptool
        21 camtool
         36stacktool
         37stamp-h1
        2238warptool
        23 difftool
        24 stacktool
        25 faketool
        26 dettool
        27 detselect
        28 pxdata.c
        29 magictool
        30 magicdstool
        31 caltool
        32 flatcorr
        33 pstamptool
        34 disttool
        35 receivetool
        36 
        37 pubtool
  • branches/simmosaic_branches/ippTools/src/magicdstool.c

    r24709 r27839  
    22 * magicdstool.c
    33 *
    4  * Copyright (C) 2006-2007  IfA
     4 * Copyright (C) 2006-2009  IfA
    55 *
    66 * This program is free software; you can redistribute it and/or modify it
     
    2727#include <math.h>
    2828#include <ippdb.h>
     29#include <ippStages.h>
    2930
    3031#include "pxtools.h"
     
    3233
    3334static bool definebyqueryMode(pxConfig *config);
    34 static psS64 definerunMode(pxConfig *config);
     35static bool definecopyMode(pxConfig *config);
    3536static bool updaterunMode(pxConfig *config);
    3637static bool todestreakMode(pxConfig *config);
    3738static bool adddestreakedfileMode(pxConfig *config);
     39static bool advancerunMode(pxConfig *config);
    3840static bool revertdestreakedfileMode(pxConfig *config);
     41static bool clearstatefaultsMode(pxConfig *config);
    3942static bool getskycellsMode(pxConfig *config);
    4043static bool toremoveMode(pxConfig *config);
    41 static bool torestoreMode(pxConfig *config);
    4244static bool torevertMode(pxConfig *config);
    43 
    44 static bool setmagicDSRunState(pxConfig *config, psS64 magic_id, const char *state);
    45 static bool magicDSRunComplete(pxConfig *config, bool setmagicked);
    46 static bool magicDSGetIDs(pxConfig *config, psString stage, psS64 magic_id, psS64 *stage_id, psS64 *cam_id);
     45static bool completedrevertMode(pxConfig *config);
     46static bool tocleanupMode(pxConfig *config);
     47
     48static bool setmagicDSRunState(pxConfig *config, psS64 magic_id, psString extraSetString, psMetadata *where, const char *state);
    4749
    4850# define MODECASE(caseName, func) \
     
    6567    switch (config->mode) {
    6668        MODECASE(MAGICDSTOOL_MODE_DEFINEBYQUERY,       definebyqueryMode);
    67         MODECASE(MAGICDSTOOL_MODE_DEFINERUN,           definerunMode);
     69        MODECASE(MAGICDSTOOL_MODE_DEFINECOPY,          definecopyMode);
    6870        MODECASE(MAGICDSTOOL_MODE_UPDATERUN,           updaterunMode);
    6971        MODECASE(MAGICDSTOOL_MODE_TODESTREAK,          todestreakMode);
    7072        MODECASE(MAGICDSTOOL_MODE_ADDDESTREAKEDFILE,   adddestreakedfileMode);
     73        MODECASE(MAGICDSTOOL_MODE_ADVANCERUN,          advancerunMode);
    7174        MODECASE(MAGICDSTOOL_MODE_REVERTDESTREAKEDFILE,revertdestreakedfileMode);
     75        MODECASE(MAGICDSTOOL_MODE_CLEARSTATEFAULTS,    clearstatefaultsMode);
    7276        MODECASE(MAGICDSTOOL_MODE_GETSKYCELLS,         getskycellsMode);
    7377        MODECASE(MAGICDSTOOL_MODE_TOREMOVE,            toremoveMode);
    74         MODECASE(MAGICDSTOOL_MODE_TORESTORE,           torestoreMode);
    7578        MODECASE(MAGICDSTOOL_MODE_TOREVERT,            torevertMode);
     79        MODECASE(MAGICDSTOOL_MODE_COMPLETEDREVERT,     completedrevertMode);
     80        MODECASE(MAGICDSTOOL_MODE_TOCLEANUP,           tocleanupMode);
    7681        default:
    7782            psAbort("invalid option (this should not happen)");
     
    97102static bool definebyqueryMode(pxConfig *config)
    98103{
    99     PS_ASSERT_PTR_NON_NULL(config, false);
    100     psError(PS_ERR_UNKNOWN, true, "definebyquery not implelmented yet");
    101 
    102     return false;
    103 #ifdef notyet
    104104
    105105    // Required
     106    PXOPT_LOOKUP_STR(stage, config->args, "-stage", true, false);
     107
     108    // Optional
    106109    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", false, false);
    107 
    108     // Optional
    109     PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
    110     PXOPT_LOOKUP_STR(dvodb, config->args, "-dvodb", false, false);
    111     PXOPT_LOOKUP_TIME(registered, config->args, "-registered", false, false);
     110    PXOPT_LOOKUP_STR(recoveryroot, config->args, "-recoveryroot", false, false);
     111    PXOPT_LOOKUP_BOOL(noreplace, config->args, "-noreplace", false);
     112    PXOPT_LOOKUP_STR(set_label, config->args, "-set_label", false, false);
     113    PXOPT_LOOKUP_STR(set_data_group, config->args, "-set_data_group", false, false);
     114    PXOPT_LOOKUP_STR(note, config->args, "-set_note", false, false);
     115    PXOPT_LOOKUP_BOOL(rerun, config->args, "-rerun", false);
     116    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
    112117    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    113 
    114     // Create temporary table of the best diffs
    115     {
    116         psString query = pxDataGet("magictool_definebyquery_temp_create.sql");
    117         if (!query) {
    118             psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    119             return false;
    120         }
    121 
    122         if (!p_psDBRunQuery(config->dbh, query)) {
     118    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     119
     120    // search args
     121    psMetadata *where = psMetadataAlloc();
     122    PXOPT_COPY_S64(config->args, where, "-exp_id",  "exp_id", "==");
     123    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
     124    PXOPT_COPY_S64(config->args, where, "-cam_id",  "cam_id", "==");
     125    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
     126    PXOPT_COPY_S64(config->args, where, "-diff_id", "diff_id", "==");
     127    PXOPT_COPY_S64(config->args, where, "-magic_id","magicRun.magic_id", "==");
     128    PXOPT_COPY_S32(config->args, where, "-streaks_max","streaks", "<=");
     129
     130    pxAddLabelSearchArgs (config, where, "-label", "magicRun.label", "=="); // define using magicRun label
     131
     132    ippStage stageNum = ippStringToStage(stage);
     133
     134    psString query = NULL;
     135    switch (stageNum) {
     136    case IPP_STAGE_RAW:
     137        query = pxDataGet("magicdstool_definebyquery_raw.sql");
     138        break;
     139    case IPP_STAGE_CHIP:
     140        query = pxDataGet("magicdstool_definebyquery_chip.sql");
     141        break;
     142    case IPP_STAGE_CAMERA:
     143        query = pxDataGet("magicdstool_definebyquery_camera.sql");
     144        break;
     145    case IPP_STAGE_WARP:
     146        query = pxDataGet("magicdstool_definebyquery_warp.sql");
     147        break;
     148    case IPP_STAGE_DIFF:
     149        query = pxDataGet("magicdstool_definebyquery_diff.sql");
     150        break;
     151    case IPP_STAGE_FAKE:
     152    case IPP_STAGE_STACK:
     153        psError(PXTOOLS_ERR_CONFIG, true, "%sRuns do not need to be destreaked", stage);
     154        return false;
     155    case IPP_STAGE_NONE:
     156        psError(PXTOOLS_ERR_CONFIG, true, "%s is not a valid stage", stage);
     157        return false;
     158    default:
     159        psError(PXTOOLS_ERR_PROG, true, "ippStageToString returned %d for invalid stage %s",
     160            stageNum, stage);
     161        return false;
     162    }
     163
     164    if (!query) {
     165        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
     166        return false;
     167    }
     168    char *rerun_flag =  rerun ? "\n1 " : "\n0" ;
     169
     170    if (stageNum != IPP_STAGE_DIFF) {
     171        if (psListLength(where->list)) {
     172            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     173            psStringAppend(&query, "\nAND %s", whereClause);
     174            psFree(whereClause);
     175        }
     176        psFree(where);
     177
     178        // treat limit == 0 as "no limit"
     179        if (limit) {
     180            psString limitString = psDBGenerateLimitSQL(limit);
     181            psStringAppend(&query, " %s", limitString);
     182            psFree(limitString);
     183        }
     184        if (!p_psDBRunQueryF(config->dbh, query, rerun_flag)) {
    123185            psError(PS_ERR_UNKNOWN, false, "database error");
    124             return false;
    125         }
    126         psFree(query);
    127     }
    128 
    129     // Insert list of best diffs into temporary table
    130     {
    131         psString query = pxDataGet("magictool_definebyquery_temp_insert.sql");
    132         if (!query) {
    133             psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    134             return false;
    135         }
    136 
    137         psMetadata *where = psMetadataAlloc();
    138         PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
    139         PXOPT_COPY_STR(config->args, where, "-diff_label", "diffRun.label", "==");
    140         PXOPT_COPY_F32(config->args, where, "-good_frac", "warpSkyfile.good_frac", ">=");
    141 
    142         psString whereClause = NULL;    // WHERE conditions
    143         if (psListLength(where->list)) {
    144             whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    145             psStringPrepend(&whereClause, "\n AND ");
    146         }
    147         psFree(where);
    148 
    149         if (!p_psDBRunQueryF(config->dbh, query, whereClause)) {
    150             psError(PS_ERR_UNKNOWN, false, "database error");
    151             psFree(whereClause);
    152186            psFree(query);
    153187            return false;
    154188        }
    155         psFree(whereClause);
    156         psFree(query);
    157     }
    158 
    159     // Get list of exposures ready to magic
    160     {
    161         psString query = pxDataGet("magictool_definebyquery_select.sql");
    162         if (!query) {
    163             psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    164             return false;
    165         }
    166 
    167         psString magicSkyCellNumsWhere = NULL;    // WHERE conditions for magicSkyCellNums
    168         {
    169             psMetadata *where = psMetadataAlloc();
    170             PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
    171             PXOPT_COPY_STR(config->args, where, "-diff_label", "diffRun.label", "==");
    172             PXOPT_COPY_F32(config->args, where, "-good_frac", "warpSkyfile.good_frac", ">=");
    173 
    174             if (psListLength(where->list)) {
    175                 magicSkyCellNumsWhere = psDBGenerateWhereConditionSQL(where, NULL);
    176                 psStringPrepend(&magicSkyCellNumsWhere, "\n AND ");
    177             }
    178             psFree(where);
    179         }
    180 
    181         // "available" means only concern ourselves with exposures that have all diffs completed, unless we're
    182         // told to only take what's available.
    183         // "new" means we want a new run even if there's already a magic run defined
    184         PXOPT_LOOKUP_BOOL(available, config->args, "-available", false);
    185         PXOPT_LOOKUP_BOOL(new, config->args, "-new", false);
    186 
    187         psString queryWhere = NULL;     // WHERE conditions for entire query
    188         if (available) {
    189             psStringAppend(&queryWhere, " WHERE num_done = num_todo");
    190         }
    191         if (new) {
    192             const char *newWhere = " magic_id IS NULL"; // String to add
    193             if (queryWhere) {
    194                 psStringAppend(&queryWhere, " AND %s", newWhere);
    195             } else {
    196                 psStringAppend(&queryWhere, " WHERE %s", newWhere);
    197             }
    198         }
    199         if (queryWhere) {
    200             psStringAppend(&query, " %s", queryWhere);
    201             psFree(queryWhere);
    202         }
    203 
    204 
    205         if (!p_psDBRunQueryF(config->dbh, query, magicSkyCellNumsWhere ? magicSkyCellNumsWhere : "")) {
     189    } else {
     190        // diff stage query has two types bothways and !bothways
     191        // so we need to send the rerun flag and the where data twice
     192        psString whereString = psStringCopy("");
     193        if (psListLength(where->list)) {
     194            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     195            psStringAppend(&whereString, "\nAND %s", whereClause);
     196            psFree(whereClause);
     197        }
     198        psFree(where);
     199
     200        // treat limit == 0 as "no limit"
     201        if (limit) {
     202            psString limitString = psDBGenerateLimitSQL(limit);
     203            psStringAppend(&query, " %s", limitString);
     204            psFree(limitString);
     205        }
     206
     207        if (!p_psDBRunQueryF(config->dbh, query, rerun_flag, whereString, rerun_flag, whereString)) {
    206208            psError(PS_ERR_UNKNOWN, false, "database error");
    207             psFree(magicSkyCellNumsWhere);
     209            psFree(whereString);
    208210            psFree(query);
    209211            return false;
    210212        }
    211         psFree(magicSkyCellNumsWhere);
    212         psFree(query);
    213     }
     213        psFree(whereString);
     214    }
     215    psFree(query);
    214216
    215217    psArray *output = p_psDBFetchResult(config->dbh);
     
    233235    }
    234236
    235     // Parse the list of exposures ready to magic
    236 
    237     if (!psDBTransaction(config->dbh)) {
    238         psError(PS_ERR_UNKNOWN, false, "database error");
    239         return false;
    240     }
    241 
    242     psString insert = pxDataGet("magictool_definebyquery_insert.sql"); // Insert query
     237    // Parse the list of runs ready to be destreaked
     238
     239    if (!pretend && !psDBTransaction(config->dbh)) {
     240        psError(PS_ERR_UNKNOWN, false, "database error");
     241        return false;
     242    }
    243243
    244244    psArray *list = psArrayAllocEmpty(16); // List of runs, to print
    245245    for (long i = 0; i < psArrayLength(output); i++) {
    246246        psMetadata *row = output->data[i]; // Row of interest
    247         psS64 exp_id = psMetadataLookupS64(NULL, row, "exp_id"); // Exposure identifier
     247        psS64 stage_id = psMetadataLookupS64(NULL, row, "stage_id");
     248        psS64 exp_id = psMetadataLookupS64(NULL, row, "exp_id");
     249        psS64 magic_id = psMetadataLookupS64(NULL, row, "magic_id");
     250        psS64 inv_magic_id = psMetadataLookupS64(NULL, row, "inv_magic_id");
     251        psS64 cam_id = psMetadataLookupS64(NULL, row, "cam_id");
     252        psString magicRunLabel = psMetadataLookupStr(NULL, row, "label");
     253        psString magicRunDataGroup = psMetadataLookupStr(NULL, row, "data_group");
     254        psString magicRunWorkdir = psMetadataLookupStr(NULL, row, "workdir");
     255
     256        // if workdir is not supplied use the magicRun's
     257        if (!workdir) {
     258            workdir = magicRunWorkdir;
     259        }
     260
     261        psString outroot = NULL;
     262        // set outroot to workdir/exp_id/stage for example /somewhere/424242/chip
     263        psStringAppend(&outroot, "%s/%" PRId64 "/%s", workdir, exp_id, stage);
    248264
    249265        // create a new magicRun for this group
    250         magicRunRow *run = magicRunRowAlloc(0, exp_id, "new", workdir, "dirty", label, dvodb, registered, 0);
     266        magicDSRunRow *run = magicDSRunRowAlloc(
     267                0, // magic_ds_id
     268                magic_id,
     269                inv_magic_id,
     270                "new",
     271                stage,
     272                stage_id,
     273                cam_id,
     274                set_label ? set_label : magicRunLabel,
     275                set_data_group ? set_data_group : magicRunDataGroup,
     276                outroot,
     277                recoveryroot,
     278                noreplace ? 0 :1,   // re_place
     279                0,      // remove
     280                0,      // fault
     281                note);  // remove
     282
     283        psFree(outroot);
    251284        if (!run) {
    252             psAbort("failed to alloc magicRun object");
    253         }
    254 
    255         if (!magicRunInsertObject(config->dbh, run)) {
    256             psError(PS_ERR_UNKNOWN, false, "database error");
    257             psFree(run);
    258             psFree(insert);
    259             psFree(output);
    260             psFree(list);
    261             if (!psDBRollback(config->dbh)) {
     285            psAbort("failed to alloc magicDSRun object");
     286        }
     287
     288        if (!pretend) {
     289            if (!magicDSRunInsertObject(config->dbh, run)) {
    262290                psError(PS_ERR_UNKNOWN, false, "database error");
     291                psFree(run);
     292                psFree(output);
     293                psFree(list);
     294                if (!psDBRollback(config->dbh)) {
     295                    psError(PS_ERR_UNKNOWN, false, "database error");
     296                }
     297                return false;
    263298            }
    264             return false;
    265         }
    266 
    267         psS64 magic_id = psDBLastInsertID(config->dbh); // Assigned identifier
    268         run->magic_id = magic_id;
     299            psS64 magic_ds_id = psDBLastInsertID(config->dbh); // Assigned identifier
     300            run->magic_ds_id = magic_ds_id;
     301        }
    269302
    270303        psArrayAdd(list, list->n, run);
    271304        psFree(run);
    272 
    273         // Create a suitable insertion query for this run
    274         psString thisInsert = psStringCopy(insert);
    275         {
    276             psString idString = NULL;
    277             psStringAppend(&idString, "%" PRId64, magic_id);
    278             psStringSubstitute(&thisInsert, idString, "@MAGIC_ID@");
    279             psFree(idString);
    280         }
    281         {
    282             psString idString = NULL;
    283             psStringAppend(&idString, "%" PRId64, exp_id);
    284             psStringSubstitute(&thisInsert, idString, "@EXP_ID@");
    285             psFree(idString);
    286         }
    287 
    288         if (!p_psDBRunQueryF(config->dbh, thisInsert, magic_id, exp_id)) {
    289             psError(PS_ERR_UNKNOWN, false, "database error");
    290             psFree(thisInsert);
    291             psFree(insert);
    292             psFree(output);
    293             psFree(list);
    294             if (!psDBRollback(config->dbh)) {
    295                 psError(PS_ERR_UNKNOWN, false, "database error");
    296             }
    297             return false;
    298         }
    299         psFree(thisInsert);
    300     }
    301 
    302     if (!psDBCommit(config->dbh)) {
     305    }
     306
     307    if (!pretend && !psDBCommit(config->dbh)) {
    303308        psError(PS_ERR_UNKNOWN, false, "database error");
    304309        return false;
     
    306311    psFree(output);
    307312
    308     if (!magicRunPrintObjects(stdout, list, !simple)) {
     313    if (!magicDSRunPrintObjects(stdout, list, !simple)) {
    309314        psError(PS_ERR_UNKNOWN, false, "failed to print object");
    310315        psFree(list);
     
    315320
    316321    return true;
    317 #endif // notyet
    318 }
    319 
    320 static psS64 definerunMode(pxConfig *config)
     322}
     323
     324
     325// XXX This currently allows multiple destreak runs to be queued on the same exposure if there are multiple
     326// magicRuns selected!
     327static bool definecopyMode(pxConfig *config)
     328{
     329    // Required
     330    PXOPT_LOOKUP_STR(stage, config->args, "-stage", true, false);
     331    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", true, false);
     332
     333    // Optional
     334    PXOPT_LOOKUP_STR(recoveryroot, config->args, "-recoveryroot", false, false);
     335    PXOPT_LOOKUP_BOOL(noreplace, config->args, "-noreplace", false);
     336    PXOPT_LOOKUP_STR(set_label, config->args, "-set_label", false, false);
     337    PXOPT_LOOKUP_STR(set_data_group, config->args, "-set_data_group", false, false);
     338    PXOPT_LOOKUP_STR(note, config->args, "-set_note", false, false);
     339    PXOPT_LOOKUP_BOOL(rerun, config->args, "-rerun", false);
     340    PXOPT_LOOKUP_BOOL(pretend, config->args, "-pretend", false);
     341    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     342    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     343
     344    // search args
     345    psMetadata *where = psMetadataAlloc();
     346    PXOPT_COPY_S64(config->args, where, "-exp_id",  "chipRun.exp_id", "==");
     347    PXOPT_COPY_S64(config->args, where, "-chip_id", "chipRun.chip_id", "==");
     348    PXOPT_COPY_S64(config->args, where, "-cam_id",  "camRun.cam_id", "==");
     349    PXOPT_COPY_S64(config->args, where, "-warp_id", "warpRun.warp_id", "==");
     350    PXOPT_COPY_S64(config->args, where, "-diff_id", "diffRun.diff_id", "==");
     351    PXOPT_COPY_S64(config->args, where, "-magic_id", "magicRun.magic_id", "==");
     352    PXOPT_COPY_S32(config->args, where, "-streaks_max", "magicMask.streaks", "<=");
     353
     354    pxAddLabelSearchArgs (config, where, "-magic_label", "magicRun.label", "=="); // define magic label
     355    psString labelName = NULL;                                                    // Name of label
     356    psStringAppend(&labelName, "%sRun.label", stage);
     357    pxAddLabelSearchArgs (config, where, "-stage_label", labelName, "=="); // define stageRun label
     358    psFree(labelName);
     359
     360    ippStage stageNum = ippStringToStage(stage);
     361
     362    psString query = NULL;
     363    switch (stageNum) {
     364      case IPP_STAGE_RAW:
     365        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Raw stage is not appropriate for a copied destreak");
     366        return false;
     367      case IPP_STAGE_CHIP:
     368        query = pxDataGet("magicdstool_definecopy_chip.sql");
     369        break;
     370      case IPP_STAGE_WARP:
     371        query = pxDataGet("magicdstool_definecopy_warp.sql");
     372        break;
     373      case IPP_STAGE_CAMERA:
     374      case IPP_STAGE_DIFF:
     375      case IPP_STAGE_FAKE:
     376        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "%s has not been coded.", stage);
     377        return false;
     378      case IPP_STAGE_STACK:
     379        psError(PXTOOLS_ERR_CONFIG, true, "Stacks do not need to be destreaked");
     380        return false;
     381      case IPP_STAGE_NONE:
     382        psError(PXTOOLS_ERR_CONFIG, true, "%s is not a valid stage", stage);
     383        return false;
     384      default:
     385        psError(PXTOOLS_ERR_PROG, true, "ippStageToString returned %d for invalid stage %s",
     386                stageNum, stage);
     387        return false;
     388    }
     389
     390    if (!query) {
     391        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
     392        return false;
     393    }
     394    const char *rerun_flag =  rerun ? "" : "\n"; // String to give query to activate (or not) rerun
     395
     396    if (stageNum != IPP_STAGE_DIFF) {
     397        if (psListLength(where->list)) {
     398            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     399            psStringAppend(&query, "\nAND %s", whereClause);
     400            psFree(whereClause);
     401        }
     402        psFree(where);
     403
     404        // treat limit == 0 as "no limit"
     405        if (limit) {
     406            psString limitString = psDBGenerateLimitSQL(limit);
     407            psStringAppend(&query, " %s", limitString);
     408            psFree(limitString);
     409        }
     410        if (!p_psDBRunQueryF(config->dbh, query, set_label, rerun_flag)) {
     411            psError(PS_ERR_UNKNOWN, false, "database error");
     412            psFree(query);
     413            return false;
     414        }
     415    } else {
     416        // diff stage query has two types bothways and !bothways
     417        // so we need to send the rerun flag and the where data twice
     418        psString whereString = psStringCopy("");
     419        if (psListLength(where->list)) {
     420            psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     421            psStringAppend(&whereString, "\nAND %s", whereClause);
     422            psFree(whereClause);
     423        }
     424        psFree(where);
     425
     426        // treat limit == 0 as "no limit"
     427        if (limit) {
     428            psString limitString = psDBGenerateLimitSQL(limit);
     429            psStringAppend(&query, " %s", limitString);
     430            psFree(limitString);
     431        }
     432
     433        if (!p_psDBRunQueryF(config->dbh, query, rerun_flag, whereString, rerun_flag, whereString)) {
     434            psError(PS_ERR_UNKNOWN, false, "database error");
     435            psFree(whereString);
     436            psFree(query);
     437            return false;
     438        }
     439        psFree(whereString);
     440    }
     441    psFree(query);
     442
     443    psArray *output = p_psDBFetchResult(config->dbh);
     444    if (!output) {
     445        psErrorCode err = psErrorCodeLast();
     446        switch (err) {
     447          case PS_ERR_DB_CLIENT:
     448            psError(PXTOOLS_ERR_SYS, false, "database error");
     449          case PS_ERR_DB_SERVER:
     450            psError(PXTOOLS_ERR_PROG, false, "database error");
     451          default:
     452            psError(PXTOOLS_ERR_PROG, false, "unknown error");
     453        }
     454
     455        return false;
     456    }
     457    if (!psArrayLength(output)) {
     458        psTrace("magictool", PS_LOG_INFO, "no rows found");
     459        psFree(output);
     460        return true;
     461    }
     462
     463    // Parse the list of runs ready to be destreaked
     464
     465    if (!pretend && !psDBTransaction(config->dbh)) {
     466        psError(PS_ERR_UNKNOWN, false, "database error");
     467        return false;
     468    }
     469
     470    psArray *list = psArrayAllocEmpty(16); // List of runs, to print
     471    for (long i = 0; i < psArrayLength(output); i++) {
     472        psMetadata *row = output->data[i]; // Row of interest
     473        psS64 stage_id = psMetadataLookupS64(NULL, row, "stage_id");
     474        psS64 exp_id = psMetadataLookupS64(NULL, row, "exp_id");
     475        psS64 magic_id = psMetadataLookupS64(NULL, row, "magic_id");
     476        psS64 inv_magic_id = psMetadataLookupS64(NULL, row, "inv_magic_id");
     477        psS64 cam_id = psMetadataLookupS64(NULL, row, "cam_id");
     478        psString magicRunLabel = psMetadataLookupStr(NULL, row, "label");
     479        psString magicRunDataGroup = psMetadataLookupStr(NULL, row, "data_group");
     480
     481        psString outroot = NULL;
     482        // set outroot to workdir/exp_id/stage for example /somewhere/424242/chip
     483        psStringAppend(&outroot, "%s/%" PRId64 "/%s", workdir, exp_id, stage);
     484
     485        // create a new magicRun for this group
     486        magicDSRunRow *run = magicDSRunRowAlloc(
     487                0, // magic_ds_id
     488                magic_id,
     489                inv_magic_id,
     490                "new",
     491                stage,
     492                stage_id,
     493                cam_id,
     494                set_label ? set_label : magicRunLabel,
     495                set_data_group ? set_data_group : magicRunDataGroup,
     496                outroot,
     497                recoveryroot,
     498                noreplace ? 0 :1,   // re_place
     499                0,      // remove
     500                0,      // fault
     501                note);  // remove
     502
     503        psFree(outroot);
     504        if (!run) {
     505            psAbort("failed to alloc magicDSRun object");
     506        }
     507
     508        if (!pretend) {
     509            if (!magicDSRunInsertObject(config->dbh, run)) {
     510                psError(PS_ERR_UNKNOWN, false, "database error");
     511                psFree(run);
     512                psFree(output);
     513                psFree(list);
     514                if (!psDBRollback(config->dbh)) {
     515                    psError(PS_ERR_UNKNOWN, false, "database error");
     516                }
     517                return false;
     518            }
     519            psS64 magic_ds_id = psDBLastInsertID(config->dbh); // Assigned identifier
     520            run->magic_ds_id = magic_ds_id;
     521        }
     522
     523        psArrayAdd(list, list->n, run);
     524        psFree(run);
     525    }
     526
     527    if (!pretend && !psDBCommit(config->dbh)) {
     528        psError(PS_ERR_UNKNOWN, false, "database error");
     529        return false;
     530    }
     531    psFree(output);
     532
     533    if (!magicDSRunPrintObjects(stdout, list, !simple)) {
     534        psError(PS_ERR_UNKNOWN, false, "failed to print object");
     535        psFree(list);
     536        return false;
     537    }
     538
     539    psFree(list);
     540
     541    return true;
     542}
     543
     544
     545static bool updaterunMode(pxConfig *config)
    321546{
    322547    PS_ASSERT_PTR_NON_NULL(config, false);
    323548
    324549    // required
    325     PXOPT_LOOKUP_S64(magic_id, config->args, "-magic_id", true, false);
     550    PXOPT_LOOKUP_STR(state, config->args, "-set_state", true, false);
     551
     552    // optional
     553    PXOPT_LOOKUP_STR(set_label, config->args, "-set_label", false, false);
     554    PXOPT_LOOKUP_STR(set_data_group, config->args, "-set_data_group", false, false);
     555    psString setString = NULL;
     556    if (set_label) {
     557        psStringAppend(&setString, ", label = '%s'", set_label);
     558    }
     559    if (set_data_group) {
     560        psStringAppend(&setString, ", data_group = '%s'", set_data_group);
     561    }
     562
     563    PXOPT_LOOKUP_S64(magic_ds_id, config->args, "-magic_ds_id", false, false);
     564    if (magic_ds_id) {
     565
     566        return setmagicDSRunState(config, magic_ds_id, setString, NULL, state);
     567
     568    } else if (!strcmp(state, "full")) {
     569        psError(PS_ERR_UNKNOWN, true, "magic_ds_id is required to update run state to full");
     570        return false;
     571    }
     572    // we can transition by query as well
     573
     574    psMetadata *where = psMetadataAlloc();
     575    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
     576    PXOPT_COPY_S64(config->args, where, "-stage_id", "stage_id", "==");
     577    PXOPT_COPY_STR(config->args, where, "-stage", "stage", "==");
     578    PXOPT_COPY_STR(config->args, where, "-state", "state", "==");
     579    PXOPT_COPY_STR(config->args, where, "-data_group", "data_group", "LIKE");
     580
     581    if (psListLength(where->list) < 2) {
     582        psError(PS_ERR_UNKNOWN, true, "at least 2 search arguments are required");
     583        return false;
     584    }
     585
     586
     587    PXOPT_LOOKUP_BOOL(noreplace, config->args, "-noreplace", false);
     588    if (!noreplace) {
     589        psMetadataAddS32(where, PS_LIST_TAIL, "re_place", 0, ">", 0);
     590    }
     591    bool result = setmagicDSRunState(config, magic_ds_id, setString, where, state);
     592    psFree(where);
     593
     594    return result;
     595}
     596
     597
     598static bool todestreakMode(pxConfig *config)
     599{
     600    PS_ASSERT_PTR_NON_NULL(config, false);
     601
    326602    PXOPT_LOOKUP_STR(stage, config->args, "-stage", true, false);
    327     PXOPT_LOOKUP_STR(outroot, config->args, "-outroot", true, false);
    328 
    329     // optional
    330     PXOPT_LOOKUP_STR(recoveryroot, config->args, "-recoveryroot", false, false);
    331     PXOPT_LOOKUP_BOOL(re_place, config->args, "-replace", false);
    332     PXOPT_LOOKUP_BOOL(remove, config->args, "-remove", false);
    333     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    334     PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
    335 
    336     psS64 stage_id = 0, cam_id = 0;
    337 
    338     if (!magicDSGetIDs(config, stage, magic_id, &stage_id, &cam_id)) {
    339         psError(PS_ERR_UNKNOWN, false, "failed to get ids");
    340         return false;
    341     }
    342 
    343     magicDSRunRow *run = magicDSRunRowAlloc(
    344             0,          // ID
    345             magic_id,
    346             "new",      // state
    347             stage,
    348             stage_id,
    349             cam_id,
    350             label,
    351             outroot,
    352             recoveryroot,
    353             re_place,
    354             remove
    355     );
    356 
    357     if (!run) {
    358         psError(PS_ERR_UNKNOWN, false, "failed to alloc magicRun object");
    359         return false;
    360     }
    361     if (!magicDSRunInsertObject(config->dbh, run)) {
    362         psError(PS_ERR_UNKNOWN, false, "database error");
    363         psFree(run);
    364         return false;
    365     }
    366 
    367     psS64 magic_ds_id = psDBLastInsertID(config->dbh);
    368     run->magic_ds_id = magic_ds_id;
    369 
    370     if (!magicDSRunPrintObject(stdout, run, !simple)) {
    371             psError(PS_ERR_UNKNOWN, false, "failed to print object");
    372             psFree(run);
    373             return false;
    374     }
    375 
    376     psFree(run);
    377 
    378     return magic_id;
    379 }
    380 
    381 
    382 static bool updaterunMode(pxConfig *config)
    383 {
    384     PS_ASSERT_PTR_NON_NULL(config, false);
    385 
    386     // required
    387     PXOPT_LOOKUP_S64(magic_ds_id, config->args, "-magic_ds_id", true, false);
    388     PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
    389 
    390     if (state) {
    391         // set detRun.state to state
    392         return setmagicDSRunState(config, magic_ds_id, state);
    393     }
    394 
    395     return true;
    396 }
    397 
    398 
    399 static bool todestreakMode(pxConfig *config)
    400 {
    401     PS_ASSERT_PTR_NON_NULL(config, false);
    402603
    403604    psMetadata *where = psMetadataAlloc();
    404     PXOPT_COPY_S64(config->args, where, "-magic_ds_id", "magic_ds_id", "==");
     605    PXOPT_COPY_S64(config->args, where, "-magic_ds_id", "magicDSRun.magic_ds_id", "==");
    405606    PXOPT_COPY_S64(config->args, where, "-magic_id", "magic_id", "==");
    406     pxAddLabelSearchArgs (config, where, "-label", "label", "==");
     607    pxAddLabelSearchArgs (config, where, "-label", "magicDSRun.label", "==");
    407608
    408609    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    409610    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    410611
    411     // look for "inputs" that need to processed
    412     psString query = pxDataGet("magicdstool_todestreak.sql");
     612    psString sql_file = NULL;
     613    psStringAppend(&sql_file, "magicdstool_todestreak_%s.sql", stage);
     614
     615    psString query = pxDataGet(sql_file);
    413616    if (!query) {
    414         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    415         return false;
    416     }
     617        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement from %s", sql_file);
     618        psFree(sql_file);
     619        return false;
     620    }
     621    psFree(sql_file);
    417622
    418623    if (psListLength(where->list)) {
    419624        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    420         psStringAppend(&query, " WHERE %s", whereClause);
     625        psStringAppend(&query, " AND %s", whereClause);
    421626        psFree(whereClause);
    422627    }
     
    476681{
    477682    // first query the magicDSRun to find the stage and the stage_id
    478     psString query = "SELECT stage, stage_id from magicDSRun where magic_ds_id = %" PRId64;
     683    psString query = "SELECT stage, stage_id, magic_id from magicDSRun where magic_ds_id = %" PRId64;
    479684
    480685    if (!p_psDBRunQueryF(config->dbh, query, magic_ds_id)) {
     
    501706    psMetadata *row = output->data[0];
    502707
    503     psString stage = psMetadataLookupStr(NULL, row, "stage");
     708    psString stage= psMetadataLookupStr(NULL, row, "stage");
    504709    psS64 stage_id = psMetadataLookupS64(NULL, row, "stage_id");
    505 
    506     if (!strcmp(stage, "camera")) {
    507         // no there is no magicked column in camProcessedExp
     710    psS64 magic_id = psMetadataLookupS64(NULL, row, "magic_id");
     711
     712    ippStage stageNum = ippStringToStage(stage);
     713
     714    // chose the appropriate query based on the stage
     715    switch (stageNum) {
     716    case IPP_STAGE_RAW:
     717        query = "UPDATE rawImfile SET magicked = %" PRId64 " where exp_id = %" PRId64 " AND class_id = '%s'";
     718        break;
     719    case IPP_STAGE_CHIP:
     720        query = "UPDATE chipProcessedImfile SET magicked = %" PRId64 " where chip_id = %" PRId64 " AND class_id = '%s'";
     721        break;
     722    case IPP_STAGE_CAMERA:
     723        // no there is no magicked column in camProcessedExp so we have nothing to do
    508724        psFree(output);
    509725        return true;
    510     }
    511 
    512     // chose the appropriate query based on the stage
    513     if (!strcmp(stage, "raw")) {
    514         query = "UPDATE rawImfile SET magicked = %" PRId64 " where exp_id = %" PRId64 " AND class_id = '%s'";
    515     } else if (!strcmp(stage, "chip")) {
    516         query = "UPDATE chipProcessedImfile SET magicked = %" PRId64 " where chip_id = %" PRId64 " AND class_id = '%s'";
    517     } else if (!strcmp(stage, "warp")) {
     726    case IPP_STAGE_WARP:
    518727        query = "UPDATE warpSkyfile SET magicked = %" PRId64 " where warp_id = %" PRId64 " AND skycell_id = '%s'";
    519     } else if (!strcmp(stage, "diff")) {
     728        break;
     729    case IPP_STAGE_DIFF:
    520730        query = "UPDATE diffSkyfile SET magicked = %" PRId64 " where diff_id = %" PRId64 " AND skycell_id = '%s'";
    521     } else {
     731        break;
     732    default:
    522733        psError(PS_ERR_UNKNOWN, true, "unexpected value for stage: %s found", stage);
    523734        psFree(output);
    524735        return false;
    525736    }
    526     if (!p_psDBRunQueryF(config->dbh, query, magic_ds_id, stage_id, component)) {
     737
     738    if (!p_psDBRunQueryF(config->dbh, query, magic_id, stage_id, component)) {
    527739        psError(PS_ERR_UNKNOWN, false, "database error");
    528740        return false;
     
    543755{
    544756    // first query the magicDSRun to find the stage and the stage_id
    545     psString query = "SELECT stage, stage_id from magicDSRun where magic_ds_id = %" PRId64;
     757    psString query = "SELECT stage, stage_id, magic_id from magicDSRun where magic_ds_id = %" PRId64;
    546758
    547759    if (!p_psDBRunQueryF(config->dbh, query, magic_ds_id)) {
     
    570782    psString stage = psMetadataLookupStr(NULL, row, "stage");
    571783    psS64 stage_id = psMetadataLookupS64(NULL, row, "stage_id");
    572 
     784    psS64 magic_id = psMetadataLookupS64(NULL, row, "magic_id");
     785
     786    ippStage stageNum = ippStringToStage(stage);
    573787
    574788    // chose the appropriate query based on the stage
    575     if (!strcmp(stage, "raw")) {
     789    switch (stageNum) {
     790    case IPP_STAGE_RAW:
    576791        query = "UPDATE rawExp SET magicked = %" PRId64 " where exp_id = %" PRId64;
    577     } else if (!strcmp(stage, "chip")) {
     792        break;
     793    case IPP_STAGE_CHIP:
    578794        query = "UPDATE chipRun SET magicked = %" PRId64 " where chip_id = %" PRId64;
    579     } else if (!strcmp(stage, "camera")) {
     795        break;
     796    case IPP_STAGE_CAMERA:
    580797        query = "UPDATE camRun SET magicked = %" PRId64 " where cam_id = %" PRId64;
    581     } else if (!strcmp(stage, "warp")) {
     798        break;
     799    case IPP_STAGE_WARP:
    582800        query = "UPDATE warpRun SET magicked = %" PRId64 " where warp_id = %" PRId64;
    583     } else if (!strcmp(stage, "diff")) {
     801        break;
     802    case IPP_STAGE_DIFF:
    584803        query = "UPDATE diffRun SET magicked = %" PRId64 " where diff_id = %" PRId64;
    585     } else {
     804        break;
     805    default:
    586806        psError(PS_ERR_UNKNOWN, true, "unexpected value for stage: %s found", stage);
    587807        psFree(output);
    588808        return false;
    589809    }
    590     if (!p_psDBRunQueryF(config->dbh, query, magic_ds_id, stage_id)) {
     810    if (!p_psDBRunQueryF(config->dbh, query, magic_id, stage_id)) {
    591811        psError(PS_ERR_UNKNOWN, false, "database error");
    592812        return false;
     
    616836    PXOPT_LOOKUP_STR(recovery_path_base, config->args, "-recovery_path_base", false, false);
    617837    PXOPT_LOOKUP_BOOL(setmagicked, config->args, "-setmagicked", false);
     838    PXOPT_LOOKUP_F32(streak_frac, config->args, "-streak_frac", false, false);
     839    PXOPT_LOOKUP_F32(nondiff_frac, config->args, "-nondiff_frac", false, false);
     840    PXOPT_LOOKUP_F32(run_time, config->args, "-run_time", false, false);
    618841
    619842    if (setmagicked && (fault != 0)) {
     
    638861    }
    639862
    640     if (!magicDSFileInsert(config->dbh, magic_ds_id, component, backup_path_base, recovery_path_base, fault, "full")) {
     863    if (!magicDSFileInsert(config->dbh,
     864            magic_ds_id,
     865            component,
     866            backup_path_base,
     867            recovery_path_base,
     868            streak_frac,
     869            nondiff_frac,
     870            run_time,
     871            fault,
     872            "full"  // data_state
     873        )) {
    641874            // rollback
    642875        if (!psDBRollback(config->dbh)) {
     
    647880    }
    648881
    649     if (!magicDSRunComplete(config, setmagicked)) {
    650             // rollback
    651         if (!psDBRollback(config->dbh)) {
    652             psError(PS_ERR_UNKNOWN, false, "database error");
    653         }
    654         psError(PS_ERR_UNKNOWN, false, "database error");
    655         return false;
    656     }
    657 
    658882    if (!psDBCommit(config->dbh)) {
    659883        psError(PS_ERR_UNKNOWN, false, "database error");
     
    664888}
    665889
    666 static bool magicDSGetIDs(pxConfig *config, psString stage, psS64 magic_id, psS64 *stage_id, psS64 *cam_id)
     890
     891static bool advancerunMode(pxConfig *config)
    667892{
    668893    PS_ASSERT_PTR_NON_NULL(config, false);
    669     PS_ASSERT_PTR_NON_NULL(stage, false);
    670     PS_ASSERT_PTR_NON_NULL(stage_id, false);
    671     PS_ASSERT_PTR_NON_NULL(cam_id, false);
    672 
    673     if (!strcmp(stage, "diff")) {
    674         // don't need these ids for diff stage because diff_id is in the magicRun
    675         *stage_id = 0;
    676         *cam_id = 0;
    677         return true;
    678     }
    679 
    680     int stageNum;
    681     if (!strcmp(stage, "raw")) {
    682         stageNum = 0;
    683     } else if (!strcmp(stage, "chip")) {
    684         stageNum = 1;
    685     } else if (!strcmp(stage, "camera")) {
    686         stageNum = 2;
    687     } else if (!strcmp(stage, "warp")) {
    688         stageNum = 3;
    689     } else {
    690         psError(PXTOOLS_ERR_DATA, true, "%s is not a valid value for stage", stage);
    691         return false;
    692     }
    693 
    694 
    695     psString query = pxDataGet("magicdstool_getrunids.sql");
    696     if (!query) {
    697         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    698         return false;
    699     }
    700 
    701     if (!p_psDBRunQueryF(config->dbh, query, magic_id)) {
    702         psError(PS_ERR_UNKNOWN, false, "database error");
    703         psFree(query);
    704         return false;
    705     }
    706     psFree(query);
    707 
    708     psArray *output = p_psDBFetchResult(config->dbh);
    709     if (!output) {
    710         psError(PS_ERR_UNKNOWN, false, "database error");
    711         return false;
    712     }
    713     if (!psArrayLength(output)) {
    714         psTrace("magicdstool", PS_LOG_INFO, "no rows found");
    715         psFree(output);
    716         return true;
    717     }
    718     if (psArrayLength(output) > 1) {
    719         psError(PS_ERR_UNKNOWN, true, "unexpected number of rows found %ld for magic_id %" PRId64,
    720             psArrayLength(output), magic_id);
    721         return false;
    722     }
    723     psMetadata *row = output->data[0];
    724 
    725     *cam_id = psMetadataLookupS64(NULL, row, "cam_id");
    726     if (stageNum == 0) {
    727         *stage_id = psMetadataLookupS64(NULL, row, "exp_id");
    728     } else if (stageNum == 1) {
    729         *stage_id = psMetadataLookupS64(NULL, row, "chip_id");
    730     } else if (stageNum == 2) {
    731         *stage_id = *cam_id;
    732     } else if (stageNum == 3) {
    733         *stage_id = psMetadataLookupS64(NULL, row, "warp_id");
    734     }
    735 
    736     return true;
    737 }
    738 
    739 static bool magicDSRunComplete(pxConfig *config, bool setmagicked)
    740 {
    741     PS_ASSERT_PTR_NON_NULL(config, false);
     894
     895    psMetadata *where = psMetadataAlloc();
     896    PXOPT_COPY_S64(config->args, where, "-magic_ds_id", "magicDSRun.magic_ds_id", "==");
     897    pxAddLabelSearchArgs (config, where, "-label", "magicDSRun.label", "==");
     898
     899    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    742900
    743901    // look for completed magicDSRuns
    744902    psString query = pxDataGet("magicdstool_completed_runs.sql");
    745903    if (!query) {
    746         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    747         return false;
     904        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
     905        return false;
     906    }
     907
     908    if (psListLength(where->list)) {
     909        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     910        psStringAppend(&query, " WHERE %s", whereClause);
     911        psFree(whereClause);
    748912    }
    749913
     
    765929        return true;
    766930    }
     931    if (!psDBTransaction(config->dbh)) {
     932        psError(PS_ERR_UNKNOWN, false, "database error");
     933        return false;
     934    }
    767935    for (long i = 0; i < psArrayLength(output); i++) {
    768936        psMetadata *row = output->data[i];
     
    770938        psS64 magic_ds_id = psMetadataLookupS64(NULL, row, "magic_ds_id");
    771939
    772         // if requested, set stageRun.magicked
     940        // if re_place, set stageRun.magicked
     941        bool setmagicked = psMetadataLookupBool(NULL, row, "re_place");
    773942        if (setmagicked && !setRunMagicked(config, magic_ds_id)) {
    774943            psError(PS_ERR_UNKNOWN, false, "failed to change stageRun.magicked for magic_ds_id: %" PRId64,
    775944                magic_ds_id);
     945            if (!psDBRollback(config->dbh)) {
     946                psError(PS_ERR_UNKNOWN, false, "database error");
     947            }
    776948            return false;
    777949        }
    778950
    779951        // set magicDSRun.state to 'full'
    780         if (!setmagicDSRunState(config, magic_ds_id, "full")) {
     952        if (!setmagicDSRunState(config, magic_ds_id, NULL, NULL, "full")) {
    781953            psError(PS_ERR_UNKNOWN, false, "failed to change magicDSRun.state for magic_ds_id: %" PRId64,
    782954                magic_ds_id);
    783955            psFree(output);
     956            if (!psDBRollback(config->dbh)) {
     957                psError(PS_ERR_UNKNOWN, false, "database error");
     958            }
    784959            return false;
    785960        }
    786961    }
    787 
     962    if (!psDBCommit(config->dbh)) {
     963        psError(PS_ERR_UNKNOWN, false, "database error");
     964        return false;
     965    }
    788966
    789967    return true;
     
    794972{
    795973    PS_ASSERT_PTR_NON_NULL(config, false);
     974
     975    PXOPT_LOOKUP_BOOL(i_am_sure, config->args, "-i_am_sure", true);
     976    if (!i_am_sure) {
     977        psError(PS_ERR_UNKNOWN, true, "Reverting destreaked files must be done carefully. -i_am_sure is required.");
     978        return false;
     979    }
    796980
    797981    psMetadata *where = psMetadataAlloc();
     
    801985    pxAddLabelSearchArgs (config, where, "-label", "label", "==");
    802986
    803     psString query = psStringCopy("DELETE FROM magicDSFile USING magicDSFile, magicDSRun  WHERE (magicDSRun.magic_ds_id = magicDSFile.magic_ds_id) AND magicDSFile.fault != 0");
     987    psString query = pxDataGet("magicdstool_revertdestreakedfile.sql");
    804988
    805989    if (psListLength(where->list)) {
     
    807991        psStringAppend(&query, " AND %s", whereClause);
    808992        psFree(whereClause);
     993    } else {
     994        psError(PS_ERR_UNKNOWN, true, "search arguments are required");
     995        return false;
    809996    }
    810997    psFree(where);
     
    812999    if (!p_psDBRunQuery(config->dbh, query)) {
    8131000        psError(PS_ERR_UNKNOWN, false, "failed to revert");
    814         return false;
    815     }
     1001        psFree(query);
     1002        return false;
     1003    }
     1004    psFree(query);
    8161005    return true;
    8171006}
    818 
    819 static bool getskycellsMode(pxConfig *config)
    820 {
    821     // required
    822     PXOPT_LOOKUP_S64(magic_ds_id, config->args, "-magic_ds_id", true, false);
     1007static bool clearstatefaultsMode(pxConfig *config)
     1008{
     1009    PS_ASSERT_PTR_NON_NULL(config, false);
    8231010
    8241011    psMetadata *where = psMetadataAlloc();
    825     PXOPT_COPY_STR(config->args, where, "-class_id",    "warpSkyCellMap.class_id", "==");
    826     PXOPT_COPY_STR(config->args, where, "-skycell_id",  "warpSkyCellMap.skycell_id", "==");
    827 
    828     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    829 
    830     psString query = pxDataGet("magicdstool_getskycells.sql");
    831     if (!query) {
    832         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    833         return false;
    834     }
     1012    // new state
     1013    PXOPT_LOOKUP_STR(new_state, config->args, "-set_state", false, false);
     1014    // old state (required)
     1015    PXOPT_LOOKUP_STR(state, config->args, "-state", true, false);
     1016
     1017    PXOPT_COPY_STR(config->args, where, "-state", "state", "==");
     1018    PXOPT_COPY_S64(config->args, where, "-magic_ds_id", "magicDSRun.magic_ds_id", "==");
     1019    PXOPT_COPY_S16(config->args, where, "-fault", "fault", "==");
     1020    pxAddLabelSearchArgs (config, where, "-label", "label", "==");
     1021
     1022    psString query = pxDataGet("magicdstool_clearstatefaults.sql");
    8351023
    8361024    if (psListLength(where->list)) {
    8371025        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    838         psStringAppend(&query, " AND %s", whereClause);
     1026        psStringAppend(&query, " WHERE %s", whereClause);
    8391027        psFree(whereClause);
     1028    } else {
     1029        psError(PS_ERR_UNKNOWN, true, "search arguments are required");
     1030        return false;
    8401031    }
    8411032    psFree(where);
    8421033
    843     if (!p_psDBRunQueryF(config->dbh, query, magic_ds_id)) {
    844         psError(PS_ERR_UNKNOWN, false, "database error");
     1034    if (!new_state) {
     1035        if (!strcmp(state, "failed_revert")) {
     1036            new_state = "new";
     1037        } else if (!strcmp(state, "failed_cleanup")) {
     1038            new_state = "goto_cleaned";
     1039        } else {
     1040            psError(PS_ERR_UNKNOWN, true, "unexpected value for state: %s", state);
     1041            return false;
     1042        }
     1043    }
     1044    if (!p_psDBRunQueryF(config->dbh, query, new_state)) {
     1045        psError(PS_ERR_UNKNOWN, false, "failed to revert");
    8451046        psFree(query);
    8461047        return false;
    8471048    }
    8481049    psFree(query);
    849 
     1050    return true;
     1051}
     1052
     1053static bool completedrevertMode(pxConfig *config)
     1054{
     1055    PS_ASSERT_PTR_NON_NULL(config, false);
     1056
     1057    psMetadata *where = psMetadataAlloc();
     1058    PXOPT_COPY_S64(config->args, where, "-magic_ds_id", "magicDSRun.magic_ds_id", "==");
     1059    pxAddLabelSearchArgs (config, where, "-label", "label", "==");
     1060
     1061    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     1062
     1063    psString query = pxDataGet("magicdstool_completedrevert.sql");
     1064    // treat limit == 0 as "no limit"
     1065    if (limit) {
     1066        psString limitString = psDBGenerateLimitSQL(limit);
     1067        psStringAppend(&query, " %s", limitString);
     1068        psFree(limitString);
     1069    }
     1070
     1071    psString whereString = NULL;
     1072    if (psListLength(where->list)) {
     1073        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     1074        psStringAppend(&whereString, "\nAND %s", whereClause);
     1075        psFree(whereClause);
     1076    }
     1077    psFree(where);
     1078
     1079    if (!p_psDBRunQueryF(config->dbh, query, whereString ? whereString : "")) {
     1080        psFree(whereString);
     1081        psError(PS_ERR_UNKNOWN, false, "failed to revert");
     1082        return false;
     1083    }
     1084    psFree(whereString);
     1085    psFree(query);
    8501086    psArray *output = p_psDBFetchResult(config->dbh);
    8511087    if (!output) {
     
    8671103        return true;
    8681104    }
    869 
    870     if (psArrayLength(output)) {
    871         // negative simple so the default is true
    872         if (!ippdbPrintMetadatas(stdout, output, "magicDiffSkyfile", !simple)) {
    873             psError(PS_ERR_UNKNOWN, false, "failed to print array");
     1105    for (int i=0; i<psArrayLength(output); i++) {
     1106        psMetadata *row = output->data[i];
     1107        psS64 magic_ds_id = psMetadataLookupS64(NULL, row, "magic_ds_id");
     1108        psString old_state = psMetadataLookupStr(NULL, row, "state");
     1109        psString new_state;
     1110        if (!strcmp(old_state, "goto_censored")) {
     1111            new_state = "censored";
     1112        } else if (!strcmp(old_state, "goto_restored")) {
     1113            new_state = "restored";
     1114        } else {
     1115            psError(PXTOOLS_ERR_PROG, true, "unexpected state found: %s", old_state);
    8741116            psFree(output);
    8751117            return false;
    8761118        }
    877     }
    878 
     1119        char *query2 = "UPDATE magicDSRun SET state = '%s' WHERE magic_ds_id = %" PRId64;
     1120        if (!p_psDBRunQueryF(config->dbh, query2, new_state, magic_ds_id)) {
     1121            psError(PS_ERR_UNKNOWN, false, "failed to set run magicDSRun.state to %s", new_state);
     1122            return false;
     1123        }
     1124    }
    8791125    psFree(output);
    8801126
     
    8821128}
    8831129
    884 static bool setmagicDSRunState(pxConfig *config, psS64 magic_ds_id, const char *state)
    885 {
    886     PS_ASSERT_PTR_NON_NULL(state, false);
    887 
    888     // check that state is a valid string value
    889     if (!(
    890             (strncmp(state, "new", 4) == 0)
    891             || (strncmp(state, "full", 5) == 0)
    892         )
    893     ) {
    894         psError(PS_ERR_UNKNOWN, false,
    895                 "invalid magicDSRun state: %s", state);
    896         return false;
    897     }
    898 
    899     char *query = "UPDATE magicDSRun SET state = '%s' WHERE magic_ds_id = %" PRId64;
    900     if (!p_psDBRunQueryF(config->dbh, query, state, magic_ds_id)) {
    901         psError(PS_ERR_UNKNOWN, false,
    902                 "failed to change state for magic_id %" PRId64, magic_ds_id);
    903         return false;
    904     }
    905 
    906     return true;
    907 }
    908 
    909 static bool toremoveMode(pxConfig *config)
    910 {
    911     PS_ASSERT_PTR_NON_NULL(config, false);
     1130static bool getskycellsMode(pxConfig *config)
     1131{
     1132    // required
     1133    PXOPT_LOOKUP_S64(magic_ds_id, config->args, "-magic_ds_id", true, false);
    9121134
    9131135    psMetadata *where = psMetadataAlloc();
    914     PXOPT_COPY_S64(config->args, where, "-magic_ds_id", "magic_ds_id", "==");
    915     PXOPT_COPY_S64(config->args, where, "-magic_id", "magic_id", "==");
    916     pxAddLabelSearchArgs (config, where, "-label", "label", "==");
    917 
    918     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     1136    PXOPT_COPY_S64(config->args, where, "-magic_ds_id", "magicDSRun.magic_ds_id", "==");
     1137    PXOPT_COPY_STR(config->args, where, "-class_id",    "warpSkyCellMap.class_id", "==");
     1138    PXOPT_COPY_STR(config->args, where, "-skycell_id",  "warpSkyCellMap.skycell_id", "==");
     1139
    9191140    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    9201141
    921     // look for "inputs" that need to processed
    922     psString query = pxDataGet("magicdstool_toremove.sql");
     1142    psString query = pxDataGet("magicdstool_getskycells.sql");
    9231143    if (!query) {
    924         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    925         return false;
    926     }
    927 
     1144        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
     1145        return false;
     1146    }
     1147
     1148    psString whereClause = NULL;
    9281149    if (psListLength(where->list)) {
    929         psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    930         psStringAppend(&query, " WHERE %s", whereClause);
    931         psFree(whereClause);
     1150        whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     1151        psStringPrepend(&whereClause, "\n AND ");
    9321152    }
    9331153    psFree(where);
    9341154
    935     // treat limit == 0 as "no limit"
    936     if (limit) {
    937         psString limitString = psDBGenerateLimitSQL(limit);
    938         psStringAppend(&query, " %s", limitString);
    939         psFree(limitString);
    940     }
    941 
    942     if (!p_psDBRunQuery(config->dbh, query)) {
     1155    if (!p_psDBRunQueryF(config->dbh, query, whereClause, whereClause)) {
    9431156        psError(PS_ERR_UNKNOWN, false, "database error");
    9441157        psFree(query);
     
    9691182    if (psArrayLength(output)) {
    9701183        // negative simple so the default is true
    971         if (!ippdbPrintMetadatas(stdout, output, "toremove", !simple)) {
     1184        if (!ippdbPrintMetadatas(stdout, output, "magicDiffSkyfile", !simple)) {
    9721185            psError(PS_ERR_UNKNOWN, false, "failed to print array");
    9731186            psFree(output);
     
    9801193    return true;
    9811194}
    982 static bool torestoreMode(pxConfig *config)
     1195
     1196static bool validDSRunState(const char *state)
     1197{
     1198    if (!((strcmp(state, "new") == 0) ||
     1199          (strcmp(state, "full") == 0) ||
     1200          (strcmp(state, "drop") == 0) ||
     1201          (strcmp(state, "failed_revert") == 0) ||
     1202          (strcmp(state, "failed_cleanup") == 0) ||
     1203          (strcmp(state, "restored") == 0) ||
     1204          (strcmp(state, "censored") == 0) ||
     1205          (strcmp(state, "cleaned") == 0) ||
     1206          (strcmp(state, "goto_restored") == 0) ||
     1207          (strcmp(state, "goto_censored") == 0) ||
     1208          (strcmp(state, "goto_cleaned") == 0))
     1209        ) {
     1210        return false;
     1211    } else {
     1212        return true;
     1213    }
     1214}
     1215
     1216static bool setmagicDSRunState(pxConfig *config, psS64 magic_ds_id, psString extraSetStr, psMetadata *where, const char *state)
     1217{
     1218    PS_ASSERT_PTR_NON_NULL(state, false);
     1219
     1220    if (!validDSRunState(state)) {
     1221        psError(PS_ERR_UNKNOWN, false,
     1222                "invalid magicDSRun state: %s", state);
     1223        return false;
     1224    }
     1225
     1226    psString query = NULL;
     1227    psStringAppend(&query, "UPDATE magicDSRun SET state = '%s' %s\n", state, extraSetStr ? extraSetStr : "");
     1228    if (magic_ds_id) {
     1229        psStringAppend(&query, " WHERE magic_ds_id = %" PRId64, magic_ds_id);
     1230    } else if (where && psListLength(where->list)) {
     1231        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     1232        psStringAppend(&query, " WHERE %s", whereClause);
     1233        psFree(whereClause);
     1234    } else {
     1235        psError(PS_ERR_UNKNOWN, true, "search arguments are required");
     1236        return false;
     1237    }
     1238
     1239    if (!strcmp(state, "goto_cleaned")) {
     1240        // Don't set state back to goto_cleaned if it is already cleaned
     1241        psStringAppend(&query, " AND (magicDSRun.state != 'cleaned')");
     1242
     1243        // don't clean up magicDSRun's where stage is camera
     1244        psStringAppend(&query, " AND (magicDSRun.stage != 'camera')");
     1245    }
     1246
     1247    if (!p_psDBRunQuery(config->dbh, query)) {
     1248        psError(PS_ERR_UNKNOWN, false,
     1249                "failed to change state for magic_id %" PRId64, magic_ds_id);
     1250        return false;
     1251    }
     1252
     1253    return true;
     1254}
     1255
     1256static bool toremoveMode(pxConfig *config)
    9831257{
    9841258    PS_ASSERT_PTR_NON_NULL(config, false);
     
    9931267
    9941268    // look for "inputs" that need to processed
    995     psString query = pxDataGet("magicdstool_torestore.sql");
     1269    psString query = pxDataGet("magicdstool_toremove.sql");
    9961270    if (!query) {
    997         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     1271        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
    9981272        return false;
    9991273    }
     
    10421316    if (psArrayLength(output)) {
    10431317        // negative simple so the default is true
    1044         if (!ippdbPrintMetadatas(stdout, output, "torestore", !simple)) {
     1318        if (!ippdbPrintMetadatas(stdout, output, "toremove", !simple)) {
    10451319            psError(PS_ERR_UNKNOWN, false, "failed to print array");
    10461320            psFree(output);
     
    10541328}
    10551329
    1056 
    10571330static bool torevertMode(pxConfig *config)
    10581331{
     
    10741347    psString query = pxDataGet(sql_file);
    10751348    if (!query) {
    1076         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement from %s", sql_file);
     1349        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement from %s", sql_file);
    10771350        psFree(sql_file);
    10781351        return false;
     
    11361409
    11371410
     1411static bool tocleanupMode(pxConfig *config)
     1412{
     1413    PS_ASSERT_PTR_NON_NULL(config, false);
     1414
     1415    psMetadata *where = psMetadataAlloc();
     1416
     1417    PXOPT_COPY_STR(config->args, where, "-stage", "stage", "==");
     1418    PXOPT_COPY_S64(config->args, where, "-magic_ds_id", "magic_ds_id", "==");
     1419    PXOPT_COPY_S64(config->args, where, "-magic_id", "magic_id", "==");
     1420    pxAddLabelSearchArgs (config, where, "-label", "magicDSRun.label", "==");
     1421
     1422    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     1423    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     1424
     1425    psString query = pxDataGet("magicdstool_tocleanup.sql");
     1426    if (!query) {
     1427        psError(PXTOOLS_ERR_SYS, false, "failed to retreive SQL statement");
     1428        return false;
     1429    }
     1430
     1431    if (psListLength(where->list)) {
     1432        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     1433        psStringAppend(&query, " AND %s", whereClause);
     1434        psFree(whereClause);
     1435    }
     1436    psFree(where);
     1437
     1438    // treat limit == 0 as "no limit"
     1439    if (limit) {
     1440        psString limitString = psDBGenerateLimitSQL(limit);
     1441        psStringAppend(&query, " %s", limitString);
     1442        psFree(limitString);
     1443    }
     1444
     1445    if (!p_psDBRunQuery(config->dbh, query)) {
     1446        psError(PS_ERR_UNKNOWN, false, "database error");
     1447        psFree(query);
     1448        return false;
     1449    }
     1450    psFree(query);
     1451
     1452    psArray *output = p_psDBFetchResult(config->dbh);
     1453    if (!output) {
     1454        psErrorCode err = psErrorCodeLast();
     1455        switch (err) {
     1456            case PS_ERR_DB_CLIENT:
     1457                psError(PXTOOLS_ERR_SYS, false, "database error");
     1458            case PS_ERR_DB_SERVER:
     1459                psError(PXTOOLS_ERR_PROG, false, "database error");
     1460            default:
     1461                psError(PXTOOLS_ERR_PROG, false, "unknown error");
     1462        }
     1463
     1464        return false;
     1465    }
     1466    if (!psArrayLength(output)) {
     1467        psTrace("magicdstool", PS_LOG_INFO, "no rows found");
     1468        psFree(output);
     1469        return true;
     1470    }
     1471
     1472    if (psArrayLength(output)) {
     1473        // negative simple so the default is true
     1474        if (!ippdbPrintMetadatas(stdout, output, "tocleanup", !simple)) {
     1475            psError(PS_ERR_UNKNOWN, false, "failed to print array");
     1476            psFree(output);
     1477            return false;
     1478        }
     1479    }
     1480
     1481    psFree(output);
     1482
     1483    return true;
     1484}
Note: See TracChangeset for help on using the changeset viewer.