ATLAS Offline Software
Loading...
Searching...
No Matches
xAOD::RAuxStore::impl Struct Reference
Collaboration diagram for xAOD::RAuxStore::impl:

Public Member Functions

StatusCode scanInputTuple ()
 Scans the input ntuple for auxiliary data fields and sets up the necessary structures to access them.
const std::type_info * auxFieldType (const ROOT::RFieldBase &field, std::string *expectedClassName=nullptr)
 This function retrieves the type information for a given auxiliary field.
StatusCode setupAuxField (const ROOT::RFieldBase &field, std::string_view auxName)
 This function sets up an auxiliary field by determining its type and attempting to register it with the auxiliary type registry.

Public Attributes

Membersm_data
 Variables coming from AuxStoreBase.
ROOT::RNTupleReader * m_inTuple = nullptr
 The ntuple being read from.
ROOT::RNTupleWriter * m_outTuple = nullptr
 The ntuple being written to.
bool m_inputScanned = false
 "Scan status" of the input RNTuple
::Long64_t m_entry
 The entry to load from the ntuple.
std::vector< std::unique_ptr< RFieldHandle > > m_fields
 Fields containing the various auxiliary variables.
std::vector< boolm_fieldsWritten
 "Write status" of the different variables
std::vector< boolm_missingFields
 Mark fields we've found to be missing.
mutex_t m_mutex
 Mutex object used for multithreaded synchronisation.

Detailed Description

Definition at line 249 of file RAuxStore.cxx.

Member Function Documentation

◆ auxFieldType()

const std::type_info * xAOD::RAuxStore::impl::auxFieldType ( const ROOT::RFieldBase & field,
std::string * expectedClassName = nullptr )
inline

This function retrieves the type information for a given auxiliary field.

It uses the field's inspector to determine the type and handles cases where the expected class or collection proxy is not available.

Parameters
fieldThe field to get the type of
expectedClassNameThe (optional) name of the expected (on disk) class
Returns
A pointer to the type information for the field

Definition at line 350 of file RAuxStore.cxx.

351 {
352
353 // Get the type name of the field. Not worrying about automatic schema
354 // evolution for now.
355 const std::string typeName = field.GetTypeName();
356 ::TClass* expectedClass = ::TClass::GetClass(typeName.c_str());
357 if (expectedClassName) {
358 if (expectedClass) {
359 *expectedClassName = expectedClass->GetName();
360 } else {
361 *expectedClassName = typeName;
362 }
363 }
364
365 // If this is a primitive variable, and we're still not sure whether this
366 // is a store for an object or a container, the answer is given...
367 if ((Utils::isPrimitiveType(typeName)) &&
368 (m_data.m_structMode == EStructMode::kUndefinedStore)) {
369 m_data.m_structMode = EStructMode::kObjectStore;
370 }
371
372 // Get the type_info of the branch.
373 const std::type_info* ti = nullptr;
374 if (m_data.m_structMode == EStructMode::kObjectStore) {
375 if (expectedClass) {
376 ti = expectedClass->GetTypeInfo();
377 } else {
378 ti = &(Utils::getTypeInfo(typeName));
379 }
380 } else {
381 if (!expectedClass) {
382 ::Warning("xAOD::RAuxStore::impl::auxFieldType",
383 "Couldn't get the type of field \"%s\"",
384 field.GetFieldName().c_str());
385 } else {
386 ::TVirtualCollectionProxy* prox = expectedClass->GetCollectionProxy();
387
388 if (!prox) {
389 TClass* cl2 = details::lookupVectorType(*expectedClass);
390 if (cl2) {
391 prox = cl2->GetCollectionProxy();
392 }
393 }
394
395 if (!prox) {
396 ::Warning("xAOD::RAuxStore::impl::auxFieldType",
397 "Couldn't get the type of field \"%s\"",
398 field.GetFieldName().c_str());
399 } else {
400 if (prox->GetValueClass()) {
401 ti = prox->GetValueClass()->GetTypeInfo();
402 } else {
403 ti = &(Utils::getTypeInfo(prox->GetType()));
404 }
405 }
406 }
407 }
408
409 return ti;
410 }
@ kUndefinedStore
The structure mode is not defined.
@ kObjectStore
The object describes a single object.
const std::type_info & getTypeInfo(EDataType type)
This function is used when reading a primitive branch from an input file without the user explicitly ...
bool isPrimitiveType(std::string_view typeName)
Check if the type name describes a primitive type.
TClass * lookupVectorType(TClass &cl)
Internal function used by xAOD::TAuxStore and xAOD::RAuxStore.
Members & m_data
Variables coming from AuxStoreBase.

◆ scanInputTuple()

