ATLAS Offline Software
Loading...
Searching...
No Matches
python.TriggerConfigAccessBase.ConfigDBLoader Class Reference
Inheritance diagram for python.TriggerConfigAccessBase.ConfigDBLoader:
Collaboration diagram for python.TriggerConfigAccessBase.ConfigDBLoader:

Public Member Functions

 __init__ (self, configType, dbalias, dbkey)
 setQuery (self, query)
 getQueryDefinition (self, schemaVersion)
dict[str, Any] load (self)
str getWriteFilename (self)
 confirmConfigType (self, config)

Static Public Member Functions

 getResolvedFileName (filename, pathenv="")
 getConnectionParameters (dbalias)
 getSchema (connStr)
 readSchemaVersion (qdict, session)
 getCoralQuery (session, queryStr, qdict=None)

Public Attributes

 dbalias = dbalias
 dbkey = dbkey
dict query = {}
 schema = None
ConfigType configType = configType

Detailed Description

Definition at line 101 of file TriggerConfigAccessBase.py.

Constructor & Destructor Documentation

◆ __init__()

python.TriggerConfigAccessBase.ConfigDBLoader.__init__ ( self,
configType,
dbalias,
dbkey )

Definition at line 102 of file TriggerConfigAccessBase.py.

102 def __init__(self, configType, dbalias, dbkey):
103 super().__init__(configType)
104 self.dbalias = dbalias
105 self.dbkey = dbkey
106 self.query = {}
107 self.schema = None
108

Member Function Documentation

◆ confirmConfigType()

python.TriggerConfigAccessBase.ConfigLoader.confirmConfigType ( self,
config )
inherited
checks that the in-file specification of the configuration type matches the expected type

Definition at line 51 of file TriggerConfigAccessBase.py.

51 def confirmConfigType(self,config):
52 """
53 checks that the in-file specification of the configuration type matches the expected type
54 """
55 if config['filetype'] != self.configType:
56 raise RuntimeError("Can not load file with filetype '%s' when expecting '%s'" % (config['filetype'], self.configType.filetype))
57

◆ getConnectionParameters()

python.TriggerConfigAccessBase.ConfigDBLoader.getConnectionParameters ( dbalias)
static

Definition at line 129 of file TriggerConfigAccessBase.py.

129 def getConnectionParameters(dbalias):
130 dblookupFile = ConfigDBLoader.getResolvedFileName("dblookup.xml", "CORAL_DBLOOKUP_PATH")
131 dbp = ET.parse(dblookupFile)
132 listOfServices = []
133 foundAlias = False
134 for logSvc in dbp.iter("logicalservice"):
135 if logSvc.attrib["name"] != dbalias:
136 continue
137 foundAlias = True
138 listOfServices = [ serv.attrib["name"] for serv in logSvc.iter("service") ]
139 if len(listOfServices) == 0:
140 raise RuntimeError("DB %s has no services listed in %s" % (dbalias, dblookupFile))
141 break
142 if not foundAlias:
143 raise RuntimeError("DB %s not available in %s" % (dbalias, dblookupFile))
144
145 if "FRONTIER_SERVER" not in os.environ:
146 # remove all frontier connnections in the list if the environment FRONTIER_SERVER variable does not exist
147 # this speeds up the resolution of the connection specification (dbalias)
148 listOfServices: list[str] = [svc for svc in listOfServices if not svc.startswith("frontier:")]
149
150 # now get the account and pw for oracle connections
151 credentials: dict[str, Any] = dict.fromkeys(listOfServices)
152
153 for svc in filter(lambda s : s.startswith("frontier:"), listOfServices):
154 credentials[svc] = {}
155 credentials[svc]["user"] = svc
156 credentials[svc]["password"] = ""
157
158 try:
159 authFile = ConfigDBLoader.getResolvedFileName("authentication.xml", "CORAL_AUTH_PATH")
160 except Exception as e:
161 log.warning("File authentication.xml is not available! Oracle connection cannot be established. Exception message is: %s",e)
162 else:
163 for svc in filter(lambda s : s.startswith("oracle:"), listOfServices):
164 ap = ET.parse(authFile)
165 count = 0
166 for con in filter( lambda c: c.attrib["name"]==svc, ap.iter("connection")):
167 credentials[svc] = dict([(par.attrib["name"],par.attrib["value"]) for par in con])
168 count += 1
169 if count==0:
170 raise RuntimeError("No credentials found for connection %s from service %s for db %s" % (con,svc,dbalias))
171 if count>1:
172 raise RuntimeError("More than 1 connection found in %s for service %s" % (authFile, svc))
173
174 return credentials
175

