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