ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMTreeBranchLoader.cxx
Revision: 1.4
Committed: Thu Jul 16 21:02:05 2009 UTC (15 years, 9 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_032, Mit_031, Mit_025c_branch2, Mit_025c_branch1, Mit_030, Mit_029c, Mit_029b, Mit_030_pre1, Mit_029a, Mit_029, Mit_029_pre1, Mit_028a, Mit_025c_branch0, Mit_028, Mit_027a, Mit_027, Mit_026, Mit_025e, Mit_025d, Mit_025c, Mit_025b, Mit_025a, Mit_025, Mit_025pre2, Mit_024b, Mit_025pre1, Mit_024a, Mit_024, Mit_023, Mit_022a, Mit_022, Mit_020d, TMit_020d, Mit_020c, Mit_021, Mit_021pre2, Mit_021pre1, Mit_020b, Mit_020a, Mit_020, Mit_020pre1, Mit_018, Mit_017, Mit_017pre3, Mit_017pre2, Mit_017pre1, Mit_016, Mit_015b, Mit_015a, Mit_015, Mit_014e, Mit_014d, Mit_014c, Mit_014b, Mit_014a, Mit_014, Mit_014pre3, Mit_014pre2, Mit_014pre1, Mit_013d, Mit_013c, Mit_013b, Mit_013a, Mit_013, Mit_013pre1, Mit_012i, Mit_012h, Mit_012g, Mit_012f, Mit_012e, Mit_012d, Mit_012c, Mit_012b, Mit_012a, Mit_012, Mit_011a, Mit_011, Mit_010a, Mit_010, HEAD
Branch point for: Mit_025c_branch
Changes since 1.3: +2 -2 lines
Log Message:
use same include paths as rest of code. Remember to always remove this when committing to the svn version.

File Contents

# Content
1 //
2 // $Id: TAMTreeBranchLoader.cxx,v 1.3 2009/07/13 19:20:25 loizides Exp $
3 //
4
5 #include "MitAna/TAM/interface/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",
97 "Address already allocated! Must call DeleteMemory() first!");
98 return;
99 }
100
101 fBAddr = fClass->New();
102 }
103
104
105 //______________________________________________________________________________
106 Bool_t TAMTreeBranchLoader::CheckBrClass(const type_info& ptrtype,
107 const TClass& cls)
108 {
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 Error("Clear", "Could not clear the clones array for branch %s",
269 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 Int_t ret = 0;
302
303 // do not reread branch
304 if (entry!=fBranch->GetReadEntry())
305 ret = fBranch->GetEntry(entry);
306
307 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 if (brname.IsNull())
333 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 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 }
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 }