Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

rcReportGen.py

00001 #!/usr/local/bin/python
00002 #
00003 #                               Copyright 2002
00004 #                                     by
00005 #                        The Board of Trustees of the
00006 #                     Leland Stanford Junior University.
00007 #                            All rights reserved.
00008 #
00009 
00010 __facility__ = "Online"
00011 __abstract__ = "Run report generator class for RunControl"
00012 __author__   = "S. Tuvi <stuvi@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online"
00013 __date__     = "02/10/2003"
00014 __version__  = "$Revision: 2.13 $"
00015 __credits__  = "SLAC"
00016 
00017 import LATTE.copyright_SLAC
00018 
00019 import os
00020 import logging as log
00021 import time
00022 import calendar
00023 import cStringIO
00024 
00025 from xml.sax.saxutils  import XMLGenerator
00026 from xml.parsers.expat import ParserCreate
00027 
00028 from qt    import Qt, QVariant, QDate, QDateTime
00029 from qtsql import QSqlDatabase, QSqlCursor
00030 
00031 UNITS_INT    = 0
00032 UNITS_LONG   = 1
00033 UNITS_FLOAT  = 2
00034 UNITS_STRING = 3
00035 UNITS_LIST   = 4
00036 UNITS_DICT   = 5
00037 
00038 UNIT_MAP = {
00039             'OperatorId'      : UNITS_LONG,
00040             'EventCount'      : UNITS_LONG,
00041             'BadEventCount'   : UNITS_LONG,
00042             'ErrorEventCount' : UNITS_LONG,
00043             'PauseCount'      : UNITS_INT,
00044             'ElapsedTime'     : UNITS_FLOAT,
00045             'CompletionStatus': UNITS_INT,
00046            }
00047 
00048 # Shift Dictionary
00049 SHIFT_DICT =  { 0: ("T00:00:00", "T08:00:00", "Owl"),
00050                 1: ("T08:00:00", "T16:00:00", "Day"),
00051                 2: ("T16:00:00", "T00:00:00", "Swing")
00052               }
00053 
00054 class rcReportGen(object):
00055   def __init__(self, fileName="rcReport.out", prefs=None):
00056     self.__fileName  = fileName
00057     self.__prefs     = prefs
00058     if prefs is not None:
00059       self.__elognbl   = int(prefs["elognbl"])
00060     else:
00061       self.__elognbl   = 0
00062 
00063 
00064   def initialize(self, tstamp=None):
00065     self.__tstamp = tstamp
00066     self.__repFields = []
00067     self.__repData = []
00068     self.__repUnits = []
00069     if self.__elognbl:
00070       self.__sqldriver = 'QMYSQL3'
00071       if 'ELOGBOOK_DB' in os.environ:
00072         dbname = os.environ['ELOGBOOK_DB']
00073       else:
00074         dbname = 'elogbook'
00075       if QSqlDatabase.isDriverAvailable(self.__sqldriver):
00076         self.__db = QSqlDatabase.addDatabase(self.__sqldriver)
00077         if not self.connectDB(dbname):
00078           log.error("Error opening database %s"
00079                     " disabling Elogbook integration" % dbname)
00080           log.error(str(self.__db.lastError().text()))
00081           self.__elognbl = 0
00082         else:
00083           log.debug("Database %s opened successfully" % dbname)
00084       else:
00085         log.error("The SQL driver %s is not available,"
00086                   " disabling Elogbook integration" % self.__sqldriver)
00087         self.__elognbl = 0
00088 
00089   def connectDB(self, dbname):
00090     if 'ELOGBOOK_HOST' in os.environ:
00091       host = os.environ['ELOGBOOK_HOST']
00092     else:
00093       host = 'localhost'
00094     self.__db.setHostName(host)
00095     self.__db.setUserName('elogbook')
00096     self.__db.setPassword('elogbook')
00097     self.__db.setDatabaseName(dbname)
00098     return self.__db.open()
00099 
00100   def disconnectDB(self):
00101     return self.__db.close()
00102 
00103   def addField(self, field, data, units=UNITS_STRING):
00104     if field == 'TimeStamp':
00105       self.__tstamp = data
00106     else:
00107       self.__repFields.append(field)
00108       self.__repData.append(data)
00109       self.__repUnits.append(units)
00110 
00111   def writeReportCSV(self):
00112     if not os.path.exists(self.__fileName):
00113       f = file(self.__fileName, 'w+')
00114       i = 0
00115       for header in self.__repFields:
00116         f.write(header)
00117         i = i + 1
00118         if i < len(self.__repFields):
00119           f.write(',')
00120       f.write('\n')
00121 
00122     f = file(self.__fileName, 'a+')
00123     i = 0
00124     for data in self.__repData:
00125       f.write('"'+data+'"')
00126       i = i + 1
00127       if i < len(self.__repData):
00128         f.write(',')
00129     f.write('\n')
00130     f.close()
00131 
00132   def writeReportXML(self):
00133     if not os.path.exists(self.__fileName):
00134       f = file(self.__fileName, 'w+')
00135       newReportFile = 1
00136     else:
00137       f = file(self.__fileName, 'a+')
00138       newReportFile = 0
00139 
00140     result = cStringIO.StringIO()
00141     gen = XMLGenerator(result)
00142     if newReportFile:
00143       gen.startDocument()
00144     if self.__tstamp is None:
00145       self.__tstamp = time.gmtime()
00146     self.__tstamp = str(self.__tstamp)
00147     gen.startElement("testReport", {'timestamp': self.__tstamp})
00148     i = 0
00149     for header in self.__repFields:
00150       gen.startElement(header,{})
00151       gen.characters(self.__repData[i])
00152       gen.endElement(header)
00153       i = i + 1
00154     gen.endElement("testReport")
00155     if newReportFile:
00156       gen.endDocument()
00157     f.write(result.getvalue()+'\n')
00158     f.close()
00159     if self.__elognbl:
00160       if self.writeReportSQL() == 0:
00161         self.addShift(self.__tstamp)
00162       self.disconnectDB()
00163 
00164   def writeReportSQL(self):
00165     fieldMap = {'RunId': 'RunID',
00166                 'OperatorId': 'OperatorID'
00167                }
00168 
00169     dateFields = ['TimeStamp', 'StartTime', 'EndTime']
00170 
00171     self.__repFields.append('TimeStamp')
00172     self.__repData.append(self.__tstamp)
00173     table = "elogreport"
00174     cur = QSqlCursor(table)
00175     fields = [f.name() for f in self.__db.recordInfo(table)]
00176     recBuffer = cur.primeInsert()
00177     additional = ""
00178     for i in range(len(self.__repFields)):
00179       field = self.__repFields[i]
00180       if field in fieldMap:
00181         field = fieldMap[field]
00182       if field in dateFields:
00183         t = eval(self.__repData[i])
00184         value = "%04d-%02d-%02d %02d:%02d:%02d" % (t[0], t[1], t[2], t[3], t[4], t[5])
00185       else:
00186         value = self.__repData[i]
00187       if field in fields:
00188         recBuffer.setValue(field, QVariant(value))
00189       else:
00190         # Tue Mar 15 14:05:15 2005: RiC debug log commented out.
00191         #log.debug("Can not find field %s in table %s. Adding it to the 'Additional Fields' column."
00192         #         % (field, table))
00193         additional = additional + field + "???" + value + "!!!"
00194       if additional != "":
00195         recBuffer.setValue("AdditionFields", QVariant(additional))
00196     if cur.insert() != 1:
00197       log.error("Could not insert elogreport record, dumping field data:")
00198       for i in range(len(self.__repFields)):
00199         log.error("\t%s\t\t\t%s" % (self.__repFields[i], self.__repData[i]))
00200       log.error("SQL Error text: %s", str(cur.lastError().text()))
00201       return -1
00202     return 0
00203 
00204   def readReportXML(self):
00205     # 3 handler functions
00206     def start_element(name, attrs):
00207       #print 'Start element:', str(name), attrs
00208       self.__data = ''
00209       if str(name) == 'testReport':
00210         self.__tstamp = str(attrs['timestamp'])
00211         self.__repFields.append('TimeStamp')
00212         self.__repData.append(self.__tstamp)
00213         self.__repUnits.append(UNITS_STRING)
00214       else:
00215         self.__repFields.append(str(name))
00216     def end_element(name):
00217       #print 'End element:', str(name)
00218       name = str(name)
00219       if name != 'testReport':
00220         self.__repData.append(self.__data)
00221         if name in UNIT_MAP:
00222           self.__repUnits.append(UNIT_MAP[name])
00223         else:
00224           self.__repUnits.append(UNITS_STRING)
00225     def char_data(data):
00226       #print 'Character data:', str(data)
00227       if self.__data is not None:
00228         self.__data += str(data)
00229     def external_entity_ref_handler(context,base,systemId,publicId):
00230       subParser = p.ExternalEntityParserCreate(context)
00231       subParser.StartElementHandler = start_element
00232       subParser.EndElementHandler = end_element
00233       subParser.CharacterDataHandler = char_data
00234       subParser.ParseFile(file(systemId))
00235       return 1
00236     self.__data = None
00237     p = ParserCreate()
00238     p.ExternalEntityRefHandler = external_entity_ref_handler
00239     p.Parse("""<!DOCTYPE report [<!ENTITY reportfile SYSTEM \""""+self.__fileName+"""\">
00240             ]><report>&reportfile;</report>""")
00241 
00242   def getReportFields(self):
00243     return self.__repFields
00244 
00245   def getReportData(self):
00246     return self.__repData
00247 
00248   def getReportUnits(self):
00249     return self.__repUnits
00250 
00251   def getTimestamp(self):
00252     return self.__tstamp
00253 
00254   def addShift(self,tstamp):
00255     (shiftID, startLocal, endLocal, type) = self.getShiftInfo(eval(tstamp))
00256     dateTime    = QDateTime().currentDateTime()
00257     timeStamp   = self.obtainGMTime(dateTime)
00258     # Shift Cursor
00259     shiftFilter = "ShiftID='" + str(shiftID) + "'"
00260     shiftCursor = self.obtainCursor("elogshiftsummary", shiftFilter)
00261     # If there are no records, create a new one
00262     if not shiftCursor.isValid():
00263       cursorBuffer = shiftCursor.primeInsert()
00264       cursorBuffer.setValue("ShiftID",    QVariant(shiftID))
00265       cursorBuffer.setValue("ShiftType",  QVariant(type))
00266       cursorBuffer.setValue("StartTime",  QVariant(startLocal))
00267       cursorBuffer.setValue("EndTime",    QVariant(endLocal))
00268       cursorBuffer.setValue("LastUpdate", QVariant(timeStamp))
00269       count = shiftCursor.insert()
00270       log.debug("rcReportGen: Added new shift id: %s, type: %s, startLocal: %s, endLocal: %s, timestamp: %s for run timestamp: %s"
00271                 % (shiftID, type, startLocal, endLocal, timeStamp, tstamp))
00272       log.debug("rcReportGen: Inserted record count: %d" % count)
00273       log.debug("rcReportGen: Last error: %s" % str(shiftCursor.lastError().text()))
00274       shiftCursor.update()
00275       #print "New Shift Type: ", type
00276       #print "New Shift Start: ", startLocal
00277       #print "New Shift End: ", endLocal
00278       #print "New Shift Last Update: ", timeStamp
00279       return True
00280     else:
00281       #print "Shift for run: ", tstamp, " already exists in the database."
00282       pass
00283 
00284 
00285   def getShiftInfo(self,t):
00286     #print "Timestamp=", t
00287     timeStampGMT = self.convertTimeTuple(t)
00288     timeStampLocal = self.obtainLocalTime(timeStampGMT)
00289     QTimeStampLocal = QDateTime.fromString(timeStampLocal, Qt.ISODate)
00290     #print "Run timestamp GMT: ", timeStampGMT, "Run timestamp Local: ", timeStampLocal
00291     timeStamp = timeStampLocal.split('T')
00292     date = timeStamp[0]
00293     time = timeStamp[1]
00294     #print "Date:", date, "Time:", time
00295     #Obtain End Date (Local)
00296     startQDate = QDate().fromString(date, Qt.ISODate)
00297     endQDate   = startQDate.addDays(1)
00298     endDate    = str(endQDate.toString(Qt.ISODate))
00299     #print "End Date: ", endDate
00300     # Date tag for ShiftID
00301     dateList = date.split('-')
00302     dateTag = dateList[0] + dateList[1] + dateList[2]
00303     #print "Date Tag: ", dateTag
00304     # If run timeStamp is within shift obtain ShiftID
00305     for shift in SHIFT_DICT:
00306       (startT, endT, type) = SHIFT_DICT[shift]
00307       startLocal = date + startT
00308       if shift == 2:
00309         endLocal = endDate + endT
00310       else:
00311         endLocal = date + endT
00312       startQDateTime = QDateTime.fromString(startLocal, Qt.ISODate)
00313       endQDateTime   = QDateTime.fromString(endLocal,   Qt.ISODate)
00314       # The Core Code:
00315       # secsTo Returns the number of seconds from this datetime1 to (datetime2)
00316       # which is negative if dt is earlier than this datetime).
00317       # Example: datetime1.secsTo(datetime2) > 0 if datetime2 is later than datetime1
00318       secsToStartTime = startQDateTime.secsTo(QTimeStampLocal)
00319       secsToEndTime   = endQDateTime.secsTo(QTimeStampLocal)
00320       #print "Shift: ", shift, "Start: ", startLocal, " End: ", endLocal
00321       #print "Shift: ", shift, "Secs To Start: ", secsToStartTime, "Secs To End: ", secsToEndTime
00322       if secsToStartTime >= 0 and secsToEndTime <= 0:
00323         shiftID    = dateTag + str(shift)
00324         return (shiftID, startLocal, endLocal, type)
00325 
00326   def obtainLocalTime(self, dateTime):
00327     dateTime = str(dateTime)
00328     splitTime = dateTime.split('T')
00329     #print dateTime, splitTime
00330     dateTime = splitTime[0] + splitTime[1]
00331     timeStamp = time.strptime(dateTime, "%Y-%m-%d%H:%M:%S")
00332     localTimeTuple = time.localtime(calendar.timegm(timeStamp))
00333     localTime = self.convertTimeTuple(localTimeTuple)
00334     return localTime
00335 
00336   def obtainGMTime(self, dateTime):
00337     dateTime = str(dateTime.toString(Qt.ISODate))
00338     splitTime = dateTime.split('T')
00339     dateTime = splitTime[0] + splitTime[1]
00340     timeStamp = time.strptime(dateTime, "%Y-%m-%d%H:%M:%S")
00341     gmTimeTuple = time.gmtime(time.mktime(timeStamp))
00342     gmTime = self.convertTimeTuple(gmTimeTuple)
00343     return gmTime
00344 
00345   def convertTimeTuple(self, timeTuple):
00346     timeStamp =  "%04d" % timeTuple[0] + "-" + \
00347                  "%02d" % timeTuple[1] + "-" + \
00348                  "%02d" % timeTuple[2] + "T" + \
00349                  "%02d" % timeTuple[3] + ":" + \
00350                  "%02d" % timeTuple[4] + ":" + \
00351                  "%02d" % timeTuple[5]
00352     return timeStamp
00353 
00354   def obtainCursor(self, table, filter):
00355     shiftCursor = QSqlCursor(table, True, self.__db)
00356     shiftCursor.setFilter(filter)
00357     shiftCursor.select()
00358     shiftCursor.next()
00359     return shiftCursor

Generated on Fri Jul 21 13:26:31 2006 for LATTE R04-12-00 by doxygen 1.4.3