◆ getCoralQuery()

python.TriggerConfigAccessBase.ConfigDBLoader.getCoralQuery ( session,
queryStr,
qdict = None )
static
Parse output, tables and condition from the query string into coral query object

Definition at line 222 of file TriggerConfigAccessBase.py.

222 def getCoralQuery(session, queryStr, qdict = None):
223 ''' Parse output, tables and condition from the query string into coral query object'''
224 query = session.nominalSchema().newQuery()
225
226 if qdict is not None:
227 queryStr = queryStr.format(**qdict)
228
229 # bind vars
230 bindVars = coral.AttributeList() # type: ignore
231 bindVarsInQuery = re.findall(r":(\w*)", queryStr)
232 if len(bindVarsInQuery) > 0 and qdict is None:
233 log.error("Query has bound-variable syntax but no value dictionary is provided. Query: %s", queryStr)
234 for k in bindVarsInQuery:
235 bindVars.extend(k, "int")
236 bindVars[k].setData(qdict[k])
237
238 output = queryStr.split("SELECT")[1].split("FROM")[0]
239 for field in output.split(','):
240 query.addToOutputList(field)
241
242 log.debug("Conversion for Coral of query: %s", queryStr)
243
244 for table in queryStr.split("FROM")[1].split("WHERE")[0].split(","):
245 tableSplit = list(filter(None, table.split(" ")))
246 # Schema name is stripped from TableList in Coral query
247 query.addToTableList(tableSplit[0].split(".")[1], tableSplit[1])
248
249 if "WHERE" in queryStr:
250 cond = queryStr.split("WHERE")[1]
251 m = re.match("(.*)(?i: ORDER *BY )(.*)", cond) # check for "order by" clause
252 if m:
253 where, order = m.groups()
254 query.setCondition(where, bindVars)
255 query.addToOrderList(order)
256 else:
257 query.setCondition(cond, bindVars)
258
259 return query
260
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177

◆ getQueryDefinition()

python.TriggerConfigAccessBase.ConfigDBLoader.getQueryDefinition ( self,
schemaVersion )
Choose query based on schema version, based on TrigConf::TrigDBLoader::getQueryDefinition 

Definition at line 261 of file TriggerConfigAccessBase.py.

261 def getQueryDefinition(self, schemaVersion):
262 '''Choose query based on schema version, based on TrigConf::TrigDBLoader::getQueryDefinition '''
263 maxDefVersion = 0
264 for vkey in self.query.keys():
265 if vkey>maxDefVersion and vkey<=schemaVersion:
266 maxDefVersion = vkey
267
268 if maxDefVersion == 0:
269 raise RuntimeError("No query available for schema version {0}".format(schemaVersion))
270
271 return self.query[maxDefVersion]
272

◆ getResolvedFileName()

python.TriggerConfigAccessBase.ConfigDBLoader.getResolvedFileName ( filename,
pathenv = "" )
static
looks for file, first absolute, then by resolving envvar pathenv

Definition at line 117 of file TriggerConfigAccessBase.py.

117 def getResolvedFileName(filename, pathenv=""):
118 """ looks for file, first absolute, then by resolving envvar pathenv"""
119 if os.access(filename,os.R_OK):
120 return filename
121 pathlist = os.getenv(pathenv,'').split(os.pathsep)
122 for path in pathlist:
123 f = os.path.join( path, filename )
124 if os.access( f, os.R_OK ):
125 return f
126 raise RuntimeError("Can't read file %s, neither locally nor in %s" % (filename, pathenv) )
127

