![]() |
ATLAS Offline Software
|
A variant of TBranchElement that can call converters when reading objects in split mode.
More...
#include <TConvertingBranchElement.h>
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. | |
| TConvertingBranchElement & | operator= (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 | |
| TVirtualConverter * | fConv |
| 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. | |
A variant of TBranchElement that can call converters when reading objects in split mode.
Definition at line 64 of file TConvertingBranchElement.h.
| TConvertingBranchElement::TConvertingBranchElement | ( | ) |
Constructor.
Definition at line 287 of file TConvertingBranchElement.cxx.
|
virtual |
Destructor.
Constructor.
Get rid of any temporary objects which we made.
Definition at line 304 of file TConvertingBranchElement.cxx.
|
private |
|
private |
Add dummy nodes if needed to recover the correct tree structure.
|
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.
|
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.
|
virtual |
Read all branches into the previously-declared object.
| entry | The ntuple row to read. |
| getall | If 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.
|
static |
Set up to allow for conversions in split mode.
Definition at line 335 of file TConvertingBranchElement.cxx.
|
protectedvirtual |
Initialize data member offsets.
(Overridden internal method.)
|
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.
|
staticprivate |
new() method for this object.
| p | Address for placement new, or nullptr. |
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.
| p | Address for placement new, or 0. |
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.
|
private |
If true, try to delete the.
|
protected |
Read leaves into I/O buffers for this branch.
| b | Root I/O buffer. |
|
protected |
|
private |
@branch Read in the subbranches of this branch.
| entry | The entry number to read. |
| getall | If true, read all branches, even if disabled. |
| dont_reset | If true, don't reset the TBuffer read pointer. |
|
virtual |
Reset branch addresses and maybe delete the object.
|
virtual |
|
static |
Set the deletion flag.
| flag | If true, try to delete the branch object on branch deletion. |
|
virtual |
Read or write this object.
| R__b | The Root buffer. |
|
private |
Definition at line 195 of file TConvertingBranchElement.h.
|
private |
Conversion for this branch.
Definition at line 196 of file TConvertingBranchElement.h.
|
private |
Saved branch type. The original.
Definition at line 208 of file TConvertingBranchElement.h.
|
private |
True if we're doing a container.
Definition at line 210 of file TConvertingBranchElement.h.
|
private |
Class for conversion.
Definition at line 197 of file TConvertingBranchElement.h.
|
private |
Pointer to tmp obj used for conversion.
Definition at line 198 of file TConvertingBranchElement.h.
|
private |
Saved branch list. If we change.
Definition at line 203 of file TConvertingBranchElement.h.
|
staticprivate |
Flag that the next read should.
Definition at line 213 of file TConvertingBranchElement.h.
|
staticconstexprprivate |
Flag used to mark dummy nodes created by BuildConvertedElisions.
Definition at line 155 of file TConvertingBranchElement.h.