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.
 impl (const EventContext &ctx, Members &data)

Public Attributes

const EventContext & m_ctx
 The context for this event.
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 = 0
 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 250 of file RAuxStore.cxx.

Constructor & Destructor Documentation

◆ impl()

xAOD::RAuxStore::impl::impl ( const EventContext & ctx,
Members & data )
inline

Definition at line 571 of file RAuxStore.cxx.

572 : m_ctx(ctx), m_data(data)
573 {}
const EventContext & m_ctx
The context for this event.
Members & m_data
Variables coming from AuxStoreBase.

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 351 of file RAuxStore.cxx.

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

◆ 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 259 of file RAuxStore.cxx.

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

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

const EventContext& xAOD::RAuxStore::impl::m_ctx

The context for this event.

Definition at line 576 of file RAuxStore.cxx.

◆ m_data

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

Variables coming from AuxStoreBase.

Definition at line 579 of file RAuxStore.cxx.

◆ m_entry

::Long64_t xAOD::RAuxStore::impl::m_entry = 0

The entry to load from the ntuple.

Definition at line 590 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 593 of file RAuxStore.cxx.

◆ m_fieldsWritten

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

"Write status" of the different variables

Definition at line 595 of file RAuxStore.cxx.

◆ m_inputScanned

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

"Scan status" of the input RNTuple

Definition at line 587 of file RAuxStore.cxx.

◆ m_inTuple

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

The ntuple being read from.

Definition at line 582 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 597 of file RAuxStore.cxx.

◆ m_mutex

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

Mutex object used for multithreaded synchronisation.

Definition at line 600 of file RAuxStore.cxx.

◆ m_outTuple

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

The ntuple being written to.

Definition at line 584 of file RAuxStore.cxx.


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