15#include "TBufferFile.h"
16#include "TVirtualCollectionProxy.h"
29#include "TStreamerInfo.h"
32#include <sys/resource.h>
44 if (!clidsvc.retrieve()){
48 if (!clidsvc->getTypeNameOfID(clid, name).isSuccess()) {
51 (void)TClass::GetClass(
name.c_str());
71 const std::type_info* getElementType (
const std::string& tname,
72 std::string& elementTypeName ) {
73 TClass* cls = TClass::GetClass( tname.c_str() );
74 if ( cls ==
nullptr )
return nullptr;
75 TVirtualCollectionProxy* prox = cls->GetCollectionProxy();
76 if ( prox ==
nullptr )
return nullptr;
77 if ( prox->GetValueClass() !=
nullptr ) {
78 elementTypeName = prox->GetValueClass()->GetName();
79 return prox->GetValueClass()->GetTypeInfo();
82 elementTypeName =
type.getTypeName();
83 return type.getTypeInfo();
89 std::string stripStdVec (
const std::string& s_in) {
91 std::string::size_type pos{0};
92 while ((pos =
s.find (
"std::vector<")) != std::string::npos) {
105 bool versionChange(
const std::string& type1,
const std::string& type2) {
106 static const std::regex
re(
".+(_v[0-9]+).*");
108 return ( std::regex_match(type1, m1,
re) and
109 std::regex_match(type2, m2,
re) and
110 m1.str(1) !=
m2.str(1) );
118 using Payload = std::vector<uint32_t>;
120 bool operator()(
int level,
bool ,
const char* location,
const char* ) {
121 if ( level >= kError && location && strstr(location,
"TBufferFile::ReadClass")) {
123 struct rlimit core_limit;
124 getrlimit(RLIMIT_CORE, &core_limit);
125 core_limit.rlim_cur = core_limit.rlim_max;
126 setrlimit(RLIMIT_CORE, &core_limit);
128 std::cout <<
"TriggerEDMDeserialiserAlg: Raising core dump soft size limit to " << core_limit.rlim_cur
129 <<
" and trying to dump core file..." << std::endl;
133 if ( level >= kError && location && strstr(location,
"TClass::Load")) {
134 std::cout <<
"TriggerEDMDeserialiserAlg: buff dump; start " << m_start <<
"\n";
136 std::cout <<
"TriggerEDMDeserialiserAlg: payload dump\n";
137 CxxUtils::hexdump (std::cout, m_payload->data(), m_payload->size() *
sizeof(Payload::value_type));
143 handleError (
const char* buf,
size_t bufsize,
const Payload* payload,
145 : m_buf (
buf), m_bufsize (bufsize), m_payload (
payload), m_start(
start)
151 const Payload* m_payload;
169 #if __cpp_lib_array_constexpr >= 201811L
177 #if __cpp_lib_array_constexpr >= 201811L
185 #if __cpp_lib_array_constexpr >= 201811L
197 #if __cpp_lib_array_constexpr >= 201811L
201 return start + (*start);
207 std::vector<std::string> labels;
217 std::memcpy( buffer, &(*dataStart),
dataSize(start) );
221std::unique_ptr<TList> TriggerEDMDeserialiserAlg::s_streamerInfoList{};
233 return StatusCode::SUCCESS;
238 s_streamerInfoList.reset();
239 return StatusCode::SUCCESS;
246 if ( not resultHandle.isValid() ) {
248 return StatusCode::FAILURE;
252 const Payload* dataptr =
nullptr;
253 if ( resultHandle->getSerialisedData(
m_moduleID, dataptr ).isFailure() ) {
256 return StatusCode::SUCCESS;
259 return StatusCode::FAILURE;
263 return StatusCode::SUCCESS;
269 std::unique_ptr<char[]> buff = std::make_unique<char[]>(buffSize);
272 auto resize = [&buffSize, &buff](
const size_t neededSize ) ->
void {
273 if ( neededSize > buffSize ) {
274 buffSize = neededSize;
275 buff = std::make_unique<char[]>(buffSize);
289 std::string previousKey;
290 while ( start != dataptr->end() ) {
293 std::string transientTypeName, transientTypeInfoName;
299 std::string persistentTypeName{ descr[0] };
300 const std::string key{ descr[1] };
311 " type: "<< transientTypeName <<
" (" << transientTypeInfoName <<
")" <<
312 " persistent type: " << persistentTypeName <<
" key: " << key <<
" size: " << bsize );
327 CxxUtils::FPControl fpcontrol;
328 if (persistentTypeName ==
"xAOD::BTaggingTrigAuxContainer_v1") {
329 fpcontrol.holdExceptions();
332 size_t usedBytes{ bsize };
333 void* obj{
nullptr };
337 obj =
m_serializerSvc->deserialize( buff.get(), usedBytes, classDesc );
340 ATH_MSG_DEBUG(
"Deserialised object of ptr: " << obj <<
" which used: " << usedBytes <<
341 " bytes from available: " << bsize );
342 if ( obj ==
nullptr ) {
343 ATH_MSG_ERROR(
"Deserialisation of object of CLID " << clid <<
" and transientTypeName " <<
344 transientTypeName <<
" # " << key <<
" failed" );
345 return StatusCode::FAILURE;
347 const bool isxAODInterfaceContainer = (transientTypeName.rfind(
"xAOD", 0) != std::string::npos and
348 transientTypeName.find(
"Aux") == std::string::npos and
349 transientTypeName.find(
"ElementLink") == std::string::npos);
350 const bool isxAODAuxContainer = (transientTypeName.rfind(
"xAOD", 0) != std::string::npos and
351 transientTypeName.find(
"Aux") != std::string::npos);
352 const bool isxAODDecoration = transientTypeName.find(
"vector") != std::string::npos;
353 const bool isTPContainer = persistentTypeName.find(
"_p") != std::string::npos;
354 const bool isVersionChange = versionChange(persistentTypeName, transientTypeInfoName);
357 isxAODAuxContainer, isxAODDecoration, isTPContainer ) );
359 if ( isTPContainer or isVersionChange ) {
360 if ( isVersionChange )
ATH_MSG_DEBUG(
"Version change detected from " << persistentTypeName <<
" to "
361 << transientTypeInfoName <<
". Will invoke PT converter." );
363 std::string decodedTransientName;
364 void * converted =
m_tpTool->convertPT( persistentTypeName, obj, decodedTransientName );
374 if ( isxAODInterfaceContainer or isxAODAuxContainer or isTPContainer ) {
376 const std::string outputName =
m_prefix + key;
378 outputName,
false,
false );
379 if ( proxyPtr ==
nullptr ) {
380 ATH_MSG_WARNING(
"Recording of object of CLID " << clid <<
" and name " << outputName <<
" failed" );
383 if ( isxAODInterfaceContainer ) {
387 if (xAODInterfaceContainer!=
nullptr &&
388 xAODInterfaceContainer->
trackIndices() && currentAuxStore==
nullptr) {
389 ATH_MSG_DEBUG(
"Container with key " << previousKey <<
" is missing its Aux store");
392 currentAuxStore =
nullptr;
395 ATH_MSG_WARNING(
"No BaseInfoBase for CLID "<< clid <<
" and name " << outputName);
397 xAODInterfaceContainer =
402 }
else if (isxAODAuxContainer) {
404 ATH_CHECK( key.find(
'.') == key.size()-1 );
405 ATH_CHECK( currentAuxStore ==
nullptr and xAODInterfaceContainer !=
nullptr );
411 xAODInterfaceContainer->
setStore(auxHolder);
415 currentAuxStore =
nullptr;
416 xAODInterfaceContainer =
nullptr;
419 }
else if ( isxAODDecoration ) {
420 if(
m_skipDuplicates and (currentAuxStore ==
nullptr || xAODInterfaceContainer ==
nullptr)) {
421 ATH_MSG_DEBUG(
"Decoration " << key <<
" encountered with no active container. Assume this was already handled.");
423 ATH_CHECK( currentAuxStore !=
nullptr and xAODInterfaceContainer !=
nullptr );
425 currentAuxStore, xAODInterfaceContainer ) );
430 return StatusCode::SUCCESS;
437 const bool isPacked = persistentTypeName.find(
"SG::PackedContainer") != std::string::npos;
442 std::string regTypeName = stripStdVec( registry.
getVecTypeName(
id) );
443 if ( regTypeName != stripStdVec(transientTypeName) and transientTypeName.find(
"ElementLink") == std::string::npos )
447 if ( regTypeName != stripStdVec(tname.
getTypeName()) ) {
448 ATH_MSG_INFO(
"Schema evolution required for decoration \"" << decorationName <<
"\" from " << transientTypeName <<
" to " << registry.
getVecTypeName(
id ) <<
" not handled yet");
449 return StatusCode::SUCCESS;
453 std::string elementTypeName;
454 const std::type_info* elt_tinfo = getElementType( transientTypeName, elementTypeName );
456 ATH_MSG_DEBUG(
"Dynamic decoration: \"" << decorationName <<
"\" of type " << transientTypeName <<
" will create a dynamic ID, stored type" << elementTypeName );
459 ATH_MSG_DEBUG(
"Unstreaming decoration \"" << decorationName <<
"\" of type " << transientTypeName <<
" aux ID " <<
id <<
" class " << persistentTypeName <<
" packed " << isPacked );
460 std::unique_ptr<SG::IAuxTypeVector>
vec( registry.
makeVectorFromData (
id, obj,
nullptr, isPacked,
true) );
462 ATH_MSG_DEBUG(
"Size for \"" << decorationName <<
"\" " <<
vec->size() <<
" interface " << interfaceContainer->
size_v() );
464 if (
vec->size() != 0 ) {
469 accessor.getDataArray( *interfaceContainer );
471 return StatusCode::SUCCESS;
475 ATH_MSG_DEBUG(
"Recognised type " << transientTypeName <<
" as: "
476 << (isxAODInterfaceContainer ?
"xAOD Interface Container":
"" )
477 << (isxAODAuxContainer ?
"xAOD Aux Container ":
"" )
478 << ( isDecoration ?
"xAOD Decoration" :
"")
479 << ( isTPContainer ?
"T/P Container " :
"") );
481 const std::vector<bool> typeOfContainer( { isxAODInterfaceContainer, isxAODAuxContainer, isDecoration, isTPContainer } );
482 const size_t count = std::count( typeOfContainer.begin(), typeOfContainer.end(),
true );
484 ATH_MSG_ERROR(
"Could not recognise the kind of container " << transientTypeName );
485 return StatusCode::FAILURE;
488 ATH_MSG_ERROR(
"Ambiguous container kind deduced from the transient type name " << transientTypeName );
490 << (isxAODInterfaceContainer ?
"xAOD Interface Context":
"" )
491 << (isxAODAuxContainer ?
" xAOD Aux Container ":
"" )
492 << ( isDecoration ?
"xAOD Decoration" :
"")
493 << ( isTPContainer ?
"T/P Container " :
"") );
494 return StatusCode::FAILURE;
496 return StatusCode::SUCCESS;
501 std::lock_guard<std::mutex> lock(
s_mutex);
503 if (s_streamerInfoList) {
507 std::string extStreamerInfos =
"bs-streamerinfos.root";
510 TFile extFile(extFilePath.c_str());
512 s_streamerInfoList = std::unique_ptr<TList>(extFile.GetStreamerInfoList());
513 for(
const auto&& infObj: *s_streamerInfoList) {
514 TString t_name=infObj->GetName();
515 if (t_name.BeginsWith(
"listOfRules")){
520 TStreamerInfo*
inf =
dynamic_cast<TStreamerInfo*
>(infObj);
522 TClass *cl =
inf->GetClass();
524 ATH_MSG_DEBUG(
"external TStreamerInfo for " << cl->GetName() <<
525 " checksum: " << std::hex <<
inf->GetCheckSum() << std::dec );
const boost::regex re(r_e)
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
An auxiliary data store that holds data internally.
Handle mappings between names and auxid_t.
Basic definitions for auxiliary types.
std::vector< size_t > vec
uint32_t CLID
The Class ID type.
Helper to control FP exceptions.
This are the SEAL debug aids, adapted to build in Atlas, after the drop of that project.
This is the signal handler from SEAL, adapted to build in Atlas, after the drop of that project.
convert to and from a SG storable
int fragmentCount(uint32_t data, int id)
Run a MT piece of code with an alternate root error handler.
ServiceHandle< StoreGateSvc > & evtStore()
An algorithm that can be simultaneously executed in multiple threads.
static void coredump(int sig,...)
Drop a core dump and continue.
Allows to insert void* returned from serialisation into the store.
virtual void * object() override
Object reference supporting deferred reading from StoreGate.
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
std::string getTypeName() const
Return the name of this type.
Run a MT piece of code with an alternate root error handler.
ConstAuxElement::TypelessConstAccessor TypelessConstAccessor
An auxiliary data store that holds data internally.
void addVector(std::unique_ptr< IAuxTypeVector > vec, bool isDecoration)
Explicitly add a vector to the store.
Handle mappings between names and auxid_t.
SG::auxid_t findAuxID(const std::string &name, const std::string &clsname="") const
Look up a name -> auxid_t mapping.
std::unique_ptr< IAuxTypeVector > makeVectorFromData(SG::auxid_t auxid, void *data, IAuxTypeVector *linkedVector, bool isPacked, bool ownFlag) const
Construct an IAuxTypeVector object from a vector.
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.
Manage index tracking and synchronization of auxiliary data.
void setStore(SG::IAuxStore *store)
Set the store associated with this object.
bool trackIndices() const
Return true if index tracking is enabled for this container.
virtual size_t size_v() const =0
Return the size of the container.
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 for objects taking part in direct ROOT I/O.
Interface for non-const operations on an auxiliary store.
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
void addVector(std::unique_ptr< IAuxTypeVector > vec, bool isDecoration)
Explicitly add a vector to the store.
WritableAuxStore()=default
from the HLTResultMT Each serialised collection is a chunk of words with the content as described bel...
virtual StatusCode initialize() override
Gaudi::Property< int > m_initialSerialisationBufferSize
Gaudi::Property< bool > m_permitMissingModule
static constexpr size_t CLIDOffset
Payload::const_iterator PayloadIterator
static std::mutex s_mutex
static constexpr size_t NameLengthOffset
static constexpr size_t NameOffset
ServiceHandle< IAthenaSerializeSvc > m_serializerSvc
SG::ReadHandleKey< HLT::HLTResultMT > m_resultKey
virtual StatusCode finalize() override
ToolHandle< TrigSerTPTool > m_tpTool
Gaudi::Property< std::string > m_prefix
StatusCode deserialiseDynAux(const std::string &transientTypeName, const std::string &persistentTypeName, const std::string &decorationName, void *obj, WritableAuxStore *currentAuxStore, SG::AuxVectorBase *interface) const
Handle decoration.
TriggerEDMDeserialiserAlg(const std::string &name, ISvcLocator *pSvcLocator)
Gaudi::Property< bool > m_skipDuplicates
StatusCode checkSanity(const std::string &transientTypeName, bool isxAODInterfaceContainer, bool isxAODAuxContainer, bool isDecoration, bool isTPContainer) const
Checker for data integrity, one and only one of the passed booleans can be true, else FAILURE is retu...
StatusCode deserialise(const Payload *dataptr) const
Performs actual deserialisation loop.
ServiceHandle< IClassIDSvc > m_clidSvc
std::vector< uint32_t > Payload
Gaudi::Property< int > m_moduleID
void add_bs_streamerinfos()
virtual StatusCode execute(const EventContext &context) const override
Find the auxid for a dynamic branch.
bool contains(const std::string &s, const std::string ®x)
does a string contain the substring
int count(std::string s, const std::string ®x)
count how many occurances of a regx are in a string
Helpers to make a nice dump of a region of memory.
void hexdump(std::ostream &s, const void *addr, size_t n, size_t offset=0)
Make a hex dump of memory.
Collection of helper functions for raw pointer operations on the bytestream payload.
TDA::PayloadIterator toNextFragment(TDA::PayloadIterator start)
Returns starting point of the next fragment, can be == end()
size_t dataSize(TDA::PayloadIterator start)
Size in bytes of the buffer that is needed to decode next fragment data content.
std::vector< std::string > collectionDescription(TDA::PayloadIterator start)
String description of the collection stored in the next fragment, returns persistent type name and th...
TriggerEDMDeserialiserAlg TDA
CLID collectionCLID(TDA::PayloadIterator start)
CLID of the collection stored in the next fragment.
size_t nameLength(TDA::PayloadIterator start)
Length of the serialised name payload.
void toBuffer(TDA::PayloadIterator start, char *buffer)
Copies fragment to the buffer, no size checking, use dataSize to do so.
static const auxid_t null_auxid
To signal no aux data item.
CxxUtils::RefCountedPtr< T > DataObjectSharedPtr
SG::auxid_t getDynamicAuxID(const std::type_info &ti, const std::string &name, const std::string &elementTypeName, const std::string &branch_type_name, bool standalone, SG::auxid_t linked_auxid)
Find the auxid for a dynamic branch.
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.