diff --git a/Database/IOVDbSvc/python/CondDB.py b/Database/IOVDbSvc/python/CondDB.py new file mode 100644 index 0000000000000000000000000000000000000000..013066b510b1807d0e40a2ee8bcde035cce4e994 --- /dev/null +++ b/Database/IOVDbSvc/python/CondDB.py @@ -0,0 +1,437 @@ +# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration + +# CondDB.py +# Configuration for Athena conditions DB access +# usage: +# from IOVDbSvc.CondDB import conddb +# then add folders with +# conddb.addFolder('INDET','/Indet/Align') +# conddb.addFolder('INDET,'/Indet/Align <tag>my_explicit_tag</tag>') or +# conddb.addFolderWithTag('INDET','/Indet/Align','my_explicit_tag') +# conddb.addFolderSplitOnline('INDET','/Indet/OnlineF','/Indet/OfflineF') +# conddb.addFolderSplitMC('INDET','/Indet/DataFolder','/Indet/MCFolder') +# override a tag with +# conddb.addOverride('/Indet/Align','override_tag_value') +# block a folder from being added later +# conddb.blockFolder('/Indet/Align') +# add a folder even though blocked +# conddb.addFolder('INDET','/Indet/Align',True) +# conddb.addFolderWithTag('INDET','/Indet/Align','my_explicit_tag',True) +# add markup (additional XML) to existing folder specifications +# conddb.addMarkup('/Indet/Align','<channelSelection>1:3</channelSelection>') +# +# If the className argument is provided to addFolder, then also register +# with CondInputLoader. + +import os + +from AthenaCommon.AppMgr import ServiceMgr as svcMgr +from IOVSvc.IOVSvcConf import CondSvc +from IOVSvc.IOVSvcConf import CondInputLoader +from AthenaServices.AthenaServicesConf import Athena__ConditionsCleanerSvc +from AthenaServices.AthenaServicesConf import Athena__DelayedConditionsCleanerSvc +from AthenaCommon.AlgSequence import AthSequencer +from AthenaCommon.ConcurrencyFlags import jobproperties as jp + + +svcMgr += CondSvc() + +condSeq = AthSequencer("AthCondSeq") +if not hasattr(condSeq, "CondInputLoader"): + condInputLoader = CondInputLoader( "CondInputLoader") + # We always want CondInputLoader to be first in the condSeq + # for serial running + condSeq.insert(0, condInputLoader) +else: + condInputLoader = condSeq.CondInputLoader + +# Enable conditions garbage collection. +nConcurrentEvents = max(1,jp.ConcurrencyFlags.NumConcurrentEvents()) +cleaner = Athena__DelayedConditionsCleanerSvc(RingSize = 2*nConcurrentEvents) +svcMgr += cleaner +svcMgr += Athena__ConditionsCleanerSvc (CleanerSvc = cleaner) + +class CondDB: + "Class to hold configuration information for Athena conditions DB access" + def __init__(self,doOldStyleConfig=False): + "Setup conditions DB - IOVDbSvc and connections according to GlobalFlags" + from AthenaCommon.AppMgr import ServiceMgr as svcMgr + from AthenaCommon.Logging import logging + self.msg = logging.getLogger( 'IOVDbSvc.CondDB' ) + self.msg.debug("Loading basic services for CondDBSetup...") + + # AthenaPool and IOVDbSvc configuration + from AthenaPoolCnvSvc import AthenaPool # noqa: F401 + from IOVDbSvc import IOVDb # noqa: F401 + # local access to IOVDbSvc parameters + self.iovdbsvc=svcMgr.IOVDbSvc + + # initialise list of allowed DBs + self.dblist={} + # and list of blocked folders + self.blocklist=[] + + # decide which instance to setup + # default database + self.dbname='' + # names for MC and data database in case forceMC/forceData are used + self.dbmc='' + self.dbdata='' + self.poolcats=[] + from AthenaCommon.GlobalFlags import globalflags + from AthenaCommon.AthenaCommonFlags import athenaCommonFlags + self.isOnline=athenaCommonFlags.isOnline() + self.isMC=not globalflags.DataSource()=='data' + if (globalflags.DetGeo() in ['atlas','commis']): + # ATLAS full or commissioning geometry + self.dbmc='OFLP200' + self.dbdata=globalflags.DatabaseInstance() #could be 'auto' + if self.isMC: + # Monte Carlo + self.dbname=self.dbmc + self.poolcats=['oflcond'] + else: + # real data + if (self.dbdata=='auto'): + project_name = '' + if athenaCommonFlags.FilesInput(): + from PyUtils.MetaReader import read_metadata + metadata = read_metadata(athenaCommonFlags.FilesInput()) + project_name = metadata[athenaCommonFlags.FilesInput()[0]]['project_name'] + + self.dbdata=self._InstanceFromProjectName(project_name) + self.msg.info("Configuring database instance '%s' based on project tag '%s'", self.dbdata, project_name) + self.dbname=self.dbdata + self.poolcats=['comcond','oflcond'] + elif (globalflags.DetGeo() in ['ctbh8','ctbh6']): + self.dbmc='TMCP200' + self.dbdata='TBDP200' + if self.isMC: + # 2004 combined testbeam, Monte Carlo + self.dbname=self.dbmc + self.poolcats=['tbcond','oflcond'] + else: + # 2004 combined testbeam, real data + self.dbname=self.dbdata + self.poolcats=['tbcond','oflcond'] + else: + raise RuntimeError("Unknown globalflags.DetGeo: %s" % globalflags.DetGeo()) + if (self.dbname!=''): + self.msg.info('Setting up conditions DB access to instance %s', self.dbname) + # set up all access options - online schemas + self._SetAcc('INDET','COOLONL_INDET') + self._SetAcc('INDET_ONL','COOLONL_INDET') + self._SetAcc('PIXEL','COOLONL_PIXEL') + self._SetAcc('PIXEL_ONL','COOLONL_PIXEL') + self._SetAcc('SCT','COOLONL_SCT') + self._SetAcc('SCT_ONL','COOLONL_SCT') + self._SetAcc('TRT','COOLONL_TRT') + self._SetAcc('TRT_ONL','COOLONL_TRT') + self._SetAcc('LAR','COOLONL_LAR') + self._SetAcc('LAR_ONL','COOLONL_LAR') + self._SetAcc('TILE','COOLONL_TILE') + self._SetAcc('TILE_ONL','COOLONL_TILE') + self._SetAcc('MUON','COOLONL_MUON') + self._SetAcc('MUON_ONL','COOLONL_MUON') + self._SetAcc('MUONALIGN','COOLONL_MUONALIGN') + self._SetAcc('MUONALIGN_ONL','COOLONL_MUONALIGN') + self._SetAcc('MDT','COOLONL_MDT') + self._SetAcc('MDT_ONL','COOLONL_MDT') + self._SetAcc('RPC','COOLONL_RPC') + self._SetAcc('RPC_ONL','COOLONL_RPC') + self._SetAcc('TGC','COOLONL_TGC') + self._SetAcc('TGC_ONL','COOLONL_TGC') + self._SetAcc('CSC','COOLONL_CSC') + self._SetAcc('CSC_ONL','COOLONL_CSC') + self._SetAcc('TDAQ','COOLONL_TDAQ') + self._SetAcc('TDAQ_ONL','COOLONL_TDAQ') + self._SetAcc('GLOBAL','COOLONL_GLOBAL') + self._SetAcc('GLOBAL_ONL','COOLONL_GLOBAL') + self._SetAcc('TRIGGER','COOLONL_TRIGGER') + self._SetAcc('TRIGGER_ONL','COOLONL_TRIGGER') + self._SetAcc('CALO','COOLONL_CALO') + self._SetAcc('CALO_ONL','COOLONL_CALO') + self._SetAcc('FWD','COOLONL_FWD') + self._SetAcc('FWD_ONL','COOLONL_FWD') + # set up all access options - offline schemas + # only do this if isOnline flag is NOT set + # or MC flag is set, to allow HLT testing using MC database + if (self.isMC or not self.isOnline): + self._SetAcc('INDET_OFL','COOLOFL_INDET') + self._SetAcc('PIXEL_OFL','COOLOFL_PIXEL') + self._SetAcc('SCT_OFL','COOLOFL_SCT') + self._SetAcc('TRT_OFL','COOLOFL_TRT') + self._SetAcc('LAR_OFL','COOLOFL_LAR') + self._SetAcc('TILE_OFL','COOLOFL_TILE') + self._SetAcc('MUON_OFL','COOLOFL_MUON') + self._SetAcc('MUONALIGN_OFL','COOLOFL_MUONALIGN') + self._SetAcc('MDT_OFL','COOLOFL_MDT') + self._SetAcc('RPC_OFL','COOLOFL_RPC') + self._SetAcc('TGC_OFL','COOLOFL_TGC') + self._SetAcc('CSC_OFL','COOLOFL_CSC') + self._SetAcc('TDAQ_OFL','COOLOFL_TDAQ') + self._SetAcc('DCS_OFL','COOLOFL_DCS') + self._SetAcc('GLOBAL_OFL','COOLOFL_GLOBAL') + self._SetAcc('TRIGGER_OFL','COOLOFL_TRIGGER') + self._SetAcc('CALO_OFL','COOLOFL_CALO') + self._SetAcc('FWD_OFL','COOLOFL_FWD') + else: + self.msg.info('Running in online mode - no access to COOLOFL schemas') + self.iovdbsvc.OnlineMode=True + + # setup default connection to localfile, and put in LOCAL symbol + localfile="sqlite://;schema=mycool.db;dbname=" + self.dblist['LOCAL']=localfile + self.iovdbsvc.dbConnection=localfile+self.dbname + + # setup knowledge of dbinstance in IOVDbSvc, for global tag x-check + self.iovdbsvc.DBInstance=self.dbname + + + # setup DBReplicaSvc to veto DBRelease SQLite files if real data + if not self.isMC: + from DBReplicaSvc.DBReplicaSvcConf import DBReplicaSvc + svcMgr+=DBReplicaSvc(COOLSQLiteVetoPattern="/DBRelease/") + + # enable Frontier cache alignment if it looks like Frontier will + # be used (via FRONTIER_SERVER variable) + # but not for HLT (ATR-4646) + if 'FRONTIER_SERVER' in os.environ.keys() and os.environ['FRONTIER_SERVER']!="" and not self.isOnline: + self.iovdbsvc.CacheAlign=3 + + # setup PoolSvc catalogues + from PoolSvc.PoolSvcConf import PoolSvc + if not hasattr (svcMgr, 'PoolSvc'): + svcMgr+=PoolSvc() + # add the standard catalogues + # Set entries which will be resolved using ATLAS_POOLCOND_PATH + # (if set) - the actual resolution is done inside PoolSvc C++ + for i in self.poolcats: + svcMgr.PoolSvc.ReadCatalog+=["apcfile:poolcond/PoolCat_%s.xml" % i] + svcMgr.PoolSvc.ReadCatalog+=["apcfile:poolcond/PoolFileCatalog.xml"] + else: + raise RuntimeError('Not enough configuration information to setup ConditionsDB access (are GlobalFlags being used?)') + self.msg.debug("Loading basic services for CondDBSetup... [DONE]") + + def addFolder(self,ident,folder,force=False,forceMC=False,forceData=False, + className=None,extensible=False): + """Add access to the given folder, in the identified subdetector schema. +If EXTENSIBLE is set, then if we access an open-ended IOV at the end of the list, +the end time for this range will be set to just past the current event. +Subsequent accesses will update this end time for subsequent events. +This allows the possibility of later adding a new IOV using IOVSvc::setRange.""" + # first check if access to this folder was blocked, unless forcing + for block in self.blocklist: + if (folder.find(block)>=0 and not force): return + folderadd='' + # now check if ident is defined, and add folder + if (ident in self.dblist.keys()): + folderadd="<db>%s%s</db> %s" % (self.dblist[ident],self._GetName(forceMC,forceData),folder) + elif (ident==''): + folderadd=folder + elif (ident.find('.')>0): + # interpret the identifier as a filename for SQLite file + folderadd='<db>sqlite://;schema=%s;dbname=%s</db> %s' % (ident,self._GetName(forceMC,forceData),folder) + else: + raise RuntimeError("Conditions database identifier %s is not defined" % ident) + if extensible: + folderadd = folderadd + '<extensible/>' + + self.iovdbsvc.Folders+=[folderadd] + + if className: + key = (className, self.extractFolder(folder)) + if key not in condInputLoader.Load: + condInputLoader.Load.add(key) + + def addFolderWithTag(self,ident,folder,tag,force=False,forceMC=False,forceData=False,className=None): + "Add access to the given folder/schema, using a specified tag" + self.addFolder(ident,folder+" <tag>%s</tag>" % tag,force,forceMC,forceData,className=className) + + def addFolderSplitOnline(self,ident,folder1,folder2,force=False,forceMC=False,forceData=False, + className=None,extensible=False): + "Add access to given folder, using folder1 online, folder2 offline" + if self.isOnline and not self.isMC: + self.addFolder(ident,folder1,force=force,forceMC=forceMC,forceData=forceData, + className=className,extensible=extensible) + return folder1 + else: + self.addFolder(ident+'_OFL',folder2,force=force,forceMC=forceMC,forceData=forceData, + className=className,extensible=extensible) + return folder2 + + def addFolderSplitMC(self,ident,folder1,folder2,force=False,forceMC=False,forceData=False,className=None): + "Add access to given folder, using folder1 (online) for real data, folde2 (offline) for MC" + if self.isMC: + self.addFolder(ident+'_OFL',folder2,force=force,forceMC=forceMC,forceData=forceData,className=className) + else: + self.addFolder(ident,folder1,force=force,forceMC=forceMC,forceData=forceData,className=className) + + def addOverride(self,folder,tag): + "Add a tag override for the specified folder" + overrideDirective = '<prefix>%s</prefix> <tag>%s</tag>' % (folder,tag) + if overrideDirective not in self.iovdbsvc.overrideTags: + self.iovdbsvc.overrideTags+=[overrideDirective] + + def blockFolder(self,folder): + "Block use of specified conditions DB folder so data can be read from elsewhere" + self.blocklist+=[folder] + # check existing list of folders and remove it if found + for i in range(0,len(self.iovdbsvc.Folders)): + if (self.iovdbsvc.Folders[i].find(folder)>=0): + del self.iovdbsvc.Folders[i] + break + + folderName = self.extractFolder(folder) + for f in condInputLoader.Load: + if (f[-1] == folderName): + condInputLoader.Load.remove(f) # OK since we break after this + break + + def folderRequested(self,folder): + "Return true if the given folder has already been requested" + for i in self.iovdbsvc.Folders: + if (i.find(folder)>=0): return True + return False + + def addMarkup(self,folder,markup): + "Add given XML markup to folder string for given folder" + nmod=0 + for i in range(0,len(self.iovdbsvc.Folders)): + if (self.iovdbsvc.Folders[i].find(folder)>=0): + self.iovdbsvc.Folders[i]+=markup + nmod+=1 + if (nmod==0): + raise RuntimeError("conddb.addMarkup: Folder %s is not known to IOVDbSvc" % folder) + + + def setGlobalTag(self,tag): + "Set the GlobalTag value used as the key for hierarhical conditions" + self.iovdbsvc.GlobalTag=tag + + + def setRequireLock(self,lock=True): + "Set the flag indicating global tags will be required to be locked" + self.iovdbsvc.CheckLock=lock + + def setWriteDataToFile(self, writeData=False): + "Set option to write data to file" + self.iovdbsvc.OutputToFile=writeData + + def setCrestToFile(self, crestData=False): + "Set option to write CREST data to file" + self.iovdbsvc.CrestToFile=crestData + + + def extractFolder(self,folderstr): + "Extract the folder name (non-XML text) from a IOVDbSvc.Folders entry" + fname="" + xmltag="" + ix=0 + while ix<len(folderstr): + if (folderstr[ix]=='<' and xmltag==""): + ix2=folderstr.find('>',ix) + if (ix2!=-1): + xmltag=(folderstr[ix+1:ix2]).strip() + ix=ix2+1 + if xmltag[-1] == '/': + xmltag="" + ix=ix+1 + elif (folderstr[ix:ix+2]=='</' and xmltag!=""): + ix2=folderstr.find('>',ix) + if (ix2!=-1): + xmltag="" + ix=ix2+1 + else: + ix2=folderstr.find('<',ix) + if ix2==-1: ix2=len(folderstr) + if (xmltag==""): fname=fname+folderstr[ix:ix2] + ix=ix2 + return fname.strip() + + + def dumpFolderTags(self,outfile,folderNames=False,folderOrigin=False): + "Write out folder-specific tag names to file, for use with AtlCoolCopy tools" + ofile=open(outfile,'w') + for folderstr in self.iovdbsvc.Folders: + # extract tag specifications and write in file + if (folderNames): + # also extract the name of the folder - all non-XML text + fname=self.extractFolder(folderstr) + if (fname!=""): + dbtype="" + # find the database schema and insert :ONL or :OFL + if (folderOrigin): + if '<db>' in folderstr: + idx1=folderstr.find('<db>')+4 + idx2=folderstr.find('</db>') + if (idx2>0): + dbname=folderstr[idx1:idx2].strip() + if 'ONL' in dbname: + dbtype=':ONL' + elif 'OFL' in dbname: + dbtype=':OFL' + ofile.write('--folder %s%s\n' % (fname,dbtype)) + if '<tag>' in folderstr: + idx1=folderstr.find('<tag>')+5 + idx2=folderstr.find('</tag>') + if (idx2>0): + tag=folderstr[idx1:idx2].strip() + # do not write out TagInfo magic tags, except when giving + # folderOrigin + if ((tag.find('TagInfo')!=0 and tag!='HEAD') or folderOrigin): + ofile.write('--tag %s\n' % tag) + # also extract any special tag names from overrideTags list + for folderstr in self.iovdbsvc.overrideTags: + # extract tag specifications and write in file + if '<tag>' in folderstr: + idx1=folderstr.find('<tag>')+5 + idx2=folderstr.find('</tag>') + if (idx2>0): + tag=folderstr[idx1:idx2].strip() + # do not write out TagInfo magic tags + if (tag.find('TagInfo')!=0 and tag!='HEAD'): + ofile.write('--tag %s\n' % tag) + ofile.close() + + def dumpFolderReadReal(self,outfile): + "Dump configuration information for use in ReadReal in AthenaDBTestRec" + ofile=open(outfile,'w') + ofile.write('FolderList=%s\n' % self.iovdbsvc.Folders.__repr__()) + ofile.close() + + def GetInstance(self,forceMC=False,forceData=False): + "Get the name of the DB instance in use (e.g. OFLP200)" + return self._GetName(forceMC,forceData) + + + def _SetAcc(self,ident,schema): + "Internal helper function to setup database access string" + self.dblist[ident]="%s/" % schema + + def _GetName(self,forceMC,forceData): + "Internal get db instance name, taking into account forceData/MC flags" + if forceMC: + return self.dbmc + elif forceData: + return self.dbdata + else: + return self.dbname + + #decide database instance based on project tag dataXX_ + def _InstanceFromProjectName(self,projectName): + try: + year=int(projectName[4:6]) + except Exception: + self.msg.warning(f"Failed to extract year from project tag '{projectName}', using CONDBR2.") + return "CONDBR2" + + if (year>13): + return "CONDBR2" + else: + return "COMP200" + + +# make instance for use +# false indicates no backward compatibility objects +conddb=CondDB(False) diff --git a/Database/IOVDbSvc/python/IOVDb.py b/Database/IOVDbSvc/python/IOVDb.py new file mode 100644 index 0000000000000000000000000000000000000000..dd3384b2604cda0dfe93918a658312593616d7a4 --- /dev/null +++ b/Database/IOVDbSvc/python/IOVDb.py @@ -0,0 +1,55 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + +## @file IOVDb.py +## @brief Core job python configurable to setup IOVDbSvc +## @author RD Schaffer <R.D.Schaffer@cern.ch> +############################################################### +# +# The core jobOptions for IOVDbSvc +# Setup the basic sercives +# +#============================================================== +# +# Required libs: + +def _loadBasicIOVDb(): + """Loads the basic services for IOVDbSvc""" + + ## make sure we have been -at least- minimally correctly configured + import AthenaCommon.AtlasUnixStandardJob # noqa: F401 + + from AthenaCommon.Logging import logging + from AthenaCommon.AppMgr import ServiceMgr as svcMgr + + msg = logging.getLogger( 'loadBasicIOVDb' ) + msg.debug( "Loading basic services for IOVDbSvc..." ) + + # Load IOVDbSvc + from IOVDbSvc.IOVDbSvcConf import IOVDbSvc + svcMgr += IOVDbSvc() + + # Set IOVDbSvc as proxy provider + from AthenaCommon.ConfigurableDb import getConfigurable + if not hasattr (svcMgr, 'ProxyProviderSvc'): + svcMgr += getConfigurable("ProxyProviderSvc")() + svcMgr.ProxyProviderSvc.ProviderNames += [ "IOVDbSvc" ] + + # Load IOVSvc + from IOVSvc.IOVSvcConf import IOVSvc + svcMgr += IOVSvc() + + # Load EventInfoMgt + import EventInfoMgt.EventInfoMgtInit # noqa: F401 + + # add in /TagInfo to be read from File meta data + svcMgr.IOVDbSvc.Folders+=["/TagInfo<metaOnly/>"] + + msg.debug( "Loading basic services for IOVDb... [DONE]" ) + return + +## load basic services configuration at module import +_loadBasicIOVDb() + +## clean-up: avoid running multiple times this method +del _loadBasicIOVDb +