Logo ROOT   6.12/07
Reference Guide
TRefTable.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Rene Brun 28/09/2001
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 TRefTable
13 \ingroup Containers
14 A TRefTable maintains the association between a referenced object
15 and the parent object supporting this referenced object.
16 
17 The parent object is typically a branch of a TTree. For each object
18 referenced in a TTree entry, the corresponding entry in the TTree's
19 TBranchRef::fRefTable contains the index of the branch that
20 needs to be loaded to bring the object into memory.
21 
22 Persistency of a TRefTable is split into two parts:
23  - entry specific information is stored (read) by FillBuffer
24  (ReadBuffer). For each referenced object the object's fUniqueID
25  and the referencing TRef::fPID is stored (to allow the TRefTable
26  to autoload references created by different processes).
27  - non-entry specific, i.e. global information is stored (read) by
28  the Streamer function. This comprises all members marked as
29  persistent.
30 
31 As TObject::fUniqueID is only unique for a given TProcessID, a table
32 of unique IDs is kept for each used TProcessID. There is no natural
33 order of TProcessIDs, so TRefTable stores a vector of the TGUID of
34 all known TProcessIDs in fProcessGUIDs; the index of a TProcessID in
35 this vector defines the index of the auto-loading info in fParentIDs
36 for that TProcessID. The mapping of TProcessID* to index is cached
37 for quick non-persistent lookup.
38 */
39 
40 #include "TRefTable.h"
41 #include "TBuffer.h"
42 #include "TObjArray.h"
43 #include "TProcessID.h"
44 #include <algorithm>
45 
47 
49 ////////////////////////////////////////////////////////////////////////////////
50 /// Default constructor for I/O.
51 
52 TRefTable::TRefTable() : fNumPIDs(0), fAllocSize(0), fN(0), fParentIDs(0), fParentID(-1),
53  fDefaultSize(10), fUID(0), fUIDContext(0), fSize(0), fParents(0), fOwner(0)
54 {
55  fgRefTable = this;
56 }
57 
58 ////////////////////////////////////////////////////////////////////////////////
59 /// Create a TRefTable with initial size.
60 
62  fNumPIDs(0), fAllocSize(0), fN(0), fParentIDs(0), fParentID(-1),
63  fDefaultSize(size<10 ? 10 : size), fUID(0), fUIDContext(0), fSize(0), fParents(new TObjArray(1)), fOwner(owner)
64 {
65  fgRefTable = this;
66 }
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// Destructor.
70 
72 {
73  delete [] fAllocSize;
74  delete [] fN;
75  for (Int_t pid = 0; pid < fNumPIDs; ++pid) {
76  delete [] fParentIDs[pid];
77  }
78  delete [] fParentIDs;
79  delete fParents;
80  if (fgRefTable == this) fgRefTable = 0;
81 }
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 /// Add a new uid to the table.
85 /// we add a new pair (uid,fparent) to the map
86 /// This function is called by TObject::Streamer or TStreamerInfo::WriteBuffer
87 
89 {
90  if (!context)
92  Int_t iid = GetInternalIdxForPID(context);
93 
94  Int_t newsize = 0;
95  uid = uid & 0xffffff;
96  if (uid >= fAllocSize[iid]) {
97  newsize = uid + uid / 2;
98  if (newsize < fDefaultSize)
99  newsize = fDefaultSize;
100  newsize = ExpandForIID(iid, newsize);
101  }
102  if (newsize < 0) {
103  Error("Add", "Cannot allocate space to store uid=%d", uid);
104  return -1;
105  }
106  if (fParentID < 0) {
107  Error("Add", "SetParent must be called before adding uid=%d", uid);
108  return -1;
109  }
110  fParentIDs[iid][uid] = fParentID + 1;
111  if (uid >= fN[iid]) fN[iid] = uid + 1;
112  return uid;
113 }
114 
115 
116 ////////////////////////////////////////////////////////////////////////////////
117 /// Add the internal index for fProcessIDs, fAllocSize, etc given a PID.
118 
120 {
121  if (!procid)
123  Int_t pid = procid->GetUniqueID();
124  if (fMapPIDtoInternal.size() <= (size_t) pid)
126 
127  Int_t iid = fMapPIDtoInternal[pid];
128  if (iid == -1) {
129  // need to update
130  iid = FindPIDGUID(procid->GetTitle());
131  if (iid == -1) {
132  fProcessGUIDs.push_back(procid->GetTitle());
133  iid = fProcessGUIDs.size() - 1;
134  }
135  fMapPIDtoInternal[pid] = iid;
136  }
137 
138  ExpandPIDs(iid + 1);
139  return iid;
140 }
141 
142 ////////////////////////////////////////////////////////////////////////////////
143 /// Clear all entries in the table.
144 
145 void TRefTable::Clear(Option_t * /*option*/ )
146 {
147  for (Int_t iid = 0; iid < fNumPIDs; ++iid) {
148  memset(fParentIDs[iid], 0, sizeof(Int_t) * fN[iid]);
149  }
150  memset(fN, 0, sizeof(Int_t) * fNumPIDs);
151  fParentID = -1;
152 }
153 
154 ////////////////////////////////////////////////////////////////////////////////
155 /// Expand fParentIDs to newsize for ProcessID pid.
156 
158 {
159  Int_t iid = GetInternalIdxForPID(pid);
160  if (iid < 0) return -1;
161  return ExpandForIID(iid, newsize);
162 }
163 
164 ////////////////////////////////////////////////////////////////////////////////
165 /// Expand fParentIDs to newsize for internel ProcessID index iid.
166 
168 {
169  if (newsize < 0) return newsize;
170  if (newsize != fAllocSize[iid]) {
171  Int_t *temp = fParentIDs[iid];
172  if (newsize != 0) {
173  fParentIDs[iid] = new Int_t[newsize];
174  if (newsize < fAllocSize[iid])
175  memcpy(fParentIDs[iid], temp, newsize * sizeof(Int_t));
176  else {
177  memcpy(fParentIDs[iid], temp, fAllocSize[iid] * sizeof(Int_t));
178  memset(&fParentIDs[iid][fAllocSize[iid]], 0,
179  (newsize - fAllocSize[iid]) * sizeof(Int_t));
180  }
181  } else {
182  fParentIDs[iid] = 0;
183  }
184  if (fAllocSize[iid]) delete [] temp;
185  fAllocSize[iid] = newsize;
186  }
187  return newsize;
188 }
189 
190 ////////////////////////////////////////////////////////////////////////////////
191 /// Expand the arrays of managed PIDs
192 
194 {
195  if (numpids <= fNumPIDs) return;
196 
197  // else add to internal tables
198  Int_t oldNumPIDs = fNumPIDs;
199  fNumPIDs = numpids;
200 
201  Int_t *temp = fAllocSize;
202  fAllocSize = new Int_t[fNumPIDs];
203  if (temp) memcpy(fAllocSize, temp, oldNumPIDs * sizeof(Int_t));
204  memset(&fAllocSize[oldNumPIDs], 0,
205  (fNumPIDs - oldNumPIDs) * sizeof(Int_t));
206  delete [] temp;
207 
208  temp = fN;
209  fN = new Int_t[fNumPIDs];
210  if (temp) memcpy(fN, temp, oldNumPIDs * sizeof(Int_t));
211  memset(&fN[oldNumPIDs], 0, (fNumPIDs - oldNumPIDs) * sizeof(Int_t));
212  delete [] temp;
213 
214  Int_t **temp2 = fParentIDs;
215  fParentIDs = new Int_t *[fNumPIDs];
216  if (temp2) memcpy(fParentIDs, temp2, oldNumPIDs * sizeof(Int_t *));
217  memset(&fParentIDs[oldNumPIDs], 0,
218  (fNumPIDs - oldNumPIDs) * sizeof(Int_t*));
219 }
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Fill buffer b with the fN elements in fParentdIDs.
223 /// This function is called by TBranchRef::FillLeaves.
224 
226 {
227  b << -fNumPIDs; // write out "-" to signal new TRefTable buffer format using PID table
228  for (Int_t iid = 0; iid < fNumPIDs; ++iid) {
229  b << fN[iid];
230  b.WriteFastArray(fParentIDs[iid], fN[iid]);
231  }
232 }
233 
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 /// Get fProcessGUIDs' index of the TProcessID with GUID guid
237 
238 Int_t TRefTable::FindPIDGUID(const char *guid) const
239 {
240  std::vector<std::string>::const_iterator posPID
241  = std::find(fProcessGUIDs.begin(), fProcessGUIDs.end(), guid);
242  if (posPID == fProcessGUIDs.end()) return -1;
243  return posPID - fProcessGUIDs.begin();
244 }
245 
246 ////////////////////////////////////////////////////////////////////////////////
247 /// Return object corresponding to uid.
248 
249 TObject *TRefTable::GetParent(Int_t uid, TProcessID *context /* =0 */ ) const
250 {
251  if (!fParents) return 0;
252 
253  Int_t iid = -1;
254  if (!context) context = TProcessID::GetSessionProcessID();
255  iid = GetInternalIdxForPID(context);
256 
257  uid = uid & 0xFFFFFF;
258  if (uid < 0 || uid >= fN[iid]) return 0;
259  Int_t pnumber = fParentIDs[iid][uid] - 1;
260  Int_t nparents = fParents->GetEntriesFast();
261  if (pnumber < 0 || pnumber >= nparents) return 0;
262  return fParents->UncheckedAt(pnumber);
263 }
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// Get the index for fProcessIDs, fAllocSize, etc given a PID.
267 /// Uses fMapPIDtoInternal and the pid's GUID / fProcessGUID
268 
270 {
271  return const_cast <TRefTable*>(this)->AddInternalIdxForPID(procid);
272 }
273 
274 ////////////////////////////////////////////////////////////////////////////////
275 /// Get the index for fProcessIDs, fAllocSize, etc given a PID.
276 /// Uses fMapPIDtoInternal and the pid's GUID / fProcessGUID
277 
279 {
281 }
282 
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// Static function returning the current TRefTable.
286 
288 {
289  return fgRefTable;
290 }
291 
292 ////////////////////////////////////////////////////////////////////////////////
293 /// This function is called by TRef::Streamer or TStreamerInfo::ReadBuffer
294 /// when reading a reference.
295 /// This function, in turns, notifies the TRefTable owner for action.
296 /// eg, when the owner is a TBranchRef, TBranchRef::Notify is called
297 /// to read the branch containing the referenced object.
298 
300 {
301  return fOwner->Notify();
302 }
303 
304 ////////////////////////////////////////////////////////////////////////////////
305 /// Fill buffer b with the fN elements in fParentdIDs.
306 /// This function is called by TBranchRef::ReadLeaves
307 
309 {
310  Int_t firstInt = 0; // we don't know yet what it means
311  b >> firstInt;
312 
313  Int_t numIids = -1;
314  Int_t startIid = 0;
315  if (firstInt < 0) numIids = -firstInt; // new format
316  else {
317  // old format, only one PID
318  numIids = 1;
319 
320  TProcessID *fileProcessID = b.GetLastProcessID(this);
321 
322  startIid = GetInternalIdxForPID(fileProcessID);
323  if (startIid == -1) {
324  fProcessGUIDs.push_back(fileProcessID->GetTitle());
325  startIid = fProcessGUIDs.size() - 1;
326  }
327  numIids += startIid;
328  }
329 
330  ExpandPIDs(numIids);
331  for (Int_t iid = startIid; iid < numIids; ++iid) {
332  Int_t newN = 0;
333  if (firstInt < 0) b >> newN;
334  else newN = firstInt;
335  if (newN > fAllocSize[iid])
336  ExpandForIID(iid, newN + newN / 2);
337  fN[iid] = newN;
338  b.ReadFastArray(fParentIDs[iid], fN[iid]);
339  }
340 }
341 
342 ////////////////////////////////////////////////////////////////////////////////
343 /// Clear all entries in the table.
344 
345 void TRefTable::Reset(Option_t * /*option*/ )
346 {
347  Clear();
348  if (fParents) fParents->Clear();
349 }
350 
351 ////////////////////////////////////////////////////////////////////////////////
352 /// -- Set current parent object, typically a branch of a tree.
353 ///
354 /// This function is called by TBranchElement::Fill() and by
355 /// TBranchElement::GetEntry().
356 
357 Int_t TRefTable::SetParent(const TObject* parent, Int_t branchID)
358 {
359  if (!fParents) {
360  return -1;
361  }
362  Int_t nparents = fParents->GetEntriesFast();
363  if (branchID != -1) {
364  // -- The branch already has an id cached, just use it.
365  fParentID = branchID;
366  }
367  else {
368  // -- The branch does *not* have an id cached, find it or generate one.
369  // Lookup the branch.
370  fParentID = fParents->IndexOf(parent);
371  if (fParentID < 0) {
372  // -- The branch is not known, generate an id number.
373  fParents->AddAtAndExpand(const_cast<TObject*>(parent), nparents);
374  fParentID = nparents;
375  }
376  }
377  return fParentID;
378 }
379 
380 ////////////////////////////////////////////////////////////////////////////////
381 /// Static function setting the current TRefTable.
382 
384 {
385  fgRefTable = table;
386 }
387 
388 ////////////////////////////////////////////////////////////////////////////////
389 /// Stream an object of class TRefTable.
390 
391 void TRefTable::Streamer(TBuffer &R__b)
392 {
393  if (R__b.IsReading()) {
394  R__b.ReadClassBuffer(TRefTable::Class(),this);
395  } else {
396  R__b.WriteClassBuffer(TRefTable::Class(),this);
397  //make sure that all TProcessIDs referenced in the Tree are put to the buffer
398  //this is important in case the buffer is a TMessage to be sent through a TSocket
399 #if 0
400  TObjArray *pids = TProcessID::GetPIDs();
401  Int_t npids = pids->GetEntries();
402  Int_t npid2 = fProcessGUIDs.size();
403  for (Int_t i = 0; i < npid2; i++) {
404  TProcessID *pid;
405  for (Int_t ipid = 0;ipid<npids;ipid++) {
406  pid = (TProcessID*)pids->At(ipid);
407  if (!pid) continue;
408  if (!strcmp(pid->GetTitle(),fProcessGUIDs[i].c_str()))
409  R__b.WriteProcessID(pid);
410  }
411  }
412 #endif
413  }
414 }
Int_t fParentID
[fNumPIDs][fAllocSize] array of Parent IDs
Definition: TRefTable.h:42
static TProcessID * GetProcessID(UShort_t pid)
static function returning a pointer to TProcessID number pid in fgPIDs
Definition: TProcessID.cxx:232
TObject * fOwner
Definition: TRefTable.h:48
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:375
Bool_t IsReading() const
Definition: TBuffer.h:83
An array of TObjects.
Definition: TObjArray.h:37
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:320
const char Option_t
Definition: RtypesCore.h:62
static UInt_t GetNProcessIDs()
Return the (static) number of process IDs.
Definition: TProcessID.cxx:240
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
virtual Int_t Add(Int_t uid, TProcessID *context=0)
Add a new uid to the table.
Definition: TRefTable.cxx:88
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
virtual void Clear(Option_t *="")
Clear all entries in the table.
Definition: TRefTable.cxx:145
static void SetRefTable(TRefTable *table)
Static function setting the current TRefTable.
Definition: TRefTable.cxx:383
Int_t GetInternalIdxForPID(TProcessID *procid) const
Get the index for fProcessIDs, fAllocSize, etc given a PID.
Definition: TRefTable.cxx:269
void ExpandPIDs(Int_t numpids)
Expand the arrays of managed PIDs.
Definition: TRefTable.cxx:193
static TObjArray * GetPIDs()
static: returns array of TProcessIDs
Definition: TProcessID.cxx:321
TObjArray * fParents
Definition: TRefTable.h:47
void Class()
Definition: Class.C:29
Int_t fSize
TProcessID the current uid is referring to.
Definition: TRefTable.h:46
virtual Bool_t Notify()
This method must be overridden to handle object notification.
Definition: TObject.cxx:506
Int_t * fN
[fNumPIDs] allocated size of array fParentIDs for each ProcessID
Definition: TRefTable.h:40
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
Int_t fNumPIDs
Definition: TRefTable.h:38
virtual UShort_t WriteProcessID(TProcessID *pid)=0
Always return 0 (current processID).
Definition: TBuffer.cxx:332
virtual TProcessID * GetLastProcessID(TRefTable *reftable) const =0
Int_t AddInternalIdxForPID(TProcessID *procid)
Add the internal index for fProcessIDs, fAllocSize, etc given a PID.
Definition: TRefTable.cxx:119
static TRefTable * fgRefTable
cache of pid to index in fProcessGUIDs
Definition: TRefTable.h:51
virtual ~TRefTable()
Destructor.
Definition: TRefTable.cxx:71
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
virtual void Reset(Option_t *="")
Clear all entries in the table.
Definition: TRefTable.cxx:345
virtual void ReadBuffer(TBuffer &b)
Fill buffer b with the fN elements in fParentdIDs.
Definition: TRefTable.cxx:308
std::vector< Int_t > fMapPIDtoInternal
Definition: TRefTable.h:50
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual Int_t ExpandForIID(Int_t iid, Int_t newsize)
Expand fParentIDs to newsize for internel ProcessID index iid.
Definition: TRefTable.cxx:167
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
std::vector< std::string > fProcessGUIDs
Definition: TRefTable.h:49
Int_t * fAllocSize
number of known ProcessIDs
Definition: TRefTable.h:39
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
UInt_t fUID
default size for a new PID array
Definition: TRefTable.h:44
Int_t fDefaultSize
current parent ID in fParents (latest call to SetParent)
Definition: TRefTable.h:43
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
#define ClassImp(name)
Definition: Rtypes.h:359
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
virtual Int_t Expand(Int_t pid, Int_t newsize)
Expand fParentIDs to newsize for ProcessID pid.
Definition: TRefTable.cxx:157
virtual Int_t SetParent(const TObject *parent, Int_t branchID)
– Set current parent object, typically a branch of a tree.
Definition: TRefTable.cxx:357
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:589
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:35
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:275
virtual void FillBuffer(TBuffer &b)
Fill buffer b with the fN elements in fParentdIDs.
Definition: TRefTable.cxx:225
Mother of all ROOT objects.
Definition: TObject.h:37
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
Int_t ** fParentIDs
[fNumPIDs] current maximum number of IDs in array fParentIDs for each ProcessID
Definition: TRefTable.h:41
TProcessID * fUIDContext
Current uid (set by TRef::GetObject)
Definition: TRefTable.h:45
Int_t FindPIDGUID(const char *guid) const
Get fProcessGUIDs&#39; index of the TProcessID with GUID guid.
Definition: TRefTable.cxx:238
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
TRefTable()
Default constructor for I/O.
Definition: TRefTable.cxx:52
virtual Bool_t Notify()
This function is called by TRef::Streamer or TStreamerInfo::ReadBuffer when reading a reference...
Definition: TRefTable.cxx:299
TObject * GetParent(Int_t uid, TProcessID *context=0) const
Return object corresponding to uid.
Definition: TRefTable.cxx:249