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

Public Member Functions

StatusCode scanInputTree ()
 Scan the input TTree for auxiliary branches.
const std::type_info * auxBranchType (::TBranch &br, std::string_view auxName, bool staticBranch, std::string *expectedClassName=nullptr)
 Find the type_info to use as the aux type for a given branch.
StatusCode setupAuxBranch (::TBranch &br, std::string_view auxName, bool staticBranch)
 Register one input branch as an available auxiliary variable.

Public Attributes

Membersm_data
 Variables coming from AuxStoreBase.
int m_basketSize = 2048
 The basket size for the output branches.
int m_splitLevel = 0
 The split level for the output branches.
::TTree * m_inTree = nullptr
 The TTree being read from.
::TTree * m_outTree = nullptr
 The TTree being written to.
bool m_inputScanned = false
 "Scan status" of the input TTree
std::vector< std::unique_ptr< TBranchHandle > > m_branches
 Branches reading the various auxiliary variables.
std::vector< boolm_branchesWritten
 "Write status" of the different variables
std::vector< boolm_missingBranches
 Mark branches we've found to be missing.
mutex_t m_mutex
 Mutex object used for multithreaded synchronisation.

Detailed Description

Definition at line 423 of file TAuxStore.cxx.

Member Function Documentation

◆ auxBranchType()

const std::type_info * xAOD::TAuxStore::impl::auxBranchType ( ::TBranch & br,
std::string_view auxName,
bool staticBranch,
std::string * expectedClassName = nullptr )
inline

Find the type_info to use as the aux type for a given branch.

Definition at line 545 of file TAuxStore.cxx.

547 {
548
549 // Get the branch's type:
550 ::TClass* expectedClass = nullptr;
551 ::EDataType expectedType = kOther_t;
552 if (br.GetExpectedType(expectedClass, expectedType) &&
553 ((!staticBranch) || (!auxName.starts_with("m_")))) {
554 ::Warning("xAOD::TAuxStore::impl::auxBranchType",
555 "Couldn't get the type of branch \"%s\"", br.GetName());
556 }
557
558 // Check for schema evolution:
559 // If a branch has automatic schema evolution from one class to another,
560 // then what we get from GetExpectedType will be the on-disk class.
561 // What we have in memory is given by GetCurrentClass.
562 if (expectedClass) {
563 if (TBranchElement* bre = dynamic_cast<TBranchElement*>(&br)) {
564 TClass* newClass = bre->GetCurrentClass();
565 if (newClass && newClass != expectedClass) {
566 expectedClass = newClass;
567 }
568 }
569 if (expectedClassName) {
570 *expectedClassName = expectedClass->GetName();
571 }
572 }
573
574 // If this is a primitive variable, and we're still not sure whether this
575 // is a store for an object or a container, the answer is given...
576 if ((!expectedClass) &&
577 (m_data.m_structMode == EStructMode::kUndefinedStore)) {
578 m_data.m_structMode = EStructMode::kObjectStore;
579 }
580
581 // Get the type_info of the branch.
582 const std::type_info* ti = nullptr;
583 if (m_data.m_structMode == EStructMode::kObjectStore) {
584 if (expectedClass) {
585 ti = expectedClass->GetTypeInfo();
586 } else {
587 ti = &(Utils::getTypeInfo(expectedType));
588 }
589 } else {
590 if (!expectedClass) {
591 if ((!staticBranch) || (!auxName.starts_with("m_"))) {
592 ::Warning("xAOD::TAuxStore::impl::auxBranchType",
593 "Couldn't get the type of branch \"%s\"", br.GetName());
594 }
595 } else {
596 ::TVirtualCollectionProxy* prox = expectedClass->GetCollectionProxy();
597
598 if (!prox) {
599 TClass* cl2 = details::lookupVectorType(*expectedClass);
600 if (cl2) {
601 prox = cl2->GetCollectionProxy();
602 }
603 }
604
605 if (!prox) {
606 if ((!staticBranch) || (!auxName.starts_with("m_"))) {
607 ::Warning("xAOD::TAuxStore::impl::auxBranchType",
608 "Couldn't get the type of branch \"%s\"", br.GetName());
609 }
610 } else {
611 if (prox->GetValueClass()) {
612 ti = prox->GetValueClass()->GetTypeInfo();
613 } else {
614 ti = &(Utils::getTypeInfo(prox->GetType()));
615 }
616 }
617 }
618 }
619
620 return ti;
621 }
@ 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 ...
TClass * lookupVectorType(TClass &cl)
Internal function used by xAOD::TAuxStore and xAOD::RAuxStore.
Members & m_data
Variables coming from AuxStoreBase.

