ATLAS Offline Software
Loading...
Searching...
No Matches
CacheGlobalMemory.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5/**********************************************************************************
6 * @Project: TrigDecisionTool
7 * @Package: TrigDecisionTool
8 * @Class : CacheGlobalMemory
9 *
10 * @brief registry for ChainGroups
11 *
12 * @author Michael Begel <michael.begel@cern.ch> - Brookhaven National Laboratory
13 * @author Lukas Heinrich <lukas.heinrich@cern.ch> - NYU
14 *
15 ***********************************************************************************/
16
17#include <string>
18#include <vector>
19#include <iostream>
20#include <iterator>
21#include <unordered_map>
22
26
30
32
36
37#ifndef XAOD_ANALYSIS
41#endif
42
46
47#ifndef XAOD_STANDALONE
49#else
50#include "AsgMessaging/Check.h"
51#endif
52
53
54const Trig::ChainGroup* Trig::CacheGlobalMemory::createChainGroup(const std::vector< std::string >& triggerNames,
55 const std::string& alias,
56 TrigDefs::Group props) const {
57 // mutex in case this is called directly
58 std::lock_guard<std::recursive_mutex> lock(m_cgmMutex);
59 auto nc_this ATLAS_THREAD_SAFE = const_cast<Trig::CacheGlobalMemory*>(this);
60
61 // create a proper key
62 std::vector< std::string > key=Trig::keyWrap(triggerNames);
63
64 auto [itr, inserted] = m_chainGroups.try_emplace (key, /*ChainGroup*/ key, *nc_this);
65 if (inserted) {
66 nc_this->updateChainGroup(itr->second, props);
67 m_chainGroupsRef[key] = &(itr->second);
68 }
69 // this overwrites the pointer in the map each time in case the alias needs defining
70 if (!alias.empty()) {
71 std::vector< std::string > key_alias=Trig::keyWrap(Trig::convertStringToVector(alias));
72 auto [alias_itr, alias_inserted] = m_chainGroupsRef.try_emplace (key_alias, &m_chainGroups.at(key));
73 if (!alias_inserted && alias_itr->second!=m_chainGroupsRef[key]) {
74 throw std::runtime_error("TrigDecisionTool: The alias "+alias+
75 " already exists and cannot be overwritten.");
76 }
77 }
78
79 return m_chainGroupsRef[key];
80}
81
83Trig::CacheGlobalMemory::getChainGroup (const std::vector<std::string>& triggerNames,
84 TrigDefs::Group props) const
85{
86 std::lock_guard<std::recursive_mutex> lock(m_cgmMutex);
87 auto searchRes = m_chainGroupsRef.find(triggerNames);
88
89 if ( searchRes != m_chainGroupsRef.end()) {
90 return searchRes->second;
91 }
92 return createChainGroup(triggerNames, /*alias*/{}, props);
93}
94
95
96size_t
98{
99 std::lock_guard<std::recursive_mutex> lock(m_cgmMutex);
100 return m_chainGroupsRef.size();
101}
102
103
107
108
110 const TrigConf::CTPConfig* ctp) {
111 std::lock_guard<std::recursive_mutex> lock(m_cgmMutex);
112 ATH_MSG_DEBUG( "Updating configuration" );
113 // store a global reference to the initial answer
114 m_confChains = confChains;
115 if ( !ctp ) {
116 ATH_MSG_WARNING( "No LVL1 config, something went wrong, TDT will "
117 "not attempt accessing HLT too" );
118 m_confItems = nullptr;
119 return;
120 }
121 m_confItems = &(ctp->menu().items());
122
123 // rebuild all the caches with decision information
124
125 //clear cache completely because underlying config objects might have changed
126 m_itemsCache.clear();
127
128 const std::vector<float>& prescales = ctp->prescaleSet().prescales_float();
129 for(auto item : ctp->menu().items() ) {
130 const auto ctpid = item->ctpId();
131 m_itemsCache.try_emplace(ctpid,
132 /*LVL1CTP::Lvl1Item*/ item->name(), 0,
133 0, 0, 0, prescales[ctpid]);
134 ATH_MSG_DEBUG( "new configuration for item" << item->name() );
135 }
136 ATH_MSG_DEBUG( "Updating configuration, done with L1" );
137
138 //clear cache completely because underlying config objects might have changed
139 m_l2chainsCache.clear();
140 m_efchainsCache.clear();
141 m_mConfChains.clear();
142
143 if ( ! confChains ) {
144 ATH_MSG_WARNING( "No chains in configuration, probably run w/o HLT" );
145 } else {
146
147 ATH_MSG_DEBUG("Updating Configuration chains. Number of conf chains: " << m_confChains->size());
148
149 // updating internal map of conf chains (this map is only used for fast lookup)
150 for(auto ch : *m_confChains) {
151 m_mConfChains[ch->chain_name()] = ch;
152 }
153
154 // updating internal cache of HLT::Chains
155 for(auto ch : *m_confChains) {
156 // std::cerr << "CacheGlobalMemory::update updating chain" << (*cChIt)->chain_name() << std::endl;
157 int cntr = ch->chain_counter();
158 if( ch->level()=="L2" ) {
159 m_l2chainsCache.emplace(cntr, /*HLT::Chain*/ch);
160 } else {//merged chains are stored in efchains
161 m_efchainsCache.emplace(cntr, /*HLT::Chain*/ch);
162 }
163 }
164 ATH_MSG_DEBUG( "Updating configuration, done with basic HLT based on "
165 << m_confChains->size() << " configuration chains" );
166
167
168 // code for the streams and pre-defined groups
169 // -- assume that the groups and streams have all changed!!!
170 m_groups.clear();
171 m_streams.clear();
172
173 for(auto ch : *m_confChains) {
174 if (( ch->level() == "EF" || ch->level() == "HLT") && !ch->streams().empty() ) {
175 ATH_MSG_DEBUG( "Stream: " << ch->chain_name() << " " << ch->streams().size() );
176 for(auto stream : ch->streams()) {
177 ATH_MSG(DEBUG) << " " << stream->stream();
178 m_streams[stream->stream()].push_back(ch->chain_name());
179 }
180 ATH_MSG(DEBUG) << endmsg;
181 }
182 if ( ( ch->level() == "EF" || ch->level() == "HLT") && !ch->groups().empty() ) {
183 ATH_MSG_DEBUG( "Groups: " << ch->chain_name() << " " << ch->groups().size() );
184 for(auto& group : ch->groups()) {
185 ATH_MSG(DEBUG) << " " << group;
186 m_groups[group].push_back(ch->chain_name());
187 }
188 ATH_MSG(DEBUG) << endmsg;
189 }
190 }
191 }
192
193 // update all defined chainGroups
194 for (auto& [key, group] : m_chainGroups) {
195 updateChainGroup(group);
196 }
197 ATH_MSG_DEBUG( "Updating configuration done" );
198}
199
200
201const HLT::Chain* Trig::CacheGlobalMemory::chain(const std::string& name) const {
202 std::lock_guard<std::recursive_mutex> lock(m_cgmMutex);
203 auto i = m_efchainsByName.find(name);
204 if (i != m_efchainsByName.end()) {
205 return i->second;
206 }
207 i = m_l2chainsByName.find(name);
208 if ( i != m_l2chainsByName.end() ) {
209 return i->second;
210 }
211 return nullptr;
212}
213
215 return chain(ch.chain_name());
216}
217
218const TrigConf::HLTChain* Trig::CacheGlobalMemory::config_chain(const std::string& name) const {
219 ChainHashMap_t::const_iterator f = m_mConfChains.find(name);
220 if ( f == m_mConfChains.end() ){
221 return nullptr;
222 }
223 return f->second;
224}
225
227 explicit itemByName(const std::string& name) : m_name(name) {}
228 bool operator() (const TrigConf::TriggerItem* it) {
229 return m_name == it->name();
230 }
231 const std::string & m_name;
232};
233
234const TrigConf::TriggerItem* Trig::CacheGlobalMemory::config_item(const std::string& name) const {
235 TrigConf::ItemContainer::const_iterator f = find_if(m_confItems->begin(), m_confItems->end(), itemByName(name));
236 if ( f == m_confItems->end() )
237 return nullptr;
238 return *f;
239}
240
242 // Cannot be locked (CacheGlobalMemory::update > createChainGroup > ChainGroup::update > calculatePrescale > L1Prescale > CacheGlobalMemory::item_prescale)
243 // find items in cache
244 if ( m_itemsCache.count(ctpid) == 0 ) {
245 ATH_MSG_ERROR( "item of CTP: " << ctpid
246 << " is not present in the configuration" );
247 return 0;
248 }
249 return m_itemsCache.find(ctpid)->second.prescaleFactor();
250}
251
253 return item(i.name());
254 // unsigned cntr = i.ctpId();
255 // if ( m_items.find(cntr) != m_items.end())
256 // return m_items.find(cntr)->second;
257 // return 0;
258}
259
260const LVL1CTP::Lvl1Item* Trig::CacheGlobalMemory::item(const std::string& name) const {
261 if ( m_itemsByName.find(name) != m_itemsByName.end())
262 return m_itemsByName.find(name)->second;
263 return nullptr;
264}
265
267 std::lock_guard<std::recursive_mutex> lock(m_cgmMutex);
268 ATH_MSG_VERBOSE("asserting decision with unpacker " << m_unpacker.get());
269
270 // here we unpack the decision. Note: the navigation will be unpacked only on demand (see navigation())
271 bool contains_xAOD_decision = false;
272
273#ifndef XAOD_ANALYSIS // Full Athena
274 bool is_l1result_configured = false;
275 bool contains_decision = false;
276 bool contains_old_event_info = false;
277#endif
278
279 const EventContext& context = Gaudi::Hive::currentContext();
280 if(!m_unpacker){
281 ATH_MSG_INFO("decision not set on first (?) assert. deciding how to unpack");
282
283 //Lukas 26-06-2015: we're hard coding the configuration for now
284 //but we have setters and getters for m_trigDecisionKey (as CGM datamemer)
285 //so we could in the future use the ones set by the python configuration
286 //we're hardcoding in order not to require python configuration changes
287
288 if (!m_decisionKeyPtr->empty()) {
290 contains_xAOD_decision = decisionReadHandle.isValid();
291 }
292
293#ifndef XAOD_ANALYSIS // Full Athena
294
295 if (!m_oldDecisionKeyPtr->empty()) {
297 contains_decision = oldDecisionReadHandle.isValid();
298 if (contains_decision) {
299 is_l1result_configured = oldDecisionReadHandle->getL1Result().isConfigured();
300 }
301 }
302
303 if (!m_oldEventInfoKeyPtr->empty()) {
304 SG::ReadHandle<EventInfo> oldEventInfoHandle = SG::makeHandle(*m_oldEventInfoKeyPtr, context);
305 contains_old_event_info = oldEventInfoHandle.isValid();
306 }
307
308 // January 2020: Note, switched the order here. DecisionUnpackerStandalone is given preference
309 // over DecisionUnpackerAthena
310 if ( contains_xAOD_decision ){
311 ATH_MSG_INFO("SG contains xAOD decision, use DecisionUnpackerStandalone");
312 m_unpacker = std::make_unique<DecisionUnpackerStandalone>
315 }
316 else if( is_l1result_configured ){
317 ATH_MSG_INFO("SG contains AOD decision, use DecisionUnpackerAthena");
318 m_unpacker = std::make_unique<DecisionUnpackerAthena>(CxxUtils::as_const_ptr(m_oldDecisionKeyPtr));
319 }
320 else if (contains_old_event_info) {
321 ATH_MSG_INFO("SG contains NO(!) L1Result in the AOD TrigDecision, assuming also no HLTResult. Read from EventInfo");
322 m_unpacker = std::make_unique<DecisionUnpackerEventInfo>(CxxUtils::as_const_ptr(m_oldEventInfoKeyPtr));
323 }
324#else
325 if ( contains_xAOD_decision ){
326 ATH_MSG_INFO("SG contains xAOD decision, use DecisionUnpackerStandalone");
327 m_unpacker = std::make_unique<DecisionUnpackerStandalone>(m_decisionKeyPtr, m_run2NavigationKeyPtr);
328 }
329#endif
330
331 }//if(!m_unpacker)
332
333 // cppcheck-suppress duplicateCondition
334 if(!m_unpacker){
335 std::stringstream extra;
336#ifndef XAOD_ANALYSIS // Full Athena
337 extra << ". Looked for old TrigDec::TrigDecision? "
338 << (m_oldDecisionKeyPtr->empty() ? "NO" : "YES")
339 << ", has TrigDec::TrigDecision? "
340 << (contains_decision ? "YES" : "NO")
341 << ", TrigDec::TrigDecision has L1? "
342 << (is_l1result_configured ? "YES" : "NO")
343 << ". Looked for old EventInfo? "
344 << (m_oldEventInfoKeyPtr->empty() ? "NO" : "YES")
345 << ", has old EventInto? "
346 << (contains_old_event_info ? "YES" : "NO");
347#endif
348 ATH_MSG_ERROR("No source of Trigger Decision in file. "
349 << "(Looked for xAOD::TrigDecision? "
350 << (m_decisionKeyPtr->empty() ? "NO" : "YES")
351 << ", has xAOD::TrigDecision? "
352 << (contains_xAOD_decision ? "YES" : "NO")
353 << extra.str()
354 << ". Check UseRun1DecisionFormat and UseOldEventInfoDecisionFormat flags if reading pre-xAOD or BS input).");
355 throw std::runtime_error("Trig::CacheGlobalMemory::assert_decision(): No source of Trigger Decision in file.");
356 }
357
358 if( !m_decisionUnpacked ) {
359 // this method is locked
360 auto nc_this ATLAS_THREAD_SAFE = const_cast<Trig::CacheGlobalMemory*>(this);
361 if( nc_this->unpackDecision(context).isFailure() ) {
362 ATH_MSG_WARNING( "TrigDecion object incorrect (for chains)" );
363 }
364 else{
365 ATH_MSG_VERBOSE("unpacked decision");
366 }
367 }
368
369 return true;
370}
371
376
377StatusCode Trig::CacheGlobalMemory::unpackDecision(const EventContext& ctx) {
378 // locked already through assert_decision
379
380 ATH_MSG_DEBUG("Unpacking TrigDecision");
381 m_decisionUnpacked = true;
382 m_deleteAtEndOfEvent.clear();
383
384 bool unpackHLT = ( m_confChains != nullptr );
385 ATH_CHECK( m_unpacker->unpackDecision( ctx, m_itemsByName, m_itemsCache,
388 m_bgCode, unpackHLT ) );
389 return StatusCode::SUCCESS;
390}
391
392
394 std::lock_guard<std::recursive_mutex> lock(m_cgmMutex);
395
397
398 // Navigation
399 // protect from unpacking in case HLT was not run
400 // (i.e. configuration chains are 0)
401 if( m_confChains == nullptr ) {
402 return StatusCode::SUCCESS;
403 }
404
405 // Failing to unpack the navigation is not a failure, as it may be missing
406 // from the xAOD file:
407 const EventContext& context = Gaudi::Hive::currentContext();
408 if( ! m_unpacker->unpackNavigation( context, m_navigation ).isSuccess() ) {
409 [[maybe_unused]] static std::atomic<bool> warningPrinted =
410 [&]() { ATH_MSG_WARNING( "TrigNavigation unpacking failed" );
411 return true; }();
412 }
413 // Return gracefully:
414 return StatusCode::SUCCESS;
415}
416
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG(lvl)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
Helper for getting a const version of a pointer.
Define macros for attributes used to control the static checker.
This class represents one chain of signatures, i.e.
Definition Chain.h:64
virtual bool isValid() override final
Can the handle be successfully dereferenced?
list of all HLT chains in a trigger menu
HLT chain configuration information.
char m_bgCode
the encoded bunchgroup information
std::recursive_mutex m_cgmMutex
R3 MT protection only against –threads > 1.
std::unordered_map< std::string, const HLT::Chain * > m_efchainsByName
L2 chains keyed by chain name (chainging every event)
StatusCode unpackNavigation()
unpacks HLT navigation structure (object access)
std::map< CTPID, LVL1CTP::Lvl1Item > m_itemsCache
cache of all CTP items possible (given configuration)
ChainHashMap_t m_mConfChains
map of conf chains
const LVL1CTP::Lvl1Item * item(const std::string &name) const
CTP item from given name.
SG::ReadHandleKey< TrigDec::TrigDecision > * m_oldDecisionKeyPtr
Parent TDT's read handle key.
bool m_decisionUnpacked
Was decision unpacked for this event?
const TrigConf::HLTChain * config_chain(const std::string &name) const
HLT config chain from given name.
bool assert_decision() const
checks if new event arrived with the decision Need to use before any call to CacheGlobalMemory.
const Trig::ChainGroup * getChainGroup(const std::vector< std::string > &triggerNames, TrigDefs::Group props) const
std::unordered_map< std::string, const HLT::Chain * > m_l2chainsByName
L2 chains keyed by chain name (chainging every event)
const HLT::Chain * chain(const std::string &name) const
HLT chain object from given name (0 pointer returned if no match)
const TrigConf::ItemContainer * m_confItems
items configuration
const Trig::ChainGroup * createChainGroup(const std::vector< std::string > &patterns, const std::string &alias="", TrigDefs::Group props=TrigDefs::Group::Default) const
creates new chain group
bool m_navigationUnpacked
Was navigation unpacked for this event?
void updateChainGroup(Trig::ChainGroup &chainGroup, TrigDefs::Group props=TrigDefs::Group::Default)
unpacks everything that belongs to a ChainGroup
std::map< CHAIN_COUNTER, HLT::Chain > m_efchainsCache
cache of all EF chains possible (given configuration)
StatusCode unpackDecision(const EventContext &ctx)
unpacks whole trigger decision for the event
const TrigConf::HLTChainList * m_confChains
all chains configuration
std::map< std::string, std::vector< std::string > > m_groups
mapping from group to list of chains
std::map< std::string, std::vector< std::string > > m_streams
mapping from stream to list of chains
SG::ReadHandleKey< xAOD::TrigDecision > * m_decisionKeyPtr
Parent TDT's read handle key.
const TrigConf::TriggerItem * config_item(const std::string &name) const
CTP config item from given name.
HLT::TrigNavStructure * m_navigation
Navigation owned by CGM.
void update(const TrigConf::HLTChainList *confChains, const TrigConf::CTPConfig *ctp)
Updates configuration of the chain groups (i.e.
SG::ReadHandleKey< xAOD::TrigNavigation > * m_run2NavigationKeyPtr
Parent TDT's read handle key.
std::unique_ptr< IDecisionUnpacker > m_unpacker ATLAS_THREAD_SAFE
Trigger decision unpacker helper.
std::map< CHAIN_COUNTER, HLT::Chain > m_l2chainsCache
cache of all L2 chains possible (given configuration)
float item_prescale(int ctpid) const
Prescale for CPT item.
std::unordered_map< std::string, const LVL1CTP::Lvl1Item * > m_itemsByName
items keyed by configuration name (chainging every event)
SG::ReadHandleKey< EventInfo > * m_oldEventInfoKeyPtr
Parent TDT's read handle key.
void reset_decision()
invalidate previously unpacked decision Needs to be called at the start of a new event.
void update(const TrigConf::HLTChainList *confChains, const TrigConf::ItemContainer *confItems, TrigDefs::Group prop=TrigDefs::Group::Default)
const T * as_const_ptr(const T *p)
Helper for getting a const version of a pointer.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Group
Properties of a chain group.
std::vector< std::string > convertStringToVector(const std::string &triggerNames)
makes a split of list of chains into the vector of chains
std::vector< std::string > keyWrap(const std::vector< std::string > &triggerNames)
normalizes the list of triggers (patterns) by sorting and uniquing them
#define DEBUG
Definition page_access.h:11
itemByName(const std::string &name)
const std::string & m_name