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());
59 using SG::AuxStoreInternal::addVector;
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;
130 Athena::DebugAids::coredump(SIGSEGV);
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;
189 return start + (*start);
195 std::vector<std::string> labels;
205 std::memcpy( buffer, &(*dataStart),
dataSize(start) );
209std::unique_ptr<TList> TriggerEDMDeserialiserAlg::s_streamerInfoList{};
221 return StatusCode::SUCCESS;
226 s_streamerInfoList.reset();
227 return StatusCode::SUCCESS;
234 if ( not resultHandle.isValid() ) {
236 return StatusCode::FAILURE;
240 const Payload* dataptr =
nullptr;
241 if ( resultHandle->getSerialisedData(
m_moduleID, dataptr ).isFailure() ) {
244 return StatusCode::SUCCESS;
247 return StatusCode::FAILURE;
251 return StatusCode::SUCCESS;
255 const Payload* dataptr )
const {
258 std::unique_ptr<char[]> buff = std::make_unique<char[]>(buffSize);
261 auto resize = [&buffSize, &buff](
const size_t neededSize ) ->
void {
262 if ( neededSize > buffSize ) {
263 buffSize = neededSize;
264 buff = std::make_unique<char[]>(buffSize);
273 std::unique_ptr<WritableAuxStore> currentAuxStoreOwner;
279 std::string previousKey;
280 while ( start != dataptr->end() ) {
283 std::string transientTypeName, transientTypeInfoName;
289 std::string persistentTypeName{ descr[0] };
290 const std::string key{ descr[1] };
301 " type: "<< transientTypeName <<
" (" << transientTypeInfoName <<
")" <<
302 " persistent type: " << persistentTypeName <<
" key: " << key <<
" size: " << bsize );
317 CxxUtils::FPControl fpcontrol;
318 if (persistentTypeName ==
"xAOD::BTaggingTrigAuxContainer_v1") {
319 fpcontrol.holdExceptions();
322 size_t usedBytes{ bsize };
323 void* obj{
nullptr };
327 obj =
m_serializerSvc->deserialize( buff.get(), usedBytes, classDesc );
330 ATH_MSG_DEBUG(
"Deserialised object of ptr: " << obj <<
" which used: " << usedBytes <<
331 " bytes from available: " << bsize );
332 if ( obj ==
nullptr ) {
333 ATH_MSG_ERROR(
"Deserialisation of object of CLID " << clid <<
" and transientTypeName " <<
334 transientTypeName <<
" # " << key <<
" failed" );
335 return StatusCode::FAILURE;
337 const bool isxAODInterfaceContainer = (transientTypeName.starts_with(
"xAOD") and
338 not transientTypeName.contains(
"Aux") and
339 not transientTypeName.contains(
"ElementLink"));
340 const bool isxAODAuxContainer = (transientTypeName.starts_with(
"xAOD") and
341 transientTypeName.contains(
"Aux"));
342 const bool isxAODDecoration = transientTypeName.contains(
"vector");
343 const bool isTPContainer = persistentTypeName.contains(
"_p");
344 const bool isVersionChange = versionChange(persistentTypeName, transientTypeInfoName);
347 isxAODAuxContainer, isxAODDecoration, isTPContainer ) );
349 if ( isTPContainer or isVersionChange ) {
350 if ( isVersionChange )
ATH_MSG_DEBUG(
"Version change detected from " << persistentTypeName <<
" to "
351 << transientTypeInfoName <<
". Will invoke PT converter." );
353 std::string decodedTransientName;
354 void * converted =
m_tpTool->convertPT( persistentTypeName, obj, decodedTransientName );
364 if ( isxAODInterfaceContainer or isxAODAuxContainer or isTPContainer ) {
365 const std::string outputName =
m_prefix + key;
368 ATH_MSG_WARNING(
"No BaseInfoBase for CLID "<< clid <<
" and name " << outputName);
373 outputName,
false,
false );
374 if ( proxyPtr ==
nullptr ) {
375 ATH_MSG_WARNING(
"Recording of object of CLID " << clid <<
" and name " << outputName <<
" failed" );
378 if ( isxAODInterfaceContainer ) {
382 if (xAODInterfaceContainer!=
nullptr &&
383 xAODInterfaceContainer->
trackIndices() && currentAuxStore==
nullptr) {
384 ATH_MSG_DEBUG(
"Container with key " << previousKey <<
" is missing its Aux store");
387 currentAuxStore =
nullptr;
389 }
else if (isxAODAuxContainer) {
391 ATH_CHECK( key.find(
'.') == key.size()-1 );
392 ATH_CHECK( currentAuxStore ==
nullptr and xAODInterfaceContainer !=
nullptr );
397 xAODInterfaceContainer->
setStore(auxHolder);
398 currentAuxStoreOwner = std::make_unique<WritableAuxStore>();
399 currentAuxStore = currentAuxStoreOwner.get();
403 p->setStore( currentAuxStoreOwner.release() );
405 currentAuxStore =
nullptr;
406 xAODInterfaceContainer =
nullptr;
409 }
else if ( isxAODDecoration ) {
410 if(
m_skipDuplicates and (currentAuxStore ==
nullptr || xAODInterfaceContainer ==
nullptr)) {
411 ATH_MSG_DEBUG(
"Decoration " << key <<
" encountered with no active container. Assume this was already handled.");
413 ATH_CHECK( currentAuxStore !=
nullptr and xAODInterfaceContainer !=
nullptr );
415 transientTypeName, persistentTypeName, key, obj,
416 currentAuxStore, xAODInterfaceContainer ) );
421 return StatusCode::SUCCESS;
427 const std::string& transientTypeName,
const std::string& persistentTypeName,
const std::string& decorationName,
429 const bool isPacked = persistentTypeName.contains(
"SG::PackedContainer");
432 SG::auxid_t id = registry.findAuxID ( decorationName );
434 std::string regTypeName = stripStdVec( registry.getVecTypeName(
id) );
435 if ( regTypeName != stripStdVec(transientTypeName) and not transientTypeName.contains(
"ElementLink") )
439 if ( regTypeName != stripStdVec(tname.
getTypeName()) ) {
440 ATH_MSG_INFO(
"Schema evolution required for decoration \"" << decorationName <<
"\" from " << transientTypeName <<
" to " << registry.getVecTypeName(
id ) <<
" not handled yet");
441 return StatusCode::SUCCESS;
445 std::string elementTypeName;
446 const std::type_info* elt_tinfo = getElementType( transientTypeName, elementTypeName );
448 ATH_MSG_DEBUG(
"Dynamic decoration: \"" << decorationName <<
"\" of type " << transientTypeName <<
" will create a dynamic ID, stored type" << elementTypeName );
451 ATH_MSG_DEBUG(
"Unstreaming decoration \"" << decorationName <<
"\" of type " << transientTypeName <<
" aux ID " <<
id <<
" class " << persistentTypeName <<
" packed " << isPacked );
452 std::unique_ptr<SG::IAuxTypeVector>
vec( registry.makeVectorFromData (
id, obj,
nullptr, isPacked,
true) );
454 ATH_MSG_DEBUG(
"Size for \"" << decorationName <<
"\" " <<
vec->size() <<
" interface " << interfaceContainer->
size_v() );
456 if (
vec->size() != 0 ) {
457 vec->toTransient( ctx );
459 currentAuxStore->addVector(std::move(
vec),
false);
462 accessor.getDataArray( *interfaceContainer );
464 return StatusCode::SUCCESS;
468 ATH_MSG_DEBUG(
"Recognised type " << transientTypeName <<
" as: "
469 << (isxAODInterfaceContainer ?
"xAOD Interface Container":
"" )
470 << (isxAODAuxContainer ?
"xAOD Aux Container ":
"" )
471 << ( isDecoration ?
"xAOD Decoration" :
"")
472 << ( isTPContainer ?
"T/P Container " :
"") );
474 const std::vector<bool> typeOfContainer( { isxAODInterfaceContainer, isxAODAuxContainer, isDecoration, isTPContainer } );
475 const size_t count = std::count( typeOfContainer.begin(), typeOfContainer.end(),
true );
477 ATH_MSG_ERROR(
"Could not recognise the kind of container " << transientTypeName );
478 return StatusCode::FAILURE;
481 ATH_MSG_ERROR(
"Ambiguous container kind deduced from the transient type name " << transientTypeName );
483 << (isxAODInterfaceContainer ?
"xAOD Interface Context":
"" )
484 << (isxAODAuxContainer ?
" xAOD Aux Container ":
"" )
485 << ( isDecoration ?
"xAOD Decoration" :
"")
486 << ( isTPContainer ?
"T/P Container " :
"") );
487 return StatusCode::FAILURE;
489 return StatusCode::SUCCESS;
496 if (s_streamerInfoList) {
500 std::string extStreamerInfos =
"bs-streamerinfos.root";
503 TFile extFile(extFilePath.c_str());
505 s_streamerInfoList = std::unique_ptr<TList>(extFile.GetStreamerInfoList());
506 for(
const auto&& infObj: *s_streamerInfoList) {
507 TString t_name=infObj->GetName();
508 if (t_name.BeginsWith(
"listOfRules")){
513 TStreamerInfo*
inf =
static_cast<TStreamerInfo*
>(infObj);
515 TClass *cl =
inf->GetClass();
517 ATH_MSG_DEBUG(
"external TStreamerInfo for " << cl->GetName() <<
518 " checksum: " << std::hex <<
inf->GetCheckSum() << std::dec );
#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_INFO(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.
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
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)
DataBucket holding the object as an untyped pointer.
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.
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.
Handle mappings between names and auxid_t.
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.
Interface for objects taking part in direct ROOT I/O.
Interface for non-const operations on an auxiliary store.
virtual void toTransient(const EventContext &ctx)=0
Perform post-read processing on this store.
Helper class to provide const generic access to aux data.
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
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
StatusCode deserialiseDynAux(const EventContext &ctx, const std::string &transientTypeName, const std::string &persistentTypeName, const std::string &decorationName, void *obj, WritableAuxStore *currentAuxStore, SG::AuxVectorBase *interface) const
Handle decoration.
virtual StatusCode finalize() override
ToolHandle< TrigSerTPTool > m_tpTool
Gaudi::Property< std::string > m_prefix
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 EventContext &ctx, 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
DataBucket holding the object as an untyped (void*) pointer.
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.
constexpr TDA::PayloadIterator toNextFragment(TDA::PayloadIterator start)
Returns starting point of the next fragment, can be == end().
constexpr 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
constexpr CLID collectionCLID(TDA::PayloadIterator start)
CLID of the collection stored in the next fragment.
constexpr 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.
AuxStoreInternal(bool standalone=false)
An auxiliary data store that holds data internally.
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.