From b76c563946dcd4c1aba0ec2cbff81d54d3001ed5 Mon Sep 17 00:00:00 2001 From: Joerg Stelzer <joerg.stelzer@cern.ch> Date: Mon, 7 Sep 2020 18:00:54 +0000 Subject: [PATCH] Added Condalg to provide L1Prescales This is needed for instance for writing the xAOD trigger metadata (ATR-21373) --- .../TrigConfigSvc/python/TrigConfigSvcCfg.py | 29 +++ .../TrigConfigSvc/src/L1PrescaleCondAlg.cxx | 189 ++++++++++++++++++ .../TrigConfigSvc/src/L1PrescaleCondAlg.h | 66 ++++++ .../src/components/TrigConfigSvc_entries.cxx | 2 + 4 files changed, 286 insertions(+) create mode 100644 Trigger/TrigConfiguration/TrigConfigSvc/src/L1PrescaleCondAlg.cxx create mode 100644 Trigger/TrigConfiguration/TrigConfigSvc/src/L1PrescaleCondAlg.h diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py b/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py index 81e31ee22aa..21a01776c99 100644 --- a/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py +++ b/Trigger/TrigConfiguration/TrigConfigSvc/python/TrigConfigSvcCfg.py @@ -7,6 +7,9 @@ from AthenaConfiguration.ComponentFactory import CompFactory from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator import json +def getL1PrescaleFolderName(): + return "/TRIGGER/LVL1/Lvl1ConfigKey <tag>HEAD</tag>" + def getHLTPrescaleFolderName(): return "/TRIGGER/HLT/PrescaleKey <tag>HEAD</tag>" @@ -193,6 +196,32 @@ def TrigConfigSvcCfg( flags ): acc.addService( getHLTConfigSvc( flags ) ) return acc +def L1PrescaleCondAlgCfg( flags ): + log = logging.getLogger('TrigConfigSvcCfg') + log.info("Setting up L1PrescaleCondAlg") + from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + acc = ComponentAccumulator() + TrigConf__L1PrescaleCondAlg = CompFactory.getComp("TrigConf::L1PrescaleCondAlg") + l1PrescaleCondAlg = TrigConf__L1PrescaleCondAlg("L1PrescaleCondAlg") + + tc = getTrigConfigFromFlag( flags ) + l1PrescaleCondAlg.Source = tc["source"] + from AthenaCommon.AthenaCommonFlags import athenaCommonFlags + if athenaCommonFlags.isOnline(): + from IOVDbSvc.IOVDbSvcConfig import addFolders + acc.merge(addFolders(flags, getL1PrescaleFolderName(), "TRIGGER_ONL", className="AthenaAttributeList")) + log.info("Adding folder %s to CompAcc", getL1PrescaleFolderName() ) + if tc["source"] == "COOL": + l1PrescaleCondAlg.TriggerDB = tc["dbconn"] + elif tc["source"] == "DB": + l1PrescaleCondAlg.TriggerDB = tc["dbconn"] + l1PrescaleCondAlg.L1Psk = tc["l1psk"] + elif tc["source"] == "FILE": + l1PrescaleCondAlg.Filename = getL1PrescalesSetFileName( flags ) + else: + raise RuntimeError("trigger configuration flag 'trigConfig' starts with %s, which is not understood" % tc["source"]) + acc.addCondAlgo(l1PrescaleCondAlg) + return acc def HLTPrescaleCondAlgCfg( flags ): log = logging.getLogger('TrigConfigSvcCfg') diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/src/L1PrescaleCondAlg.cxx b/Trigger/TrigConfiguration/TrigConfigSvc/src/L1PrescaleCondAlg.cxx new file mode 100644 index 00000000000..1925d6ba680 --- /dev/null +++ b/Trigger/TrigConfiguration/TrigConfigSvc/src/L1PrescaleCondAlg.cxx @@ -0,0 +1,189 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "./L1PrescaleCondAlg.h" +#include "TrigConfIO/TrigDBL1PrescalesSetLoader.h" +#include "TrigConfIO/JsonFileLoader.h" +#include "TrigConfInterfaces/IJobOptionsSvc.h" + +#include "CoolKernel/types.h" + +#include <memory> + +TrigConf::L1PrescaleCondAlg::L1PrescaleCondAlg(const std::string& name, ISvcLocator* pSvcLocator) : + AthReentrantAlgorithm(name, pSvcLocator) +{} + + +std::shared_ptr<TrigConf::L1PrescalesSet> +TrigConf::L1PrescaleCondAlg::createFromFile( const std::string & filename ) const { + auto pss = std::make_shared<L1PrescalesSet>(); + // load the file into the L1 prescales set + ATH_MSG_DEBUG( "Setting up JsonFileLoader with file " << filename ); + TrigConf::JsonFileLoader psLoader; + psLoader.setLevel(TrigConf::MSGTC::WARNING); + ATH_MSG_DEBUG( "Going to load prescales" ); + if( psLoader.loadFile( filename, *pss) ) { + ATH_MSG_INFO( "L1 prescales set successfully loaded from file " << filename ); + } else { + ATH_MSG_WARNING( "Failed loading L1 prescales set from file " << filename ); // will be made an error later + pss = nullptr; + } + return pss; +} + + +std::shared_ptr<TrigConf::L1PrescalesSet> +TrigConf::L1PrescaleCondAlg::createFromDB( unsigned int psk, bool isRun3 ) const { + if( ! isRun3 ) { + ATH_MSG_WARNING( "Currently it is not possible to load run 2 prescale sets from the database. Will not load L1 psk " << psk ); + return nullptr; + } + auto pss = std::make_shared<L1PrescalesSet>(); + // load the L1 psk into the L1 prescales set + ATH_MSG_DEBUG( "Setting up TrigDBL1PrescalesSetLoader with DB connection " << m_dbConnection.value() ); + TrigConf::TrigDBL1PrescalesSetLoader psLoader(m_dbConnection); + psLoader.setLevel(TrigConf::MSGTC::WARNING); + ATH_MSG_DEBUG( "Going to load prescales" ); + try { + psLoader.loadL1Prescales( psk, *pss ); + } + catch(std::exception & e) { + ATH_MSG_WARNING( "Failed loading L1 prescales set from db with key " << psk ); // will be made an error later + ATH_MSG_WARNING( e.what() ); + pss = nullptr; + } + return pss; +} + + + +StatusCode +TrigConf::L1PrescaleCondAlg::initialize() { + + ATH_MSG_DEBUG("L1PrescaleCondAlg::initialize()"); + + ATH_CHECK(m_pskFolderInputKey.initialize()); + if( m_configSource == "FILE" || m_configSource == "DB" ) { + renounce( m_pskFolderInputKey ); // need to disable updates when the COOL folder changes + } + + ATH_CHECK(m_l1PrescalesSetOutputKey.initialize()); + + if( m_configSource == "COOL" && m_dbConnection == "JOSVC" ) { + if( auto joSvc = serviceLocator()->service<TrigConf::IJobOptionsSvc>( "JobOptionsSvc" ) ) { + if( joSvc->l1PrescaleKey()>0 ) { + m_psk = joSvc->l1PrescaleKey(); + m_dbConnection = joSvc->server(); + ATH_MSG_INFO("Set psk to " << m_psk << " and db connection to " << m_dbConnection ); + } + } else { + ATH_MSG_DEBUG("Did not locate TrigConf::IJobOptionsSvc"); + } + } + + ATH_MSG_INFO(m_configSource); + ATH_MSG_INFO(m_dbConnection); + ATH_MSG_INFO(m_psk); + ATH_MSG_INFO(m_filename); + + if( m_configSource == "FILE" ) { + + // index 0 indicates that the configuration is from a file, a DB + // PSK is greater than 0 + m_pssMap[0] = createFromFile( m_filename ); + + } else if( m_psk != 0u ) { + + // this is for the case where the reading from the DB was + // configured and also when we read from COOL online and get a + // PSK through the JobOptionsSvc + m_pssMap[m_psk] = createFromDB( m_psk, true ); + + } + + return StatusCode::SUCCESS; +} + +StatusCode +TrigConf::L1PrescaleCondAlg::execute(const EventContext& ctx) const { + + ATH_MSG_DEBUG("L1PrescaleCondAlg::execute with lb " << ctx.eventID().lumi_block()); + + unsigned int l1Psk = m_psk; + EventIDRange range; + + if(m_configSource == "COOL") { + // get prescale key and range from COOL + SG::ReadCondHandle<AthenaAttributeList> readH(m_pskFolderInputKey, ctx); + const AthenaAttributeList * pskAL{ *readH }; + if ( pskAL == nullptr ) { + ATH_MSG_FATAL("Null pointer to the read conditions object of " << m_pskFolderInputKey.key()); + return StatusCode::FAILURE; + } + if (not readH.range(range)) { + ATH_MSG_FATAL("Failed to retrieve validity range for " << readH.key()); + return StatusCode::FAILURE; + } else { + ATH_MSG_DEBUG("Read handle has range " << range); + } + // get the prescale key from the cool folder + l1Psk = (*pskAL)["Lvl1PrescaleConfigurationKey"].data<cool::UInt32>(); + ATH_MSG_INFO( "Extracted the L1 PSK " << l1Psk << " for run " << ctx.eventID().run_number() + << " and lb " << ctx.eventID().lumi_block() ); + } else { + + // in case of reading from DB or from FILE, the EventID range is always the full run + EventIDBase::number_type run = ctx.eventID().run_number(); + EventIDBase start, stop; + start.set_run_number(run); + start.set_lumi_block(0); + stop.set_run_number(run+1); + stop.set_lumi_block(0); + range = EventIDRange(start,stop); + + } + + std::shared_ptr<L1PrescalesSet> pss; + + if( m_configSource == "FILE" ) { + + pss = m_pssMap.at(0); + + } else if ( l1Psk != 0 ) { + + auto pssi = m_pssMap.find( l1Psk ); + + if( pssi == m_pssMap.end()) { + + bool isRun3 = range.start().run_number()>350000; + + pss = m_pssMap[l1Psk] = createFromDB( l1Psk, isRun3 ); + + } else { + + pss = pssi->second; + + } + + } else { + + ATH_MSG_ERROR( "Failed loading L1 prescales set (not reading from FILE and no psk known)" ); + return StatusCode::FAILURE; + + } + + // record L1 prescales set + SG::WriteCondHandle<TrigConf::L1PrescalesSet> writeCondHandle(m_l1PrescalesSetOutputKey, ctx); + + if( pss == nullptr ) { + ATH_MSG_INFO("Recording empty L1 prescales set with range " << range); + ATH_CHECK( writeCondHandle.record( range, new L1PrescalesSet ) ); + } else { + ATH_MSG_INFO("Recording L1 prescales set with range " << range); + ATH_CHECK( writeCondHandle.record( range, new L1PrescalesSet(*pss) ) ); + } + + return StatusCode::SUCCESS; +} diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/src/L1PrescaleCondAlg.h b/Trigger/TrigConfiguration/TrigConfigSvc/src/L1PrescaleCondAlg.h new file mode 100644 index 00000000000..ee0743d212b --- /dev/null +++ b/Trigger/TrigConfiguration/TrigConfigSvc/src/L1PrescaleCondAlg.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGCONFIGSVC__L1PRESCALECONDALG +#define TRIGCONFIGSVC__L1PRESCALECONDALG + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" + +#include "StoreGate/ReadCondHandleKey.h" +#include "StoreGate/WriteCondHandleKey.h" +#include "TrigConfData/L1PrescalesSet.h" + +#include "AthenaPoolUtilities/AthenaAttributeList.h" + +#include <tbb/concurrent_unordered_map.h> + +#include <memory> + +namespace TrigConf { + + /** + * @brief Condition algorithm to provide the L1 trigger menu + * + * The algorithm will provide the menu configuration through a conditions handle using \c TrigConf::L1Menu to present the data + * + * It is able to load the configuration in the following 3 ways + * * File-based menu description: for most test environments: for test jobs with no database involved + * * DB-based menu description where the DB keys are provided as algorithm job-properties: for reprocessing grid jobs with new menus + * * DB-based menu description where the DB keys are taken from COOL: for offline reconstruction jobs + */ + class L1PrescaleCondAlg : public AthReentrantAlgorithm { + public: + L1PrescaleCondAlg(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~L1PrescaleCondAlg() = default; + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + + private: + + // helper function to load a L1 prescales set from a file + std::shared_ptr<L1PrescalesSet> createFromFile( const std::string & filename ) const; + + // helper function to load a L1 prescales set from a prescale key + std::shared_ptr<L1PrescalesSet> createFromDB( unsigned int psk, bool isRun3 ) const; + + // map the prescale key to a L1PrescalesSet + mutable tbb::concurrent_unordered_map<unsigned int, std::shared_ptr<L1PrescalesSet>> m_pssMap; + + // input key to the L1 Prescale Key folder + SG::ReadCondHandleKey<AthenaAttributeList> m_pskFolderInputKey{ this, "PSKFolder", "/TRIGGER/LVL1/Lvl1ConfigKey", "SG Key of AthenaAttributeList containing l1 psk"}; + + // output key to store the L1PrescalesSet + SG::WriteCondHandleKey<TrigConf::L1PrescalesSet> m_l1PrescalesSetOutputKey{ this, "L1Prescales", "L1Prescales", "L1 prescales"}; + + // properties + Gaudi::Property< std::string > m_configSource { this, "Source", "FILE", "Configuration source, can be 'FILE', 'DB', or 'COOL'" }; + Gaudi::Property< std::string > m_dbConnection { this, "TriggerDB", "", "DB connection alias or 'JOSVC', used when property Source set to 'DB' or set to 'COOL'." }; + Gaudi::Property< unsigned int > m_psk { this, "L1Psk", 0, "L1 prescale key, used when property 'Source' set to 'DB'" }; + Gaudi::Property< std::string > m_filename { this, "Filename", "", "L1 prescale json file, used when property 'Source' set to 'FILE'" }; + + }; + +} +#endif diff --git a/Trigger/TrigConfiguration/TrigConfigSvc/src/components/TrigConfigSvc_entries.cxx b/Trigger/TrigConfiguration/TrigConfigSvc/src/components/TrigConfigSvc_entries.cxx index 23687473007..2a8fb252576 100644 --- a/Trigger/TrigConfiguration/TrigConfigSvc/src/components/TrigConfigSvc_entries.cxx +++ b/Trigger/TrigConfiguration/TrigConfigSvc/src/components/TrigConfigSvc_entries.cxx @@ -5,6 +5,7 @@ #include "../TrigConfJobOptionsSvc.h" #include "../TrigConfigSvc.h" +#include "../L1PrescaleCondAlg.h" #include "../HLTPrescaleCondAlg.h" DECLARE_COMPONENT( TrigConf::L1TopoConfigSvc ) @@ -14,4 +15,5 @@ DECLARE_COMPONENT( TrigConf::JobOptionsSvc ) DECLARE_COMPONENT( TrigConf::DSConfigSvc ) DECLARE_COMPONENT( TrigConf::TrigConfigSvc ) +DECLARE_COMPONENT( TrigConf::L1PrescaleCondAlg ) DECLARE_COMPONENT( TrigConf::HLTPrescaleCondAlg ) -- GitLab