Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TBranchClones.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Rene Brun 11/02/96
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TBranchClones.h"
13 
14 #include "TBasket.h"
15 #include "TClass.h"
16 #include "TClonesArray.h"
17 #include "TDataMember.h"
18 #include "TDataType.h"
19 #include "TFile.h"
20 #include "TLeafI.h"
21 #include "TRealData.h"
22 #include "TTree.h"
23 
24 #include <cstring>
25 
26 ClassImp(TBranchClones);
27 
28 /** \class TBranchClones
29 \ingroup tree
30 
31 A Branch for the case of an array of clone objects.
32 
33 See TTree.
34 */
35 
36 ////////////////////////////////////////////////////////////////////////////////
37 /// Default and i/o constructor.
38 
39 TBranchClones::TBranchClones()
40 : TBranch()
41 , fList(0)
42 , fRead(0)
43 , fN(0)
44 , fNdataMax(0)
45 , fBranchCount(0)
46 {
47 }
48 
49 ////////////////////////////////////////////////////////////////////////////////
50 /// Constructor.
51 
52 TBranchClones::TBranchClones(TTree *tree, const char* name, void* pointer, Int_t basketsize, Int_t compress, Int_t splitlevel)
53 : TBranch()
54 , fList(0)
55 , fRead(0)
56 , fN(0)
57 , fNdataMax(0)
58 , fBranchCount(0)
59 {
60  Init(tree,0,name,pointer,basketsize,compress,splitlevel);
61 }
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 /// Constructor.
65 
66 TBranchClones::TBranchClones(TBranch *parent, const char* name, void* pointer, Int_t basketsize, Int_t compress, Int_t splitlevel)
67 : TBranch()
68 , fList(0)
69 , fRead(0)
70 , fN(0)
71 , fNdataMax(0)
72 , fBranchCount(0)
73 {
74  Init(0,parent,name,pointer,basketsize,compress,splitlevel);
75 }
76 
77 ////////////////////////////////////////////////////////////////////////////////
78 /// Initialization (non-virtual, to be called from constructor).
79 
80 void TBranchClones::Init(TTree *tree, TBranch *parent, const char* name, void* pointer, Int_t basketsize, Int_t compress, Int_t splitlevel)
81 {
82  if (tree==0 && parent!=0) tree = parent->GetTree();
83  fTree = tree;
84  fMother = parent ? parent->GetMother() : this;
85  fParent = parent;
86 
87  TString leaflist;
88  TString branchname;
89  TString branchcount;
90  SetName(name);
91  if ((compress == -1) && tree->GetDirectory()) {
92  TFile* bfile = 0;
93  if (tree->GetDirectory()) {
94  bfile = tree->GetDirectory()->GetFile();
95  }
96  if (bfile) {
97  compress = bfile->GetCompressionSettings();
98  }
99  }
100  char* cpointer = (char*) pointer;
101  char** ppointer = (char**) pointer;
102  fList = (TClonesArray*) *ppointer;
103  fAddress = cpointer;
104  TClass* cl = fList->GetClass();
105  if (!cl) {
106  return;
107  }
108  tree->BuildStreamerInfo(cl);
109  fClassName = cl->GetName();
110  fSplitLevel = splitlevel;
111 
112  // Create a branch to store the array count.
113  if (basketsize < 100) {
114  basketsize = 100;
115  }
116  leaflist.Form("%s_/I", name);
117  branchcount.Form("%s_", name);
118  fBranchCount = new TBranch(this, branchcount, &fN, leaflist, basketsize);
119  fBranchCount->SetBit(kIsClone);
120  TLeaf* leafcount = (TLeaf*) fBranchCount->GetListOfLeaves()->UncheckedAt(0);
121  fDirectory = fTree->GetDirectory();
122  fFileName = "";
123 
124  // Loop on all public data members of the class and its base classes.
125  const char* itype = 0;
126  TRealData* rd = 0;
127  TIter next(cl->GetListOfRealData());
128  while ((rd = (TRealData *) next())) {
129  if (rd->TestBit(TRealData::kTransient)) continue;
130 
131  if (rd->IsObject()) {
132  continue;
133  }
134  TDataMember* member = rd->GetDataMember();
135  if (!member->IsPersistent()) {
136  // -- Skip non-persistent members.
137  continue;
138  }
139  if (!member->IsBasic() || member->IsaPointer()) {
140  Warning("BranchClones", "Cannot process: %s::%s", cl->GetName(), member->GetName());
141  continue;
142  }
143  // Forget TObject part if splitlevel = 2.
144  if ((splitlevel > 1) || fList->TestBit(TClonesArray::kForgetBits) || cl->CanIgnoreTObjectStreamer()) {
145  if (!std::strcmp(member->GetName(), "fBits")) {
146  continue;
147  }
148  if (!std::strcmp(member->GetName(), "fUniqueID")) {
149  continue;
150  }
151  }
152  tree->BuildStreamerInfo(TClass::GetClass(member->GetFullTypeName()));
153  TDataType* membertype = member->GetDataType();
154  Int_t type = membertype->GetType();
155  if (!type) {
156  Warning("BranchClones", "Cannot process: %s::%s of type zero!", cl->GetName(), member->GetName());
157  continue;
158  }
159 
160  if (type == 1) {
161  itype = "B";
162  } else if (type == 2) {
163  itype = "S";
164  } else if (type == 3) {
165  itype = "I";
166  } else if (type == 5) {
167  itype = "F";
168  } else if (type == 8) {
169  itype = "D";
170  } else if (type == 9) {
171  itype = "D";
172  } else if (type == 11) {
173  itype = "b";
174  } else if (type == 12) {
175  itype = "s";
176  } else if (type == 13) {
177  itype = "i";
178  }
179 
180  leaflist.Form("%s[%s]/%s", member->GetName(), branchcount.Data(), itype);
181  Int_t comp = compress;
182  branchname.Form("%s.%s", name, rd->GetName());
183  TBranch* branch = new TBranch(this, branchname, this, leaflist, basketsize, comp);
184  branch->SetBit(kIsClone);
185  TObjArray* leaves = branch->GetListOfLeaves();
186  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(0);
187  leaf->SetOffset(rd->GetThisOffset());
188  leaf->SetLeafCount(leafcount);
189  Int_t arraydim = member->GetArrayDim();
190  if (arraydim) {
191  Int_t maxindex = 1;
192  while (arraydim) {
193  maxindex *= member->GetMaxIndex(--arraydim);
194  }
195  leaf->SetLen(maxindex);
196  }
197  fBranches.Add(branch);
198  }
199 }
200 
201 ////////////////////////////////////////////////////////////////////////////////
202 /// Destructor.
203 
204 TBranchClones::~TBranchClones()
205 {
206  delete fBranchCount;
207  fBranchCount = 0;
208  fBranches.Delete();
209  // FIXME: We might own this, possible memory leak.
210  fList = 0;
211 }
212 
213 ////////////////////////////////////////////////////////////////////////////////
214 /// Browse this branch.
215 
216 void TBranchClones::Browse(TBrowser* b)
217 {
218  fBranches.Browse(b);
219 }
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Loop on all branches and fill Basket buffer.
223 
224 Int_t TBranchClones::FillImpl(ROOT::Internal::TBranchIMTHelper *imtHelper)
225 {
226  Int_t i = 0;
227  Int_t nbytes = 0;
228  Int_t nbranches = fBranches.GetEntriesFast();
229  char** ppointer = (char**) fAddress;
230  if (!ppointer) {
231  return 0;
232  }
233  fList = (TClonesArray*) *ppointer;
234  fN = fList->GetEntriesFast();
235  fEntries++;
236  if (fN > fNdataMax) {
237  fNdataMax = fList->GetSize();
238  TString branchcount;
239  branchcount.Form("%s_", GetName());
240  TLeafI* leafi = (TLeafI*) fBranchCount->GetLeaf(branchcount);
241  leafi->SetMaximum(fNdataMax);
242  for (i = 0; i < nbranches; i++) {
243  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
244  TObjArray* leaves = branch->GetListOfLeaves();
245  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(0);
246  leaf->SetAddress();
247  }
248  }
249  nbytes += fBranchCount->FillImpl(imtHelper);
250  for (i = 0; i < nbranches; i++) {
251  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
252  TObjArray* leaves = branch->GetListOfLeaves();
253  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(0);
254  leaf->Import(fList, fN);
255  nbytes += branch->FillImpl(imtHelper);
256  }
257  return nbytes;
258 }
259 
260 ////////////////////////////////////////////////////////////////////////////////
261 /// Read all branches and return total number of bytes read.
262 
263 Int_t TBranchClones::GetEntry(Long64_t entry, Int_t getall)
264 {
265  if (TestBit(kDoNotProcess) && !getall) {
266  return 0;
267  }
268  Int_t nbytes = fBranchCount->GetEntry(entry, getall);
269  TLeaf* leafcount = (TLeaf*) fBranchCount->GetListOfLeaves()->UncheckedAt(0);
270  fN = Int_t(leafcount->GetValue());
271  if (fN <= 0) {
272  if (fList) {
273  fList->Clear();
274  }
275  return 0;
276  }
277  TBranch* branch = 0;
278  Int_t nbranches = fBranches.GetEntriesFast();
279  // If fList exists, create clones array objects.
280  if (fList) {
281  fList->Clear();
282  fList->ExpandCreateFast(fN);
283  for (Int_t i = 0; i < nbranches; i++) {
284  branch = (TBranch*) fBranches.UncheckedAt(i);
285  if (((TLeaf*) branch->GetListOfLeaves()->UncheckedAt(0))->GetOffset() < 0) {
286  continue;
287  }
288  nbytes += branch->GetEntryExport(entry, getall, fList, fN);
289  }
290  } else {
291  for (Int_t i = 0; i < nbranches; i++) {
292  branch = (TBranch*) fBranches.UncheckedAt(i);
293  nbytes += branch->GetEntry(entry, getall);
294  }
295  }
296  return nbytes;
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// Print branch parameters.
301 
302 void TBranchClones::Print(Option_t *option) const
303 {
304  fBranchCount->Print(option);
305  Int_t nbranches = fBranches.GetEntriesFast();
306  for (Int_t i = 0; i < nbranches; i++) {
307  TBranch* branch = (TBranch*) fBranches.At(i);
308  branch->Print(option);
309  }
310 }
311 
312 ////////////////////////////////////////////////////////////////////////////////
313 /// Reset branch.
314 ///
315 /// - Existing buffers are deleted
316 /// - Entries, max and min are reset
317 
318 void TBranchClones::Reset(Option_t* option)
319 {
320  fEntries = 0;
321  fTotBytes = 0;
322  fZipBytes = 0;
323  Int_t nbranches = fBranches.GetEntriesFast();
324  for (Int_t i = 0; i < nbranches; i++) {
325  TBranch* branch = (TBranch*) fBranches.At(i);
326  branch->Reset(option);
327  }
328  fBranchCount->Reset();
329 }
330 
331 ////////////////////////////////////////////////////////////////////////////////
332 /// Reset branch after a merge.
333 ///
334 /// - Existing buffers are deleted
335 /// - Entries, max and min are reset
336 
337 void TBranchClones::ResetAfterMerge(TFileMergeInfo *info)
338 {
339  fEntries = 0;
340  fTotBytes = 0;
341  fZipBytes = 0;
342  Int_t nbranches = fBranches.GetEntriesFast();
343  for (Int_t i = 0; i < nbranches; i++) {
344  TBranch* branch = (TBranch*) fBranches.At(i);
345  branch->ResetAfterMerge(info);
346  }
347  fBranchCount->ResetAfterMerge(info);
348 }
349 
350 ////////////////////////////////////////////////////////////////////////////////
351 /// Set address of this branch.
352 
353 void TBranchClones::SetAddress(void* addr)
354 {
355  fReadEntry = -1;
356  fAddress = (char*) addr;
357  char** pp= (char**) fAddress;
358  if (pp && (*pp == 0)) {
359  // We've been asked to allocate an object for the user.
360  *pp= (char*) new TClonesArray(fClassName);
361  }
362  fList = 0;
363  if (pp) {
364  fList = (TClonesArray*) *pp;
365  }
366  fBranchCount->SetAddress(&fN);
367 }
368 
369 ////////////////////////////////////////////////////////////////////////////////
370 /// Reset basket size for all sub-branches.
371 
372 void TBranchClones::SetBasketSize(Int_t buffsize)
373 {
374  TBranch::SetBasketSize(buffsize);
375 
376  Int_t nbranches = fBranches.GetEntriesFast();
377  for (Int_t i = 0; i < nbranches; i++) {
378  TBranch* branch = (TBranch*) fBranches[i];
379  branch->SetBasketSize(fBasketSize);
380  }
381 }
382 
383 ////////////////////////////////////////////////////////////////////////////////
384 /// Serialize/Deserialize from a buffer.
385 
386 void TBranchClones::Streamer(TBuffer& b)
387 {
388  UInt_t R__s, R__c;
389  if (b.IsReading()) {
390  b.ReadVersion(&R__s, &R__c);
391  TNamed::Streamer(b);
392  b >> fCompress;
393  b >> fBasketSize;
394  b >> fEntryOffsetLen;
395  b >> fMaxBaskets;
396  b >> fWriteBasket;
397  b >> fEntryNumber;
398  b >> fEntries;
399  b >> fTotBytes;
400  b >> fZipBytes;
401  b >> fOffset;
402  b >> fBranchCount;
403  fClassName.Streamer(b);
404  fBranches.Streamer(b);
405  fTree = 0;
406  TBranch* branch = 0;
407  TLeaf* leaf = 0;
408  Int_t nbranches = fBranches.GetEntriesFast();
409  for (Int_t i = 0; i < nbranches; i++) {
410  branch = (TBranch*) fBranches[i];
411  branch->SetBit(kIsClone);
412  leaf = (TLeaf*) branch->GetListOfLeaves()->UncheckedAt(0);
413  leaf->SetOffset(-1);
414  }
415  fRead = 1;
416  TClass* cl = TClass::GetClass((const char*) fClassName);
417  if (!cl) {
418  Warning("Streamer", "Unknown class: %s. Cannot read BranchClones: %s", fClassName.Data(), GetName());
419  SetBit(kDoNotProcess);
420  return;
421  }
422  if (!cl->GetListOfRealData()) {
423  cl->BuildRealData();
424  }
425  TString branchname;
426  TRealData* rd = 0;
427  TIter next(cl->GetListOfRealData());
428  while ((rd = (TRealData*) next())) {
429  if (rd->TestBit(TRealData::kTransient)) continue;
430 
431  TDataMember* member = rd->GetDataMember();
432  if (!member || !member->IsBasic() || !member->IsPersistent()) {
433  continue;
434  }
435  TDataType* membertype = member->GetDataType();
436  if (!membertype->GetType()) {
437  continue;
438  }
439  branchname.Form("%s.%s", GetName(), rd->GetName());
440  branch = (TBranch*) fBranches.FindObject(branchname);
441  if (!branch) {
442  continue;
443  }
444  TObjArray* leaves = branch->GetListOfLeaves();
445  leaf = (TLeaf*) leaves->UncheckedAt(0);
446  leaf->SetOffset(rd->GetThisOffset());
447  }
448  b.CheckByteCount(R__s, R__c, TBranchClones::IsA());
449  } else {
450  R__c = b.WriteVersion(TBranchClones::IsA(), kTRUE);
451  TNamed::Streamer(b);
452  b << fCompress;
453  b << fBasketSize;
454  b << fEntryOffsetLen;
455  b << fMaxBaskets;
456  b << fWriteBasket;
457  b << fEntryNumber;
458  b << fEntries;
459  b << fTotBytes;
460  b << fZipBytes;
461  b << fOffset;
462  b << fBranchCount;
463  fClassName.Streamer(b);
464  fBranches.Streamer(b);
465  b.SetByteCount(R__c, kTRUE);
466  }
467 }
468 
469 ////////////////////////////////////////////////////////////////////////////////
470 /// Refresh the value of fDirectory (i.e. where this branch writes/reads its buffers)
471 /// with the current value of fTree->GetCurrentFile unless this branch has been
472 /// redirected to a different file. Also update the sub-branches.
473 
474 void TBranchClones::UpdateFile()
475 {
476  fBranchCount->UpdateFile();
477  TBranch::UpdateFile();
478 }