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;
95 if ( def.size() < 2 ) {
96 ATH_MSG_ERROR(
"Invalid EDM collection specification: " << typeKeyAuxIDs);
97 return StatusCode::FAILURE;
100 const std::string_view typeKeyAux = def[0];
101 const std::string_view configuredType = typeKeyAux.substr( 0, typeKeyAux.find(
'#') );
102 const std::string_view key = typeKeyAux.substr( typeKeyAux.find(
'#')+1, typeKeyAux.find(
'.')-typeKeyAux.find(
'#') );
104 std::string transientType;
105 std::string persistentType;
108 if ( configuredType.find(
'_') == std::string::npos ) {
109 transientType = configuredType;
111 transientType = configuredType.substr( 0, configuredType.find(
'_') );
114 if (
m_clidSvc->getIDOfTypeName(transientType, clid).isFailure() ) {
115 ATH_MSG_ERROR(
"Can not find CLID for " << transientType <<
" that is needed for serialisation " << key );
116 return StatusCode::FAILURE;
118 ATH_MSG_VERBOSE(
"Decoded transient type: " << transientType <<
" with the CLID " << clid );
119 if ( transientType == configuredType ) {
120 std::string realTypeName;
121 if(
m_clidSvc->getTypeInfoNameOfID( clid, realTypeName ).isFailure() ) {
122 ATH_MSG_ERROR(
"Can not find real type name for " << transientType <<
" that is needed for serialisation " << key );
123 return StatusCode::FAILURE;
125 persistentType = transientType +
version( realTypeName );
126 ATH_MSG_VERBOSE(transientType <<
" = "<< configuredType <<
" thus obtained real type name from clid svc " << realTypeName <<
" forming persistent type name "<< persistentType );
128 persistentType = configuredType;
135 ATH_MSG_ERROR(
"The type " << persistentType <<
" is not known to ROOT serialiser" );
136 return StatusCode::FAILURE;
140 if ( def.size() > 2 && def[2].find(
"allowTruncation") != std::string::npos ) {
141 ATH_MSG_DEBUG(
"Truncation allowed for " << configuredType <<
"#" << key);
146 std::sort(moduleIdVec.begin(), moduleIdVec.end());
148 if (moduleIdVec.empty()) {
149 ATH_MSG_ERROR(
"No HLT result module IDs given for " << typeKeyAux );
150 return StatusCode::FAILURE;
153 ATH_MSG_DEBUG(
"Transient type " << transientType <<
" persistent type " << persistentType <<
" will be written to " << moduleIdVec.size() <<
" result ROBFragments with IDs: "
154 << moduleIdVec <<
"" );
156 if ( persistentType.rfind(
"xAOD", 0) != std::string::npos ) {
158 if ( typeKeyAux.find(
'.') != std::string::npos ) {
160 const std::string allVars = std::string(typeKeyAux.substr( typeKeyAux.find(
'.')+1 ));
161 if (!allVars.empty()) {
162 std::set<std::string> variableNames;
163 boost::split( variableNames, allVars, [](
const char c){
return c ==
'.'; } );
164 if (msgLvl(MSG::DEBUG)) {
165 for (
const auto& el: variableNames ) {
169 sel.selectAux( variableNames );
171 addressVec.push_back( {transientType, persistentType, clid, std::string(key), moduleIdVec,
Address::Category::xAODAux, truncationMode,
sel} );
176 addressVec.push_back( {transientType, persistentType, clid, std::string(key), moduleIdVec,
Address::Category::OldTP, truncationMode} );
178 return StatusCode::SUCCESS;
183 buffer.push_back( address.
clid );
185 std::vector<uint32_t> serializedLabel;
187 std::vector<std::string> descr({address.
persType, address.
key});
188 ss.serialize( descr, serializedLabel );
189 buffer.push_back( serializedLabel.size() );
190 buffer.insert( buffer.end(), serializedLabel.begin(), serializedLabel.end() );
191 return StatusCode::SUCCESS;
198 buffer.push_back(
sz );
199 const size_t neededSize = std::ceil(
double(
sz)/
sizeof(uint32_t) );
200 const size_t existingSize = buffer.size();
201 buffer.resize(existingSize + neededSize);
202 std::memcpy(buffer.data() + existingSize,
data,
sz);
203 return StatusCode::SUCCESS;
214 const SG::IAuxStoreIO* auxStoreIO = dObjAux->template cast<SG::IAuxStoreIO> (
nullptr,
true);
215 if ( auxStoreIO ==
nullptr ) {
216 ATH_MSG_DEBUG(
"Can't obtain AuxContainerBase of " << address.
key <<
" no dynamic variables presumably" );
217 return StatusCode::SUCCESS;
222 if ( selected.empty() ) {
223 ATH_MSG_VERBOSE(
"Empty set of dynamic variables to store, do nothing" );
224 return StatusCode::SUCCESS;
226 ATH_MSG_DEBUG(
"Ready for serialisation of " << selected.size() <<
" dynamic variables");
231 const std::type_info* tinfo = auxStoreIO->
getIOType (auxVarID);
233 const std::string fullTypeName = System::typeinfoName( *tinfo );
236 TClass* cls = TClass::GetClass (*tinfo);
239 ATH_MSG_DEBUG(
"Streaming '" << decorationName <<
"' of type '" << typeName
240 <<
"' fulltype '" << fullTypeName <<
"' aux ID '" << auxVarID <<
"' class '" << cls->GetName() );
243 if (
m_clidSvc->getIDOfTypeName(typeName, clid).isFailure() ) {
244 if (
m_clidSvc->getIDOfTypeInfoName(fullTypeName, clid).isFailure() ) {
245 ATH_MSG_ERROR(
"Unable to obtain CLID for either typeName:" << typeName <<
" or fullTypeName:" << fullTypeName);
246 ATH_MSG_ERROR(
"Please check if this is something which should obtain a CLID via TriggerEDMCLIDs.h");
247 return StatusCode::FAILURE;
254 const void* rawptr = auxStoreIO->
getIOData( auxVarID );
260 if ( mem ==
nullptr or
sz == 0 ) {
261 ATH_MSG_ERROR(
"Serialisation of " << address.
persType <<
"#" << address.
key <<
"."<< decorationName <<
" unsuccessful" );
262 return StatusCode::FAILURE;
266 std::vector<uint32_t> fragment;
272 fragment[0] = fragment.size();
274 delete []
static_cast<const char*
>( mem );
276 buffer.insert( buffer.end(), fragment.begin(), fragment.end() );
279 return StatusCode::SUCCESS;
289 ATH_MSG_DEBUG(
"Streamed to buffer at address " << mem <<
" of " <<
sz <<
" bytes" );
291 if ( mem ==
nullptr or
sz == 0 ) {
293 return StatusCode::FAILURE;
297 std::vector<uint32_t> fragment;
300 if ( mem !=
nullptr )
delete []
static_cast<const char*
>( mem );
303 ATH_MSG_DEBUG( address.
transType <<
"#" << address.
key <<
" Fragment size: " << fragment.size()*
sizeof(uint32_t) <<
" bytes");
304 fragment[0] = fragment.size();
305 buffer.insert( buffer.end(), fragment.begin(), fragment.end() );
307 return StatusCode::SUCCESS;
313 std::vector<uint32_t>& buffer,
324 if (data_interface !=
nullptr) {
341 size_t baseSize = buffer.size();
343 return StatusCode::SUCCESS;
347 size_t nDynWritten = 0;
349 if ( nDynWritten > 0 ) {
350 ATH_MSG_DEBUG(
" Fragment size including " << (buffer.size() - baseSize)*
sizeof(uint32_t) <<
" bytes from "
351 << nDynWritten <<
"x DynAux : " << buffer.size()*
sizeof(uint32_t) );
353 return StatusCode::SUCCESS;
359 std::string converterPersistentType;
368 return StatusCode::SUCCESS;
373 if ( dObj ==
nullptr ) {
374 ATH_MSG_DEBUG(
"Data Object with the CLID " << address.
clid <<
" and the key " << address.
key <<
" is missing");
375 return StatusCode::SUCCESS;
379 if ( rawptr ==
nullptr ) {
380 ATH_MSG_DEBUG(
"Data Object with key " << address.
key <<
" can not be converted to void* for streaming" );
381 return StatusCode::SUCCESS;
394 ATH_MSG_ERROR(
"Unknown Address category - neither of xAODInterface, xAODAux, OldTP");
395 return StatusCode::FAILURE;
402 ATH_MSG_ERROR(
"Trying to fill a result which is not empty! Likely misconfiguration, returning a FAILURE");
403 return StatusCode::FAILURE;
414 auto debugInfoData = std::make_unique<xAOD::TrigCompositeContainer>();
415 auto debugInfoAux = std::make_unique<xAOD::TrigCompositeAuxContainer>();
416 debugInfoData->setStore(debugInfoAux.get());
417 ATH_CHECK(debugInfo.record(std::move(debugInfoData), std::move(debugInfoAux)));
421 if (activeModules.empty()) {
422 ATH_MSG_DEBUG(
"No active module IDs in this event. This is normal for events accepted "
423 <<
"only to calibration streams. Skip all EDM serialisation.");
424 return StatusCode::SUCCESS;
428 std::vector<uint32_t> buffer;
429 buffer.reserve(1000);
431 std::unordered_map<uint16_t, std::vector<uint32_t>> deferredInterfaceBuffer;
434 std::vector<uint16_t> addressActiveModuleIds;
435 std::set_intersection(address.moduleIdVec.begin(), address.moduleIdVec.end(),
436 activeModules.begin(), activeModules.end(),
437 std::back_inserter(addressActiveModuleIds));
438 if (addressActiveModuleIds.empty()) {
439 ATH_MSG_DEBUG(
"Streaming of " << address.persTypeName() <<
" is skipped "
440 <<
"because its module IDs are not active in this event");
447 if (buffer.empty()) {
448 ATH_MSG_DEBUG(
"Streaming of " << address.persTypeName() <<
" is skipped");
452 const size_t thisFragmentSize = buffer.size()*
sizeof(uint32_t);
453 ATH_MSG_DEBUG(
"Serialised size of " << address.persTypeName() <<
" is " << thisFragmentSize <<
" bytes" );
454 for (
const uint16_t
id : addressActiveModuleIds) {
460 deferredInterfaceBuffer[id]=buffer;
464 ATH_CHECK(
tryAddData(resultToFill,
id, buffer, address.truncationMode, deferredInterfaceBuffer));
466 deferredInterfaceBuffer.erase(
id);
471 ATH_MSG_DEBUG(
"Module " <<
id <<
" payload after inserting " << address.persTypeName() <<
" has "
473 truncationInfoMap[id].push_back({&address, thisFragmentSize,
true});
477 " truncated - could not add " << address.persTypeName() <<
479 truncationInfoMap[id].push_back({&address, thisFragmentSize,
false});
487 return StatusCode::SUCCESS;
492 const std::vector<uint32_t>&
data,
494 const std::unordered_map<uint16_t, std::vector<uint32_t>> & deferredInterfaceBuffer)
const {
496 ATH_MSG_ERROR(
"Module ID " <<
id <<
" missing from TruncationThresholds map. Cannot determine if result needs truncation");
497 return StatusCode::FAILURE;
504 size_t currentTotalSizeWords = 0;
506 const uint32_t currentTotalSizeBytes = currentTotalSizeWords*
sizeof(uint32_t);
508 const uint32_t extraSizeBytes =
data.size()*
sizeof(uint32_t);
513 ATH_MSG_DEBUG(
"Skipping adding data to result with module ID " <<
id <<
" because of full-result truncation");
519 ATH_MSG_DEBUG(
"Skipping adding data to truncated result with module ID " <<
id);
528 ATH_MSG_DEBUG(
"Adding data to result with module ID " <<
id);
531 return StatusCode::SUCCESS;
540 ATH_MSG_ERROR(
"HLT result truncation on total size! Limit of "
542 <<
" MB exceeded. Flagging all module IDs as truncated.");
548 for (
const auto& [
id, truncationInfoVec] : truncationInfoMap) {
552 debugInfoCont.
push_back(debugInfoThisModule);
553 xAOD::TrigComposite::Accessor<uint16_t> moduleId(
"moduleId");
554 xAOD::TrigComposite::Accessor<uint32_t>
totalSize(
"totalSize");
555 xAOD::TrigComposite::Accessor<std::vector<std::string>> typeNameVec(
"typeName");
556 xAOD::TrigComposite::Accessor<std::vector<uint32_t>> sizeVec(
"size");
557 xAOD::TrigComposite::Accessor<std::vector<char>> isRecordedVec(
"isRecorded");
558 std::pair<std::string, size_t> largestRecorded{
"None", 0};
559 std::pair<std::string, size_t> largestDropped{
"None", 0};
560 std::pair<std::string, size_t> firstDropped{
"None", 0};
561 moduleId(*debugInfoThisModule) = id;
562 uint32_t sizeSum = 0;
563 bool severeTruncation =
false;
564 bool truncated =
false;
567 sizeSum += truncationInfo.size;
568 typeNameVec(*debugInfoThisModule).push_back(truncationInfo.addrPtr->persTypeName());
569 sizeVec(*debugInfoThisModule).push_back(truncationInfo.size);
570 isRecordedVec(*debugInfoThisModule).push_back(
static_cast<char>(truncationInfo.recorded));
571 if (truncationInfo.recorded && truncationInfo.size > largestRecorded.second) {
572 largestRecorded = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
574 if (!truncationInfo.recorded && truncationInfo.size > largestDropped.second) {
575 largestDropped = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
577 if (!truncationInfo.recorded && !truncated) {
578 firstDropped = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
582 if (!truncationInfo.recorded) {
586 totalSize(*debugInfoThisModule) = sizeSum;
587 msg(severeTruncation ? MSG::ERROR : MSG::WARNING)
588 <<
"HLT result truncation" << (severeTruncation ?
"." :
" in low priority collections.")
589 <<
" Module ID: " <<
id <<
", limit: "
591 << sizeSum/1024. <<
" kB, largest recorded collection: " << largestRecorded.first
592 <<
" (" << largestRecorded.second/1024. <<
" kB), largest dropped collection: "
593 << largestDropped.first <<
" (" << largestDropped.second/1024. <<
" kB), "
594 <<
" first dropped collection: " <<firstDropped.first <<
" (" << firstDropped.second/1024. <<
" kB)"
601 std::stringstream
ss;
602 ss <<
"Passing chains in this event: ";
610 const std::string prefix = severeTruncation ?
"" :
"Allowed";
614 prefix+
"Truncation_LargestName",
615 largestRecorded.second > largestDropped.second ? largestRecorded.first : largestDropped.first);
617 prefix+
"Truncation_LargestSize",
618 largestRecorded.second > largestDropped.second ? largestRecorded.second/1024. : largestDropped.second/1024.);
623 if (!debugInfoCont.
empty()) {
624 std::vector<Address> debugInfoAddressVec;
625 const std::string debugInfoID = std::string(
"xAOD::TrigCompositeContainer#")+
m_debugInfoWHKey.key()+
";0";
626 const std::string debugInfoAuxID = std::string(
"xAOD::TrigCompositeAuxContainer#")+
m_debugInfoWHKey.key()+
"Aux.;0";
629 std::vector<uint32_t> buffer;
630 for (
const Address& address : debugInfoAddressVec) {
637 return StatusCode::SUCCESS;
641 if ( name.find(
"DataVector") != std::string::npos ) {
642 size_t start = name.find(
'_');
643 return name.substr( start, name.find(
'>') - start );
645 if ( name.find(
'_') != std::string::npos ) {
646 return name.substr( name.find(
'_') );
652 std::set<uint16_t> activeIDs;
653 for (
const eformat::helper::StreamTag& st : result.getStreamTags()) {
654 if (st.robs.empty() && st.dets.empty()) {
658 for (
const uint32_t robid : st.robs) {
659 eformat::helper::SourceIdentifier sid(robid);
660 if (sid.subdetector_id() != eformat::SubDetector::TDAQ_HLT) {
663 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
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
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.
std::vector< std::string > tokenize(std::string_view the_str, std::string_view delimiters)
Splits the string into smaller substrings.
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.
static constexpr CLID ID()