Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TBranchRef.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Rene Brun 19/08/2004
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, 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 /** \class TBranchRef
13 \ingroup tree
14 
15 A branch containing and managing a TRefTable for TRef autoloading.
16 It loads the TBranch containing a referenced object when requested
17 by TRef::GetObject(), so the reference can be resolved. The
18 information which branch to load is stored by TRefTable. Once a
19 TBranch has read the TBranchRef's current entry it will not be told
20 to re-read, in case the use has changed objects read from the
21 branch.
22 
23 ### LIMITATION :
24 Note that this does NOT allow for autoloading of references spanning
25 different entries. The TBranchRef's current entry has to correspond
26 to the entry of the TBranch containing the referenced object.
27 
28 The TRef cannot be stored in a top-level branch which is a
29 TBranchObject for the auto-loading to work. E.g. you cannot store
30 the TRefs in TObjArray, and create a top-level branch storing this
31 TObjArray.
32 */
33 
34 #include "TBranchRef.h"
35 #include "TBuffer.h"
36 #include "TTree.h"
37 #include "TBasket.h"
38 #include "TFile.h"
39 #include "TFriendElement.h"
40 
41 ClassImp(TBranchRef);
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// Default constructor.
45 
46 TBranchRef::TBranchRef(): TBranch(), fRequestedEntry(-1), fRefTable(0)
47 {
48  fReadLeaves = (ReadLeaves_t)&TBranchRef::ReadLeavesImpl;
49  fFillLeaves = (FillLeaves_t)&TBranchRef::FillLeavesImpl;
50 }
51 
52 ////////////////////////////////////////////////////////////////////////////////
53 /// Main constructor called by TTree::BranchRef.
54 
55 TBranchRef::TBranchRef(TTree *tree)
56  : TBranch(), fRequestedEntry(-1), fRefTable(0)
57 {
58  if (!tree) return;
59  SetName("TRefTable");
60  SetTitle("List of branch numbers with referenced objects");
61  fRefTable = new TRefTable(this,100);
62 
63  fCompress = 1;
64  fBasketSize = 32000;
65  fAddress = 0;
66  fBasketBytes = new Int_t[fMaxBaskets];
67  fBasketEntry = new Long64_t[fMaxBaskets];
68  fBasketSeek = new Long64_t[fMaxBaskets];
69 
70  for (Int_t i=0;i<fMaxBaskets;i++) {
71  fBasketBytes[i] = 0;
72  fBasketEntry[i] = 0;
73  fBasketSeek[i] = 0;
74  }
75 
76  fTree = tree;
77  fMother = this;
78  fDirectory = fTree->GetDirectory();
79  fFileName = "";
80  fReadLeaves = (ReadLeaves_t)&TBranchRef::ReadLeavesImpl;
81  fFillLeaves = (FillLeaves_t)&TBranchRef::FillLeavesImpl;
82 }
83 
84 ////////////////////////////////////////////////////////////////////////////////
85 /// Typical destructor.
86 
87 TBranchRef::~TBranchRef()
88 {
89  delete fRefTable;
90 }
91 
92 ////////////////////////////////////////////////////////////////////////////////
93 /// Clear entries in the TRefTable.
94 
95 void TBranchRef::Clear(Option_t *option)
96 {
97  if (fRefTable) fRefTable->Clear(option);
98 }
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// Fill the branch basket with the referenced objects parent numbers.
102 
103 Int_t TBranchRef::FillImpl(ROOT::Internal::TBranchIMTHelper *imtHelper)
104 {
105  Int_t nbytes = TBranch::FillImpl(imtHelper);
106  return nbytes;
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// This function is called by TRefTable::Notify, itself called by
111 /// TRef::GetObject.
112 /// The function reads the branch containing the object referenced
113 /// by the TRef.
114 
115 Bool_t TBranchRef::Notify()
116 {
117  if (!fRefTable) fRefTable = new TRefTable(this,100);
118  UInt_t uid = fRefTable->GetUID();
119  TProcessID* context = fRefTable->GetUIDContext();
120  if (fReadEntry != fRequestedEntry) {
121  // Load the RefTable if we need to.
122  GetEntry(fRequestedEntry);
123  }
124  TBranch *branch = (TBranch*)fRefTable->GetParent(uid, context);
125  if (branch) {
126  // don't re-read, the user might have changed some object
127  if (branch->GetReadEntry() != fRequestedEntry)
128  branch->GetEntry(fRequestedEntry);
129  } else {
130  //scan the TRefTable of possible friend Trees
131  TList *friends = fTree->GetListOfFriends();
132  if (!friends) return kTRUE;
133  TObjLink *lnk = friends->FirstLink();
134  while (lnk) {
135  TFriendElement* elem = (TFriendElement*)lnk->GetObject();
136  TTree *tree = elem->GetTree();
137  TBranchRef *bref = tree->GetBranchRef();
138  if (bref) {
139  if (bref->GetReadEntry() != fRequestedEntry) {
140  bref->GetEntry(fRequestedEntry);
141  }
142  branch = (TBranch*)bref->GetRefTable()->GetParent(uid, context);
143  if (branch) {
144  // don't re-read, the user might have changed some object
145  if (branch->GetReadEntry() != fRequestedEntry)
146  branch->GetEntry(fRequestedEntry);
147  return kTRUE;
148  }
149  }
150  lnk = lnk->Next();
151  }
152  }
153  return kTRUE;
154 }
155 
156 ////////////////////////////////////////////////////////////////////////////////
157 /// Print the TRefTable branch.
158 
159 void TBranchRef::Print(Option_t *option) const
160 {
161  TBranch::Print(option);
162 }
163 
164 ////////////////////////////////////////////////////////////////////////////////
165 /// This function called by TBranch::GetEntry overloads TBranch::ReadLeaves.
166 
167 void TBranchRef::ReadLeavesImpl(TBuffer &b)
168 {
169  if (!fRefTable) fRefTable = new TRefTable(this,100);
170  fRefTable->ReadBuffer(b);
171 }
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 /// This function called by TBranch::Fill overloads TBranch::FillLeaves.
175 
176 void TBranchRef::FillLeavesImpl(TBuffer &b)
177 {
178  if (!fRefTable) fRefTable = new TRefTable(this,100);
179  fRefTable->FillBuffer(b);
180 }
181 
182 ////////////////////////////////////////////////////////////////////////////////
183 /// - Existing buffers are deleted
184 /// - Entries, max and min are reset
185 /// - TRefTable is cleared.
186 
187 void TBranchRef::Reset(Option_t *option)
188 {
189  TBranch::Reset(option);
190  if (!fRefTable) fRefTable = new TRefTable(this,100);
191  fRefTable->Reset();
192 }
193 
194 ////////////////////////////////////////////////////////////////////////////////
195 /// Reset a Branch after a Merge operation (drop data but keep customizations)
196 /// TRefTable is cleared.
197 
198 void TBranchRef::ResetAfterMerge(TFileMergeInfo *info)
199 {
200  TBranch::ResetAfterMerge(info);
201  if (!fRefTable) fRefTable = new TRefTable(this,100);
202  fRefTable->Reset();
203 }
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 /// Set the current parent branch.
207 ///
208 /// This function is called by TBranchElement::GetEntry()
209 /// and TBranchElement::Fill() when reading or writing
210 /// branches that may contain referenced objects.
211 
212 Int_t TBranchRef::SetParent(const TObject* object, Int_t branchID)
213 {
214  if (!fRefTable) {
215  fRefTable = new TRefTable(this, 100);
216  }
217  TRefTable::SetRefTable(fRefTable);
218  return fRefTable->SetParent(object, branchID);
219 }
220