ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMTreeBranchLoader.cxx
Revision: 1.3
Committed: Mon Jul 13 19:20:25 2009 UTC (15 years, 9 months ago) by loizides
Content type: text/plain
Branch: MAIN
Changes since 1.2: +6 -4 lines
Log Message:
Cleanup

File Contents

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