ATLAS Offline Software
Loading...
Searching...
No Matches
Holder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include <sstream>
6#include <regex>
7#include <tbb/concurrent_unordered_map.h>
8
11#include "TrigAuxStore.h"
18
22#include "CxxUtils/ClassName.h"
23#include "GaudiKernel/IConversionSvc.h"
24#include "RootUtils/Type.h"
25#include "TClass.h"
26#include "TROOT.h"
27#include "TVirtualCollectionProxy.h"
28
29
30using namespace HLTNavDetails;
31
32
33/*****************************************************************************
34 *
35 * INNER CLASS (fatures handling)
36 *
37 *****************************************************************************/
39 : m_serializer("TrigTSerializer/TrigTSerializer")
40{}
41
42IHolder::IHolder(const std::string& prefix, const std::string& label, uint16_t idx )
45 m_subTypeIndex(idx),
46 m_serializer("TrigTSerializer/TrigTSerializer")
47{
48}
49
50
53
54void IHolder::prepare(const asg::AsgMessaging& logger, HLT::AccessProxy* sg, IConversionSvc* objSerializer, bool readonly) {
55 m_storeGate = sg;
57 m_objectserializerSvc = objSerializer;
58 m_readonly = readonly;
59}
60
61bool IHolder::serialize(std::vector<uint32_t>& output) const {
62
63 ATH_MSG_DEBUG("Holder<T> serialize, " << *this );
64 // if feature to be forgotten then indication of it is simply 0 size of serialized vector
65
66 output.push_back( typeClid() );
67 output.push_back( m_subTypeIndex );
68
69 // label
70 std::vector<uint32_t> serializedLabel;
72 ss.serialize( m_label, serializedLabel );
73 output.push_back( serializedLabel.size() );
74 output.insert(output.end(), serializedLabel.begin(), serializedLabel.end());
75 return true;
76}
77
79 std::vector<uint32_t>& output,
80 size_t& payloadsize) {
81 bool header_ser = serialize(output);
82 if(!header_ser){
83 ATH_MSG_ERROR(" header serialization failed ");
84 return false;
85 }
86 std::vector<uint32_t> payload;
87 bool payload_ser = serializePayload(payload, sel);
88 if(!payload_ser){
89 ATH_MSG_ERROR(" payload serialization failed ");
90 return false;
91 }
92 payloadsize = payload.size();
93 output.insert(output.end(), payload.begin(), payload.end());
94 return true;
95}
96
97std::string IHolder::generateAliasKey(CLID c, uint16_t sti, const std::string& label, unsigned size) {
98 std::ostringstream ss;
99 ss << "HLTAutoKey_" << label << "_" << c << "_" << sti << "_" << (size == 0xffffffff ? "back" : "to") << "_" << m_uniqueCounter;
100 std::string st = ss.str();
101 ATH_MSG_DEBUG("IHolder::generateAliasKey generated key: " << st);
103 return st;
104}
105
106void IHolder::print(MsgStream& m) const {
107 m << "type: " << typeName() << "(" << typeClid() << ")" << " container: " << collectionName() << "(" << containerClid() << ")"
108 << "label: \"" << label() << "\" subTypeIndex: " << subTypeIndex();
109}
110
111MsgStream& HLTNavDetails::operator<< ( MsgStream& m, const HLTNavDetails::IHolder& h ) {
112 h.print (m);
113 return m;
114}
115
116// only construct the regex once
117namespace HLTNavDetails {
118 const std::regex rx1(R"(_v[0-9]+$)");
119}
120
121std::string HLTNavDetails::formatSGkey(const std::string& prefix, const std::string& containername, const std::string& label){
122 // Memoize already used keys
123 static tbb::concurrent_unordered_map<std::string,std::string> memo ATLAS_THREAD_SAFE;
124 const std::string key = prefix+containername+label;
125
126 const auto itr = memo.find(key);
127 if (itr!=memo.end()) return itr->second;
128
129 // Remove version
130 std::string ret = std::regex_replace(containername,rx1,std::string(""));
131
132 // Replace :: with __
133 size_t pos = ret.find("::");
134 if (pos!=std::string::npos) ret.replace(pos,2,"__");
135
136 // Add prefix and label
137 ret = prefix + "_" + ret;
138 if (label == "Aux.")
139 ret += label;
140 else if (!label.empty())
141 ret += ("_" + label);
142
143 memo.insert({key, ret});
144 return ret;
145}
146
147bool HLTNavDetails::IHolder::deserializePayload(const std::vector<uint32_t>& dataBlob, int version){
148 const std::string sgkey = key();
149 ::HLT::class_id_type feature_clid = typeClid();
150 ::HLT::class_id_type container_clid = containerClid();
151 const std::string container_typename = collectionName();
152
153 if ( m_storeGate->transientContains(container_clid, sgkey) ) {
154 ATH_MSG_VERBOSE("deserialize: while working on: " << container_typename << " and key: " << sgkey
155 << " from serialized form found it in SG already, sync with it");
156 syncWithSG();
157 }
158
159 ATH_MSG_VERBOSE("deserializing a data blob of size " << dataBlob.size() << " navi version is " << version);
160 ATH_MSG_DEBUG("holder type clid " << feature_clid<< " collection clid: " << container_clid);
161
162 if (container_clid<1){
163 ATH_MSG_WARNING("holder type clid " << feature_clid << " collection clid: " << container_clid);
164 }
165
166 typedef std::vector<uint32_t>::const_iterator it_type;
167 it_type it = std::begin(dataBlob);
168
169 if(!dataBlob.size()) return false;
170
171 std::vector<uint32_t> first, second;
172
173 if(version == 4){
174 auto firstsize = *(it++);
175 ATH_MSG_VERBOSE("first part has size: " << firstsize);
176
177 first = std::vector<uint32_t>(it,it+firstsize);
178
179 std::advance(it,firstsize);
180
181 if(!(it!=dataBlob.end())){
182 ATH_MSG_VERBOSE("this datablob only has a first part (non xAOD case)");
183 }
184 else{
185 auto secondsize = *(it++);
186 ATH_MSG_VERBOSE("second part has size: " << secondsize);
187 second = std::vector<uint32_t>(it,it+secondsize);
188 std::advance(it,secondsize);
189 }
190 }
191 else{
192 first = std::vector<uint32_t>(dataBlob.begin(),dataBlob.end());
193 }
194
195 TrigStreamAddress addr(container_clid, sgkey, "", 0, 0);
196 addr.add(first);
197 DataObject* dobj(0);
198
199 if (m_objectserializerSvc->createObj(&addr, dobj).isFailure() ){
200 ATH_MSG_WARNING("deserialize main: failed");
201 return false;
202 }
203
204 bool setcontainer = setDataObject(dobj);
205 if (DataBucketBase* dbb = dynamic_cast<DataBucketBase*> (dobj)) {
206 dbb->relinquish();
207 delete dbb;
208 }
209 if(!setcontainer) return false;
210
211 DataObject* dobjaux(0);
212 if(!second.empty()){
213 std::string sgkeyaux = sgkey+"Aux.";
214 ATH_MSG_VERBOSE("aux clid was deduced to be: " << auxClidOrZero());
215 TrigStreamAddress auxaddr(auxClidOrZero(), sgkeyaux, "", 0, 0);
216 auxaddr.add(second);
217
218 if (m_objectserializerSvc->createObj(&auxaddr, dobjaux).isFailure() ){
219 ATH_MSG_WARNING("Aux Store deserialization failed");
220 return false;
221 }
222
223 // Handle dynamic variables.
224 if (it != dataBlob.end()) {
225 DataBucketBase* dobjBaseAux = static_cast<DataBucketBase*>(dobjaux);
226
227 SG::IAuxStore* istore = nullptr;
228 if (xAOD::AuxContainerBase* auxstore =
229 dobjBaseAux->template cast<xAOD::AuxContainerBase> (nullptr, false))
230 {
231 istore = auxstore;
232 }
233
234 if (!istore || !deserializeDynVars (dataBlob,
235 it - dataBlob.begin(),
236 *istore))
237 {
238 ATH_MSG_WARNING("Aux Store dynamic var deserialization failed");
239 return false;
240 }
241 }
242
243 bool setaux = setAuxDataObject(dobjaux);
244 if (DataBucketBase* dbb = dynamic_cast<DataBucketBase*> (dobjaux)) {
245 dbb->relinquish();
246 delete dbb;
247 }
248 if(!setaux) return false;
249 }
250 return true;
251}
252
253bool HLTNavDetails::IHolder::serializePayload(std::vector<uint32_t>& dataBlob,
254 const xAOD::AuxSelection& sel) {
255 DataObject* dobj = getDataObject();
256
257 if(!dobj){
258 ATH_MSG_WARNING("data object points to null. can't serialize");
259 }
260
261 ATH_MSG_VERBOSE("creating serialized representation for " << dobj);
262
263
264 TrigStreamAddress* addr(0);
265 if ( m_objectserializerSvc->createRep(dobj, *pp_cast<IOpaqueAddress>(&addr) ).isSuccess() ) {
266 ATH_MSG_VERBOSE("serialization of feature (object) successful, blob size: " << addr->get().size());
267 dataBlob.push_back(addr->get().size());
268 dataBlob.insert(dataBlob.end(), addr->get().begin(), addr->get().end());
269 // above should be optimized (need to know if in case of failed serialization addr->get() contains empty data vector)
270 }
271 else{
272 ATH_MSG_ERROR("Container serialization Failure");
273 return false;
274 }
275 DataBucketBase* dobjBase = static_cast<DataBucketBase*>(dobj);
276 if ( dobjBase ) {
277 dobjBase->relinquish();
278 ATH_MSG_VERBOSE("serialization giving up the ownership");
279 }
280 delete dobj;
281 delete addr;
282
283 DataObject* dobjaux = getAuxDataObject();
284
285 ATH_MSG_VERBOSE("aux object: " << dobjaux);
286
287 TrigStreamAddress* auxaddr(0);
288 if(dobjaux){
289 ATH_MSG_VERBOSE("AuxStore serialization");
290 if(m_objectserializerSvc->createRep(dobjaux,*pp_cast<IOpaqueAddress>(&auxaddr) ).isSuccess() ){
291 ATH_MSG_VERBOSE("aux conversion success! aux blob has size: " << auxaddr->get().size());
292 dataBlob.push_back(auxaddr->get().size());
293 dataBlob.insert(dataBlob.end(), auxaddr->get().begin(), auxaddr->get().end());
294 }
295 else{
296 ATH_MSG_ERROR("AuxStore serialization Failure");
297 return false;
298 }
299 DataBucketBase* dobjBaseAux = static_cast<DataBucketBase*>(dobjaux);
300
301 const SG::IAuxStoreIO* iio = nullptr;
302 if (const xAOD::AuxContainerBase* auxstore =
303 dobjBaseAux->template cast<xAOD::AuxContainerBase> (nullptr, true))
304 {
305 iio = auxstore;
306 }
307
308 dobjBaseAux->relinquish();
309 ATH_MSG_VERBOSE("serialization giving up the ownership of Aux");
310 delete dobjaux;
311 delete auxaddr;
312
313 // Handle dynamic variables.
314 if (iio) {
315 if (!serializeDynVars (*iio, sel, dataBlob)) {
316 ATH_MSG_ERROR("Serialization of dynamic aux variables failed.");
317 return false;
318 }
319 }
320 }
321 ATH_MSG_VERBOSE("finished serializing payload. size: " << dataBlob.size());
322
323 return true;
324}
325
326
345 const xAOD::AuxSelection& sel,
346 std::vector<uint32_t>& dataBlob)
347{
348 // Loop over all selected variables.
350 SG::auxid_set_t auxids = sel.getSelectedAuxIDs (iio.getDynamicAuxIDs());
351 for (SG::auxid_t id : auxids) {
352 // Get the TClass of the object being saved.
353 const std::type_info* tinfo = iio.getIOType (id);
354 if (!tinfo) {
355 ATH_MSG_ERROR("serialize aux dyn vars failed: can't get type_info.");
356 return false;
357 }
358 TClass* cls = TClass::GetClass (*tinfo);
359 if (!cls) {
360 ATH_MSG_ERROR("serialize aux dyn vars failed: can't get TClass.");
361 return false;
362 }
363
364 // Serialize the object data to a temp buffer.
365 std::vector<uint32_t> serialized =
366 m_serializer->serialize (cls->GetName(), iio.getIOData (id));
367
368 // Concatenate header header information to the output buffer:
369 // attribute name and data type.
371 std::vector<uint32_t> serializedName;
372 ss.serialize (r.getName(id), serializedName); // FIXME: handle class part?
373 dataBlob.push_back (serializedName.size());
374 dataBlob.insert(dataBlob.end(), serializedName.begin(), serializedName.end());
375
376 std::vector<uint32_t> serializedType;
377 ss.serialize (cls->GetName(), serializedType);
378 dataBlob.push_back (serializedType.size());
379 dataBlob.insert(dataBlob.end(), serializedType.begin(), serializedType.end());
380
381 // Add the object data itself to the output buffer.
382 dataBlob.push_back (serialized.size());
383 dataBlob.insert(dataBlob.end(), serialized.begin(), serialized.end());
384 }
385
386 return true;
387}
388
389
404bool IHolder::deserializeDynVars (const std::vector<uint32_t>& dataBlob,
405 size_t offs,
406 SG::IAuxStore& store)
407{
408 SG::IAuxStoreHolder* holder = dynamic_cast<SG::IAuxStoreHolder*> (&store);
409 if (!holder) {
410 ATH_MSG_ERROR("deserialize aux dyn vars failed: can't convert to IAuxStoreHolder.");
411 return false;
412 }
413
414 std::unique_ptr<SG::IAuxStore> newstore = deserializeDynVars (dataBlob, offs);
415 if (!newstore) return false;
416 holder->setStore (newstore.release());
417 return true;
418}
419
420
421namespace {
422
423
424// Change instances of std::vector<...> to vector<...> in the input string,
425// for comparing class names.
426std::string stripStdVec (const std::string& s_in)
427{
428 std::string s = s_in;
429 std::string::size_type pos{0};
430 while ((pos = s.find ("std::vector<")) != std::string::npos) {
431 s.erase (pos, 5);
432 }
433 return s;
434}
435
436
437} // anonymous namespace
438
439
450std::unique_ptr<SG::IAuxStore>
451IHolder::deserializeDynVars (const std::vector<uint32_t>& dataBlob,
452 size_t offs)
453{
456
457 // New dynamic store.
458 auto store = std::make_unique<HLTNavDetails::TrigAuxStore>();
459
460 // Read through the buffer starting at @c offs.
461 std::vector<uint32_t>::const_iterator it = dataBlob.begin() + offs;
462 while (it < dataBlob.end()) {
463 // Read the attribute and type names from the buffer.
464 size_t name_size = *it++;
465 std::string name;
466 ss.deserialize (it, it+name_size, name);
467 it += name_size;
468
469 size_t tname_size = *it++;
470 std::string tname;
471 ss.deserialize (it, it+tname_size, tname);
472 it += tname_size;
473
474 // Object size.
475 size_t var_size = *it++;
476
477 const static char* const packed_pref = "SG::PackedContainer<";
478 const static unsigned int packed_preflen = strlen(packed_pref);
479 std::string vecname = tname;
480 if (strncmp (vecname.c_str(), packed_pref, packed_preflen) == 0) {
481 // Convert from SG::PackedContainer<T> to vector<T>.
482 // Also strip out a std::allocator<T> argument, but leave
483 // any other allocator.
484 auto makeRules = []() {
486 rules.add ("SG::PackedContainer<$T, std::allocator<$T> >",
487 "vector<$T>");
488 rules.add ("SG::PackedContainer<$T, allocator<$T> >",
489 "vector<$T>");
490 rules.add ("SG::PackedContainer<$T, $ALLOC>",
491 "vector<$T, $ALLOC>");
492 return rules;
493 };
494 const static CxxUtils::ClassName::Rules rules = makeRules();
495 vecname = rules.apply (vecname);
496 }
497
498 // Handle schema evolution. If we're expecting a different
499 // type for the variable, then use that name instead.
500 SG::auxid_t id = r.findAuxID (name);
501 if (id != SG::null_auxid && stripStdVec(r.getVecTypeName(id)) != stripStdVec(vecname)) {
502 vecname = r.getVecTypeName (id);
503 tname = vecname;
504 }
505
506 // Handle the case where we don't have a registered type for this
507 // auxiliary variable.
508 if (id == SG::null_auxid)
509 {
510 std::string elementTypeName;
511 const std::type_info* elt_tinfo = getElementType (vecname, elementTypeName);
512 if (elt_tinfo)
513 id = SG::getDynamicAuxID (*elt_tinfo, name, elementTypeName, tname, false, SG::null_auxid);
514 if (id == SG::null_auxid) {
515 ATH_MSG_ERROR("deserialize aux dyn var failed; can't find auxid for:" << name);
516 return std::unique_ptr<SG::IAuxStore> (std::move(store));
517 }
518 }
519
520 // Read the object from the buffer.
521 std::vector<uint32_t> buf (it, it+var_size);
522 void* obj = m_serializer->deserialize (tname, buf);
523 it += var_size;
524
525 bool isPacked = (strncmp (tname.c_str(), packed_pref, packed_preflen) == 0);
526 std::unique_ptr<SG::IAuxTypeVector> vec
527 (r.makeVectorFromData (id, obj, nullptr, isPacked, true));
528 store->addVector (std::move(vec), false);
529 }
530
531 return std::unique_ptr<SG::IAuxStore> (std::move(store));
532}
533
534
542const std::type_info*
543IHolder::getElementType (const std::string& tname,
544 std::string& elementTypeName) const
545{
546 TClass* cls = TClass::GetClass (tname.c_str());
547 if (!cls) return nullptr;
548 TVirtualCollectionProxy* prox = cls->GetCollectionProxy();
549 if (!prox) return nullptr;
550 if (prox->GetValueClass()) {
551 elementTypeName = prox->GetValueClass()->GetName();
552 return prox->GetValueClass()->GetTypeInfo();
553 }
554 RootUtils::Type typ (prox->GetType());
555 elementTypeName = typ.getTypeName();
556 return typ.getTypeInfo();
557}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
An auxiliary data store that holds data internally.
Handle mappings between names and auxid_t.
a static registry of CLID->typeName entries.
std::vector< size_t > vec
Recursively separate out template arguments in a C++ class name.
uint32_t CLID
The Class ID type.
static Double_t ss
Aux store instance used to hold dynamic variables deserialized from the bytestream.
Wrapper for ROOT types.
#define ATLAS_THREAD_SAFE
A set of transformation rules to use with ClassName.
std::string apply(const std::string &name) const
Apply transformations to a class name.
void add(const ClassName &pattern, const ClassName &replacement)
Add a new transformation rule.
A non-templated base class for DataBucket, allows to access the transient object address as a void*.
virtual void relinquish()=0
Give up ownership of the DataBucket contents.
std::string generateAliasKey(CLID c, uint16_t sti, const std::string &label, unsigned size)
Definition Holder.cxx:97
virtual const std::string & key() const =0
returns the containers StoreGate key
bool serializeWithPayload(const xAOD::AuxSelection &sel, std::vector< uint32_t > &output, size_t &payloadsize)
serializes this Holder including payload
Definition Holder.cxx:78
virtual CLID containerClid() const =0
ToolHandle< ITrigSerializerToolBase > m_serializer
Serializer tool; used for dynamic variables.
Definition Holder.h:248
virtual DataObject * getAuxDataObject()=0
std::string m_label
label given to the objects in this holder (labels given at attachFeature)
Definition Holder.h:243
virtual bool syncWithSG(SG::OwnershipPolicy policy=SG::OWN_ELEMENTS)=0
const std::string & label() const
returns the label of objects stores by this holder
Definition Holder.h:86
virtual bool setDataObject(DataObject *dobj)=0
virtual bool serialize(std::vector< uint32_t > &output) const
serializes this Holder
Definition Holder.cxx:61
bool serializeDynVars(const SG::IAuxStoreIO &iio, const xAOD::AuxSelection &sel, std::vector< uint32_t > &dataBlob)
Serialize all selected dynamic variables for an xAOD object.
Definition Holder.cxx:344
HLT::AccessProxy * m_storeGate
pointer to SG
Definition Holder.h:164
const asg::AsgMessaging * m_logger
Definition Holder.h:162
virtual void print(MsgStream &m) const
Definition Holder.cxx:106
uint16_t m_subTypeIndex
index to notify how many objects of given type we have (we need to record it in case of slimming will...
Definition Holder.h:244
bool serializePayload(std::vector< uint32_t > &dataBlob, const xAOD::AuxSelection &sel)
serializes the payload of this Holder
Definition Holder.cxx:253
const std::type_info * getElementType(const std::string &tname, std::string &elementTypeName) const
Find the type of an element of a vector.
Definition Holder.cxx:543
std::string m_prefix
prefix for key given to the objects
Definition Holder.h:242
bool deserializePayload(const std::vector< uint32_t > &dataBlob, int version)
deserialization of holder payload
Definition Holder.cxx:147
virtual CLID auxClidOrZero() const =0
IConversionSvc * m_objectserializerSvc
pointer to object serializer
Definition Holder.h:163
virtual CLID typeClid() const =0
returns the CLID of objects stores by this holder
virtual DataObject * getDataObject()=0
virtual const std::string & prefix() const
returns the containers StoreGate prefix
Definition Holder.h:91
bool deserializeDynVars(const std::vector< uint32_t > &dataBlob, size_t offs, SG::IAuxStore &store)
Read dynamic auxiliary variables from a serialized buffer.
Definition Holder.cxx:404
virtual const std::string & typeName() const =0
returns the object's name stored by this holder
virtual const std::string & collectionName() const =0
returns the collection's name stored by this holder
uint16_t subTypeIndex() const
returns the index (short number used when linking object to the TE) of objects stores by this holder
Definition Holder.h:112
virtual void prepare(const asg::AsgMessaging &logger, HLT::AccessProxy *sg, IConversionSvc *objSerializer, bool readonly)
prepares this holder by setting messaging, StoreGate access and providing serializer
Definition Holder.cxx:54
virtual bool setAuxDataObject(DataObject *dobjaux)=0
Wrapper for ROOT types.
Definition Type.h:40
std::string getTypeName() const
Return the name of this type.
Definition Type.cxx:329
const std::type_info * getTypeInfo() const
Return the type_info for the described type.
Definition Type.cxx:366
Handle mappings between names and auxid_t.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Interface for objects taking part in direct ROOT I/O.
virtual void setStore(IAuxStore *store)=0
Give an auxiliary store object to the holder object.
Interface providing I/O for a generic auxiliary store.
Definition IAuxStoreIO.h:44
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.
Interface for non-const operations on an auxiliary store.
Definition IAuxStore.h:48
A set of aux data identifiers.
Definition AuxTypes.h:47
Utility class (not a tool or so) to serialize strings into stream of 32bit integers.
IOpaqueAddress for TrigSerializenCnvSvc.
void add(const std::vector< uint32_t > &a)
const std::vector< uint32_t > & get() const
Class mimicking the AthMessaging class from the offline software.
Common base class for the auxiliary containers.
Class helping in dealing with dynamic branch selection.
Find the auxid for a dynamic branch.
int r
Definition globals.cxx:22
static Root::TMsgLogger logger("iLumiCalc")
std::string label(const std::string &format, int i)
Definition label.h:19
const std::regex rx1(R"(_v[0-9]+$)")
std::string formatSGkey(const std::string &prefix, const std::string &containername, const std::string &label)
declaration of formatting function.
Definition Holder.cxx:121
MsgStream & operator<<(MsgStream &m, const HLTNavDetails::IHolder &nav)
Definition Holder.cxx:111
StoreGateSvc AccessProxy
Definition AccessProxy.h:17
static const auxid_t null_auxid
To signal no aux data item.
Definition AuxTypes.h:30
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.
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27