6#include <boost/core/demangle.hpp>
7#include <boost/algorithm/string.hpp>
8#include "Gaudi/Interfaces/IOptionsSvc.h"
9#include "GaudiKernel/IToolSvc.h"
10#include "GaudiKernel/System.h"
29 constexpr uint16_t fullResultTruncationID = std::numeric_limits<uint16_t>::max();
33 const std::string& name,
34 const IInterface* parent )
35 : base_class(
type, name, parent ) {}
51 auto jobOptionsSvc = service<Gaudi::Interfaces::IOptionsSvc>(
"JobOptionsSvc",
false);
52 if (!jobOptionsSvc.isValid()) {
53 ATH_MSG_WARNING(
"Could not retrieve JobOptionsSvc, will not update the EventSizeHardLimitMB property");
56 if (jobOptionsSvc->has(
"DataFlowConfig.DF_MaxEventSizeMB")) {
57 if (
m_eventSizeHardLimitMB.fromString(jobOptionsSvc->get(
"DataFlowConfig.DF_MaxEventSizeMB")).isSuccess()) {
59 <<
" from DataFlowConfig.DF_MaxEventSizeMB");
62 ATH_MSG_ERROR(
"Could not convert DataFlowConfig.DF_MaxEventSizeMB to integer. Leaving EventSizeHardLimitMB="
67 ATH_MSG_DEBUG(
"Could not retrieve DataFlowConfig.DF_MaxEventSizeMB from JobOptionsSvc. This is fine if running "
68 <<
"offline, but should not happen online. Leaving EventSizeHardLimitMB="
77 return StatusCode::FAILURE;
86 return StatusCode::SUCCESS;
93 std::vector<std::string> def;
94 boost::split( def, typeKeyAuxIDs, boost::is_any_of(
";") );
96 if ( def.size() < 2 ) {
97 ATH_MSG_ERROR(
"Invalid EDM collection specification: " << typeKeyAuxIDs);
98 return StatusCode::FAILURE;
101 const std::string typeKeyAux = def[0];
102 const std::string configuredType = typeKeyAux.substr( 0, typeKeyAux.find(
'#') );
103 const std::string key = typeKeyAux.substr( typeKeyAux.find(
'#')+1, typeKeyAux.find(
'.')-typeKeyAux.find(
'#') );
105 std::string transientType;
106 std::string persistentType;
109 if ( configuredType.find(
'_') == std::string::npos ) {
110 transientType = configuredType;
112 transientType = configuredType.substr( 0, configuredType.find(
'_') );
115 if (
m_clidSvc->getIDOfTypeName(transientType, clid).isFailure() ) {
116 ATH_MSG_ERROR(
"Can not find CLID for " << transientType <<
" that is needed for serialisation " << key );
117 return StatusCode::FAILURE;
119 ATH_MSG_VERBOSE(
"Decoded transient type: " << transientType <<
" with the CLID " << clid );
120 if ( transientType == configuredType ) {
121 std::string realTypeName;
122 if(
m_clidSvc->getTypeInfoNameOfID( clid, realTypeName ).isFailure() ) {
123 ATH_MSG_ERROR(
"Can not find real type name for " << transientType <<
" that is needed for serialisation " << key );
124 return StatusCode::FAILURE;
126 persistentType = transientType +
version( realTypeName );
127 ATH_MSG_VERBOSE(transientType <<
" = "<< configuredType <<
" thus obtained real type name from clid svc " << realTypeName <<
" forming persistent type name "<< persistentType );
129 persistentType = configuredType;
136 ATH_MSG_ERROR(
"The type " << persistentType <<
" is not known to ROOT serialiser" );
137 return StatusCode::FAILURE;
141 if ( def.size() > 2 && def[2].find(
"allowTruncation") != std::string::npos ) {
142 ATH_MSG_DEBUG(
"Truncation allowed for " << configuredType <<
"#" << key);
146 std::vector<std::string> splitModuleIDs;
147 boost::split( splitModuleIDs, def[1], boost::is_any_of(
",") );
148 std::vector<uint16_t> moduleIdVec;
149 for (
const auto& module: splitModuleIDs ) moduleIdVec.push_back( std::stoi( module ) );
150 std::sort(moduleIdVec.begin(), moduleIdVec.end());
152 if (moduleIdVec.empty()) {
153 ATH_MSG_ERROR(
"No HLT result module IDs given for " << typeKeyAux );
154 return StatusCode::FAILURE;
157 ATH_MSG_DEBUG(
"Transient type " << transientType <<
" persistent type " << persistentType <<
" will be written to " << moduleIdVec.size() <<
" result ROBFragments with IDs: "
158 << moduleIdVec <<
"" );
160 if ( persistentType.rfind(
"xAOD", 0) != std::string::npos ) {
162 if ( typeKeyAux.find(
'.') != std::string::npos ) {
164 const std::string allVars = typeKeyAux.substr( typeKeyAux.find(
'.')+1 );
165 if (!allVars.empty()) {
166 std::set<std::string> variableNames;
167 boost::split( variableNames, allVars, [](
const char c){
return c ==
'.'; } );
168 if (msgLvl(MSG::DEBUG)) {
169 for (
const auto& el: variableNames ) {
173 sel.selectAux( variableNames );
180 addressVec.push_back( {transientType, persistentType, clid, key, moduleIdVec,
Address::Category::OldTP, truncationMode} );
182 return StatusCode::SUCCESS;
187 buffer.push_back( address.
clid );
189 std::vector<uint32_t> serializedLabel;
191 std::vector<std::string> descr({address.
persType, address.
key});
192 ss.serialize( descr, serializedLabel );
193 buffer.push_back( serializedLabel.size() );
194 buffer.insert( buffer.end(), serializedLabel.begin(), serializedLabel.end() );
195 return StatusCode::SUCCESS;
202 buffer.push_back(
sz );
203 const size_t neededSize = std::ceil(
double(
sz)/
sizeof(uint32_t) );
204 const size_t existingSize = buffer.size();
205 buffer.resize(existingSize + neededSize);
206 std::memcpy(buffer.data() + existingSize,
data,
sz);
207 return StatusCode::SUCCESS;
218 const SG::IAuxStoreIO* auxStoreIO = dObjAux->template cast<SG::IAuxStoreIO> (
nullptr,
true);
219 if ( auxStoreIO ==
nullptr ) {
220 ATH_MSG_DEBUG(
"Can't obtain AuxContainerBase of " << address.
key <<
" no dynamic variables presumably" );
221 return StatusCode::SUCCESS;
226 if ( selected.
empty() ) {
227 ATH_MSG_VERBOSE(
"Empty set of dynamic variables to store, do nothing" );
228 return StatusCode::SUCCESS;
230 ATH_MSG_DEBUG(
"Ready for serialisation of " << selected.
size() <<
" dynamic variables");
235 const std::type_info* tinfo = auxStoreIO->
getIOType (auxVarID);
237 const std::string fullTypeName = System::typeinfoName( *tinfo );
240 TClass* cls = TClass::GetClass (*tinfo);
243 ATH_MSG_DEBUG(
"Streaming '" << decorationName <<
"' of type '" << typeName
244 <<
"' fulltype '" << fullTypeName <<
"' aux ID '" << auxVarID <<
"' class '" << cls->GetName() );
247 if (
m_clidSvc->getIDOfTypeName(typeName, clid).isFailure() ) {
248 if (
m_clidSvc->getIDOfTypeInfoName(fullTypeName, clid).isFailure() ) {
249 ATH_MSG_ERROR(
"Unable to obtain CLID for either typeName:" << typeName <<
" or fullTypeName:" << fullTypeName);
250 ATH_MSG_ERROR(
"Please check if this is something which should obtain a CLID via TriggerEDMCLIDs.h");
251 return StatusCode::FAILURE;
258 const void* rawptr = auxStoreIO->
getIOData( auxVarID );
264 if ( mem ==
nullptr or
sz == 0 ) {
265 ATH_MSG_ERROR(
"Serialisation of " << address.
persType <<
"#" << address.
key <<
"."<< decorationName <<
" unsuccessful" );
266 return StatusCode::FAILURE;
270 std::vector<uint32_t> fragment;
276 fragment[0] = fragment.size();
278 delete []
static_cast<const char*
>( mem );
280 buffer.insert( buffer.end(), fragment.begin(), fragment.end() );
283 return StatusCode::SUCCESS;
293 ATH_MSG_DEBUG(
"Streamed to buffer at address " << mem <<
" of " <<
sz <<
" bytes" );
295 if ( mem ==
nullptr or
sz == 0 ) {
297 return StatusCode::FAILURE;
301 std::vector<uint32_t> fragment;
304 if ( mem !=
nullptr )
delete []
static_cast<const char*
>( mem );
307 ATH_MSG_DEBUG( address.
transType <<
"#" << address.
key <<
" Fragment size: " << fragment.size()*
sizeof(uint32_t) <<
" bytes");
308 fragment[0] = fragment.size();
309 buffer.insert( buffer.end(), fragment.begin(), fragment.end() );
311 return StatusCode::SUCCESS;
317 std::vector<uint32_t>& buffer,
328 if (data_interface !=
nullptr) {
345 size_t baseSize = buffer.size();
347 return StatusCode::SUCCESS;
351 size_t nDynWritten = 0;
353 if ( nDynWritten > 0 ) {
354 ATH_MSG_DEBUG(
" Fragment size including " << (buffer.size() - baseSize)*
sizeof(uint32_t) <<
" bytes from "
355 << nDynWritten <<
"x DynAux : " << buffer.size()*
sizeof(uint32_t) );
357 return StatusCode::SUCCESS;
363 std::string converterPersistentType;
372 return StatusCode::SUCCESS;
377 if ( dObj ==
nullptr ) {
378 ATH_MSG_DEBUG(
"Data Object with the CLID " << address.
clid <<
" and the key " << address.
key <<
" is missing");
379 return StatusCode::SUCCESS;
383 if ( rawptr ==
nullptr ) {
384 ATH_MSG_DEBUG(
"Data Object with key " << address.
key <<
" can not be converted to void* for streaming" );
385 return StatusCode::SUCCESS;
398 ATH_MSG_ERROR(
"Unknown Address category - neither of xAODInterface, xAODAux, OldTP");
399 return StatusCode::FAILURE;
406 ATH_MSG_ERROR(
"Trying to fill a result which is not empty! Likely misconfiguration, returning a FAILURE");
407 return StatusCode::FAILURE;
418 auto debugInfoData = std::make_unique<xAOD::TrigCompositeContainer>();
419 auto debugInfoAux = std::make_unique<xAOD::TrigCompositeAuxContainer>();
420 debugInfoData->setStore(debugInfoAux.get());
421 ATH_CHECK(debugInfo.record(std::move(debugInfoData), std::move(debugInfoAux)));
425 if (activeModules.empty()) {
426 ATH_MSG_DEBUG(
"No active module IDs in this event. This is normal for events accepted "
427 <<
"only to calibration streams. Skip all EDM serialisation.");
428 return StatusCode::SUCCESS;
432 std::vector<uint32_t> buffer;
433 buffer.reserve(1000);
435 std::unordered_map<uint16_t, std::vector<uint32_t>> deferredInterfaceBuffer;
438 std::vector<uint16_t> addressActiveModuleIds;
439 std::set_intersection(address.moduleIdVec.begin(), address.moduleIdVec.end(),
440 activeModules.begin(), activeModules.end(),
441 std::back_inserter(addressActiveModuleIds));
442 if (addressActiveModuleIds.empty()) {
443 ATH_MSG_DEBUG(
"Streaming of " << address.persTypeName() <<
" is skipped "
444 <<
"because its module IDs are not active in this event");
451 if (buffer.empty()) {
452 ATH_MSG_DEBUG(
"Streaming of " << address.persTypeName() <<
" is skipped");
456 const size_t thisFragmentSize = buffer.size()*
sizeof(uint32_t);
457 ATH_MSG_DEBUG(
"Serialised size of " << address.persTypeName() <<
" is " << thisFragmentSize <<
" bytes" );
458 for (
const uint16_t
id : addressActiveModuleIds) {
464 deferredInterfaceBuffer[id]=buffer;
468 ATH_CHECK(
tryAddData(resultToFill,
id, buffer, address.truncationMode, deferredInterfaceBuffer));
470 deferredInterfaceBuffer.erase(
id);
475 ATH_MSG_DEBUG(
"Module " <<
id <<
" payload after inserting " << address.persTypeName() <<
" has "
477 truncationInfoMap[id].push_back({&address, thisFragmentSize,
true});
481 " truncated - could not add " << address.persTypeName() <<
483 truncationInfoMap[id].push_back({&address, thisFragmentSize,
false});
491 return StatusCode::SUCCESS;
496 const std::vector<uint32_t>&
data,
498 const std::unordered_map<uint16_t, std::vector<uint32_t>> & deferredInterfaceBuffer)
const {
500 ATH_MSG_ERROR(
"Module ID " <<
id <<
" missing from TruncationThresholds map. Cannot determine if result needs truncation");
501 return StatusCode::FAILURE;
508 size_t currentTotalSizeWords = 0;
510 const uint32_t currentTotalSizeBytes = currentTotalSizeWords*
sizeof(uint32_t);
512 const uint32_t extraSizeBytes =
data.size()*
sizeof(uint32_t);
517 ATH_MSG_DEBUG(
"Skipping adding data to result with module ID " <<
id <<
" because of full-result truncation");
523 ATH_MSG_DEBUG(
"Skipping adding data to truncated result with module ID " <<
id);
532 ATH_MSG_DEBUG(
"Adding data to result with module ID " <<
id);
535 return StatusCode::SUCCESS;
544 ATH_MSG_ERROR(
"HLT result truncation on total size! Limit of "
546 <<
" MB exceeded. Flagging all module IDs as truncated.");
552 for (
const auto& [
id, truncationInfoVec] : truncationInfoMap) {
556 debugInfoCont.
push_back(debugInfoThisModule);
562 std::pair<std::string, size_t> largestRecorded{
"None", 0};
563 std::pair<std::string, size_t> largestDropped{
"None", 0};
564 std::pair<std::string, size_t> firstDropped{
"None", 0};
565 moduleId(*debugInfoThisModule) = id;
566 uint32_t sizeSum = 0;
567 bool severeTruncation =
false;
568 bool truncated =
false;
571 sizeSum += truncationInfo.size;
572 typeNameVec(*debugInfoThisModule).push_back(truncationInfo.addrPtr->persTypeName());
573 sizeVec(*debugInfoThisModule).push_back(truncationInfo.size);
574 isRecordedVec(*debugInfoThisModule).push_back(
static_cast<char>(truncationInfo.recorded));
575 if (truncationInfo.recorded && truncationInfo.size > largestRecorded.second) {
576 largestRecorded = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
578 if (!truncationInfo.recorded && truncationInfo.size > largestDropped.second) {
579 largestDropped = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
581 if (!truncationInfo.recorded && !truncated) {
582 firstDropped = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
586 if (!truncationInfo.recorded) {
590 totalSize(*debugInfoThisModule) = sizeSum;
591 msg(severeTruncation ? MSG::ERROR : MSG::WARNING)
592 <<
"HLT result truncation" << (severeTruncation ?
"." :
" in low priority collections.")
593 <<
" Module ID: " <<
id <<
", limit: "
595 << sizeSum/1024. <<
" kB, largest recorded collection: " << largestRecorded.first
596 <<
" (" << largestRecorded.second/1024. <<
" kB), largest dropped collection: "
597 << largestDropped.first <<
" (" << largestDropped.second/1024. <<
" kB), "
598 <<
" first dropped collection: " <<firstDropped.first <<
" (" << firstDropped.second/1024. <<
" kB)"
605 std::stringstream
ss;
606 ss <<
"Passing chains in this event: ";
614 const std::string prefix = severeTruncation ?
"" :
"Allowed";
618 prefix+
"Truncation_LargestName",
619 largestRecorded.second > largestDropped.second ? largestRecorded.first : largestDropped.first);
621 prefix+
"Truncation_LargestSize",
622 largestRecorded.second > largestDropped.second ? largestRecorded.second/1024. : largestDropped.second/1024.);
627 if (!debugInfoCont.
empty()) {
628 std::vector<Address> debugInfoAddressVec;
629 const std::string debugInfoID = std::string(
"xAOD::TrigCompositeContainer#")+
m_debugInfoWHKey.key()+
";0";
630 const std::string debugInfoAuxID = std::string(
"xAOD::TrigCompositeAuxContainer#")+
m_debugInfoWHKey.key()+
"Aux.;0";
633 std::vector<uint32_t> buffer;
634 for (
const Address& address : debugInfoAddressVec) {
641 return StatusCode::SUCCESS;
645 if ( name.find(
"DataVector") != std::string::npos ) {
646 size_t start = name.find(
'_');
647 return name.substr( start, name.find(
'>') - start );
649 if ( name.find(
'_') != std::string::npos ) {
650 return name.substr( name.find(
'_') );
656 std::set<uint16_t> activeIDs;
657 for (
const eformat::helper::StreamTag& st :
result.getStreamTags()) {
658 if (st.robs.empty() && st.dets.empty()) {
662 for (
const uint32_t robid : st.robs) {
663 eformat::helper::SourceIdentifier sid(robid);
664 if (sid.subdetector_id() != eformat::SubDetector::TDAQ_HLT) {
667 activeIDs.insert(sid.module_id());
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Handle mappings between names and auxid_t.
Helper functions intended to be called from the debugger.
Provide an interface for finding inheritance information at run time.
uint32_t CLID
The Class ID type.
char data[hepevt_bytes_allocation_ATLAS]
Interface providing I/O for a generic auxiliary store.
xAOD::TrigComposite Decision
void decisionIDs(const Decision *d, DecisionIDContainer &id)
Extracts DecisionIDs stored in the Decision object.
static unsigned int totalSize(const MultiDimArray< T, N > &ht)
convert to and from a SG storable
bit_t size() const
Count the number of 1 bits in the set.
bool empty() const
Return true if there are no 1 bits in the set.
A non-templated base class for DataBucket, allows to access the transient object address as a void*.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
bool empty() const noexcept
Returns true if the collection is empty.
A container class for data required to build online output from HLT.
const std::set< uint16_t > & getTruncatedModuleIds() const
Getter for the truncation information.
void addTruncatedModuleId(const uint16_t moduleId, bool severeTruncation=true)
Add module ID to the list of truncated results.
void addSerialisedData(const uint16_t moduleId, const std::vector< uint32_t > &data)
Append serialised data (copy of input) for a given moduleId, doesn't remove existing data.
const std::unordered_map< uint16_t, std::vector< uint32_t > > & getSerialisedData() const
Serialised data getter.
std::string name() const
reports human redable name
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
The Athena Transient Store API.
DataObject * accessData(const CLID &id) const
find proxy and access its data. Returns 0 to flag failure
SG::Accessor< T, ALLOC > Accessor
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
std::string getVecTypeName(SG::auxid_t auxid) const
Return the type of the STL vector used to hold an aux data item.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
The non-template portion of the BaseInfo implementation.
static const BaseInfoBase * find(CLID clid)
Find the BaseInfoBase instance for clid.
void * cast(void *p, CLID clid) const
Cast to a base pointer.
Interface providing I/O for a generic auxiliary store.
virtual const std::type_info * getIOType(SG::auxid_t auxid) const =0
Return the type of the data to be stored for one aux data item.
virtual const void * getIOData(SG::auxid_t auxid) const =0
Return a pointer to the data to be stored for one aux data item.
virtual const SG::auxid_set_t & getDynamicAuxIDs() const =0
Get the list of all dynamically created variables.
A set of aux data identifiers.
Utility class (not a tool or so) to serialize strings into stream of 32bit integers.
static TScopeAdapter ByNameNoQuiet(const std::string &name, Bool_t load=kTRUE)
void Destruct(void *place) const
Bool_t IsComplete() const
Common base class for the auxiliary containers.
Class helping in dealing with dynamic branch selection.
virtual SG::auxid_set_t getSelectedAuxIDs(const SG::auxid_set_t &fullset) const
Return which variables were selected to be written out.
Helper to copy an aux store while applying thinning.
const ExtendedEventContext & getExtendedEventContext(const EventContext &ctx)
Retrieve an extended context from a context object.
void copyAuxStoreThinned(const SG::IConstAuxStore &orig, SG::IAuxStore ©, const SG::ThinningInfo *info)
Helper to copy an aux store while applying thinning.
bool fromStorable(DataObject *pDObj, T *&pTrans, bool quiet=false, IRegisterTransient *irt=0, bool isConst=true)
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
size_t auxid_t
Identifier for a particular aux data item.
const Decision * getTerminusNode(SG::ReadHandle< DecisionContainer > &container)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
TrigCompositeContainer_v1 TrigCompositeContainer
Declare the latest version of the container.
TrigComposite_v1 TrigComposite
Declare the latest version of the class.