StatusCode xAOD::RAuxStore::impl::scanInputTuple ( )
inline

Scans the input ntuple for auxiliary data fields and sets up the necessary structures to access them.

It ensures that the input ntuple is properly scanned and the auxiliary data fields are set up.

Returns
StatusCode::SUCCESS if the function was successful, something else otherwise

Definition at line 258 of file RAuxStore.cxx.

258 {
259
260 // Check if an input ntuple is even available.
261 if (!m_inTuple) {
262 // It's not an error if it isn't.
263 return StatusCode::SUCCESS;
264 }
265
266 // Check if the input was already scanned.
267 if (m_inputScanned) {
268 return StatusCode::SUCCESS;
269 }
270
271 // Iterate over all fields of the input ntuple.
272 for (const ROOT::RFieldBase* field :
273#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 35, 0)
274 m_inTuple->GetModel().GetConstFieldZero().GetConstSubfields()
275#else
276 m_inTuple->GetModel().GetConstFieldZero().GetSubFields()
277#endif // ROOT_VERSION_CODE >= ROOT_VERSION(6, 35, 0)
278 ) {
279
280 // Get the name of the current field.
281 const std::string fieldName = field->GetQualifiedFieldName();
282
283 // Look for static fields.
284 if (m_data.m_topStore && (fieldName == m_data.m_prefix)) {
285
286 // Loop over the sub-fields of this field.
287 for (const ROOT::RFieldBase* subField :
288#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 35, 0)
289 field->GetConstSubfields()
290#else
291 field->GetSubFields()
292#endif // ROOT_VERSION_CODE >= ROOT_VERSION(6, 35, 0)
293 ) {
294
295 // Get the type of this sub-field.
296 const std::string& typeName = subField->GetTypeName();
297
298 // Skip this entry if it refers to a base class.
299 if (typeName.starts_with("xAOD::") ||
300 typeName.starts_with("SG::") ||
301 typeName.starts_with("DMTest::") ||
302 typeName.starts_with("ILockable")) {
303 continue;
304 }
305
306 // Set up this field.
307 RETURN_CHECK("xAOD::RAuxStore::impl::scanInputNtuple",
308 setupAuxField(*subField, subField->GetFieldName()));
309 }
310 // Don't check the rest of the loop's body:
311 continue;
312 }
313
314 // if fieldname doesnt start with the value of m_dynPrefix, skip
315 if (fieldName.starts_with(m_data.m_dynPrefix) == false) {
316 continue;
317 }
318 if (fieldName == m_data.m_dynPrefix) {
319 ::Error("xAOD::RAuxStore::impl::scanInputNtuple",
320 "Dynamic field with empty name found on container: %s",
321 m_data.m_prefix.c_str());
322 continue;
323 }
324 // The auxiliary property name:
325 std::string_view auxName = fieldName;
326 std::string::size_type spos = auxName.find(':');
327 if (spos != std::string::npos) {
328 auxName = auxName.substr(spos + 1);
329 }
330 // Leave the rest up to the function that is shared with the
331 // dynamic fields:
332 RETURN_CHECK("xAOD::RAuxStore::scanInputNtuple",
333 setupAuxField(*field, auxName));
334 }
335
336 // the input was successfully scanned:
337 m_inputScanned = true;
338 return StatusCode::SUCCESS;
339 }
#define RETURN_CHECK(CONTEXT, EXP)
Helper macro for checking return codes in a compact form in the code.
Definition ReturnCheck.h:26
bool m_inputScanned
"Scan status" of the input RNTuple
ROOT::RNTupleReader * m_inTuple
The ntuple being read from.
StatusCode setupAuxField(const ROOT::RFieldBase &field, std::string_view auxName)
This function sets up an auxiliary field by determining its type and attempting to register it with t...

◆ setupAuxField()

StatusCode xAOD::RAuxStore::impl::setupAuxField ( const ROOT::RFieldBase & field,
std::string_view auxName )
inline

This function sets up an auxiliary field by determining its type and attempting to register it with the auxiliary type registry.

If the field type is not known, it tries to create a factory for the field's type. The function handles both static and dynamic fields and updates the set of known auxiliary IDs upon success.

Parameters
fieldThe field to set up
auxNameThe name of the auxiliary property, extracted from the field's name
Returns
StatusCode::SUCCESS if the function was successful, something else otherwise

Definition at line 424 of file RAuxStore.cxx.

