8#include "Gaudi/Interfaces/IOptionsSvc.h"
9#include "GaudiKernel/System.h"
28 constexpr uint16_t fullResultTruncationID = std::numeric_limits<uint16_t>::max();
32 const std::string& name,
33 const IInterface* parent )
34 : 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(
'#') );
106 const size_t pos = configuredType.find(
'_');
107 const std::string transientType{ pos==std::string::npos ? configuredType : configuredType.substr(0, pos) };
110 std::string persistentType;
111 if (
m_clidSvc->getIDOfTypeName(transientType, clid).isFailure() ) {
112 ATH_MSG_ERROR(
"Can not find CLID for " << transientType <<
" that is needed for serialisation " << key );
113 return StatusCode::FAILURE;
115 ATH_MSG_VERBOSE(
"Decoded transient type: " << transientType <<
" with the CLID " << clid );
117 if ( transientType == configuredType ) {
118 std::string realTypeName;
119 if(
m_clidSvc->getTypeInfoNameOfID( clid, realTypeName ).isFailure() ) {
120 ATH_MSG_ERROR(
"Can not find real type name for " << transientType <<
" that is needed for serialisation " << key );
121 return StatusCode::FAILURE;
123 persistentType = transientType +
version( realTypeName );
124 ATH_MSG_VERBOSE(transientType <<
" = "<< configuredType <<
" thus obtained real type name from clid svc " << realTypeName <<
" forming persistent type name "<< persistentType );
126 persistentType = configuredType;
133 ATH_MSG_ERROR(
"The type " << persistentType <<
" is not known to ROOT serialiser" );
134 return StatusCode::FAILURE;
138 if ( def.size() > 2 && def[2].contains(
"allowTruncation") ) {
139 ATH_MSG_DEBUG(
"Truncation allowed for " << configuredType <<
"#" << key);
144 std::sort(moduleIdVec.begin(), moduleIdVec.end());
146 if (moduleIdVec.empty()) {
147 ATH_MSG_ERROR(
"No HLT result module IDs given for " << typeKeyAux );
148 return StatusCode::FAILURE;
151 ATH_MSG_DEBUG(
"Transient type " << transientType <<
" persistent type " << persistentType <<
" will be written to " << moduleIdVec.size() <<
" result ROBFragments with IDs: "
152 << moduleIdVec <<
"" );
154 if ( persistentType.starts_with(
"xAOD") ) {
156 if ( typeKeyAux.contains(
'.') ) {
158 const std::string allVars = std::string(typeKeyAux.substr( typeKeyAux.find(
'.')+1 ));
159 if (!allVars.empty()) {
160 const auto variableNames = allVars | std::views::split(
'.') | std::ranges::to<std::set<std::string>>();
161 if (msgLvl(MSG::DEBUG)) {
162 for (
const auto& el: variableNames ) {
166 sel.selectAux( variableNames );
168 addressVec.push_back( {transientType, std::move(persistentType), std::move(classDesc), clid,
171 addressVec.push_back( {transientType, std::move(persistentType), std::move(classDesc), clid,
175 addressVec.push_back( {transientType, std::move(persistentType), std::move(classDesc), clid,
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;
213 const SG::IAuxStoreIO* auxStoreIO = dObjAux->template cast<SG::IAuxStoreIO> (
nullptr,
true);
214 if ( auxStoreIO ==
nullptr ) {
215 ATH_MSG_DEBUG(
"Can't obtain AuxContainerBase of " << address.
key <<
" no dynamic variables presumably" );
216 return StatusCode::SUCCESS;
221 if ( selected.empty() ) {
222 ATH_MSG_VERBOSE(
"Empty set of dynamic variables to store, do nothing" );
223 return StatusCode::SUCCESS;
225 ATH_MSG_DEBUG(
"Ready for serialisation of " << selected.size() <<
" dynamic variables");
232 const auto itr = m_dynAuxAddress.find(auxVarID);
233 if ( itr != m_dynAuxAddress.end() ) {
234 auxAddress = &(itr->second);
242 const std::type_info* tinfo = auxStoreIO->
getIOType (auxVarID);
245 TClass* cls = TClass::GetClass (*tinfo);
249 if (
m_clidSvc->getIDOfTypeName(typeName, clid).isFailure() ) {
250 const std::string fullTypeName = System::typeinfoName( *tinfo );
251 if (
m_clidSvc->getIDOfTypeInfoName(fullTypeName, clid).isFailure() ) {
252 ATH_MSG_ERROR(
"Unable to obtain CLID for either typeName:" << typeName <<
" or fullTypeName:" << fullTypeName);
253 ATH_MSG_ERROR(
"Please check if this is something which should obtain a CLID via TriggerEDMCLIDs.h");
254 return StatusCode::FAILURE;
263 const auto& [itr, inserted] = m_dynAuxAddress.emplace( auxVarID, std::move(addr) );
264 auxAddress = &(itr->second);
268 "', aux ID " << auxVarID <<
", class '" << auxAddress->
classDesc.
Class()->GetName() <<
269 "'" <<
", CLID " << auxAddress->
clid );
271 const void* rawptr = auxStoreIO->
getIOData( auxVarID );
277 if ( mem ==
nullptr or
sz == 0 ) {
279 return StatusCode::FAILURE;
283 std::vector<uint32_t> fragment;
286 fragment[0] = fragment.size();
288 delete []
static_cast<const char*
>( mem );
290 buffer.insert( buffer.end(), fragment.begin(), fragment.end() );
293 return StatusCode::SUCCESS;
302 ATH_MSG_DEBUG(
"Streamed to buffer at address " << mem <<
" of " <<
sz <<
" bytes" );
304 if ( mem ==
nullptr or
sz == 0 ) {
306 return StatusCode::FAILURE;
310 std::vector<uint32_t> fragment;
313 if ( mem !=
nullptr )
delete []
static_cast<const char*
>( mem );
316 ATH_MSG_DEBUG( address.
transType <<
"#" << address.
key <<
" Fragment size: " << fragment.size()*
sizeof(uint32_t) <<
" bytes");
317 fragment[0] = fragment.size();
318 buffer.insert( buffer.end(), fragment.begin(), fragment.end() );
320 return StatusCode::SUCCESS;
326 std::vector<uint32_t>& buffer,
336 if (data_interface !=
nullptr) {
353 size_t baseSize = buffer.size();
355 return StatusCode::SUCCESS;
359 size_t nDynWritten = 0;
361 if ( nDynWritten > 0 ) {
362 ATH_MSG_DEBUG(
" Fragment size including " << (buffer.size() - baseSize)*
sizeof(uint32_t) <<
" bytes from "
363 << nDynWritten <<
"x DynAux : " << buffer.size()*
sizeof(uint32_t) );
365 return StatusCode::SUCCESS;
371 std::string converterPersistentType;
372 void * persistent =
m_tpTool->convertTP( address.
transType, data, converterPersistentType );
379 return StatusCode::SUCCESS;
384 if ( dObj ==
nullptr ) {
385 ATH_MSG_DEBUG(
"Data Object with the CLID " << address.
clid <<
" and the key " << address.
key <<
" is missing");
386 return StatusCode::SUCCESS;
390 if ( rawptr ==
nullptr ) {
391 ATH_MSG_DEBUG(
"Data Object with key " << address.
key <<
" can not be converted to void* for streaming" );
392 return StatusCode::SUCCESS;
405 ATH_MSG_ERROR(
"Unknown Address category - neither of xAODInterface, xAODAux, OldTP");
406 return StatusCode::FAILURE;
413 ATH_MSG_ERROR(
"Trying to fill a result which is not empty! Likely misconfiguration, returning a FAILURE");
414 return StatusCode::FAILURE;
425 auto debugInfoData = std::make_unique<xAOD::TrigCompositeContainer>();
426 auto debugInfoAux = std::make_unique<xAOD::TrigCompositeAuxContainer>();
427 debugInfoData->setStore(debugInfoAux.get());
428 ATH_CHECK(debugInfo.record(std::move(debugInfoData), std::move(debugInfoAux)));
432 if (activeModules.empty()) {
433 ATH_MSG_DEBUG(
"No active module IDs in this event. This is normal for events accepted "
434 <<
"only to calibration streams. Skip all EDM serialisation.");
435 return StatusCode::SUCCESS;
439 std::vector<uint32_t> buffer;
440 buffer.reserve(1000);
442 std::unordered_map<uint16_t, std::vector<uint32_t>> deferredInterfaceBuffer;
445 std::vector<uint16_t> addressActiveModuleIds;
446 std::set_intersection(address.moduleIdVec.begin(), address.moduleIdVec.end(),
447 activeModules.begin(), activeModules.end(),
448 std::back_inserter(addressActiveModuleIds));
449 if (addressActiveModuleIds.empty()) {
450 ATH_MSG_DEBUG(
"Streaming of " << address.persTypeName() <<
" is skipped "
451 <<
"because its module IDs are not active in this event");
459 if (buffer.empty()) {
460 ATH_MSG_DEBUG(
"Streaming of " << address.persTypeName() <<
" is skipped");
464 const size_t thisFragmentSize = buffer.size()*
sizeof(uint32_t);
465 ATH_MSG_DEBUG(
"Serialised size of " << address.persTypeName() <<
" is " << thisFragmentSize <<
" bytes" );
466 for (
const uint16_t
id : addressActiveModuleIds) {
472 deferredInterfaceBuffer[id]=buffer;
476 ATH_CHECK(
tryAddData(resultToFill,
id, buffer, address.truncationMode, deferredInterfaceBuffer));
478 deferredInterfaceBuffer.erase(
id);
483 ATH_MSG_DEBUG(
"Module " <<
id <<
" payload after inserting " << address.persTypeName() <<
" has "
485 truncationInfoMap[id].push_back({&address, thisFragmentSize,
true});
489 " truncated - could not add " << address.persTypeName() <<
491 truncationInfoMap[id].push_back({&address, thisFragmentSize,
false});
499 return StatusCode::SUCCESS;
504 const std::vector<uint32_t>& data,
506 const std::unordered_map<uint16_t, std::vector<uint32_t>> & deferredInterfaceBuffer)
const {
508 ATH_MSG_ERROR(
"Module ID " <<
id <<
" missing from TruncationThresholds map. Cannot determine if result needs truncation");
509 return StatusCode::FAILURE;
516 size_t currentTotalSizeWords = 0;
517 for (
const auto& [i, d] : hltResult.
getSerialisedData()) currentTotalSizeWords += d.size();
518 const uint32_t currentTotalSizeBytes = currentTotalSizeWords*
sizeof(uint32_t);
520 const uint32_t extraSizeBytes = data.size()*
sizeof(uint32_t);
525 ATH_MSG_DEBUG(
"Skipping adding data to result with module ID " <<
id <<
" because of full-result truncation");
531 ATH_MSG_DEBUG(
"Skipping adding data to truncated result with module ID " <<
id);
540 ATH_MSG_DEBUG(
"Adding data to result with module ID " <<
id);
543 return StatusCode::SUCCESS;
552 ATH_MSG_ERROR(
"HLT result truncation on total size! Limit of "
554 <<
" MB exceeded. Flagging all module IDs as truncated.");
560 for (
const auto& [
id, truncationInfoVec] : truncationInfoMap) {
564 debugInfoCont.
push_back(debugInfoThisModule);
565 xAOD::TrigComposite::Accessor<uint16_t> moduleId(
"moduleId");
566 xAOD::TrigComposite::Accessor<uint32_t>
totalSize(
"totalSize");
567 xAOD::TrigComposite::Accessor<std::vector<std::string>> typeNameVec(
"typeName");
568 xAOD::TrigComposite::Accessor<std::vector<uint32_t>> sizeVec(
"size");
569 xAOD::TrigComposite::Accessor<std::vector<char>> isRecordedVec(
"isRecorded");
570 std::pair<std::string, size_t> largestRecorded{
"None", 0};
571 std::pair<std::string, size_t> largestDropped{
"None", 0};
572 std::pair<std::string, size_t> firstDropped{
"None", 0};
573 moduleId(*debugInfoThisModule) = id;
574 uint32_t sizeSum = 0;
575 bool severeTruncation =
false;
576 bool truncated =
false;
579 sizeSum += truncationInfo.size;
580 typeNameVec(*debugInfoThisModule).push_back(truncationInfo.addrPtr->persTypeName());
581 sizeVec(*debugInfoThisModule).push_back(truncationInfo.size);
582 isRecordedVec(*debugInfoThisModule).push_back(
static_cast<char>(truncationInfo.recorded));
583 if (truncationInfo.recorded && truncationInfo.size > largestRecorded.second) {
584 largestRecorded = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
586 if (!truncationInfo.recorded && truncationInfo.size > largestDropped.second) {
587 largestDropped = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
589 if (!truncationInfo.recorded && !truncated) {
590 firstDropped = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
594 if (!truncationInfo.recorded) {
598 totalSize(*debugInfoThisModule) = sizeSum;
599 msg(severeTruncation ? MSG::ERROR : MSG::WARNING)
600 <<
"HLT result truncation" << (severeTruncation ?
"." :
" in low priority collections.")
601 <<
" Module ID: " <<
id <<
", limit: "
603 << sizeSum/1024. <<
" kB, largest recorded collection: " << largestRecorded.first
604 <<
" (" << largestRecorded.second/1024. <<
" kB), largest dropped collection: "
605 << largestDropped.first <<
" (" << largestDropped.second/1024. <<
" kB), "
606 <<
" first dropped collection: " <<firstDropped.first <<
" (" << firstDropped.second/1024. <<
" kB)"
613 std::stringstream
ss;
614 ss <<
"Passing chains in this event: ";
622 const std::string prefix = severeTruncation ?
"" :
"Allowed";
626 prefix+
"Truncation_LargestName",
627 largestRecorded.second > largestDropped.second ? largestRecorded.first : largestDropped.first);
629 prefix+
"Truncation_LargestSize",
630 largestRecorded.second > largestDropped.second ? largestRecorded.second/1024. : largestDropped.second/1024.);
635 if (!debugInfoCont.
empty()) {
636 std::vector<Address> debugInfoAddressVec;
637 const std::string debugInfoID = std::string(
"xAOD::TrigCompositeContainer#")+
m_debugInfoWHKey.key()+
";0";
638 const std::string debugInfoAuxID = std::string(
"xAOD::TrigCompositeAuxContainer#")+
m_debugInfoWHKey.key()+
"Aux.;0";
641 std::vector<uint32_t> buffer;
642 for (
const Address& address : debugInfoAddressVec) {
649 return StatusCode::SUCCESS;
653 if ( name.contains(
"DataVector") ) {
654 const size_t start = name.find(
'_');
655 return name.substr( start, name.find(
'>') - start );
657 const size_t pos = name.find(
'_');
658 return (pos == std::string::npos ? std::string{} : name.substr( pos ));
662 std::set<uint16_t> activeIDs;
663 for (
const eformat::helper::StreamTag& st : result.getStreamTags()) {
664 if (st.robs.empty() && st.dets.empty()) {
668 for (
const uint32_t robid : st.robs) {
669 eformat::helper::SourceIdentifier sid(robid);
670 if (sid.subdetector_id() != eformat::SubDetector::TDAQ_HLT) {
673 activeIDs.insert(sid.module_id());
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(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.
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()