ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMTreeBranchLoader.cxx
Revision: 1.1
Committed: Tue May 27 19:13:21 2008 UTC (16 years, 11 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_004, MITHEP_2_0_x
Log Message:
TAM trunk 5120

File Contents

# User Rev Content
1 loizides 1.1 //
2     // $Id: TAMTreeBranchLoader.cxx 5120 2008-05-07 18:17:33Z loizides $
3     //
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     Int_t ret = fBranch->GetEntry(entry);
300     if(ret<0) {
301     Error("GetEntry",
302     "I/O error in file [%s] (at entry %lld) "
303     "when accessing branch with name [%s] in requested branch list.",
304     (fBranch->GetFileName()!=0) ? (fBranch->GetFileName()) : "null",
305     entry, fBranch->GetName());
306     }
307    
308     return ret;
309     }
310    
311    
312     //______________________________________________________________________________
313     Bool_t TAMTreeBranchLoader::Notify(TTree* tree)
314     {
315     // Notify via TAMSelector and TAMBranchInfo that a tree is
316     // being connected from a (new) file.
317     // Therefore get branch information and perform type checking.
318     // Set branch address if CheckBrType() was successful.
319    
320     R__ASSERT( tree != 0 );
321    
322     // get branch with requested branch name
323     // first check if given name is alias
324     TString brname(tree->GetAlias(GetBInfo()->GetName()));
325     if(brname.IsNull())
326     brname=GetBInfo()->GetName();
327     fBranch = tree->GetBranch(brname);
328    
329     if (fBranch == 0) {
330     Error("Notify", "GetBranch(%s) failed.", GetBInfo()->GetName());
331     return kFALSE;
332     }
333    
334     // get branch information and check if types match
335     if (CheckBrTypeAllModules()==kFALSE) {
336     Error("Notify", "CheckBrTypeAllModules failed.");
337     return kFALSE;
338     }
339    
340     // allocate memory on heap at fBAddr
341     if(!fBAddr)
342     AllocateMemory();
343    
344     // set the branch address to point to fBAddr
345     SetBranchAddress();
346    
347     return kTRUE;
348     }
349    
350    
351     //______________________________________________________________________________
352     void TAMTreeBranchLoader::SetBranchAddress()
353     {
354     // Set the branch address to point to our memory (fBAddr).
355    
356     if (fIsClass) {
357     // branch stores object
358     fBranch->SetAddress( &(fBAddr) );
359     } else {
360     // branch stores fundamentals
361     if (fLeafSizeConst) {
362     fBranch->SetAddress(fBAddr);
363     } else {
364     SetLeafAddresses();
365     }
366     }
367     }
368    
369    
370     //______________________________________________________________________________
371     void TAMTreeBranchLoader::SetLeafAddresses()
372     {
373     // Loop over the leaves in the branch and the data members of
374     // a (typical) struct/class used to read the branch
375     // assign the individual leaves to have address corresponding to
376     // fBAddr + (offset of each data member). This function is
377     // only used when the data members of the struct have different sizes and
378     // assumes that each module's pointer references a class or struct that
379     // is organized in the same way as any other module.
380     // CheckBrStruct() assures that this really is the case.
381    
382     const type_info& usrAdrType = GetBInfo()->GetType();
383     TClass* cls = TClass::GetClass(usrAdrType);
384     if (cls!=0) {
385     TList* members = cls->GetListOfDataMembers();
386     if ( (members!=0) && (members->IsEmpty()==kFALSE) ) {
387     TObjArray* lvs = fBranch->GetListOfLeaves();
388     if (lvs!=0) {
389     if (members->GetSize() == lvs->GetEntriesFast()) {
390     TIter nextlf(lvs);
391     TIter nextmem(members);
392     TDataMember* dm = dynamic_cast<TDataMember*>(nextmem());
393     TLeaf* lf = dynamic_cast<TLeaf*>(nextlf());
394     for (; ( (lf!=0) && (dm!=0) );
395     dm = dynamic_cast<TDataMember*>(nextmem()),
396     lf = dynamic_cast<TLeaf*>(nextlf()) ) {
397     // the cast is just to prevent compiler warnings
398     lf->SetAddress( static_cast<Char_t*>(fBAddr)
399     + dm->GetOffset() );
400     }
401     } else {
402     Error("SetLeafAddresses",
403     "Class [%s] has [%d] members, while branch [%s] "
404     "has [%d] leaves.",
405     cls->GetName(), members->GetSize(),
406     fBranch->GetName(), lvs->GetEntriesFast());
407     }
408     } else {
409     Error("SetLeafAddresses",
410     "Could not get list of leaves for branch [%s].",
411     fBranch->GetName());
412     }
413     } else {
414     Error("SetLeafAddresses",
415     "Could not get list of data members for class [%s].",
416     cls->GetName());
417     }
418     } else {
419     Error("SetLeafAddresses",
420     "Could not get class for pointer of type [%s].",
421     usrAdrType.name());
422     }
423     }