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

# Content
1 //
2 // $Id: TAMTreeBranchLoader.cxx,v 1.1 2008/05/27 19:13:21 loizides Exp $
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 = 0;
300
301 // do not reread branch
302 if (entry!=fBranch->GetReadEntry())
303 ret = fBranch->GetEntry(entry);
304
305 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 if (brname.IsNull())
331 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 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 }
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 }