1 |
#!/usr/bin/env python
|
2 |
|
3 |
import os
|
4 |
import sys
|
5 |
from DatabaseParser import ConnectDB
|
6 |
import re
|
7 |
import cx_Oracle
|
8 |
import eventContent
|
9 |
|
10 |
try: ## set is builtin in python 2.6.4 and sets is deprecated
|
11 |
set
|
12 |
except NameError:
|
13 |
from sets import Set
|
14 |
|
15 |
class MenuAnalyzer:
|
16 |
def __init__(self,name):
|
17 |
##default ranges
|
18 |
self.maxModuleNameLength = 300
|
19 |
self.maxModulesPerPath = 50
|
20 |
self.maxPaths = 500
|
21 |
self.maxEndPaths = 30
|
22 |
|
23 |
##required streams
|
24 |
self.requiredStreamsAndPDs = { 'Calibration' : ['TestEnablesEcalHcalDT'],'EcalCalibration' : ['EcalLaser'],
|
25 |
'TrackerCalibration' : ['TestEnablesTracker'], 'DQM' : 'OnlineMonitor'}
|
26 |
self.ExpressStreamName = 'Express'
|
27 |
self.expressPDs = { 'ExpressPhysics' : 'Collisions',
|
28 |
'ExpressCosmics' : 'Cosmics' }
|
29 |
|
30 |
self.expressType = ''
|
31 |
|
32 |
self.menuName = name
|
33 |
self.endPathList = set()
|
34 |
self.perPathModuleList={}
|
35 |
self.perModuleTypeList={}
|
36 |
self.perStreamPDList={}
|
37 |
self.perPDPathList={}
|
38 |
self.Results={}
|
39 |
self.ModuleList=[]
|
40 |
self.ESModuleList=[]
|
41 |
self.eventContent={}
|
42 |
self.ParkingTriggers=[]
|
43 |
self.NotParkingTriggers=[]
|
44 |
|
45 |
self.AnalysisList=[]
|
46 |
|
47 |
|
48 |
## statically define the analysis map: new analyses must be registered here
|
49 |
self.AnalysisMap = {
|
50 |
'moduleLength' : self.checkModuleLength,
|
51 |
'numberOfPaths' : self.checkNumPaths,
|
52 |
'numberOfEndPaths' : self.checkNumEndPaths,
|
53 |
'reqStreamsAndPDs' : self.reqStreamsAndPDs,
|
54 |
'checkExpress' : self.checkExpress,
|
55 |
'checkNameFormats' :self.checkNameFormats,
|
56 |
'checkEventContent':self.checkEventContent,
|
57 |
'checkL1Unmask':self.checkL1Unmask,
|
58 |
'checkDQMStream':self.checkDQMStream,
|
59 |
'checkStreamB':self.checkStreamB
|
60 |
}
|
61 |
self.ProblemDescriptions = {
|
62 |
'moduleLength':'Modules too long',
|
63 |
'numberOfPaths':'Too many paths',
|
64 |
'numberOfEndPaths':'Too many endpaths',
|
65 |
'reqStreamsAndPDs':'Missing required stream/PD',
|
66 |
'checkExpress' : 'Invalid or missing express stream/PD',
|
67 |
'checkNameFormats' : 'Invalid PD or path name format',
|
68 |
'checkEventContent' : 'Invalid Event Content',
|
69 |
'checkL1Unmask' : 'L1 Unmask Module in Menu',
|
70 |
'checkDQMStream' : 'Check that the DQM stream contains correct trigger',
|
71 |
'checkStreamB' : 'Check all parking triggers in stream B'
|
72 |
}
|
73 |
|
74 |
self.T0REGEXP = { ## These are the regexps that T0 uses to access things
|
75 |
# Regexp for save file name paths. We don't process anything else.
|
76 |
'RXSAFEPATH' : re.compile("^[-A-Za-z0-9_]+$"),
|
77 |
# Regexp for valid dataset names.
|
78 |
'RXDATASET' : re.compile("^[-A-Za-z0-9_]+$"),
|
79 |
# Regexp for valid RelVal dataset names.
|
80 |
'RXRELVALMC' : re.compile("^/RelVal[^/]+/(CMSSW(?:_[0-9]+)+(?:_pre[0-9]+)?)[-_].*$"),
|
81 |
'RXRELVALDATA' : re.compile("^/[^/]+/(CMSSW(?:_[0-9]+)+(?:_pre[0-9]+)?)[-_].*$"),
|
82 |
# Regexp for online DQM files.
|
83 |
'RXONLINE' : re.compile("^(?:.*/)?DQM_V(\d+)(_[A-Za-z0-9]+)?_R(\d+)\.root$"),
|
84 |
# Regexp for offline DQM files.
|
85 |
'RXOFFLINE' : re.compile("^(?:.*/)?DQM_V(\d+)_R(\d+)((?:__[-A-Za-z0-9_]+){3})\.root$"),
|
86 |
# Regexp for acquisition era part of the processed dataset name.
|
87 |
'RXERA' : re.compile("^([A-Za-z]+\d+|CMSSW(?:_[0-9]+)+(?:_pre[0-9]+)?)")
|
88 |
}
|
89 |
|
90 |
def AddAnalysis(self,name):
|
91 |
self.AnalysisList.append(name)
|
92 |
|
93 |
def AddAllAnalyses(self):
|
94 |
for name in self.AnalysisMap.iterkeys():
|
95 |
self.AddAnalysis(name)
|
96 |
|
97 |
def Analyze(self):
|
98 |
cursor = ConnectDB('hlt')
|
99 |
self.GetModules(cursor)
|
100 |
self.GetESModules(cursor)
|
101 |
self.GetStreamsPathsPDs(cursor)
|
102 |
self.GetEventContent(cursor)
|
103 |
isError = False
|
104 |
if len(self.perStreamPDList) == 0:
|
105 |
print "FATAL ERROR: Cannot find any streams in this menu"
|
106 |
isError=True
|
107 |
if len(self.perPDPathList) ==0:
|
108 |
print "FATAL ERROR: Cannot find any PDs in this menu"
|
109 |
isError=True
|
110 |
if isError:
|
111 |
print "ABORTING"
|
112 |
sys.exit()
|
113 |
self.findParkingTriggers()
|
114 |
for analysis in self.AnalysisList:
|
115 |
if not self.AnalysisMap.has_key(analysis):
|
116 |
print "ERROR: Analysis %s not defined" % (analysis,)
|
117 |
continue
|
118 |
self.AnalysisMap[analysis]()
|
119 |
|
120 |
|
121 |
def checkModuleLength(self):
|
122 |
self.Results['moduleLength'] = []
|
123 |
for modName,type in self.perModuleTypeList.iteritems():
|
124 |
if len(modName) > self.maxModuleNameLength: self.Results['moduleLength'].append(modName)
|
125 |
|
126 |
def checkNumPaths(self):
|
127 |
if len(self.perPathModuleList) > self.maxPaths:
|
128 |
self.Results['numberOfPaths'] = len(self.perPathModuleList)
|
129 |
else:
|
130 |
self.Results['numberOfPaths'] = 0
|
131 |
def checkNumEndPaths(self):
|
132 |
if len(self.endPathList) > self.maxEndPaths:
|
133 |
self.Results['numberOfEndPaths'] = len(self.endPathList)
|
134 |
else:
|
135 |
self.Results['numberOfEndPaths'] = 0
|
136 |
def reqStreamsAndPDs(self):
|
137 |
self.Results['reqStreamsAndPDs'] = []
|
138 |
for stream,PDList in self.requiredStreamsAndPDs.iteritems():
|
139 |
if not self.perStreamPDList.has_key(stream): self.Results['reqStreamsAndPDs'].append(stream)
|
140 |
for PD in PDList:
|
141 |
if not PD in self.requiredStreamsAndPDs[stream]: self.Results['reqStreamsAndPDs'].append(stream+'::'+PD)
|
142 |
|
143 |
def checkExpress(self):
|
144 |
self.Results['checkExpress'] = []
|
145 |
if not self.perStreamPDList.has_key(self.ExpressStreamName):
|
146 |
self.Results['checkExpress'].append(self.ExpressStreamName)
|
147 |
return
|
148 |
|
149 |
if len(self.perStreamPDList[self.ExpressStreamName]) >1:
|
150 |
self.Results['checkExpress'].append("MULTIPLE_PDS")
|
151 |
if len(self.perStreamPDList[self.ExpressStreamName]) <1:
|
152 |
self.Results['checkExpress'].append("NO_PDS")
|
153 |
|
154 |
for PD in self.perStreamPDList[self.ExpressStreamName]:
|
155 |
if not self.expressPDs.has_key(PD):
|
156 |
self.Results['checkExpress'].append(self.ExpressStreamName+"::"+PD)
|
157 |
else:
|
158 |
self.expressType = self.expressPDs[PD]
|
159 |
|
160 |
|
161 |
|
162 |
def checkNameFormats(self):
|
163 |
self.Results['checkNameFormats']=[]
|
164 |
for PD,path in self.perPDPathList.iteritems():
|
165 |
if not self.T0REGEXP['RXDATASET'].match(PD):
|
166 |
for k,v in self.perStreamPDList.iteritems():
|
167 |
if PD in v:
|
168 |
self.Results['checkNameFormats'].append(k+"::"+PD+"::"+str(path))
|
169 |
break
|
170 |
self.Results['checkNameFormats'].append('NO STREAM::'+PD+"::"+str(path))
|
171 |
for path in self.perPathModuleList.iterkeys():
|
172 |
if not self.T0REGEXP['RXSAFEPATH'].match(path):
|
173 |
self.Results['checkNameFormats'].append(path)
|
174 |
|
175 |
def checkEventContent(self):
|
176 |
self.Results['checkEventContent']=[]
|
177 |
for stream,content in self.eventContent.iteritems():
|
178 |
#first check for a drop statement
|
179 |
if not ('drop *' in content or 'drop *_hlt*_*_*' in content):
|
180 |
self.Results['checkEventContent'].append(stream+'::drop *')
|
181 |
if not eventContent.requiredEventContent.has_key(stream): continue
|
182 |
requiredContent = eventContent.requiredEventContent[stream]
|
183 |
for entry in requiredContent:
|
184 |
if not entry in content:
|
185 |
self.Results['checkEventContent'].append(stream+'::'+entry)
|
186 |
|
187 |
def checkL1Unmask(self):
|
188 |
self.Results['checkL1Unmask']=[]
|
189 |
if 'L1GtTriggerMaskAlgoTrigTrivialProducer' in self.ESModuleList:
|
190 |
self.Results['checkL1Unmask'].append('L1GtTriggerMaskAlgoTrigTrivialProducer')
|
191 |
if 'L1GtTriggerMaskTechTrigTrivialProducer' in self.ESModuleList:
|
192 |
self.Results['checkL1Unmask'].append('L1GtTriggerMaskTechTrigTrivialProducer')
|
193 |
|
194 |
|
195 |
def findParkingPDs(self):
|
196 |
ParkingPDs=[]
|
197 |
NotParkingPDs=[]
|
198 |
for PD in self.perStreamPDList["A"]: # look at PDs only in stream A
|
199 |
if PD.find("Parked")!=-1: #look for PDs with Parked in the name
|
200 |
ParkingPDs.append(PD)
|
201 |
else:
|
202 |
NotParkingPDs.append(PD)
|
203 |
return (ParkingPDs,NotParkingPDs)
|
204 |
|
205 |
def findParkingTriggers(self):
|
206 |
ParkingPDs,NotParkingPDs = self.findParkingPDs()
|
207 |
for PD in NotParkingPDs:
|
208 |
for trig in self.perPDPathList[PD]: self.NotParkingTriggers.append(trig) # first append ALL triggers from the not in parking PDs
|
209 |
for PD in ParkingPDs:
|
210 |
for trig in self.perPDPathList[PD]:
|
211 |
if not trig in self.NotParkingTriggers: self.ParkingTriggers.append(trig) # get triggers that don't show up in the non-parking PDs
|
212 |
|
213 |
|
214 |
def checkDQMStream(self):
|
215 |
self.Results['checkDQMStream']=[]
|
216 |
for trig in self.NotParkingTriggers:
|
217 |
if trig.find("LogMonitor")!=-1: continue
|
218 |
if not trig in self.perPDPathList["OnlineMonitor"]: self.Results['checkDQMStream'].append("NotInDQM::%s"%trig)
|
219 |
for trig in self.ParkingTriggers:
|
220 |
if trig in self.perPDPathList["OnlineMonitor"]: self.Results['checkDQMStream'].append("ParkingTriggerInDQM::%s"%trig)
|
221 |
|
222 |
def checkStreamB(self):
|
223 |
self.Results['checkStreamB']=[]
|
224 |
for trig in self.ParkingTriggers:
|
225 |
if not trig in self.perPDPathList["ParkingMonitor"]: self.Results['checkStreamB'].append("ParkingTriggerNotInStreamB::%s" %trig)
|
226 |
|
227 |
def GetModules(self,cursor):
|
228 |
sqlquery ="""
|
229 |
SELECT I.NAME,E.NAME,D.NAME,I.ISENDPATH
|
230 |
FROM
|
231 |
CMS_HLT.PARAMETERS B,
|
232 |
CMS_HLT.SUPERIDPARAMETERASSOC C,
|
233 |
CMS_HLT.MODULETEMPLATES D,
|
234 |
CMS_HLT.MODULES E,
|
235 |
CMS_HLT.PATHMODULEASSOC F,
|
236 |
CMS_HLT.CONFIGURATIONPATHASSOC G,
|
237 |
CMS_HLT.CONFIGURATIONS H,
|
238 |
CMS_HLT.PATHS I
|
239 |
WHERE
|
240 |
B.PARAMID = C.PARAMID AND
|
241 |
C.SUPERID = F.MODULEID AND
|
242 |
E.TEMPLATEID = D.SUPERID AND
|
243 |
F.MODULEID = E.SUPERID AND
|
244 |
F.PATHID=G.PATHID AND
|
245 |
I.PATHID=G.PATHID AND
|
246 |
G.CONFIGID=H.CONFIGID AND
|
247 |
H.CONFIGDESCRIPTOR='%s'
|
248 |
""" % (self.menuName,)
|
249 |
|
250 |
cursor.execute(sqlquery)
|
251 |
for PathName,ModuleName,ModuleType,endPath in cursor.fetchall():
|
252 |
if not self.perPathModuleList.has_key(PathName): self.perPathModuleList[PathName] = []
|
253 |
self.perPathModuleList[PathName].append(ModuleName)
|
254 |
self.perModuleTypeList[ModuleName] = ModuleType
|
255 |
if not ModuleName in self.ModuleList: self.ModuleList.append(ModuleName)
|
256 |
if endPath: self.endPathList.add(PathName)
|
257 |
|
258 |
|
259 |
def GetStreamsPathsPDs(self,cursor):
|
260 |
sqlquery= """
|
261 |
SELECT A.STREAMLABEL,E.NAME,F.DATASETLABEL
|
262 |
FROM
|
263 |
CMS_HLT.STREAMS A,
|
264 |
CMS_HLT.CONFIGURATIONS B,
|
265 |
CMS_HLT.CONFIGURATIONPATHASSOC C,
|
266 |
CMS_HLT.PATHSTREAMDATASETASSOC D,
|
267 |
CMS_HLT.PATHS E,
|
268 |
CMS_HLT.PRIMARYDATASETS F
|
269 |
WHERE
|
270 |
B.CONFIGDESCRIPTOR='%s' AND
|
271 |
C.CONFIGID=B.CONFIGID AND
|
272 |
D.PATHID=C.PATHID AND
|
273 |
A.STREAMID=D.STREAMID AND
|
274 |
E.PATHID = C.PATHID AND
|
275 |
F.DATASETID = D.DATASETID
|
276 |
""" % (self.menuName,)
|
277 |
|
278 |
cursor.execute(sqlquery)
|
279 |
for StreamName,PathName,PDName in cursor.fetchall():
|
280 |
if not self.perStreamPDList.has_key(StreamName): self.perStreamPDList[StreamName] = []
|
281 |
if not PDName in self.perStreamPDList[StreamName]: self.perStreamPDList[StreamName].append(PDName)
|
282 |
if not self.perPDPathList.has_key(PDName): self.perPDPathList[PDName] = []
|
283 |
self.perPDPathList[PDName].append(PathName)
|
284 |
|
285 |
def GetESModules(self,cursor):
|
286 |
sqlquery = """
|
287 |
SELECT UNIQUE(F.NAME)
|
288 |
FROM
|
289 |
CMS_HLT.ESMODULES F,
|
290 |
CMS_HLT.CONFIGURATIONESMODULEASSOC G,
|
291 |
CMS_HLT.CONFIGURATIONS H
|
292 |
WHERE
|
293 |
G.ESMODULEID = F.SUPERID AND
|
294 |
G.CONFIGID=H.CONFIGID AND
|
295 |
H.CONFIGDESCRIPTOR='%s'
|
296 |
""" % (self.menuName,)
|
297 |
|
298 |
cursor.execute(sqlquery)
|
299 |
for ModuleName, in cursor.fetchall():
|
300 |
if not ModuleName in self.ESModuleList: self.ESModuleList.append(ModuleName)
|
301 |
|
302 |
def GetEventContent(self,cursor):
|
303 |
sqlquery = """
|
304 |
SELECT A.STREAMLABEL,H.STATEMENTTYPE,H.CLASSN,H.MODULEL,H.EXTRAN,H.PROCESSN
|
305 |
FROM
|
306 |
CMS_HLT.STREAMS A,
|
307 |
CMS_HLT.CONFIGURATIONS B,
|
308 |
CMS_HLT.CONFIGURATIONPATHASSOC C,
|
309 |
CMS_HLT.PATHSTREAMDATASETASSOC D,
|
310 |
CMS_HLT.PATHS E,
|
311 |
CMS_HLT.ECSTREAMASSOC F,
|
312 |
CMS_HLT.ECSTATEMENTASSOC G,
|
313 |
CMS_HLT.EVENTCONTENTSTATEMENTS H
|
314 |
WHERE
|
315 |
B.CONFIGDESCRIPTOR='%s' AND
|
316 |
C.CONFIGID=B.CONFIGID AND
|
317 |
D.PATHID=C.PATHID AND
|
318 |
A.STREAMID=D.STREAMID AND
|
319 |
E.PATHID = C.PATHID AND
|
320 |
F.STREAMID = D.STREAMID AND
|
321 |
G.EVENTCONTENTID=F.EVENTCONTENTID AND
|
322 |
H.STATEMENTID=G.STATEMENTID
|
323 |
""" % (self.menuName,)
|
324 |
|
325 |
cursor.execute(sqlquery)
|
326 |
for stream,keep,Class,module,extra,process in cursor.fetchall():
|
327 |
if not self.eventContent.has_key(stream): self.eventContent[stream]=[]
|
328 |
statement = "%s_%s_%s_%s" % (Class,module,extra,process,)
|
329 |
if statement == "*_*_*_*": statement = "*"
|
330 |
if keep == 1: statement = "keep "+statement
|
331 |
else: statement = "drop "+statement
|
332 |
if not statement in self.eventContent[stream]:
|
333 |
self.eventContent[stream].append( statement )
|