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

Public Attributes

const EventContext & m_ctx
 The context for this event.
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 428 of file TAuxStore.cxx.

Constructor & Destructor Documentation

◆ impl()

xAOD::TAuxStore::impl::impl ( const EventContext & ctx,
Members & data,
int basketSize,
int splitLevel )
inline

Definition at line 795 of file TAuxStore.cxx.

797 {}
int splitLevel() const
Get the split level of the output branches.
int basketSize() const
Get the size of the baskets created for the output branches.
int m_basketSize
The basket size for the output branches.
Members & m_data
Variables coming from AuxStoreBase.
int m_splitLevel
The split level for the output branches.
const EventContext & m_ctx
The context for this event.

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 550 of file TAuxStore.cxx.

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

◆ 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 447 of file TAuxStore.cxx.

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

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

◆ m_branchesWritten

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

"Write status" of the different variables

Definition at line 822 of file TAuxStore.cxx.

◆ m_ctx

const EventContext& xAOD::TAuxStore::impl::m_ctx

The context for this event.

Definition at line 800 of file TAuxStore.cxx.

◆ m_data

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

Variables coming from AuxStoreBase.

Definition at line 804 of file TAuxStore.cxx.

◆ m_inputScanned

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

"Scan status" of the input TTree

Definition at line 817 of file TAuxStore.cxx.

◆ m_inTree

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

The TTree being read from.

Definition at line 812 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 825 of file TAuxStore.cxx.

◆ m_mutex

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

Mutex object used for multithreaded synchronisation.

Definition at line 828 of file TAuxStore.cxx.

◆ m_outTree

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

The TTree being written to.

Definition at line 814 of file TAuxStore.cxx.

◆ m_splitLevel

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

The split level for the output branches.

Definition at line 809 of file TAuxStore.cxx.


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