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"
33 const std::string&
name,
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 ) {
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 ==
'.'; } );
169 for (
const auto&
el: variableNames ) {
173 sel.selectAux( variableNames );
182 return StatusCode::SUCCESS;
189 std::vector<uint32_t> serializedLabel;
192 ss.serialize(
descr, serializedLabel );
193 buffer.push_back( serializedLabel.size() );
194 buffer.insert(
buffer.end(), serializedLabel.begin(), serializedLabel.end() );
195 return StatusCode::SUCCESS;
203 const size_t neededSize = std::ceil(
double(
sz)/
sizeof(
uint32_t) );
204 const size_t existingSize =
buffer.size();
205 buffer.resize(existingSize + neededSize);
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);
240 TClass*
cls = TClass::GetClass (*tinfo);
244 <<
"' fulltype '" << fullTypeName <<
"' aux ID '" << auxVarID <<
"' class '" <<
cls->GetName() );
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 ) {
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 );
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 ) {
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 ) {
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;
435 std::unordered_map<uint16_t, std::vector<uint32_t>> deferredInterfaceBuffer;
438 std::vector<uint16_t> addressActiveModuleIds;
440 activeModules.begin(), activeModules.end(),
441 std::back_inserter(addressActiveModuleIds));
442 if (addressActiveModuleIds.empty()) {
444 <<
"because its module IDs are not active in this event");
457 ATH_MSG_DEBUG(
"Serialised size of " <<
address.persTypeName() <<
" is " << thisFragmentSize <<
" bytes" );
458 for (
const uint16_t id : addressActiveModuleIds) {
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);
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;
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;
641 return StatusCode::SUCCESS;
645 if (
name.find(
"DataVector") != std::string::npos ) {
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());