◆ getSchema()

python.TriggerConfigAccessBase.ConfigDBLoader.getSchema ( connStr)
static
Read schema from connection string 

Definition at line 177 of file TriggerConfigAccessBase.py.

177 def getSchema(connStr):
178 ''' Read schema from connection string '''
179 if connStr.startswith("oracle:"):
180 [_, schema] = connStr.split("/")[-2:]
181 return schema
182
183 if connStr.startswith("frontier:"):
184 import re
185 pattern = r"frontier://ATLF/\‍(\‍)/(.*)"
186 m = re.match(pattern, connStr)
187 if not m:
188 raise RuntimeError("connection string '%s' doesn't match the pattern '%s'?" % (connStr, pattern))
189 (schema, ) = m.groups()
190 return schema
191
192 if connStr.startswith("sqlite_file:"):
193 raise NotImplementedError("Python-loading of trigger configuration from sqlite has not yet been implemented")
194

◆ getWriteFilename()

str python.TriggerConfigAccessBase.ConfigDBLoader.getWriteFilename ( self)

Reimplemented from python.TriggerConfigAccessBase.ConfigLoader.

Definition at line 353 of file TriggerConfigAccessBase.py.

353 def getWriteFilename(self) -> str:
354 return "{basename}_{schema}_{dbkey}.json".format(basename = self.configType.basename, schema = self.schema, dbkey = self.dbkey)
355

◆ load()

dict[str, Any] python.TriggerConfigAccessBase.ConfigDBLoader.load ( self)

Reimplemented from python.TriggerConfigAccessBase.ConfigLoader.

Definition at line 273 of file TriggerConfigAccessBase.py.

273 def load(self) -> dict[str, Any]:
274 credentials: dict[str,Any] = ConfigDBLoader.getConnectionParameters(self.dbalias)
275
276 if not credentials:
277 log.error("No TriggerDB connections found for %s", self.dbalias)
278 raise RuntimeError(f"No TriggerDB connections found for {self.dbalias}")
279
280 svc = coral.ConnectionService() # type: ignore
281 svcconfig = svc.configuration()
282 svcconfig.disablePoolAutomaticCleanUp()
283 svcconfig.setConnectionTimeOut(0)
284
285 failureMode = 0
286 for credential in credentials:
287 log.debug("Trying credentials %s",credential)
288
289 try:
290 session = svc.connect(credential, coral.access_ReadOnly) # type: ignore
291 except Exception as e:
292 log.warning("Failed to establish connection: %s",e)
293 failureMode = max(1, failureMode)
294 continue
295
296 # Check that the FRONTIER_SERVER is set properly, if not reduce the retrial period and time out values
297 if 'FRONTIER_SERVER' in os.environ and os.environ['FRONTIER_SERVER']:
298 svcconfig.setConnectionRetrialPeriod(300)
299 svcconfig.setConnectionRetrialTimeOut(3600)
300 else:
301 svcconfig.setConnectionRetrialPeriod(1)
302 svcconfig.setConnectionRetrialTimeOut(1)
303
304 try:
305 session.transaction().start(True) # readOnly
306 self.schema = ConfigDBLoader.getSchema(credential)
307 qdict = { "schema" : self.schema, "dbkey" : self.dbkey }
308
309 # Choose query based on schema
310 schemaVersion = ConfigDBLoader.readSchemaVersion(qdict, session)
311 qstr = self.getQueryDefinition(schemaVersion)
312 # execute coral query
313 query = ConfigDBLoader.getCoralQuery(session, qstr, qdict)
314 cursor = query.execute()
315
316 except Exception as e:
317 log.warning(f"DB query on {credential} failed to execute.")
318 log.warning("Exception message: %r", e)
319 failureMode = max(2, failureMode)
320 continue # to next source
321
322 # Read query result
323 if not cursor.next():
324 # empty result
325 log.warning(f"DB query on {credential} returned empty result, likely due to non-existing key {self.dbkey}")
326 failureMode = 3
327 continue # to next source
328
329 configblob = cursor.currentRow()[0].data()
330 if type(configblob) is not str:
331 configblob = configblob.readline()
332 config = json.loads(configblob)
333 session.transaction().commit()
334
335 self.confirmConfigType(config)
336 return config
337
338 if failureMode == 1:
339 log.error("TriggerDB query: could not connect to any source for %s", self.configType.basename)
340 log.error("Considered sources: %s", ", ".join(credentials))
341 raise RuntimeError("TriggerDB query: could not connect to any source", self.configType.basename)
342 if failureMode == 2:
343 log.error("Query failed due to wrong definition for %s", self.configType.basename)
344 log.error("DB query was: %s", qstr.format(**qdict))
345 raise RuntimeError("Query failed due to wrong definition", self.configType.basename)
346 elif failureMode == 3:
347 log.error("DB key %s does not exist for %s", self.dbkey, self.configType.basename)
348 raise KeyError("DB key does not exist", self.dbkey, self.configType.basename)
349 else:
350 raise RuntimeError("Query failed for unknown reason")
351
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
#define max(a, b)
Definition cfImp.cxx:41

