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, persistentType, std::move(classDesc), clid, std::string(key), moduleIdVec,
Address::Category::xAODAux, truncationMode,
sel} );
170 addressVec.push_back( {transientType, persistentType, std::move(classDesc), clid, std::string(key), moduleIdVec,
Address::Category::xAODInterface, truncationMode} );
173 addressVec.push_back( {transientType, persistentType, std::move(classDesc), clid, std::string(key), moduleIdVec,
Address::Category::OldTP, truncationMode} );
175 return StatusCode::SUCCESS;
180 buffer.push_back( address.
clid );
182 std::vector<uint32_t> serializedLabel;
184 std::vector<std::string> descr({address.
persType, address.
key});
185 ss.serialize( descr, serializedLabel );
186 buffer.push_back( serializedLabel.size() );
187 buffer.insert( buffer.end(), serializedLabel.begin(), serializedLabel.end() );
188 return StatusCode::SUCCESS;
195 buffer.push_back(
sz );
196 const size_t neededSize = std::ceil(
double(
sz)/
sizeof(uint32_t) );
197 const size_t existingSize = buffer.size();
198 buffer.resize(existingSize + neededSize);
199 std::memcpy(buffer.data() + existingSize, data,
sz);
200 return StatusCode::SUCCESS;
210 const SG::IAuxStoreIO* auxStoreIO = dObjAux->template cast<SG::IAuxStoreIO> (
nullptr,
true);
211 if ( auxStoreIO ==
nullptr ) {
212 ATH_MSG_DEBUG(
"Can't obtain AuxContainerBase of " << address.
key <<
" no dynamic variables presumably" );
213 return StatusCode::SUCCESS;
218 if ( selected.empty() ) {
219 ATH_MSG_VERBOSE(
"Empty set of dynamic variables to store, do nothing" );
220 return StatusCode::SUCCESS;
222 ATH_MSG_DEBUG(
"Ready for serialisation of " << selected.size() <<
" dynamic variables");
229 const auto itr = m_dynAuxAddress.find(auxVarID);
230 if ( itr != m_dynAuxAddress.end() ) {
231 auxAddress = &(itr->second);
239 const std::type_info* tinfo = auxStoreIO->
getIOType (auxVarID);
242 TClass* cls = TClass::GetClass (*tinfo);
246 if (
m_clidSvc->getIDOfTypeName(typeName, clid).isFailure() ) {
247 const std::string fullTypeName = System::typeinfoName( *tinfo );
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;
260 const auto& [itr, inserted] = m_dynAuxAddress.emplace( auxVarID, std::move(addr) );
261 auxAddress = &(itr->second);
265 "', aux ID " << auxVarID <<
", class '" << auxAddress->
classDesc.
Class()->GetName() <<
266 "'" <<
", CLID " << auxAddress->
clid );
268 const void* rawptr = auxStoreIO->
getIOData( auxVarID );
274 if ( mem ==
nullptr or
sz == 0 ) {
276 return StatusCode::FAILURE;
280 std::vector<uint32_t> fragment;
283 fragment[0] = fragment.size();
285 delete []
static_cast<const char*
>( mem );
287 buffer.insert( buffer.end(), fragment.begin(), fragment.end() );
290 return StatusCode::SUCCESS;
299 ATH_MSG_DEBUG(
"Streamed to buffer at address " << mem <<
" of " <<
sz <<
" bytes" );
301 if ( mem ==
nullptr or
sz == 0 ) {
303 return StatusCode::FAILURE;
307 std::vector<uint32_t> fragment;
310 if ( mem !=
nullptr )
delete []
static_cast<const char*
>( mem );
313 ATH_MSG_DEBUG( address.
transType <<
"#" << address.
key <<
" Fragment size: " << fragment.size()*
sizeof(uint32_t) <<
" bytes");
314 fragment[0] = fragment.size();
315 buffer.insert( buffer.end(), fragment.begin(), fragment.end() );
317 return StatusCode::SUCCESS;
323 std::vector<uint32_t>& buffer,
333 if (data_interface !=
nullptr) {
350 size_t baseSize = buffer.size();
352 return StatusCode::SUCCESS;
356 size_t nDynWritten = 0;
358 if ( nDynWritten > 0 ) {
359 ATH_MSG_DEBUG(
" Fragment size including " << (buffer.size() - baseSize)*
sizeof(uint32_t) <<
" bytes from "
360 << nDynWritten <<
"x DynAux : " << buffer.size()*
sizeof(uint32_t) );
362 return StatusCode::SUCCESS;
368 std::string converterPersistentType;
369 void * persistent =
m_tpTool->convertTP( address.
transType, data, converterPersistentType );
376 return StatusCode::SUCCESS;
381 if ( dObj ==
nullptr ) {
382 ATH_MSG_DEBUG(
"Data Object with the CLID " << address.
clid <<
" and the key " << address.
key <<
" is missing");
383 return StatusCode::SUCCESS;
387 if ( rawptr ==
nullptr ) {
388 ATH_MSG_DEBUG(
"Data Object with key " << address.
key <<
" can not be converted to void* for streaming" );
389 return StatusCode::SUCCESS;
402 ATH_MSG_ERROR(
"Unknown Address category - neither of xAODInterface, xAODAux, OldTP");
403 return StatusCode::FAILURE;
410 ATH_MSG_ERROR(
"Trying to fill a result which is not empty! Likely misconfiguration, returning a FAILURE");
411 return StatusCode::FAILURE;
422 auto debugInfoData = std::make_unique<xAOD::TrigCompositeContainer>();
423 auto debugInfoAux = std::make_unique<xAOD::TrigCompositeAuxContainer>();
424 debugInfoData->setStore(debugInfoAux.get());
425 ATH_CHECK(debugInfo.record(std::move(debugInfoData), std::move(debugInfoAux)));
429 if (activeModules.empty()) {
430 ATH_MSG_DEBUG(
"No active module IDs in this event. This is normal for events accepted "
431 <<
"only to calibration streams. Skip all EDM serialisation.");
432 return StatusCode::SUCCESS;
436 std::vector<uint32_t> buffer;
437 buffer.reserve(1000);
439 std::unordered_map<uint16_t, std::vector<uint32_t>> deferredInterfaceBuffer;
442 std::vector<uint16_t> addressActiveModuleIds;
443 std::set_intersection(address.moduleIdVec.begin(), address.moduleIdVec.end(),
444 activeModules.begin(), activeModules.end(),
445 std::back_inserter(addressActiveModuleIds));
446 if (addressActiveModuleIds.empty()) {
447 ATH_MSG_DEBUG(
"Streaming of " << address.persTypeName() <<
" is skipped "
448 <<
"because its module IDs are not active in this event");
455 if (buffer.empty()) {
456 ATH_MSG_DEBUG(
"Streaming of " << address.persTypeName() <<
" is skipped");
460 const size_t thisFragmentSize = buffer.size()*
sizeof(uint32_t);
461 ATH_MSG_DEBUG(
"Serialised size of " << address.persTypeName() <<
" is " << thisFragmentSize <<
" bytes" );
462 for (
const uint16_t
id : addressActiveModuleIds) {
468 deferredInterfaceBuffer[id]=buffer;
472 ATH_CHECK(
tryAddData(resultToFill,
id, buffer, address.truncationMode, deferredInterfaceBuffer));
474 deferredInterfaceBuffer.erase(
id);
479 ATH_MSG_DEBUG(
"Module " <<
id <<
" payload after inserting " << address.persTypeName() <<
" has "
481 truncationInfoMap[id].push_back({&address, thisFragmentSize,
true});
485 " truncated - could not add " << address.persTypeName() <<
487 truncationInfoMap[id].push_back({&address, thisFragmentSize,
false});
495 return StatusCode::SUCCESS;
500 const std::vector<uint32_t>& data,
502 const std::unordered_map<uint16_t, std::vector<uint32_t>> & deferredInterfaceBuffer)
const {
504 ATH_MSG_ERROR(
"Module ID " <<
id <<
" missing from TruncationThresholds map. Cannot determine if result needs truncation");
505 return StatusCode::FAILURE;
512 size_t currentTotalSizeWords = 0;
513 for (
const auto& [
id, data] : hltResult.
getSerialisedData()) currentTotalSizeWords += data.size();
514 const uint32_t currentTotalSizeBytes = currentTotalSizeWords*
sizeof(uint32_t);
516 const uint32_t extraSizeBytes = data.size()*
sizeof(uint32_t);
521 ATH_MSG_DEBUG(
"Skipping adding data to result with module ID " <<
id <<
" because of full-result truncation");
527 ATH_MSG_DEBUG(
"Skipping adding data to truncated result with module ID " <<
id);
536 ATH_MSG_DEBUG(
"Adding data to result with module ID " <<
id);
539 return StatusCode::SUCCESS;
548 ATH_MSG_ERROR(
"HLT result truncation on total size! Limit of "
550 <<
" MB exceeded. Flagging all module IDs as truncated.");
556 for (
const auto& [
id, truncationInfoVec] : truncationInfoMap) {
560 debugInfoCont.
push_back(debugInfoThisModule);
561 xAOD::TrigComposite::Accessor<uint16_t> moduleId(
"moduleId");
562 xAOD::TrigComposite::Accessor<uint32_t>
totalSize(
"totalSize");
563 xAOD::TrigComposite::Accessor<std::vector<std::string>> typeNameVec(
"typeName");
564 xAOD::TrigComposite::Accessor<std::vector<uint32_t>> sizeVec(
"size");
565 xAOD::TrigComposite::Accessor<std::vector<char>> isRecordedVec(
"isRecorded");
566 std::pair<std::string, size_t> largestRecorded{
"None", 0};
567 std::pair<std::string, size_t> largestDropped{
"None", 0};
568 std::pair<std::string, size_t> firstDropped{
"None", 0};
569 moduleId(*debugInfoThisModule) = id;
570 uint32_t sizeSum = 0;
571 bool severeTruncation =
false;
572 bool truncated =
false;
575 sizeSum += truncationInfo.size;
576 typeNameVec(*debugInfoThisModule).push_back(truncationInfo.addrPtr->persTypeName());
577 sizeVec(*debugInfoThisModule).push_back(truncationInfo.size);
578 isRecordedVec(*debugInfoThisModule).push_back(
static_cast<char>(truncationInfo.recorded));
579 if (truncationInfo.recorded && truncationInfo.size > largestRecorded.second) {
580 largestRecorded = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
582 if (!truncationInfo.recorded && truncationInfo.size > largestDropped.second) {
583 largestDropped = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
585 if (!truncationInfo.recorded && !truncated) {
586 firstDropped = {truncationInfo.addrPtr->persTypeName(), truncationInfo.size};
590 if (!truncationInfo.recorded) {
594 totalSize(*debugInfoThisModule) = sizeSum;
595 msg(severeTruncation ? MSG::ERROR : MSG::WARNING)
596 <<
"HLT result truncation" << (severeTruncation ?
"." :
" in low priority collections.")
597 <<
" Module ID: " <<
id <<
", limit: "
599 << sizeSum/1024. <<
" kB, largest recorded collection: " << largestRecorded.first
600 <<
" (" << largestRecorded.second/1024. <<
" kB), largest dropped collection: "
601 << largestDropped.first <<
" (" << largestDropped.second/1024. <<
" kB), "
602 <<
" first dropped collection: " <<firstDropped.first <<
" (" << firstDropped.second/1024. <<
" kB)"
609 std::stringstream
ss;
610 ss <<
"Passing chains in this event: ";
618 const std::string prefix = severeTruncation ?
"" :
"Allowed";
622 prefix+
"Truncation_LargestName",
623 largestRecorded.second > largestDropped.second ? largestRecorded.first : largestDropped.first);
625 prefix+
"Truncation_LargestSize",
626 largestRecorded.second > largestDropped.second ? largestRecorded.second/1024. : largestDropped.second/1024.);
631 if (!debugInfoCont.
empty()) {
632 std::vector<Address> debugInfoAddressVec;
633 const std::string debugInfoID = std::string(
"xAOD::TrigCompositeContainer#")+
m_debugInfoWHKey.key()+
";0";
634 const std::string debugInfoAuxID = std::string(
"xAOD::TrigCompositeAuxContainer#")+
m_debugInfoWHKey.key()+
"Aux.;0";
637 std::vector<uint32_t> buffer;
638 for (
const Address& address : debugInfoAddressVec) {
645 return StatusCode::SUCCESS;
649 if ( name.contains(
"DataVector") ) {
650 const size_t start = name.find(
'_');
651 return name.substr( start, name.find(
'>') - start );
653 const size_t pos = name.find(
'_');
654 return (pos == std::string::npos ? std::string{} : name.substr( pos ));
658 std::set<uint16_t> activeIDs;
659 for (
const eformat::helper::StreamTag& st : result.getStreamTags()) {
660 if (st.robs.empty() && st.dets.empty()) {
664 for (
const uint32_t robid : st.robs) {
665 eformat::helper::SourceIdentifier sid(robid);
666 if (sid.subdetector_id() != eformat::SubDetector::TDAQ_HLT) {
669 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.
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()