425 {
426
427 // Get the (on disk) type of the field.
428 std::string expectedClassName;
429 const std::type_info* ti = auxFieldType(field, &expectedClassName);
430 if (ti == nullptr) {
431 // If we didn't find a type_info for the field, give up now...
432 return StatusCode::SUCCESS;
433 }
434
435 // Get the registry:
436 SG::AuxTypeRegistry& registry = SG::AuxTypeRegistry::instance();
437
438 // Check if the registry already knows this variable name. If yes, let's
439 // use the type known by the registry. To be able to deal with simple
440 // schema evolution in dynamic fields.
441 const std::string auxNameStr{auxName};//Get rid of this if everything is migrated to string_view
442 if (const SG::auxid_t regAuxid = registry.findAuxID(auxNameStr);
443 regAuxid != SG::null_auxid) {
444 m_data.m_auxIDs.insert(regAuxid);
445 return StatusCode::SUCCESS;
446 }
447
449 SG::auxid_t linkedAuxId = SG::null_auxid;
450
451 if (SG::AuxTypeRegistry::isLinkedName(auxNameStr)) {
453 } else if (SG::AuxTypeRegistry::classNameHasLink(expectedClassName)) {
454 const std::string linkedAttr =
456 const std::string linkedFieldName =
458 const std::type_info* linkedTi = nullptr;
459 if (::fieldExists(linkedFieldName, *m_inTuple)) {
460 linkedTi =
461 auxFieldType(m_inTuple->GetModel().GetConstField(linkedFieldName));
462 }
463 if (linkedTi) {
464 linkedAuxId = registry.getAuxID(
465 *linkedTi, linkedAttr, "",
467 }
468 if (linkedAuxId == SG::null_auxid) {
469 ::Error("xAOD::RAuxStore::setupAuxField",
470 "Could not find linked variable for %s type %s", auxName.data(),
471 expectedClassName.c_str());
472 }
473 }
474
475 // Check for an auxiliary ID for this field:
476 SG::auxid_t auxid =
477 registry.getAuxID(*ti, auxNameStr, "", flags, linkedAuxId);
478
479 // First try to find a compiled factory for the vector type:
480 if (auxid == SG::null_auxid) {
481
482 // Construct the name of the factory's class:
483 // But be careful --- if we don't exactly match the name
484 // in TClassTable, then we may trigger autoparsing. Besides the
485 // resource usage that implies, that can lead to crashes in dbg
486 // builds due to cling bugs.
487 std::string typeName = Utils::getTypeName(*ti);
488 if (typeName.starts_with("std::vector<"))
489 typeName.erase(0, 5);
490 std::string factoryClassName =
491 "SG::AuxTypeVectorFactory<" + typeName + ",allocator<" + typeName;
492 if (factoryClassName[factoryClassName.size() - 1] == '>') {
493 factoryClassName += ' ';
494 }
495 factoryClassName += "> >";
496
497 // Look for the dictionary of this type:
498 ::TClass* factoryClass = TClass::GetClass(factoryClassName.c_str());
499 if (factoryClass && factoryClass->IsLoaded()) {
500 ::TClass* baseClass = ::TClass::GetClass("SG::IAuxTypeVectorFactory");
501 if (baseClass && baseClass->IsLoaded()) {
502 const Int_t offset = factoryClass->GetBaseClassOffset(baseClass);
503 if (offset >= 0) {
504 void* factoryVoidPointer = factoryClass->New();
505 if (factoryVoidPointer) {
506 unsigned long tmp =
507 reinterpret_cast<unsigned long>(factoryVoidPointer) + offset;
508 SG::IAuxTypeVectorFactory* factory =
509 reinterpret_cast<SG::IAuxTypeVectorFactory*>(tmp);
510 registry.addFactory(
511 *ti, *factory->tiAlloc(),
512 std::unique_ptr<SG::IAuxTypeVectorFactory>(factory));
513 auxid = registry.getAuxID(*ti, auxNameStr, "", flags,
514 linkedAuxId);
515 }
516 }
517 }
518 }
519 }
520
521 // If that didn't succeed, let's assign a generic factory to this type:
522 if (auxid == SG::null_auxid && linkedAuxId == SG::null_auxid) {
523 // Construct the name of the vector type:
524 std::string vectorClassName = "std::vector<" + Utils::getTypeName(*ti);
525 if (vectorClassName[vectorClassName.size() - 1] == '>') {
526 vectorClassName += ' ';
527 }
528 vectorClassName += '>';
529
530 // Get the dictionary for the type:
531 ::TClass* vectorClass = ::TClass::GetClass(vectorClassName.c_str());
532 if (vectorClass && vectorClass->IsLoaded()) {
533 auto factory = std::make_unique<TAuxVectorFactory>(vectorClass);
534 if (factory->tiAlloc()) {
535 const std::type_info* tiAlloc = factory->tiAlloc();
536 registry.addFactory(*ti, *tiAlloc, std::move(factory));
537 } else {
538 std::string tiAllocName = factory->tiAllocName();
539 registry.addFactory(*ti, tiAllocName, std::move(factory));
540 }
541 auxid = registry.getAuxID(*ti, auxNameStr, "",
543 } else {
544 ::Warning("xAOD::RAuxStore::setupAuxField",
545 "Couldn't find dictionary for type: %s",
546 vectorClassName.c_str());
547 }
548 }
549
550 // Check if we succeeded:
551 if (auxid == SG::null_auxid) {
552 if (linkedAuxId != SG::null_auxid) {
553 ::Error("xAOD::RAuxStore::setupAuxField",
554 XAOD_MESSAGE("Dynamic ROOT vector factory not implemented for "
555 "linked types; field \"%s\""),
556 field.GetFieldName().c_str());
557 } else {
558 ::Error("xAOD::RAuxStore::setupAuxField",
559 XAOD_MESSAGE("Couldn't assign auxiliary ID to field \"%s\""),
560 field.GetFieldName().c_str());
561 }
562 return StatusCode::FAILURE;
563 }
564
565 // Remember the auxiliary ID:
566 m_data.m_auxIDs.insert(auxid);
567 return StatusCode::SUCCESS;
568 }
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
SG::auxid_t getAuxID(const std::string &name, const std::string &clsname="", const Flags flags=Flags::None, const SG::auxid_t linkedVariable=SG::null_auxid)
Look up a name -> auxid_t mapping.
SG::auxid_t findAuxID(const std::string &name, const std::string &clsname="") const
Look up a name -> auxid_t mapping.
static bool isLinkedName(const std::string &name)
Test if a variable name corresponds to a linked variable.
static std::string linkedName(const std::string &name)
Given a variable name, return the name of the corresponding linked variable.
static bool classNameHasLink(const std::string &className)
Test to see if a class name corresponds to a class with a linked variable.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
const IAuxTypeVectorFactory * addFactory(const std::type_info &ti, const std::type_info &ti_alloc, std::unique_ptr< const IAuxTypeVectorFactory > factory)
Add a new type -> factory mapping.
virtual const std::type_info * tiAlloc() const =0
Return the type_info of the vector allocator.
AuxVarFlags
Additional flags to qualify an auxiliary variable.
Definition AuxTypes.h:58
@ SkipNameCheck
Definition AuxTypes.h:81
@ Linked
Mark that this variable is linked to another one.
Definition AuxTypes.h:77
static const auxid_t null_auxid
To signal no aux data item.
Definition AuxTypes.h:30
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
std::string getTypeName(const std::type_info &ti)
This function is necessary in order to create type names that ROOT can understand.
const std::type_info * auxFieldType(const ROOT::RFieldBase &field, std::string *expectedClassName=nullptr)
This function retrieves the type information for a given auxiliary field.

Member Data Documentation

◆ m_data

Members& xAOD::RAuxStore::impl::m_data

Variables coming from AuxStoreBase.

Definition at line 571 of file RAuxStore.cxx.

◆ m_entry

::Long64_t xAOD::RAuxStore::impl::m_entry

The entry to load from the ntuple.

Definition at line 582 of file RAuxStore.cxx.

◆ m_fields

std::vector<std::unique_ptr<RFieldHandle> > xAOD::RAuxStore::impl::m_fields

Fields containing the various auxiliary variables.

Definition at line 585 of file RAuxStore.cxx.

◆ m_fieldsWritten

std::vector<bool> xAOD::RAuxStore::impl::m_fieldsWritten

"Write status" of the different variables

Definition at line 587 of file RAuxStore.cxx.

◆ m_inputScanned

bool xAOD::RAuxStore::impl::m_inputScanned = false

"Scan status" of the input RNTuple

Definition at line 579 of file RAuxStore.cxx.

◆ m_inTuple

ROOT::RNTupleReader* xAOD::RAuxStore::impl::m_inTuple = nullptr

The ntuple being read from.

Definition at line 574 of file RAuxStore.cxx.

◆ m_missingFields

std::vector<bool> xAOD::RAuxStore::impl::m_missingFields

Mark fields we've found to be missing.

Definition at line 589 of file RAuxStore.cxx.

◆ m_mutex

mutex_t xAOD::RAuxStore::impl::m_mutex
mutable

Mutex object used for multithreaded synchronisation.

Definition at line 592 of file RAuxStore.cxx.

◆ m_outTuple

ROOT::RNTupleWriter* xAOD::RAuxStore::impl::m_outTuple = nullptr

The ntuple being written to.

Definition at line 576 of file RAuxStore.cxx.


The documentation for this struct was generated from the following file: