IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 5, 2012, 5:19:48 PM (14 years ago)
Author:
mhuber
Message:

merging latest r33407 trunk changes to meh_branches/ppstack_test

Location:
branches/meh_branches/ppstack_test
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/meh_branches/ppstack_test

  • branches/meh_branches/ppstack_test/ippToPsps/jython/ipptopspsdb.py

    r32122 r33415  
    1717    Constructor
    1818    '''
    19     def __init__(self, logger, doc):
    20         super(IppToPspsDb, self).__init__(logger, doc, "ipptopspsdatabase")
    21 
    22     '''
    23     Creates a new batch
    24     '''
    25     def createNewBatch(self, batchType, stageID, survey, dvoDb, datastoreProduct):
    26 
    27         sql = "INSERT INTO batch ( \
    28                batch_type, \
    29                stage_id, \
    30                survey, \
    31                dvo_db, \
    32                datastore_product \
    33                ) VALUES ( \
    34                '" + batchType + "', \
    35                " + str(stageID) + ", \
    36                '" + survey + "', \
    37                '" + dvoDb + "', \
    38                '" + datastoreProduct + "' \
    39                )"
    40 
    41         self.execute(sql)
    42 
    43         sql = "SELECT MAX(batch_id) FROM batch"
    44 
    45         batchID = -1;
    46 
    47         try:
    48             rs = self.executeQuery(sql)
    49             rs.first()
    50             batchID = rs.getInt(1)
    51         except:
    52             self.logger.exception("Unable to get batch ID")
    53 
    54         self.logger.debug("Created new batch in ippToPsps database with batchID = %d" % batchID)
    55 
    56         return batchID;
    57 
    58     '''
    59     Returns a list of processed batch IDs that are merged but not yet deleted
    60     '''
    61     def getMergedButNotDeletedBatchIDs(self, epoch, dvoGpc1Label):
     19    def __init__(self, logger, config):
     20        super(IppToPspsDb, self).__init__(logger, config, "ipptopspsdatabase")
     21
     22        self.MAX_FAILS = 5
     23
     24    '''
     25    Returns a list of merged batch IDs that are merged but not yet deleted
     26    '''
     27    def getMergedButNotDeletedBatchIDs(self, batchType, epoch, dvoGpc1Label, column):
    6228
    6329        sql = "SELECT DISTINCT batch_id \
    6430               FROM batch \
    6531               WHERE timestamp > '" + epoch + "' \
    66                AND dvo_db = '" + dvoGpc1Label + "' \
    67                AND merged \
    68                AND !deleted"
     32               AND batch_type = '" + batchType + "' \
     33               AND dvo_db = '" + dvoGpc1Label + "' \
     34               AND merged = 1 \
     35               AND " + column + " = 0"
     36
     37        ids = []
     38        try:
     39            rs = self.executeQuery(sql)
     40            while (rs.next()): ids.append(rs.getInt(1))
     41            rs.close()
     42        except:
     43            self.logger.exception("Can't query for merged batch ids in ipptopsps Db")
     44
     45        self.logger.debug("Found %d merged but un-deleted items" % len(ids))
     46
     47        return ids
     48
     49    '''
     50    Returns a list of batch IDs marked as 'purged' but not yet deleted
     51    '''
     52    def getPurgedButNotDeletedBatchIDs(self, batchType, epoch, dvoGpc1Label, column):
     53
     54        sql = "SELECT DISTINCT batch_id \
     55               FROM batch \
     56               WHERE timestamp > '" + epoch + "' \
     57               AND batch_type = '" + batchType + "' \
     58               AND dvo_db = '" + dvoGpc1Label + "' \
     59               AND purged = 1 \
     60               AND " + column + " = 0"
     61
     62        ids = []
     63        try:
     64            rs = self.executeQuery(sql)
     65            while (rs.next()): ids.append(rs.getInt(1))
     66            rs.close()
     67        except:
     68            self.logger.exception("Can't query for merged batch ids in ipptopsps Db")
     69
     70
     71        self.logger.debug("Found %d merged but un-deleted items" % len(ids))
     72
     73        return ids
     74
     75    '''
     76    Returns a list of processed batch IDs that have been loaded to the ODM but not yet deleted
     77    '''
     78    def getLoadedToODMButNotDeletedBatchIDs(self, batchType, epoch, dvoGpc1Label, column):
     79
     80        sql = "SELECT DISTINCT batch_id \
     81               FROM batch \
     82               WHERE timestamp > '" + epoch + "' \
     83               AND batch_type = '" + batchType + "' \
     84               AND dvo_db = '" + dvoGpc1Label + "' \
     85               AND (loaded_to_ODM = -1 OR merge_worthy = 1) \
     86               AND " + column + " = 0"
     87
     88        ids = []
     89        try:
     90            rs = self.executeQuery(sql)
     91            while (rs.next()): ids.append(rs.getInt(1))
     92            rs.close()
     93        except:
     94            self.logger.exception("Can't query for merged batch ids in ipptopsps Db")
     95
     96        self.logger.debug("Found %d merged but un-deleted items" % len(ids))
     97
     98        return ids
     99
     100    '''
     101    Returns a list of merged batch IDs that are not deleted from local disk
     102    '''
     103    def getMergedButNotDeletedFromLocalDisk(self, batchType, epoch, dvoGpc1Label):
     104        return self.getMergedButNotDeletedBatchIDs(batchType, epoch, dvoGpc1Label, "deleted_local")
     105
     106    '''
     107    Returns a list of processed batch IDs that are loaded to the ODM, but not deleted from local disk
     108    '''
     109    def getLoadedToODMButNotDeletedFromLocalDisk(self, batchType, epoch, dvoGpc1Label):
     110        return self.getLoadedToODMButNotDeletedBatchIDs(batchType, epoch, dvoGpc1Label, "deleted_local")
     111
     112    '''
     113    Returns a list of processed batch IDs that are loaded to the ODM, but not deleted from datastore
     114    '''
     115    def getLoadedToODMButNotDeletedFromDatastore(self, batchType, epoch, dvoGpc1Label):
     116        return self.getLoadedToODMButNotDeletedBatchIDs(batchType, epoch, dvoGpc1Label, "deleted_datastore")
     117
     118    '''
     119    Returns a list of processed batch IDs that are loaded to the ODM, but not deleted from DXLayer
     120    '''
     121    def getLoadedToODMButNotDeletedFromDXLayer(self, batchType, epoch, dvoGpc1Label):
     122        return self.getLoadedToODMButNotDeletedBatchIDs(batchType, epoch, dvoGpc1Label, "deleted_dxlayer")
     123
     124    '''
     125    Returns a list of purged  batch IDs that not deleted from local disk
     126    '''
     127    def getPurgedButNotDeletedFromLocalDisk(self, batchType, epoch, dvoGpc1Label):
     128        return self.getPurgedButNotDeletedBatchIDs(batchType, epoch, dvoGpc1Label, "deleted_local")
     129
     130    '''
     131    Returns a list of purged batch IDs that are not deleted from datastore
     132    '''
     133    def getPurgedButNotDeletedFromDatastore(self, batchType, epoch, dvoGpc1Label):
     134        return self.getPurgedButNotDeletedBatchIDs(batchType, epoch, dvoGpc1Label, "deleted_datastore")
     135
     136
     137    '''
     138    Returns a list of processed batch IDs that are not loaded to the datastore
     139    NB we have a date constraint here because, before this time, it is possible that
     140    a test batch would be labelled as processed but not loaded to datastore, and we would NOT
     141    want to load a test batch to PSPS
     142
     143    We also check that these batches are more than 4 HOURs old, so that we don't attempt to
     144    publish something simulataneously with the client that it producing it
     145    '''
     146    def getProcessedButFailedDatastoreBatchIDs(self, epoch, dvoGpc1Label, batchType):
     147
     148        sql = "SELECT DISTINCT batch_id \
     149               FROM batch \
     150               WHERE timestamp > '" + epoch + "' \
     151               AND batch_type = '" + batchType + "' \
     152               AND dvo_db = '" + dvoGpc1Label + "' \
     153               AND processed = 1\
     154               AND loaded_to_datastore != 1 \
     155               AND timestamp > '2011-10-27' \
     156               AND timestamp < now() -  INTERVAL 4 HOUR"
    69157
    70158        ids = []
     
    74162                ids.append(rs.getInt(1))
    75163        except:
    76             self.logger.exception("Can't query for merged batch ids in ipptopsps Db")
     164            self.logger.exception("Can't query for processed batch ids not loaded to datastore ipptopsps Db")
    77165
    78166        rs.close()
    79167
    80         self.logger.debug("Found %d merged but un-deleted items" % len(ids))
    81 
    82         return ids
    83 
    84     '''
    85     Returns a list of processed batch IDs that are not yet merged for this epoch and dvo label
    86     '''
    87     def getProcessedButUnmergedBatchIDs(self, epoch, dvoGpc1Label):
    88 
    89         sql = "SELECT DISTINCT batch_id \
     168        self.logger.debug("Found %d processed but-not-on-datastore items" % len(ids))
     169
     170        return ids
     171
     172    '''
     173    Returns a list of processed batch IDs that are not yet loaded to the ODM
     174    NOTE we exclude batches already deleted from the datastore, as sometimes we delete stuff prior to loading to ODM if there is a known problem with the batch
     175    '''
     176    def getUnloadedBatchIDs(self, epoch, dvoGpc1Label, batchType):
     177
     178        sql = "SELECT batch_id \
    90179               FROM batch \
    91180               WHERE timestamp > '" + epoch + "' \
    92181               AND dvo_db = '" + dvoGpc1Label + "' \
    93                AND loaded_to_datastore \
    94                AND !merged"
     182               AND loaded_to_datastore = 1 \
     183               AND batch_type = '" + batchType + "' \
     184               AND loaded_to_ODM = 0 \
     185               AND deleted_datastore = 0"
    95186
    96187        ids = []
     
    100191                ids.append(rs.getInt(1))
    101192        except:
    102             self.logger.exception("Can't query for processed batch ids in ipptopsps Db")
     193            self.logger.exception("Can't query for unloaded batch ids in ipptopsps Db")
    103194
    104195        rs.close()
    105196
    106         self.logger.debug("Found %d processed and un-merged items" % len(ids))
    107 
    108         return ids
    109 
    110     '''
    111     Returns a list of IDs for this batch type, epoch and dvo label (i.e. either
    112             cam_ids or stack_ids) for which the spefified column is true (=1)
    113     '''
    114     def getStageIDs(self, batchType, epoch, dvoGpc1Label, column):
    115 
    116         sql = "SELECT DISTINCT stage_id \
     197        self.logger.debug("Found %d unloaded items" % len(ids))
     198
     199        return ids
     200
     201    '''
     202    Returns a list of processed batch IDs that are not yet merge_worthy and that have not failed to load
     203    NOTE we exclude batches already deleted from the datastore, as sometimes we delete stuff prior to loading to ODM if there is a known problem with the batch
     204    '''
     205    def getUnmergeWorthyBatchIDs(self, epoch, dvoGpc1Label, batchType):
     206
     207        sql = "SELECT batch_id \
     208               FROM batch \
     209               WHERE timestamp > '" + epoch + "' \
     210               AND dvo_db = '" + dvoGpc1Label + "' \
     211               AND loaded_to_datastore = 1 \
     212               AND batch_type = '" + batchType + "' \
     213               AND merge_worthy = 0 \
     214               AND loaded_to_ODM != -1 \
     215               AND deleted_datastore = 0"
     216
     217        ids = []
     218        try:
     219            rs = self.executeQuery(sql)
     220            while (rs.next()):
     221                ids.append(rs.getInt(1))
     222        except:
     223            self.logger.exception("Can't query for un-mergeworthy batch ids in ipptopsps Db")
     224
     225        rs.close()
     226
     227        self.logger.debug("Found %d unloaded items" % len(ids))
     228
     229        return ids
     230
     231    '''
     232    Returns a list of processed batch IDs that are merge_worthy, but not yet merged, for this epoch and dvo label
     233    '''
     234    def getUnmergedBatchIDs(self, epoch, dvoGpc1Label, batchType):
     235
     236        sql = "SELECT batch_id \
     237               FROM batch \
     238               WHERE timestamp > '" + epoch + "' \
     239               AND dvo_db = '" + dvoGpc1Label + "' \
     240               AND merge_worthy = 1 \
     241               AND batch_type = '" + batchType + "' \
     242               AND merged != 1"
     243
     244        ids = []
     245        try:
     246            rs = self.executeQuery(sql)
     247            while (rs.next()):
     248                ids.append(rs.getInt(1))
     249        except:
     250            self.logger.exception("Can't query for unmerged batch ids in ipptopsps Db")
     251
     252        rs.close()
     253
     254        self.logger.debug("Found %d un-merged items" % len(ids))
     255
     256        return ids
     257
     258    '''
     259    Returns a list of batch IDs for this epoch and dvo label for which the specified column is set to value
     260    '''
     261    def getBatchIDs(self, epoch, dvoGpc1Label, column, value):
     262
     263        sql = "SELECT DISTINCT batch_id \
     264               FROM batch \
     265               WHERE timestamp > '" + epoch + "' \
     266               AND dvo_db = '" + dvoGpc1Label + "' \
     267               AND " + column + " = " + str(value)
     268
     269        ids = []
     270        try:
     271            rs = self.executeQuery(sql)
     272            while (rs.next()):
     273                ids.append(rs.getInt(1))
     274        except:
     275            self.logger.exception("Can't query for batch ids with " + column + " = " + str(value) + " in ipptopsps Db")
     276
     277        rs.close()
     278
     279        self.logger.debug("Found %d batches with %s = %d" % (len(ids), column, value))
     280
     281        return ids
     282
     283    '''
     284    Returns the total detections published to the datastore for this epoch, dvo label and batch type
     285    '''
     286    def getTotalDetectionsPublished(self, batchType, epoch, dvoGpc1Label):
     287
     288        sql = "SELECT SUM(total_detections) \
    117289               FROM batch \
    118290               WHERE batch_type = '" + batchType + "' \
    119291               AND timestamp > '" + epoch + "' \
    120292               AND dvo_db = '" + dvoGpc1Label + "' \
    121                AND " + column + " = 1"
     293               AND processed = 1 \
     294               AND loaded_to_datastore = 1"
     295
     296        total = -1
     297        try:
     298            rs = self.executeQuery(sql)
     299            rs.first()
     300            total =  rs.getLong(1)
     301        except:
     302            self.logger.exception("Can't query for total detections published")
     303
     304        rs.close()
     305
     306        self.logger.debug("Found %d detections" % total)
     307
     308        return total
     309
     310    '''
     311    Returns a list of IDs for this batch type, epoch and dvo label (i.e. either
     312            cam_ids or stack_ids) for which the specified column is set to value
     313    '''
     314    def getStageIDs(self, batchType, epoch, dvoGpc1Label, column, value):
     315
     316        sql = "SELECT DISTINCT stage_id \
     317               FROM batch \
     318               WHERE batch_type = '" + batchType + "' \
     319               AND timestamp > '" + epoch + "' \
     320               AND dvo_db = '" + dvoGpc1Label + "' \
     321               AND " + column + " = " + str(value)
    122322
    123323        ids = []
     
    127327                ids.append(rs.getInt(1))
    128328        except:
    129             self.logger.exception("Can't query for ids with " + column + " = 1 in ipptopsps Db")
     329            self.logger.exception("Can't query for ids with " + column + " = " + str(value) + " in ipptopsps Db")
    130330
    131331        rs.close()
     
    136336
    137337    '''
     338    Series of getter methods that utilise getBatchIDs() method above
     339    '''
     340    def getloadedToDatastoreBatchIDs(self, epoch, dvoGpc1Label):
     341        return self.getBatchIDs(epoch, dvoGpc1Label, "loaded_to_datastore", 1)
     342    def getFailedLoadedToODMBatchIDs(self, epoch, dvoGpc1Label):
     343        return self.getBatchIDs(epoch, dvoGpc1Label, "loaded_to_ODM", -1)
     344
     345    '''
     346    TODO remove these
    138347    Series of getter methods that utilise getStageIDs() method above
    139348    '''
    140349    def getProcessedIDs(self, batchType, epoch, dvoGpc1Label):
    141         return self.getStageIDs(batchType, epoch, dvoGpc1Label, "processed")
    142     def getloadedToDatastoreIDs(self, batchType, epoch, dvoGpc1Label):
    143         return self.getStageIDs(batchType, epoch, dvoGpc1Label, "loaded_to_datastore")
     350        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "processed", 1)
     351    def getFailedProcessedIDs(self, batchType, epoch, dvoGpc1Label):
     352        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "processed", -1)
     353    def getLoadedToDatastoreIDs(self, batchType, epoch, dvoGpc1Label):
     354        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "loaded_to_datastore", 1)
     355    def getFailedLoadedToDatastoreIDs(self, batchType, epoch, dvoGpc1Label):
     356        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "loaded_to_datastore", -1)
    144357    def getLoadedToODMIDs(self, batchType, epoch, dvoGpc1Label):
    145         return self.getStageIDs(batchType, epoch, dvoGpc1Label, "loaded_to_ODM")
    146     def getMergeWothyIDs(self, batchType, epoch, dvoGpc1Label):
    147         return self.getStageIDs(batchType, epoch, dvoGpc1Label, "merge_worthy")
     358        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "loaded_to_ODM", 1)
     359    def getFailedLoadedToODMIDs(self, batchType, epoch, dvoGpc1Label):
     360        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "loaded_to_ODM", -1)
     361    def getMergeWorthyIDs(self, batchType, epoch, dvoGpc1Label):
     362        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "merge_worthy", 1)
     363    def getFailedMergeWorthyIDs(self, batchType, epoch, dvoGpc1Label):
     364        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "merge_worthy", -1)
    148365    def getMergedIDs(self, batchType, epoch, dvoGpc1Label):
    149         return self.getStageIDs(batchType, epoch, dvoGpc1Label, "merged")
     366        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "merged", 1)
     367    def getFailedMergedIDs(self, batchType, epoch, dvoGpc1Label):
     368        return self.getStageIDs(batchType, epoch, dvoGpc1Label, "merged", -1)
     369
     370    '''
     371    Returns a list of stages
     372    '''
     373    def getStages(self):
     374        return ['processed', 'loaded_to_datastore', 'loaded_to_ODM', 'merge_worthy', 'deleted_datastore', 'deleted_dxlayer', 'merged', 'deleted_local' ]
     375
     376    '''
     377    Returns a count of batches processed in the specified time period.
     378    '''
     379    def countBatchesInLastPeriod(self, batchType, epoch, dvoGpc1Label, interval):
     380
     381        sql = "SELECT COUNT(batch_id) \
     382               FROM batch \
     383               WHERE batch_type = '" + batchType + "' \
     384               AND processed = 1 \
     385               AND timestamp > '" + epoch + "' \
     386               AND dvo_db = '" + dvoGpc1Label + "' \
     387               AND timestamp BETWEEN now() - INTERVAL " + interval + " AND now()"
     388
     389        try:
     390            rs = self.executeQuery(sql)
     391            if rs.first(): return rs.getInt(1)
     392        except:
     393            self.logger.exception("Unable to count batches in interval")
     394            return 0
    150395
    151396    '''
     
    155400    def getTimeOfLastBatchPublished(self, batchType, epoch, dvoGpc1Label):
    156401
    157         minutes = None
    158 
    159         sql = "SELECT TIMESTAMPDIFF(MINUTE, timestamp, now()) \
     402        seconds = None
     403
     404        sql = "SELECT TIMESTAMPDIFF(SECOND, timestamp, now()) \
    160405               FROM batch \
    161406               WHERE batch_type = '" + batchType + "' \
    162                AND loaded_to_datastore \
     407               AND loaded_to_datastore = 1 \
    163408               AND timestamp > '" + epoch + "' \
    164409               AND dvo_db = '" + dvoGpc1Label + "' \
     
    167412        try:
    168413            rs = self.executeQuery(sql)
    169             if rs.first(): minutes = rs.getFloat(1)
     414            if rs.first(): seconds = rs.getFloat(1)
    170415        except:
    171416            self.logger.exception("Unable to get last batch published")
    172417
    173         if not minutes: return "Never"
    174 
     418        if not seconds: return "Never"
     419
     420        minutes = seconds/60.0
    175421        hours = minutes/60.0
    176         days = float(hours)/24.0
    177         weeks = float(days)/7.0
    178 
    179         if minutes < 60: return "%.1f minutes ago" % minutes
     422        days = hours/24.0
     423        weeks = days/7.0
     424
     425        if seconds < 60: return "%.1f secs ago" % seconds
     426        elif minutes < 60: return "%.1f mins ago" % minutes
    180427        elif hours < 48: return "%.1f hours ago" % hours
    181428        elif days < 7: return "%.1f days ago" % days
     
    183430
    184431    '''
    185     TODO
    186     '''
    187     def getBatchesPerDay(self, batchType, startTime, endTime=""):
    188 
    189         bph = self.getBatchesPerHour(batchType, startTime, endTime)
    190         return bph * 24
    191 
    192     '''
    193     TODO
    194     '''
    195     def getBatchesPerHour(self, batchType, startTime, endTime=""):
    196 
    197         bpm = self.getBatchesPerMinute(batchType, startTime, endTime)
    198         return bpm * 60
    199 
    200     '''
    201     TODO
    202     '''
    203     def getAverageTimePerBatch(self, batchType, startTime, endTime=""):
    204 
    205         sql = "SELECT (TIMESTAMPDIFF(MINUTE, min(timestamp), max(timestamp)) / COUNT(*)) \
    206                FROM batch \
    207                WHERE timestamp > '" + startTime + "' and batch_type = '" + batchType + "'"
    208 
    209         try:
    210             rs = self.executeQuery(sql)
    211             rs.first()
    212             time = rs.getDouble(1)
    213         except:
    214             self.logger.exception("Unable to get batches per minute")
    215 
    216         return time
    217 
    218     '''
    219     TODO
    220     '''
    221     def getBatchesPerMinute(self, batchType, startTime, endTime=""):
    222 
    223         sql = "SELECT (count(*) / TIMESTAMPDIFF(MINUTE, min(timestamp), max(timestamp)) ) \
    224                FROM batch \
    225                WHERE timestamp > '" + startTime + "' and batch_type = '" + batchType + "'"
    226 
    227         try:
    228             rs = self.executeQuery(sql)
    229             rs.first()
    230             bpm = rs.getDouble(1)
    231         except:
    232             self.logger.exception("Unable to get batches per minute")
    233 
    234         return bpm
    235 
    236     '''
    237432    Updates min/max object ID on this table and batch
    238433    '''
    239     def updateMinMaxObjID(self, batchID, minObjID, maxObjID):
     434    def updateDetectionStats(self, batchID, minObjID, maxObjID, totalDetections):
    240435
    241436        sql = "UPDATE batch SET \
    242437               min_obj_id = " + str(minObjID) + ", \
    243                max_obj_id = " + str(maxObjID) + " \
     438               max_obj_id = " + str(maxObjID) + ", \
     439               total_detections = " + str(totalDetections) + " \
    244440               WHERE batch_id = " + str(batchID)
    245441
     
    257453        self.execute(sql)
    258454
    259 
    260455    '''
    261456    Updates batch processed field
     
    265460
    266461    '''
    267     Updates batch deleted field
    268     '''
    269     def updateDeleted(self, batchID, deleted):
    270         self.updateColumn(batchID, "deleted", deleted)
     462    Updates batch deleted local field
     463    '''
     464    def updateDeletedLocal(self, batchID, value):
     465        self.updateColumn(batchID, "deleted_local", value)
     466
     467    '''
     468    Updates batch deleted datastore field
     469    '''
     470    def updateDeletedDatastore(self, batchID, value):
     471        self.updateColumn(batchID, "deleted_datastore", value)
     472
     473    '''
     474    Updates batch deleted dxlayer field
     475    '''
     476    def updateDeletedDxlayer(self, batchID, value):
     477        self.updateColumn(batchID, "deleted_dxlayer", value)
    271478
    272479    '''
     
    290497
    291498    '''
    292     Have we already processed and published this batch?
    293     '''
    294     def alreadyProcessed(self, stage_id):
     499    Is someone processing this item right now? Checks whether this was attempted within the last 2 HOUR
     500    '''
     501    def processingNow(self, batchType, stage_id, epoch, dvoGpc1Label):
    295502
    296503        sql = "SELECT COUNT(*) \
    297504               FROM batch \
    298505               WHERE stage_id = " + str(stage_id) + " \
    299                AND processed \
    300                AND loaded_to_datastore"
     506               AND batch_type = '" + batchType + "' \
     507               AND dvo_db = '" + dvoGpc1Label + "' \
     508               AND timestamp BETWEEN now() - INTERVAL 4 HOUR AND now()"
    301509
    302510        try:
     
    304512            rs.first()
    305513            if rs.getInt(1) > 0:
    306                 self.logger.error("Batch with stage_id = "+str(stage_id) + " has already been processed and published to datastore")
     514                self.logger.debugPair(str(stage_id) + " is already being processed", "skipping")
    307515                return True
    308516            else:
    309517                return False
    310518        except:
     519            self.logger.exception("Unable to check whether this batch is being processed")
     520
     521    '''
     522    Gets the batch type of this batch
     523    '''
     524    def getBatchType(self, batch_id):
     525
     526        sql = "SELECT batch_type \
     527               FROM batch \
     528               WHERE batch_id = " + str(batch_id)
     529
     530        batch_type = "NA"
     531        try:
     532            rs = self.executeQuery(sql)
     533            rs.first()
     534            batch_type = rs.getString(1)
     535        except:
    311536            self.logger.exception("Unable to check whether this batch has already been processed")
    312 
     537 
     538        return batch_type
     539
     540    '''
     541    Have we already processed this stage_id?
     542    '''
     543    def alreadyProcessed(self, batchType, stage_id, epoch, dvoGpc1Label):
     544
     545        sql = "SELECT COUNT(*) \
     546               FROM batch \
     547               WHERE stage_id = " + str(stage_id) + " \
     548               AND batch_type = '" + batchType + "' \
     549               AND timestamp > '" + epoch + "' \
     550               AND dvo_db = '" + dvoGpc1Label + "' \
     551               AND processed = 1"
     552
     553        try:
     554            rs = self.executeQuery(sql)
     555            rs.first()
     556            if rs.getInt(1) > 0:
     557                self.logger.debugPair(str(stage_id) + " has already been published", "skipping")
     558                return True
     559            else:
     560                return False
     561        except:
     562            self.logger.exception("Unable to check whether this batch has already been processed")
     563
     564    '''
     565    Has this stage_id consistently failed to process?
     566    '''
     567    def consistentlyFailed(self, batchType, stage_id, epoch, dvoGpc1Label):
     568
     569        sql = "SELECT COUNT(*) \
     570               FROM batch \
     571               WHERE stage_id = " + str(stage_id) + " \
     572               AND batch_type = '" + batchType + "' \
     573               AND timestamp > '" + epoch + "' \
     574               AND dvo_db = '" + dvoGpc1Label + "' \
     575               AND processed = -1"
     576
     577        try:
     578            rs = self.executeQuery(sql)
     579            rs.first()
     580            if rs.getInt(1) >= self.MAX_FAILS:
     581                self.logger.errorPair(str(stage_id) + " has failed %d times" % self.MAX_FAILS, "skipping")
     582                return True
     583            else:
     584                return False
     585        except:
     586            self.logger.exception("Unable to check whether this batch has consistently failed")
     587
     588    '''
     589    Returns a list of stage_ids that have failed the max number of times
     590    '''
     591    def getConsistentlyFailedIDs(self, batchType, epoch, dvoGpc1Label):
     592
     593        sql = "SELECT DISTINCT stage_id, COUNT(stage_id) AS numoccur \
     594               FROM batch \
     595               WHERE batch_type = '" + batchType + "' \
     596               AND timestamp > '" + epoch + "' \
     597               AND dvo_db = '" + dvoGpc1Label + "' \
     598               AND processed = -1 \
     599               GROUP BY stage_id HAVING numoccur >= " + str(self.MAX_FAILS)
     600
     601        ids = []
     602        try:
     603            rs = self.executeQuery(sql)
     604            while (rs.next()):
     605                ids.append(rs.getInt(1))
     606        except:
     607            self.logger.exception("Can't query for consistantly failed ids in ipptopsps Db")
     608
     609        rs.close()
     610
     611        self.logger.debug("Found %d consistantly failed stage_ids for batch type='%s'" % (len(ids), batchType))
     612
     613        return ids
     614
     615    '''
     616    Locks the batch table. This will wait if the lock is held by someone else
     617    '''
     618    def lockBatchTable(self):
     619        self.lockTable("batch")
     620
     621    '''
     622    Creates a new batch. This is done with a locked table in order that no two clients can start work on the same item
     623    '''
     624    def createNewBatch(self, batchType, stageID, config):
     625
     626        batchID = -1;
     627
     628        if config.force or \
     629            (not self.alreadyProcessed(batchType, stageID, config.epoch, config.dvoLabel) \
     630            and not self.processingNow(batchType, stageID, config.epoch, config.dvoLabel) \
     631            and not self.consistentlyFailed(batchType, stageID, config.epoch, config.dvoLabel)):
     632
     633            sql = "INSERT INTO batch ( \
     634                   batch_type, \
     635                   stage_id, \
     636                   survey, \
     637                   dvo_db, \
     638                   datastore_product \
     639                   ) VALUES ( \
     640                       '" + batchType + "', \
     641                       " + str(stageID) + ", \
     642                       '" + config.survey + "', \
     643                       '" + config.dvoLabel + "', \
     644                       '" + config.datastoreProduct + "' \
     645                       )"
     646
     647            self.execute(sql)
     648
     649            sql = "SELECT MAX(batch_id) FROM batch"
     650
     651            try:
     652                rs = self.executeQuery(sql)
     653                rs.first()
     654                batchID = rs.getInt(1)
     655                self.logger.debug("Created new batch in ippToPsps database with batchID = %d" % batchID)
     656            except:
     657                self.logger.exception("Unable to get batch ID")
     658                batchID = -1
     659
     660        return batchID;
    313661     
    314662
     
    346694        self.execute(sql)
    347695
     696    '''
     697    Resets a batch ready for re-loading to the datastore
     698    '''
     699    def resetBatch(self, batchID):
     700
     701        sql = "UPDATE batch SET \
     702               loaded_to_datastore = 0, \
     703               loaded_to_ODM = 0, \
     704               merge_worthy = 0, \
     705               merged = 0, \
     706               deleted_datastore = 0, \
     707               deleted_dxlayer = 0, \
     708               comment = 'This batch was reset, ready for re-load to datastore' \
     709               WHERE batch_id = " + str(batchID)
     710
     711        self.execute(sql)
     712
     713    '''
     714    Remove client
     715    '''
     716    def removeClient(self, host, pid):
     717        self.execute("DELETE FROM clients WHERE host = '" + host + "' AND pid = " + str(pid))
     718
     719    '''
     720    Insert client
     721    '''
     722    def insertClient(self, type, host, pid, config):
     723        self.execute("INSERT INTO clients (timestamp, type, host, pid, config) VALUES (now(), '" + type + "', '" + host + "', " + str(pid) + ", '" + config + "')")
     724
     725    '''
     726    Update clients, or inserts it for the first time
     727    '''
     728    def updateClient(self, type, host, pid, config):
     729
     730        try:
     731            self.insertClient(type, host, pid, config)
     732        except:
     733            self.execute("UPDATE clients SET timestamp = now() WHERE host = '" + host + "' AND pid = " + str(pid))
     734
     735    '''
     736    Is this client paused?
     737    '''
     738    def isPaused(self, host, pid):
     739        return self.getClientsColumnBoolean("paused", host, pid)
     740
     741    '''
     742    Is this client killed?
     743    '''
     744    def isKilled(self, host, pid):
     745        return self.getClientsColumnBoolean("killed", host, pid)
     746
     747    '''
     748    Returns boolean value for this column in clients table
     749    '''
     750    def getClientsColumnBoolean(self, col, host, pid):
     751
     752        sql = "SELECT " + col + " \
     753               FROM clients \
     754               WHERE host = '" + host + "' AND pid = " + str(pid)
     755
     756        try:
     757            rs = self.executeQuery(sql)
     758            rs.first()
     759            if rs.getInt(1) == 1: return True
     760            else: return False
     761        except:
     762            self.logger.exception("Unable to check whether " + col + " is true or false in clients table")
     763
     764        return False
     765
     766
     767    '''
     768    Populates Config object
     769    '''
     770    def readConfig(self, host, pid):
     771
     772        # first get config defined for this client
     773        sql = "SELECT config \
     774               FROM clients \
     775               WHERE host = '" + host + "' \
     776               AND pid = " + str(pid)
     777
     778        try:
     779            rs = self.executeQuery(sql)
     780            rs.first()
     781            self.config.name = rs.getString(1)
     782        except:
     783            self.logger.errorPair("No config set for", "%s (pid=%d)" % (host, pid))
     784            self.config.isLoaded = False
     785            return False
     786
     787        # now load that config
     788        sql = "SELECT \
     789        datastore_product, \
     790        datastore_type, \
     791        datastore_publish, \
     792        dvo_label, \
     793        dvo_location, \
     794        min_ra, \
     795        max_ra, \
     796        min_dec, \
     797        max_dec, \
     798        box_size, \
     799        base_path, \
     800        data_release, \
     801        delete_local, \
     802        delete_datastore, \
     803        delete_dxlayer, \
     804        epoch, \
     805        survey, \
     806        psps_survey, \
     807        queue_P2, \
     808        queue_ST \
     809        FROM config \
     810        WHERE name = '" + self.config.name + "'"
     811
     812        self.config.batchTypes = []
     813        try:
     814            rs = self.executeQuery(sql)
     815            rs.first()
     816            self.config.datastoreProduct = rs.getString(1)
     817            self.config.datastoreType = rs.getString(2)
     818            if rs.getInt(3) == 1: self.config.datastorePublishing = True
     819            else: self.config.datastorePublishing = False
     820            self.config.dvoLabel = rs.getString(4)
     821            self.config.dvoLocation = rs.getString(5)
     822            self.config.minRa = rs.getDouble(6)
     823            self.config.maxRa = rs.getDouble(7)
     824            self.config.minDec = rs.getDouble(8)
     825            self.config.maxDec = rs.getDouble(9)
     826
     827            self.config.boxSize = rs.getDouble(10)
     828            self.config.halfBox = self.config.boxSize/2.0
     829            self.config.boxSizeWithBorder = self.config.boxSize + (self.config.BORDER * 2)
     830
     831            self.config.basePath = rs.getString(11)
     832            self.config.dataRelease = rs.getInt(12)
     833            self.config.deleteLocal = rs.getInt(13)
     834            self.config.deleteDatastore = rs.getInt(14)
     835            self.config.deleteDxLayer = rs.getInt(15)
     836            self.config.epoch = rs.getString(16)
     837            self.config.survey = rs.getString(17)
     838            self.config.pspsSurvey = rs.getString(18)
     839            if rs.getInt(19) == 1: self.config.batchTypes.append("P2")
     840            if rs.getInt(20) == 1: self.config.batchTypes.append("ST")
     841            self.config.force = False # TODO
     842            self.config.test = False # TODO
     843            self.config.isLoaded = True
     844        except:
     845            self.logger.errorPair("Could not read config with name", self.config.name)
     846            self.config.isLoaded = False
     847
     848        return self.config.isLoaded
     849
     850    '''
     851    Gets id of box with these coords
     852    '''
     853    def getBoxId(self, config, ra, dec, boxSide):
     854
     855        sql = "SELECT id FROM box \
     856               WHERE config  = '" + config + "' \
     857               AND ra_center = " + str(ra) + " \
     858               AND dec_center = " + str(dec) + " \
     859               AND box_side = " + str(boxSide)
     860
     861        id = -1
     862        try:
     863            rs = self.executeQuery(sql)
     864            rs.first()
     865            id = rs.getInt(1)
     866        except:
     867            pass
     868
     869        return id
     870
     871
     872    '''
     873    Remove all boxes and associated ids in pending table
     874    '''
     875    def removeAllBoxes(self, config):
     876        self.execute("DELETE FROM box WHERE config = '" + config + "'")
     877
     878    '''
     879    Removes a box and it's associated ids in the pending table
     880    '''
     881    def removeBox(self, config, ra, dec, boxSide):
     882        self.execute("DELETE FROM box \
     883                WHERE config = '" + config + "' \
     884                AND ra_center = " + str(ra) + " \
     885                AND dec_center = " + str(dec) + " \
     886                AND box_side = " + str(boxSide))
     887
     888    '''
     889    Inserts new box into box table. If it already exisits, it returns existing box id
     890    '''
     891    def insertBox(self, config, ra, dec, boxSide):
     892
     893        id = self.getBoxId(config, ra, dec, boxSide)
     894
     895        # does not already exists so insert
     896        if id < 0:
     897
     898            sql = "INSERT INTO box \
     899                   (config, ra_center, dec_center, box_side) \
     900                   VALUES \
     901                   ('" + config + "', " + str(ra) + ", " + str(dec) + ", " + str(boxSide) + ")"
     902
     903            self.execute(sql)
     904            id = self.getBoxId(config, ra, dec, boxSide)
     905
     906        return id
     907
     908    '''
     909    Inserts new box ids into the pending table
     910    '''
     911    def insertPending(self, box_id, batchType, ids):
     912
     913        # first delete old pending items
     914        self.execute("DELETE FROM pending WHERE box_id = " + str(box_id))
     915
     916        for id in ids:
     917            sql = "INSERT INTO pending \
     918               (box_id, batch_type, stage_id) \
     919               VALUES \
     920               (" + str(box_id) + ", '" + batchType + "', " + str(id) + ")"
     921
     922            self.execute(sql)
     923
     924    '''
     925    Returns ids for all boxes with pending items
     926    '''
     927    def getBoxIds(self, config):
     928
     929        sql = "SELECT DISTINCT id \
     930               FROM box \
     931               JOIN pending ON (id = box_id)  \
     932               WHERE config = '" + config + "' \
     933               ORDER BY ra_center, dec_center"
     934
     935        ids = []
     936        try:
     937            rs = self.executeQuery(sql)
     938            while (rs.next()): ids.append(rs.getInt(1))
     939            rs.close()
     940        except:
     941            self.logger.errorPair("Can't get boxes", sql)
     942
     943        return ids
     944
     945    '''
     946    Returns dimensions of this box
     947    '''
     948    def getBoxDimensions(self, boxId):
     949
     950        sql = "SELECT ra_center, dec_center, box_side FROM box WHERE id = " + str(boxId)
     951
     952        boxDim = {}
     953        rs = self.executeQuery(sql)
     954        rs.first()
     955
     956        boxDim['RA'] = rs.getFloat(1)
     957        boxDim['DEC'] = rs.getFloat(2)
     958        boxDim['SIDE'] = rs.getFloat(3)
     959
     960        return boxDim
     961
     962    '''
     963    Returns ids for pending items in this box for this batch type
     964    '''
     965    def getPendingIds(self, boxId, batchType):
     966
     967        sql = "SELECT stage_id FROM pending WHERE batch_type = '" + batchType + "' AND box_id = " + str(boxId)
     968
     969        ids = []
     970        try:
     971            rs = self.executeQuery(sql)
     972            while (rs.next()): ids.append(rs.getInt(1))
     973            rs.close()
     974        except:
     975            self.logger.errorPair("Can't get ids from this box", sql)
     976
     977        return ids
     978
     979    '''
     980    Returns max number of pensing items in a box for this config
     981    '''
     982    def getMaxPendingInBox(self, config):
     983
     984        sql = "SELECT MAX(pending) \
     985               FROM (SELECT COUNT(stage_id) AS pending \
     986                       FROM pending \
     987                       JOIN box ON (id = box_id) \
     988                       WHERE config = '" + config + "' \
     989                       GROUP BY box_id) AS t"
     990
     991        try:
     992            rs = self.executeQuery(sql)
     993            rs.first()
     994            return rs.getInt(1)
     995        except:
     996            self.logger.errorPair("Could not count max pending", sql)
     997            return 100
     998
     999    '''
     1000    Writes density-plot data to file for pending stuff over sky for given config
     1001    '''
     1002    def createPendingDensityPlotData(self, config, DATFILE):
     1003
     1004        sql = "SELECT ra_center, dec_center, COUNT(stage_id) \
     1005               FROM box \
     1006               LEFT JOIN pending ON (id = box_id) \
     1007               WHERE config = '" + config + "' \
     1008               GROUP BY id \
     1009               ORDER BY ra_center, dec_center"
     1010
     1011        try:
     1012            rs = self.executeQuery(sql)
     1013            while (rs.next()):
     1014                print >> DATFILE, rs.getFloat(1), rs.getFloat(2), rs.getInt(3)
     1015            rs.close()
     1016        except:
     1017            self.logger.errorPair("Can't get density plot data", sql)
    3481018
    3491019    '''
     
    3521022    def __del__(self):
    3531023
    354         self.logger.debug("IppToPspsDb Desstructor")
     1024        self.logger.debug("IppToPspsDb Destructor")
    3551025        self.stmt.close()
    3561026        self.con.close()
Note: See TracChangeset for help on using the changeset viewer.