◆ readSchemaVersion()

python.TriggerConfigAccessBase.ConfigDBLoader.readSchemaVersion ( qdict,
session )
static
Read schema version form database, based on TrigConf::TrigDBLoader::schemaVersion 

Definition at line 196 of file TriggerConfigAccessBase.py.

196 def readSchemaVersion(qdict, session):
197 ''' Read schema version form database, based on TrigConf::TrigDBLoader::schemaVersion '''
198 try:
199 q = "SELECT TS_TAG FROM {schema}.TRIGGER_SCHEMA TS"
200 query = ConfigDBLoader.getCoralQuery(session, q.format(**qdict))
201 cursor = query.execute()
202 cursor.next()
203
204 versionTag = cursor.currentRow()[0].data()
205
206 versionTagPrefix = "Trigger-Run3-Schema-v"
207 if not versionTag.startswith(versionTagPrefix):
208 raise RuntimeError( "Tag format error: Trigger schema version tag %s does not start with %s", versionTag, versionTagPrefix)
209
210 vstr = versionTag[len(versionTagPrefix):]
211
212 if not vstr.isdigit():
213 raise RuntimeError( "Invalid argument when interpreting the version part %s of schema tag %s is %s", vstr, versionTag, type(vstr))
214
215 log.debug("Found schema version %s", vstr)
216 return int(vstr)
217
218 except Exception as e:
219 log.warning("Failed to read schema version: %r", e)
220

◆ setQuery()

python.TriggerConfigAccessBase.ConfigDBLoader.setQuery ( self,
query )
query template is a dictionary of queries, identified by schema version, 
similar to TrigConf::TrigDBMenuLoader::m_hltQueries and TrigConf::TrigDBMenuLoader::m_l1Queries

Reimplemented from python.TriggerConfigAccessBase.ConfigLoader.

Definition at line 109 of file TriggerConfigAccessBase.py.

109 def setQuery(self, query):
110 """
111 query template is a dictionary of queries, identified by schema version,
112 similar to TrigConf::TrigDBMenuLoader::m_hltQueries and TrigConf::TrigDBMenuLoader::m_l1Queries
113 """
114 self.query = query
115

Member Data Documentation

◆ configType

ConfigType python.TriggerConfigAccessBase.ConfigLoader.configType = configType
inherited

Definition at line 50 of file TriggerConfigAccessBase.py.

◆ dbalias

python.TriggerConfigAccessBase.ConfigDBLoader.dbalias = dbalias

Definition at line 104 of file TriggerConfigAccessBase.py.

◆ dbkey

python.TriggerConfigAccessBase.ConfigDBLoader.dbkey = dbkey

Definition at line 105 of file TriggerConfigAccessBase.py.

◆ query

dict python.TriggerConfigAccessBase.ConfigDBLoader.query = {}

Definition at line 106 of file TriggerConfigAccessBase.py.

◆ schema

python.TriggerConfigAccessBase.ConfigDBLoader.schema = None

Definition at line 107 of file TriggerConfigAccessBase.py.


The documentation for this class was generated from the following file: