ATLAS Offline Software
Loading...
Searching...
No Matches
TConvertingBranchElement Class Reference

A variant of TBranchElement that can call converters when reading objects in split mode. More...

#include <TConvertingBranchElement.h>

Inheritance diagram for TConvertingBranchElement:
Collaboration diagram for TConvertingBranchElement:

Public Member Functions

 TConvertingBranchElement ()
 Constructor.
virtual ~TConvertingBranchElement ()
 Destructor.
virtual Int_t GetEntry (Long64_t entry, Int_t getall)
 Read all branches into the previously-declared object.
virtual void Streamer (TBuffer &R__b)
 Read or write this object.
virtual void SetAddress (void *add)
 Set the address of the object to use for I/O.
virtual void ResetAddress ()
 Reset branch addresses and maybe delete the object.

Static Public Member Functions

static void Initialize ()
 Set up to allow for conversions in split mode.
static void SetDoDel (bool flag)
 Set the deletion flag.

Protected Member Functions

virtual void InitInfo ()
 Initialize the TStreamerInfo pointer.
virtual void InitializeOffsets ()
 Initialize data member offsets.
void ReadLeavesCollectionConverting (TBuffer &b)
 Read leaves into I/O buffers for this branch.
void ReadLeavesMemberBranchCountConverting (TBuffer &b)

Private Member Functions

void BuildConvertedElisions ()
 Add dummy nodes if needed to recover the correct tree structure.
void CheckForConversion ()
 Check to see if we need to worry about conversions for this branch.
void ConvResetType ()
 Recursively reset the type field of containers in conversions.
Int_t ReadSubBranches (Long64_t entry, Int_t getall, bool dont_reset)
 @branch Read in the subbranches of this branch.
TConvertingBranchElementoperator= (const TConvertingBranchElement &)
 If true, try to delete the.
 TConvertingBranchElement (const TConvertingBranchElement &)

Static Private Member Functions

static void * new_TConvertingBranchElement (void *p)
 new() method for this object.

Private Attributes

TVirtualConverterfConv
TClass * fConvClass
 Conversion for this branch.
char * fConvObject
 Class for conversion.
TObjArray * fConvOrigBranches
 Pointer to tmp obj used for conversion.
Int_t fConvOrigType
 Saved branch list. If we change.
bool fConvContainerFlag
 Saved branch type. The original.
bool fConvDontReset
 True if we're doing a container.

Static Private Attributes

static constexpr unsigned int kIsDummy = BIT(20)
 Flag used to mark dummy nodes created by BuildConvertedElisions.
static std::atomic< bool > fgDoDel = false
 Flag that the next read should.

Detailed Description

A variant of TBranchElement that can call converters when reading objects in split mode.

Definition at line 64 of file TConvertingBranchElement.h.

Constructor & Destructor Documentation

◆ TConvertingBranchElement() [1/2]

TConvertingBranchElement::TConvertingBranchElement ( )

Constructor.

Definition at line 287 of file TConvertingBranchElement.cxx.

288: fConv(nullptr)
289, fConvClass(nullptr)
290, fConvObject(nullptr)
291, fConvOrigBranches(nullptr)
292, fConvOrigType(-1)
293, fConvContainerFlag(false)
294, fConvDontReset(false)
295{
296}
Int_t fConvOrigType
Saved branch list. If we change.
bool fConvDontReset
True if we're doing a container.
bool fConvContainerFlag
Saved branch type. The original.
TClass * fConvClass
Conversion for this branch.
char * fConvObject
Class for conversion.
TObjArray * fConvOrigBranches
Pointer to tmp obj used for conversion.

◆ ~TConvertingBranchElement()

TConvertingBranchElement::~TConvertingBranchElement ( )
virtual

Destructor.

Constructor.

Get rid of any temporary objects which we made.

Definition at line 304 of file TConvertingBranchElement.cxx.

305{
306 // If we made a temporary object instance for conversions, delete it.
307 if (fConv && fConvObject)
308 fConv->DeletePersObj (fConvObject);
309
310 // If we contain dummy branches, delete them here.
311 // In that case, we should also delete the saved original branch list.
312 if (fConvOrigBranches) {
313 Int_t nbranches = fBranches.GetEntriesFast();
314 for (Int_t i = 0; i < nbranches; i++) {
315 if (fBranches[i]->TestBit (kIsDummy))
316 delete fBranches[i];
317 }
318 fBranches = *fConvOrigBranches;
319 delete fConvOrigBranches;
320 }
321
322 // If we're a dummy ourselves, we should delete the branch list.
323 if (TestBit (kIsDummy))
324 fBranches.Clear();
325
326 // Try to delete the object, if requested.
327 if (fgDoDel)
329}
virtual void ResetAddress()
Reset branch addresses and maybe delete the object.
static std::atomic< bool > fgDoDel
Flag that the next read should.
static constexpr unsigned int kIsDummy
Flag used to mark dummy nodes created by BuildConvertedElisions.

◆ TConvertingBranchElement() [2/2]

TConvertingBranchElement::TConvertingBranchElement ( const TConvertingBranchElement & )
private

Member Function Documentation

◆ BuildConvertedElisions()

void TConvertingBranchElement::BuildConvertedElisions ( )
private

Add dummy nodes if needed to recover the correct tree structure.

◆ CheckForConversion()

void TConvertingBranchElement::CheckForConversion ( )
private

Check to see if we need to worry about conversions for this branch.

Add dummy nodes if needed to recover the correct tree structure.

Set up member variables if so.

Given a TBranchElement tree structure, Root will elide some of the intermediate tree nodes. For example, given:

a a.b a.b.c a.b.c.d1 a.b.c.d2

Root will elide the c' node --- so one has node a', with child a.b', with children a.b.c.d1' and `a.b.c.d2'.

This greatly complicates the process of running conversions, if c' has a conversion. So, what we do is if we determine that a conversion is needed, we modify the tree to reinsert the elided nodes. These nodes will have the kIsDummy flag set. Further, if we do that, we remember the original branch list from the parent node (a.b' in the above example), so that if the structure is written, we can write the original, elided structure. */ void TConvertingBranchElement::BuildConvertedElisions() { Can't do anything if we can't find the TStreamerInfo. if (!fInfo) return;

The class of this branch's element. TClass* topclass = nullptr; if (fID < 0) topclass = gROOT->GetClass (GetClassName()); else { std::string s = BasenameOfBranch (GetName()); int offset = 0; TStreamerElement* elt = fInfo->GetStreamerElement(s.c_str(), offset); if (elt) topclass = elt->GetClass(); } if (!topclass) return;

Here's the plan. We start by adding all branches to the branches list. Then we walk through the members of this class (using the TStreamerInfo). If this member is contained in the branch list, then we remove it from branches and add it to noconv_branches (it wasn't elided). If it's not in the branch list, then it was elided. We look then to see if the corresponding class (or anything it contains) requires a conversion. If so, then we build a dummy node for it, and add the dummy to conv_dummies. We then look through branches, find any that actually belong to the new dummy node, remove them from branches, and add them to the dummy. If no conversion is needed, then we don't need to do anything at this point.

When we're done scanning all the members of the class, we take anything remaining in branches and move to noconv_branches (these correspond to branches with elided nodes, but with no conversions required.) Then, if we made any dummy nodes, then we replace our branch list with the concatenation of the dummy list and the noconv_branches list (saving the original branch list so that we can restore it later, if needed). std::vector<TBranch*> conv_dummies; std::vector<TBranch*> noconv_branches; std::vector<TBranch*> branches;

To start with, add all our child branches to branches. Int_t nbranches = fBranches.GetEntriesFast(); branches.reserve (nbranches); for (Int_t i=0; i < nbranches; i++) { TBranch* b = dynamic_cast<TBranchElement*> (fBranches[i]); if (b) branches.push_back (b); }

Get the TStreamerInfo for this class. If this class is a container, then we actually want to get the TStreamerInfo for the contained class. TStreamerInfo* info = GetStreamerInfoFromFile (topclass, this); if (!info && fType == 4) { TVirtualCollectionProxy* proxy = topclass->GetCollectionProxy(); if (!proxy) return; topclass = proxy->GetValueClass(); if (!topclass) return; info = GetStreamerInfoFromFile (topclass, this); } else if (fType == 3) { topclass = gROOT->GetClass (fClonesName); if (!topclass) return; info = GetStreamerInfoFromFile (topclass, this); } if (!info) return;

Now walk through all elements in the TStreamerInfo. TObjArray* elems = info->GetElements(); size_t ndata = elems->GetEntriesFast(); for (size_t ielt = 0; ielt < ndata; ++ielt) { The element. TStreamerElement* elt = reinterpret_cast<TStreamerElement*> (elems->At(ielt));

See if there's a branch corresponding to this element. If so, add it to the noconv list. bool found = false; for (unsigned i=0; i < branches.size(); i++) { TBranchElement* b = dynamic_cast<TBranchElement*>(branches[i]);

Test branch to see if corresponds to the SI element @ elt. if (b && gROOT->GetClass (b->GetClassName()) == topclass) { if (dynamic_cast<TStreamerBase*> (elt) != 0 && b->GetType() == 1) { For a base class, the test above is sufficient. found = true; } else { Test the name. std::string s = BasenameOfBranch (b->GetName()); if (s == elt->GetName()) found = true; }

if (found) { We found a branch matching the element. Move the branch from branches to noconv_branches, and exit the loop over branches. noconv_branches.push_back (b); branches.erase (branches.begin()+i); break; } } }

if (!found) { We didn't find a branch corresponding to this element. Maybe this is an elided class. If this is a class type, then see if it or anything it contains has a conversion. If so, then build a dummy node for it. TClass* cl = elt->GetClass(); if (cl && DoesClassNeedConv (cl, this)) { It needs a conversion. Make a dummy node. TClass* clparent = gROOT->GetClass (info->GetName()); TConvertingBranchElement* dum = new TConvertingBranchElement; dum->SetBit (kIsDummy); TString name; if (fID < 0) name = elt->GetName(); else { name = GetName(); if (fType == 1) { Ssiz_t i = name.Length()-1; while (i >= 0 && name[i] != '.') –i; name.Remove (i+1); } else name += "."; name += elt->GetName(); } dum->SetName (name); dum->SetTitle (name); TString namedot = name + "."; dum->SetParentClass (clparent); dum->SetClassName (info->GetName()); dum->fCheckSum = info->GetCheckSum(); dum->fClassVersion = topclass->GetClassVersion(); dum->fID = ielt; dum->fTree = this->fTree; dum->fDirectory = this->fDirectory; dum->fBranchClass = topclass; if (dynamic_cast<TStreamerBase*> (elt) != nullptr) { dum->fType = 1; Ssiz_t i = namedot.Length()-2; while (i >= 0 && namedot[i] != '.') –i; namedot.Remove (i+1); } else dum->fType = 2;

Add the dummy node to conv_dummies. conv_dummies.push_back (dum);

Find all branches that are a part of this class and move them from branches to the dummy node for (unsigned i=0; i < branches.size(); ) { TString bname = branches[i]->GetName(); if (bname.Index (namedot) == 0 && (dum->fType == 2 || BaseHasField (dynamic_cast<TStreamerBase*>(elt), bname, namedot, this))) { dum->GetListOfBranches()->Add (branches[i]); if (TConvertingBranchElement* be = dynamic_cast<TConvertingBranchElement*> (branches[i])) { be->fParentClass = cl; } branches.erase (branches.begin()+i); } else { ++i; } } } } End of loop over elements. }

Any remaining branches go to noconv_branches. for (unsigned int i=0; i < branches.size(); i++) noconv_branches.push_back (branches[i]);

if (conv_dummies.size() > 0) { We made some dummies. Replace our branch list with the concatenation of the dummy list (conv_dummies) and the branches that don't need special processing (noconv_branches — because they either did not have an elision or they didn't require a conversion). fConvOrigBranches = new TObjArray; fConvOrigBranches = fBranches; fBranches.Clear(); for (unsigned int i=0; i < conv_dummies.size(); i++) fBranches.Add (conv_dummies[i]); for (unsigned int i=0; i < noconv_branches.size(); i++) fBranches.Add (noconv_branches[i]); } }

/**

Check to see if we need to worry about conversions for this branch. Set up member variables if so.

Definition at line 596 of file TConvertingBranchElement.cxx.

597{
598 // Need @c TStreamerInfo in order to do anything.
599 if (!fInfo) return;
600
601 // Restore any elided tree nodes if there's a conversion.
603
604 // See if this element is a class.
605 const char* classname = 0;
606 int checksum = 0;
607
608 if (fID < 0) {
609 // Special case for top-level branch.
610 classname = GetClassName();
611 checksum = fCheckSum;
612 }
613 else {
614 // Otherwise, we need to look at the streamerinfo element.
615 std::string s = BasenameOfBranch (GetName());
616 int offset = 0;
617 TStreamerElement* elt = fInfo->GetStreamerElement(s.c_str(), offset);
618 if (elt) {
619 TClass* cl = elt->GetClass();
620 if (cl) {
621 classname = cl->GetName();
622 TStreamerInfo* info = GetStreamerInfoFromFile (cl, this);
623 if (info)
624 checksum = info->GetCheckSum();
625 }
626 }
627 }
628
629 if (classname) {
630 // Ok, this branch represents a class.
631 // See if there's a conversion for it.
632 TVirtualConverter* conv =
633 TConverterRegistry::Instance()->GetConverter (classname, checksum);
634
635 // If there's not a conversion and this class is a container,
636 // then we need to see if something in the container needs a conversion.
637 if (!conv && (fType == 4 || fType == 3)) {
638 // Find the contained class.
639 TClass* contclass = gROOT->GetClass (fClonesName.Data());
640 if (contclass) {
641 TStreamerInfo* info = GetStreamerInfoFromFile (contclass, this);
642 if (info) {
643 // Found the contained class with its @c TStreamerInfo.
644 // See if the contained class has a conversion.
645 conv =
646 TConverterRegistry::Instance()->GetConverter (fClonesName.Data(),
647 info->GetCheckSum());
648
649 // If the contained class, or anything it contains, has a conversion,
650 // then we need to deal with conversions when reading this container.
651 if (conv || DoesClassNeedConv (contclass, this)) {
652 fConvContainerFlag = true;
654 }
655 }
656 }
657 }
658
659 if (conv) {
660 TClass* convclass = conv->GetPersClass();
661 if (convclass) {
662 // We have a conversion! Remember the converter and persistent
663 // class, and create the temporary persistent class instance.
664 fConv = conv;
665 fConvClass = convclass;
666 fConvObject = (char*)conv->NewPersObj();
667 }
668 }
669 }
670
671 // Now see if the class containing this element has a conversion.
672 if (fID > -1) {
673 TVirtualConverter* conv =
675 fCheckSum);
676 if (conv) {
677 TClass* convclass = conv->GetPersClass();
678 if (convclass) {
679 // The class containing this class has a conversion.
680 // Change the @c TStreamerInfo to correspond to the
681 // appropriate persistent class; also change the parent class
682 // pointer.
683 Bool_t optim = TStreamerInfo::CanOptimize();
684 TStreamerInfo::Optimize(kFALSE);
685 TStreamerInfo* info =
686 dynamic_cast<TStreamerInfo*> (convclass->GetStreamerInfo (0));
687 if (info)
688 fInfo = info;
689 TStreamerInfo::Optimize(optim);
690 fParentClass = convclass;
691 }
692 }
693 }
694}
static TConverterRegistry * Instance()
Return a pointer to the global registry instance.
TVirtualConverter * GetConverter(const char *name, int checksum) const
Look up a converter in the registry by name and checksum.
void ConvResetType()
Recursively reset the type field of containers in conversions.
void BuildConvertedElisions()
Add dummy nodes if needed to recover the correct tree structure.
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]

◆ ConvResetType()

void TConvertingBranchElement::ConvResetType ( )
private

Recursively reset the type field of containers in conversions.

Recursively reset the type field of container elts in conversions.

Walk recursively through all children of this node. Any of them that have a fType corresponding to a member field within a container (31 or 41) are reset to 2 (normal member).

Definition at line 738 of file TConvertingBranchElement.cxx.

739{
740 Int_t nbranches = fBranches.GetEntriesFast();
741 for (Int_t i=0; i < nbranches; i++) {
743 dynamic_cast<TConvertingBranchElement*> (fBranches[i]);
744 if (b) {
745 if (b->fType == 41 || b->fType == 31) {
746 b->fConvOrigType = b->fType;
747 b->fType = 2;
748 }
749 b->ConvResetType();
750 }
751 }
752}

◆ GetEntry()

virtual Int_t TConvertingBranchElement::GetEntry ( Long64_t entry,
Int_t getall )
virtual

Read all branches into the previously-declared object.

Parameters
entryThe ntuple row to read.
getallIf true, force reading all branches, even those previously deactivated.

If entry = 0, then use current entry number + 1. If entry < 0, then reset entry number to 0.

Returns the number of bytes read from the input buffer. If entry does not exist, then returns 0. If an I/O error occurs, then returns -1.

◆ Initialize()

void TConvertingBranchElement::Initialize ( )
static

Set up to allow for conversions in split mode.

Definition at line 335 of file TConvertingBranchElement.cxx.

336{
337}

◆ InitializeOffsets()

virtual void TConvertingBranchElement::InitializeOffsets ( )
protectedvirtual

Initialize data member offsets.

(Overridden internal method.)

◆ InitInfo()

void TConvertingBranchElement::InitInfo ( )
protectedvirtual

Initialize the TStreamerInfo pointer.

(Overridden internal method.)

(Overridden internal method.)

This gets called by GetInfo if the fInfo pointer is null. It should initialize that pointer.

Here is where we check for a conversion.

Definition at line 706 of file TConvertingBranchElement.cxx.

707{
708 // Do the standard stuff.
709 TBranchElement::InitInfo();
710
711 // Check for a conversion.
712 if (fInfo) {
713 const_cast<TConvertingBranchElement*>(this)->CheckForConversion();
714
715 // Re-find the fID.
716 const_cast<TConvertingBranchElement*>(this)->fInit = kFALSE;
717 TBranchElement::InitInfo();
718 }
719
720 // Change ReadLeaves implementation if needed.
721 // The base class implementation works here except for the case
722 // of an STL associative container. We need to change the code
723 // for that to notice @c fConvDontReset and to use @c ReadSubBranches.
724 if (fType == 4)
726 else if (fType == 2 && (fConvOrigType == 41 || fConvOrigType == 31))
728}
void ReadLeavesMemberBranchCountConverting(TBuffer &b)
void ReadLeavesCollectionConverting(TBuffer &b)
Read leaves into I/O buffers for this branch.
void CheckForConversion()
Check to see if we need to worry about conversions for this branch.

◆ new_TConvertingBranchElement()

void * TConvertingBranchElement::new_TConvertingBranchElement ( void * p)
staticprivate

new() method for this object.

Parameters
pAddress for placement new, or nullptr.
Returns
Address of the new object.

This is installed as the New method in TBranchElement's TClass. Thus, when we read from a file a TBranchElement, we actually make an instance of this class.

Parameters
pAddress for placement new, or 0.
Returns
Address of the new object.

This is installed as the New method in TBranchElement's TClass. Thus, when we read from a file a TBranchElement, we actually make an instance of this class.

Definition at line 349 of file TConvertingBranchElement.cxx.

350{
351 if (p)
352 return new (p) TConvertingBranchElement;
353 return new TConvertingBranchElement;
354}

◆ operator=()

TConvertingBranchElement & TConvertingBranchElement::operator= ( const TConvertingBranchElement & )
private

If true, try to delete the.

◆ ReadLeavesCollectionConverting()

void TConvertingBranchElement::ReadLeavesCollectionConverting ( TBuffer & b)
protected

Read leaves into I/O buffers for this branch.

Parameters
bRoot I/O buffer.

◆ ReadLeavesMemberBranchCountConverting()

void TConvertingBranchElement::ReadLeavesMemberBranchCountConverting ( TBuffer & b)
protected

◆ ReadSubBranches()

Int_t TConvertingBranchElement::ReadSubBranches ( Long64_t entry,
Int_t getall,
bool dont_reset )
private

@branch Read in the subbranches of this branch.

Parameters
entryThe entry number to read.
getallIf true, read all branches, even if disabled.
dont_resetIf true, don't reset the TBuffer read pointer.
Returns
The number of bytes read.

◆ ResetAddress()

virtual void TConvertingBranchElement::ResetAddress ( )
virtual

Reset branch addresses and maybe delete the object.

◆ SetAddress()

virtual void TConvertingBranchElement::SetAddress ( void * add)
virtual

Set the address of the object to use for I/O.

Parameters
addObject address.

◆ SetDoDel()

void TConvertingBranchElement::SetDoDel ( bool flag)
static

Set the deletion flag.

Parameters
flagIf true, try to delete the branch object on branch deletion.

◆ Streamer()

virtual void TConvertingBranchElement::Streamer ( TBuffer & R__b)
virtual

Read or write this object.

Parameters
R__bThe Root buffer.

Member Data Documentation

◆ fConv

TVirtualConverter* TConvertingBranchElement::fConv
private

Definition at line 195 of file TConvertingBranchElement.h.

◆ fConvClass

TClass* TConvertingBranchElement::fConvClass
private

Conversion for this branch.

Definition at line 196 of file TConvertingBranchElement.h.

◆ fConvContainerFlag

bool TConvertingBranchElement::fConvContainerFlag
private

Saved branch type. The original.

Definition at line 208 of file TConvertingBranchElement.h.

◆ fConvDontReset

bool TConvertingBranchElement::fConvDontReset
private

True if we're doing a container.

Definition at line 210 of file TConvertingBranchElement.h.

◆ fConvObject

char* TConvertingBranchElement::fConvObject
private

Class for conversion.

Definition at line 197 of file TConvertingBranchElement.h.

◆ fConvOrigBranches

TObjArray* TConvertingBranchElement::fConvOrigBranches
private

Pointer to tmp obj used for conversion.

Definition at line 198 of file TConvertingBranchElement.h.

◆ fConvOrigType

Int_t TConvertingBranchElement::fConvOrigType
private

Saved branch list. If we change.

Definition at line 203 of file TConvertingBranchElement.h.

◆ fgDoDel

std::atomic< bool > TConvertingBranchElement::fgDoDel = false
staticprivate

Flag that the next read should.

Definition at line 213 of file TConvertingBranchElement.h.

◆ kIsDummy

unsigned int TConvertingBranchElement::kIsDummy = BIT(20)
staticconstexprprivate

Flag used to mark dummy nodes created by BuildConvertedElisions.

Definition at line 155 of file TConvertingBranchElement.h.


The documentation for this class was generated from the following files: