ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMTreeBranchLoader.cxx
Revision: 1.2
Committed: Mon Oct 6 16:42:50 2008 UTC (16 years, 7 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_009c, Mit_009b, Mit_009a, Mit_009, Mit_008, Mit_008pre2, Mit_008pre1, Mit_006b, Mit_006a, Mit_006, Mit_005
Changes since 1.1: +21 -7 lines
Log Message:
Check if branch needs read before you read it. Set fClass pointer for autoloading even if no usr address was given.

File Contents

# User Rev Content
1 loizides 1.1 //
2 loizides 1.2 // $Id: TAMTreeBranchLoader.cxx,v 1.1 2008/05/27 19:13:21 loizides Exp $
3 loizides 1.1 //
4    
5     #include "TAMTreeBranchLoader.h"
6    
7    
8     #ifndef ROOT_RVersion
9     #include <RVersion.h>
10     #endif
11     #ifndef ROOT_TError
12     #include "TError.h"
13     #endif
14     #ifndef ROOT_TClass
15     #include "TClass.h"
16     #endif
17     #ifndef ROOT_TList
18     #include "TList.h"
19     #endif
20     #ifndef ROOT_TFile
21     #include "TFile.h"
22     #endif
23     #ifndef ROOT_TBranch
24     #include "TBranch.h"
25     #endif
26     #ifndef ROOT_TLeaf
27     #include "TLeaf.h"
28     #endif
29     #ifndef ROOT_TDataMember
30     #include "TDataMember.h"
31     #endif
32     #ifndef ROOT_TDataType
33     #include "TDataType.h"
34     #endif
35     #ifndef ROOT_TTree
36     #include "TTree.h"
37     #endif
38     #ifndef ROOT_TROOT
39     #include "TROOT.h"
40     #endif
41     #ifndef ROOT_TClonesArray
42     #include "TClonesArray.h"
43     #endif
44    
45    
46     //////////////////////////////////////////////////////////////////////////
47     // //
48     // TAMTreeBranchLoader //
49     // //
50     // Default TAM plugin that loads data from single tree branches //
51     // into memory. //
52     // //
53     // Author : Corey Reed 07/20/2004 //
54     // Maarten Ballintijn 12/06/2005 //
55     // Constantin Loizides 12/06/2005 //
56     // //
57     //////////////////////////////////////////////////////////////////////////
58    
59     ClassImp(TAMTreeBranchLoader)
60    
61    
62     #if ROOT_VERSION_CODE < ROOT_VERSION(5,11,3)
63     #define R__ASSERT(e) \
64     if (!(e)) Fatal("", kAssertMsg, _QUOTE_(e), __LINE__, __FILE__)
65     #endif
66    
67    
68     //______________________________________________________________________________
69     TAMTreeBranchLoader::TAMTreeBranchLoader(TAMBranchInfo *binfo)
70     : TAMVirtualBranchLoader(binfo), fBAddr(0), fIsClass(kFALSE),
71     fLeafSizeConst(kTRUE), fBranch(0), fClass(0)
72     {
73     // Default constructor.
74     }
75    
76    
77     //______________________________________________________________________________
78     TAMTreeBranchLoader::~TAMTreeBranchLoader()
79     {
80     // Destructor.
81    
82     DeleteMemory();
83     fClass = 0;
84     fBranch = 0;
85     }
86    
87    
88     //______________________________________________________________________________
89     void TAMTreeBranchLoader::AllocateMemory()
90     {
91     // Allocate memory on heap.
92    
93     R__ASSERT(fClass != 0);
94    
95     if(fBAddr!=0) {
96     Fatal("AllocateMemory", "Address already allocated! Must call DeleteMemory() first!");
97     return;
98     }
99    
100     fBAddr = fClass->New();
101     }
102    
103    
104     //______________________________________________________________________________
105     Bool_t TAMTreeBranchLoader::CheckBrClass(const type_info& ptrtype, const TClass& cls)
106     {
107     // Check if the tree stores a class of the specified type
108     // ptrtype is user type and cls is type found in branch.
109    
110     // check for equality
111     const type_info *clt = cls.GetTypeInfo();
112    
113     if (clt!=0) {
114     if ( (*clt) == ptrtype ) return kTRUE;
115     } else {
116     Error("CheckBrClass",
117     "Could not get type_info for first leaf in branch [%s] "
118     "of type [%s].",fBranch->GetName(), fBranch->GetClassName());
119     return kFALSE;
120     }
121    
122     // check for inheritance hierachy
123     const TClass *ptrcls = gROOT->GetClass(ptrtype);
124    
125     if ( ptrcls!=0 ) {
126     if ( cls.InheritsFrom(ptrcls) ) return kTRUE;
127     } else {
128     Error("CheckBrClass",
129     "Could not get pointer to TClass for first leaf in branch [%s] "
130     "of type [%s].",fBranch->GetName(), fBranch->GetClassName());
131     return kFALSE;
132     }
133    
134     Error("CheckBrClass",
135     "Class of first leaf in branch [%s] is [%s], "
136     "different (not equal/derived) from pointer type [%s].",
137     fBranch->GetName(), clt->name(), ptrtype.name());
138     return kFALSE;
139     }
140    
141    
142     //______________________________________________________________________________
143     Bool_t TAMTreeBranchLoader::CheckBrStruct(TClass& cls)
144     {
145     // Given pointer is a class/struct type for a list of fundamental leaves:
146     // Check that the members correspond to the leaves,
147     // also check that the size of the members does not change
148     // (the compiler may buffer the memory between different sized
149     // members, which causes SetBranchAddress to give unexpected results).
150    
151     TList* members = cls.GetListOfDataMembers();
152     if ( (members!=0) && (members->IsEmpty()==kFALSE) ) {
153     TObjArray* lvs = fBranch->GetListOfLeaves();
154     if (lvs!=0) {
155     if (members->GetSize() == lvs->GetEntriesFast()) {
156     TIter nextlf(lvs);
157     TIter nextmem(members);
158     TDataMember* dm = dynamic_cast<TDataMember*>(nextmem());
159     TLeaf* lf = dynamic_cast<TLeaf*>(nextlf());
160     const Int_t size = dm->GetUnitSize();
161     for (; ( (lf!=0) && (dm!=0) );
162     dm = dynamic_cast<TDataMember*>(nextmem()),
163     lf = dynamic_cast<TLeaf*>(nextlf()) ) {
164     if (strcmp(lf->GetTypeName(),dm->GetTypeName())!=0) {
165     Error("CheckBrStruct",
166     "Member [%s] of class [%s] is of type [%s], "
167     "while leaf [%s] if of type [%s].",
168     dm->GetName(), cls.GetName(),
169     dm->GetTypeName(), lf->GetName(),
170     lf->GetTypeName());
171     return kFALSE;
172     } else {
173     fLeafSizeConst &= (size == dm->GetUnitSize());
174     }
175     }
176     return kTRUE;
177     } else {
178     Error("CheckBrStruct",
179     "Pointer of type [%s] has [%d] members, while branch "
180     "[%s] has [%d] leaves.",
181     cls.GetName(), members->GetSize(),
182     fBranch->GetName(), lvs->GetEntriesFast());
183     }
184     } else {
185     Error("CheckBrStruct",
186     "Could not get list of leaves for branch [%s].",
187     fBranch->GetName());
188     }
189     } else {
190     Error("CheckBrStruct",
191     "Could not get list of members for type [%s].",
192     cls.GetName());
193     }
194    
195     return kFALSE;
196     }
197    
198    
199     //______________________________________________________________________________
200     Bool_t TAMTreeBranchLoader::CheckBrType(const type_info& ptrtype)
201     {
202     // Check that the specified type (of the user's pointer) corresponds with
203     // what is in the tree:
204     // 1. Check if the tree stores a class of the specified type
205     // 2. Check the specified type is a class/struct (that is in the TClass
206     // dictionary!!) whose members correspond to the leaves in the branch.
207    
208     R__ASSERT(gROOT!=0);
209    
210     // first try the branch (works only for classes)
211     TClass* cls = gROOT->GetClass(fBranch->GetClassName());
212     if (cls!=0) {
213     // known class
214     fIsClass = kTRUE;
215     fClass = cls;
216     return CheckBrClass(ptrtype, *cls);
217     } else {
218     // pointer is a class/struct, branch is list of fundamentals
219     cls = TClass::GetClass(ptrtype);
220     if (cls!=0) {
221     fClass = cls;
222     return CheckBrStruct(*cls);
223     } else {
224     // pointer is a fundamental type (or else unknown type)
225     Error("CheckBrType",
226     "Pointer for branch [%s] is of fundamental type [%d], or "
227     "is a class/struct which is not in the TClass dictionary. "
228     "This is not supported. See documentation.",
229     fBranch->GetName(),
230     static_cast<Int_t>(TDataType::GetType(ptrtype)));
231     }
232     }
233     return kFALSE;
234     }
235    
236     //______________________________________________________________________________
237     Bool_t TAMTreeBranchLoader::CheckBrTypeAllModules()
238     {
239     // Loop over each user address and check that it's of the correct type
240     // for the data contained in this branch.
241    
242     Bool_t isok=kTRUE;
243     vector<TAMBranchInfo::BranchPtr_t*>::const_iterator end =
244     GetBInfo()->fUsrAddresses.end();
245     for (vector<TAMBranchInfo::BranchPtr_t*>::const_iterator ptr =
246     GetBInfo()->fUsrAddresses.begin(); (ptr!=end) && isok; ptr++) {
247     isok &= CheckBrType((*ptr)->GetType());
248     }
249     return isok;
250     }
251    
252     //______________________________________________________________________________
253     void TAMTreeBranchLoader::Clear(Option_t */*option*/)
254     {
255     // Clear objects in TClonesArrays that allocated memory on the heap.
256    
257     if(!fIsClass || !fBAddr)
258     return;
259    
260     TString classname(fBranch->GetClassName());
261     if (classname.CompareTo("TClonesArray")==0) {
262     TClonesArray* ca = reinterpret_cast<TClonesArray*>(fBAddr);
263     if (ca!=0) {
264     ca->Clear("C");
265     } else {
266     Error("Clear", "Could not clear the clones array for branch %s",
267     fBranch->GetName());
268     }
269     }
270     }
271    
272    
273     //______________________________________________________________________________
274     void TAMTreeBranchLoader::DeleteMemory()
275     {
276     // Delete (previously) allocated memory on heap.
277    
278     if(fClass && fBAddr) {
279     fClass->Destructor(fBAddr);
280     fBAddr = 0;
281     }
282     }
283    
284    
285     //______________________________________________________________________________
286     void* TAMTreeBranchLoader::GetAddress() const
287     {
288     // Return the branch address.
289    
290     return fBAddr;
291     }
292    
293    
294     //______________________________________________________________________________
295     Int_t TAMTreeBranchLoader::GetEntry(Long64_t entry)
296     {
297     // Get requested entry.
298    
299 loizides 1.2 Int_t ret = 0;
300    
301     // do not reread branch
302     if (entry!=fBranch->GetReadEntry())
303     ret = fBranch->GetEntry(entry);
304    
305 loizides 1.1 if(ret<0) {
306     Error("GetEntry",
307     "I/O error in file [%s] (at entry %lld) "
308     "when accessing branch with name [%s] in requested branch list.",
309     (fBranch->GetFileName()!=0) ? (fBranch->GetFileName()) : "null",
310     entry, fBranch->GetName());
311     }
312    
313     return ret;
314     }
315    
316    
317     //______________________________________________________________________________
318     Bool_t TAMTreeBranchLoader::Notify(TTree* tree)
319     {
320     // Notify via TAMSelector and TAMBranchInfo that a tree is
321     // being connected from a (new) file.
322     // Therefore get branch information and perform type checking.
323     // Set branch address if CheckBrType() was successful.
324    
325     R__ASSERT( tree != 0 );
326    
327     // get branch with requested branch name
328     // first check if given name is alias
329     TString brname(tree->GetAlias(GetBInfo()->GetName()));
330 loizides 1.2 if (brname.IsNull())
331 loizides 1.1 brname=GetBInfo()->GetName();
332     fBranch = tree->GetBranch(brname);
333    
334     if (fBranch == 0) {
335     Error("Notify", "GetBranch(%s) failed.", GetBInfo()->GetName());
336     return kFALSE;
337     }
338    
339 loizides 1.2 if (GetBInfo()->fUsrAddresses.size()) {
340     // get branch information and check if types match
341     if (CheckBrTypeAllModules()==kFALSE) {
342     Error("Notify", "CheckBrTypeAllModules failed.");
343     return kFALSE;
344     }
345     } else {
346     // zero usr addresses (only possible for autoloading)
347     TClass* cls = gROOT->GetClass(fBranch->GetClassName());
348     if (cls!=0) { // known class
349     fIsClass = kTRUE;
350     fClass = cls;
351     }
352 loizides 1.1 }
353    
354     // allocate memory on heap at fBAddr
355     if(!fBAddr)
356     AllocateMemory();
357    
358     // set the branch address to point to fBAddr
359     SetBranchAddress();
360    
361     return kTRUE;
362     }
363    
364    
365     //______________________________________________________________________________
366     void TAMTreeBranchLoader::SetBranchAddress()
367     {
368     // Set the branch address to point to our memory (fBAddr).
369    
370     if (fIsClass) {
371     // branch stores object
372     fBranch->SetAddress( &(fBAddr) );
373     } else {
374     // branch stores fundamentals
375     if (fLeafSizeConst) {
376     fBranch->SetAddress(fBAddr);
377     } else {
378     SetLeafAddresses();
379     }
380     }
381     }
382    
383    
384     //______________________________________________________________________________
385     void TAMTreeBranchLoader::SetLeafAddresses()
386     {
387     // Loop over the leaves in the branch and the data members of
388     // a (typical) struct/class used to read the branch
389     // assign the individual leaves to have address corresponding to
390     // fBAddr + (offset of each data member). This function is
391     // only used when the data members of the struct have different sizes and
392     // assumes that each module's pointer references a class or struct that
393     // is organized in the same way as any other module.
394     // CheckBrStruct() assures that this really is the case.
395    
396     const type_info& usrAdrType = GetBInfo()->GetType();
397     TClass* cls = TClass::GetClass(usrAdrType);
398     if (cls!=0) {
399     TList* members = cls->GetListOfDataMembers();
400     if ( (members!=0) && (members->IsEmpty()==kFALSE) ) {
401     TObjArray* lvs = fBranch->GetListOfLeaves();
402     if (lvs!=0) {
403     if (members->GetSize() == lvs->GetEntriesFast()) {
404     TIter nextlf(lvs);
405     TIter nextmem(members);
406     TDataMember* dm = dynamic_cast<TDataMember*>(nextmem());
407     TLeaf* lf = dynamic_cast<TLeaf*>(nextlf());
408     for (; ( (lf!=0) && (dm!=0) );
409     dm = dynamic_cast<TDataMember*>(nextmem()),
410     lf = dynamic_cast<TLeaf*>(nextlf()) ) {
411     // the cast is just to prevent compiler warnings
412     lf->SetAddress( static_cast<Char_t*>(fBAddr)
413     + dm->GetOffset() );
414     }
415     } else {
416     Error("SetLeafAddresses",
417     "Class [%s] has [%d] members, while branch [%s] "
418     "has [%d] leaves.",
419     cls->GetName(), members->GetSize(),
420     fBranch->GetName(), lvs->GetEntriesFast());
421     }
422     } else {
423     Error("SetLeafAddresses",
424     "Could not get list of leaves for branch [%s].",
425     fBranch->GetName());
426     }
427     } else {
428     Error("SetLeafAddresses",
429     "Could not get list of data members for class [%s].",
430     cls->GetName());
431     }
432     } else {
433     Error("SetLeafAddresses",
434     "Could not get class for pointer of type [%s].",
435     usrAdrType.name());
436     }
437     }