◆ scanInputTree()

StatusCode xAOD::TAuxStore::impl::scanInputTree ( )
inline

Scan the input TTree for auxiliary branches.

When writing an output tree, while reading information from an input tree, it can often happen that we want to copy the contents of some variables that we don't actually need during the event processing of this particular job. Since the user doesn't ask for all the possible input variables, this function needs to look at the input TTree, and try to figure out which of the branches in the tree belong to this object.

The function creates a "proper" or "virtual" auxiliary ID for each of the branches found, so they can be referenced in the "usual way" in the other parts of the code later on.

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

Definition at line 442 of file TAuxStore.cxx.

442 {
443
444 // Check if an input tree is even available:
445 if (!m_inTree) {
446 // It's not an error if it isn't.
447 return StatusCode::SUCCESS;
448 }
449
450 // Check if the input was already scanned:
451 if (m_inputScanned) {
452 return StatusCode::SUCCESS;
453 }
454
455 // Get a list of all branches in the tree:
456 TObjArray* branches = m_inTree->GetListOfBranches();
457
458 // Check each of them:
459 for (Int_t i = 0; i < branches->GetEntriesFast(); ++i) {
460
461 // The name of this top-level branch:
462 const TString brName = branches->At(i)->GetName();
463
464 // Access the branch pointer:
465 TBranch* br = dynamic_cast<TBranch*>(branches->At(i));
466 if (!br) {
467 ::Fatal("xAOD::TAuxStore::impl::scanInputTree",
468 XAOD_MESSAGE("Logic error detected"));
469 }
470
471 // For top-level stores let's scan the static branches as well:
472 if (m_data.m_topStore && (brName == m_data.m_prefix)) {
473
474 // Make sure the object has been instantiated so that aux data
475 // registrations will have been done.
476 br->SetAddress(0);
477
478 // Get a list of its sub-branches:
479 TObjArray* sbranches = br->GetListOfBranches();
480
481 // ...and then loop over them:
482 for (Int_t j = 0; j < sbranches->GetEntriesFast(); ++j) {
483
484 // The name of the sub-branch:
485 const TString brName = sbranches->At(j)->GetName();
486
487 // Try to make a variable name out of the branch name:
488 const TString auxName =
489 brName(brName.Index(".") + 1, brName.Length());
490
491 // Skip this entry if it refers to a base class:
492 if (auxName.BeginsWith("xAOD::") || auxName.BeginsWith("SG::") ||
493 (auxName == "ILockable")) {
494 continue;
495 }
496
497 // The sub-branch:
498 ::TBranch* sbr = dynamic_cast< ::TBranch*>(sbranches->At(j));
499 if (!sbr) {
500 ::Fatal("xAOD::TAuxStore::impl::scanInputTree",
501 XAOD_MESSAGE("Logic error detected"));
502 }
503
504 // Leave the rest up to the function that is shared with the
505 // dynamic branches:
506 //cppcheck-suppress nullPointerRedundantCheck
507 RETURN_CHECK("xAOD::TAuxStore::impl::scanInputTree",setupAuxBranch(*sbr, auxName, true));
508 }
509
510 // Don't check the rest of the loop's body:
511 continue;
512 }
513
514 // Check if it has the right prefix to be a dynamic variable:
515 if (!brName.BeginsWith(m_data.m_dynPrefix.data())) {
516 continue;
517 }
518 // It's possible to create dynamic variables with an empty name
519 // as well. Which is a bug. Such variables are just ignored
520 // for now.
521 if (brName == m_data.m_dynPrefix) {
522 ::Warning("xAOD::TAuxStore::impl::scanInputTree",
523 "Dynamic branch with empty name found on container: %s",
524 m_data.m_prefix.data());
525 continue;
526 }
527
528 // The auxiliary property name:
529 const TString auxName = brName(brName.Index(".") + 1, brName.Length());
530
531 // Leave the rest up to the function that is shared with the
532 // dynamic branches:
533 RETURN_CHECK("xAOD::TAuxStore::impl::scanInputTree",
534 setupAuxBranch(*br, auxName, false));
535 }
536
537 // Okay, the input was successfully scanned:
538 m_inputScanned = true;
539
540 // Return gracefully:
541 return StatusCode::SUCCESS;
542 }
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
#define RETURN_CHECK(CONTEXT, EXP)
Helper macro for checking return codes in a compact form in the code.
Definition ReturnCheck.h:26
StatusCode setupAuxBranch(::TBranch &br, std::string_view auxName, bool staticBranch)
Register one input branch as an available auxiliary variable.
::TTree * m_inTree
The TTree being read from.
bool m_inputScanned
"Scan status" of the input TTree

◆ setupAuxBranch()

StatusCode xAOD::TAuxStore::impl::setupAuxBranch ( ::TBranch & br,
std::string_view auxName,
bool staticBranch )
inline

Register one input branch as an available auxiliary variable.

This function takes care of assigning an auxiliary ID to a given branch. It tries its best to find an auxiliary vector factory for the branch's type, but if it fails, it still falls back to using SG::AuxTypePlaceholder as the type. In which case of course only dumb copying will be possible for the given branch. (And no vector operations on the branch's payload until the variable of the branch is accessed explicitly.)

Parameters
brPointer to the branch under investigation
auxNameThe name of the auxiliary property, extracted from the branch's name
staticBranchkTRUE if this is a "static branch", and kFALSE if it's a dynamic one
Returns
StatusCode::SUCCESS if the function was successful, something else otherwise

Definition at line 641 of file TAuxStore.cxx.

642 {
643
644 // Get the (on disk) type of the branch.
645 std::string expectedClassName;
646 const std::type_info* ti =
647 auxBranchType(br, auxName, staticBranch, &expectedClassName);
648 if (ti == nullptr) {
649 // If we didn't find a type_info for the branch, give up now...
650 return StatusCode::SUCCESS;
651 }
652
653 // Get the registry:
654 SG::AuxTypeRegistry& registry = SG::AuxTypeRegistry::instance();
655
656 // Check if the registry already knows this variable name. If yes, let's
657 // use the type known by the registry. To be able to deal with simple
658 // schema evolution in dynamic branches.
659 if (const SG::auxid_t regAuxid = registry.findAuxID(std::string{auxName});
660 regAuxid != SG::null_auxid) {
661 m_data.m_auxIDs.insert(regAuxid);
662 return StatusCode::SUCCESS;
663 }
664
666 SG::auxid_t linked_auxid = SG::null_auxid;
667
668 if (SG::AuxTypeRegistry::isLinkedName(std::string{auxName})) {
670 } else if (SG::AuxTypeRegistry::classNameHasLink(expectedClassName)) {
671 std::string linkedAttr =
672 SG::AuxTypeRegistry::linkedName(std::string{auxName});
673 std::string linkedBranch = SG::AuxTypeRegistry::linkedName(br.GetName());
674 ::TBranch* lbr = m_inTree->GetBranch(linkedBranch.c_str());
675 const std::type_info* lti = nullptr;
676 if (lbr) {
677 lti = auxBranchType(*lbr, linkedAttr, staticBranch);
678 }
679 if (lti) {
680 linked_auxid = registry.getAuxID(
681 *lti, linkedAttr, "",
683 }
684 if (linked_auxid == SG::null_auxid) {
685 ::Error("xAOD::TAuxStore::impl::setupAuxBranch",
686 "Could not find linked variable for %s type %s", auxName.data(),
687 expectedClassName.c_str());
688 }
689 }
690
691 // Check for an auxiliary ID for this branch:
692 SG::auxid_t auxid =
693 registry.getAuxID(*ti, std::string{auxName}, "", flags, linked_auxid);
694
695 // First try to find a compiled factory for the vector type:
696 if (auxid == SG::null_auxid) {
697
698 // Construct the name of the factory's class:
699 // But be careful --- if we don't exactly match the name
700 // in TClassTable, then we may trigger autoparsing. Besides the
701 // resource usage that implies, that can lead to crashes in dbg
702 // builds due to cling bugs.
703 std::string tn = Utils::getTypeName(*ti);
704 if (tn.starts_with("std::vector<")) {
705 tn.erase(0, 5);
706 }
707 std::string fac_class_name =
708 "SG::AuxTypeVectorFactory<" + tn + ",allocator<" + tn;
709 if (fac_class_name[fac_class_name.size() - 1] == '>') {
710 fac_class_name += ' ';
711 }
712 fac_class_name += "> >";
713
714 // Look for the dictionary of this type:
715 ::TClass* fac_class = TClass::GetClass(fac_class_name.c_str());
716 if (fac_class && fac_class->IsLoaded()) {
717 ::TClass* base_class = ::TClass::GetClass("SG::IAuxTypeVectorFactory");
718 if (base_class && base_class->IsLoaded()) {
719 const Int_t offs = fac_class->GetBaseClassOffset(base_class);
720 if (offs >= 0) {
721 void* fac_vp = fac_class->New();
722 if (fac_vp) {
723 unsigned long tmp =
724 reinterpret_cast<unsigned long>(fac_vp) + offs;
725 SG::IAuxTypeVectorFactory* fac =
726 reinterpret_cast<SG::IAuxTypeVectorFactory*>(tmp);
727 registry.addFactory(
728 *ti, *fac->tiAlloc(),
729 std::unique_ptr<SG::IAuxTypeVectorFactory>(fac));
730 auxid = registry.getAuxID(*ti, std::string{auxName}, "", flags,
731 linked_auxid);
732 }
733 }
734 }
735 }
736 }
737
738 // If that didn't succeed, let's assign a generic factory to this type:
739 if (auxid == SG::null_auxid && linked_auxid == SG::null_auxid) {
740
741 // Construct the name of the vector type:
742 std::string vec_class_name = "std::vector<" + Utils::getTypeName(*ti);
743 if (vec_class_name[vec_class_name.size() - 1] == '>') {
744 vec_class_name += ' ';
745 }
746 vec_class_name += '>';
747
748 // Get the dictionary for the type:
749 ::TClass* vec_class = ::TClass::GetClass(vec_class_name.c_str());
750 if (vec_class && vec_class->IsLoaded()) {
751 auto fac = std::make_unique<TAuxVectorFactory>(vec_class);
752 if (fac->tiAlloc()) {
753 const std::type_info* tiAlloc = fac->tiAlloc();
754 registry.addFactory(*ti, *tiAlloc, std::move(fac));
755 } else {
756 std::string tiAllocName = fac->tiAllocName();
757 registry.addFactory(*ti, tiAllocName, std::move(fac));
758 }
759 auxid = registry.getAuxID(*ti, std::string{auxName}, "",
761 } else {
762 ::Warning("xAOD::TAuxStore::impl::setupAuxBranch",
763 "Couldn't find dictionary for type: %s",
764 vec_class_name.c_str());
765 }
766 }
767
768 // Check if we succeeded:
769 if (auxid == SG::null_auxid) {
770 if (linked_auxid != SG::null_auxid) {
771 ::Error("xAOD::TAuxStore::impl::setupAuxBranch",
772 XAOD_MESSAGE("Dynamic ROOT vector factory not implemented for "
773 "linked types; branch "
774 "\"%s\""),
775 br.GetName());
776 } else {
777 ::Error("xAOD::TAuxStore::impl::setupAuxBranch",
778 XAOD_MESSAGE("Couldn't assign auxiliary ID to branch "
779 "\"%s\""),
780 br.GetName());
781 }
782 return StatusCode::FAILURE;
783 }
784
785 // Remember the auxiliary ID:
786 m_data.m_auxIDs.insert(auxid);
787 return StatusCode::SUCCESS;
788 }
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 * auxBranchType(::TBranch &br, std::string_view auxName, bool staticBranch, std::string *expectedClassName=nullptr)
Find the type_info to use as the aux type for a given branch.

Member Data Documentation

◆ m_basketSize

int xAOD::TAuxStore::impl::m_basketSize = 2048

The basket size for the output branches.

Definition at line 794 of file TAuxStore.cxx.

◆ m_branches

std::vector<std::unique_ptr<TBranchHandle> > xAOD::TAuxStore::impl::m_branches

Branches reading the various auxiliary variables.

Definition at line 807 of file TAuxStore.cxx.

◆ m_branchesWritten

std::vector<bool> xAOD::TAuxStore::impl::m_branchesWritten

"Write status" of the different variables

Definition at line 809 of file TAuxStore.cxx.

◆ m_data

Members& xAOD::TAuxStore::impl::m_data

Variables coming from AuxStoreBase.

Definition at line 791 of file TAuxStore.cxx.

◆ m_inputScanned

bool xAOD::TAuxStore::impl::m_inputScanned = false

"Scan status" of the input TTree

Definition at line 804 of file TAuxStore.cxx.

◆ m_inTree

::TTree* xAOD::TAuxStore::impl::m_inTree = nullptr

The TTree being read from.

Definition at line 799 of file TAuxStore.cxx.

◆ m_missingBranches

std::vector<bool> xAOD::TAuxStore::impl::m_missingBranches

Mark branches we've found to be missing.

(Because TTree::GetBranch is very expensive.)

Definition at line 812 of file TAuxStore.cxx.

◆ m_mutex

mutex_t xAOD::TAuxStore::impl::m_mutex
mutable

Mutex object used for multithreaded synchronisation.

Definition at line 815 of file TAuxStore.cxx.

◆ m_outTree

::TTree* xAOD::TAuxStore::impl::m_outTree = nullptr

The TTree being written to.

Definition at line 801 of file TAuxStore.cxx.

◆ m_splitLevel

int xAOD::TAuxStore::impl::m_splitLevel = 0

The split level for the output branches.

Definition at line 796 of file TAuxStore.cxx.


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