ATLAS Offline Software
TVirtualConverter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
14 #include "TROOT.h"
15 #include "TClass.h"
16 #include "TBaseClass.h"
17 #include "TDataMember.h"
18 #include "TClassEdit.h"
19 #include "TDataType.h"
20 #include "TBuffer.h"
21 #include "TError.h"
22 #include "TStreamerInfo.h"
23 #include <cassert>
24 #include <cstdlib>
25 
26 
27 namespace {
28 
29 
39 UInt_t CalculateCheckSum (TClass* cl, const char* name_in)
40 {
41  UInt_t id = 0;
42  int il;
43  TString name = name_in;
44  TString type;
45  il = name.Length();
46  for (int i=0; i<il; i++) id = id*3+name[i];
47 
48  TList *tlb = cl->GetListOfBases();
49  if (tlb) { // Loop over bases
50 
51  TIter nextBase(tlb);
52 
53  TBaseClass *tbc=0;
54  while((tbc=(TBaseClass*)nextBase())) {
55  name = tbc->GetName();
56  il = name.Length();
57  for (int i=0; i<il; i++) id = id*3+name[i];
58  }/*EndBaseLoop*/
59  }
60  TList *tlm = cl->GetListOfDataMembers();
61  if (tlm) { // Loop over members
62  TIter nextMemb(tlm);
63  TDataMember *tdm=0;
64  Long_t prop = 0;
65  while((tdm=(TDataMember*)nextMemb())) {
66  if (!tdm->IsPersistent()) continue;
67  // combine properties
68  prop = (tdm->Property());
69  TDataType* tdt = tdm->GetDataType();
70  if (tdt) prop |= tdt->Property();
71 
72  if ( prop&kIsStatic) continue;
73  name = tdm->GetName(); il = name.Length();
74  if (prop&kIsEnum) id = id*3 + 1;
75 
76  int i;
77  for (i=0; i<il; i++) id = id*3+name[i];
78  type = tdm->GetFullTypeName();
79  {
80  // Protect against data race inside TClassEdit.
81  // https://github.com/root-project/root/issues/10353
82  // Should be fixed in root 6.26.02.
83  R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
84  if (TClassEdit::IsSTLCont(type) != ROOT::kNotSTL)
85  type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
86  }
87 
88  il = type.Length();
89  for (i=0; i<il; i++) id = id*3+type[i];
90 
91  int dim = tdm->GetArrayDim();
92  if (prop&kIsArray) {
93  for (int i=0;i<dim;i++) id = id*3+tdm->GetMaxIndex(i);
94  }
95 
96  }/*EndMembLoop*/
97  }
98  return id;
99 }
100 
101 
102 } // anonymous namespace
103 
104 
112  TClass* trans_cls,
113  TClass* pers_cls)
114  : fTransClass (trans_cls),
115  fPersClass (pers_cls),
116  fCheckSum (checksum),
117  fOldLast (-3),
118  fPersObj (0)
119 {
120  CheckClasses();
121 }
122 
123 
132  TClass* pers_cls)
133  : fTransClass (trans_cls),
134  fPersClass (pers_cls),
135  fCheckSum (fTransClass ?
136  CalculateCheckSum (fPersClass, fTransClass->GetName()) : 0),
137  fOldLast (-3),
138  fPersObj (0)
139 {
140  CheckClasses();
141 }
142 
143 
153  const std::string& trans_cls,
154  const std::string& pers_cls)
155  : fTransClass (ToClass (trans_cls)),
156  fPersClass (ToClass (pers_cls)),
157  fCheckSum (checksum),
158  fOldLast (-3),
159  fPersObj (0)
160 {
161  CheckClasses();
162 }
163 
164 
174 TVirtualConverter::TVirtualConverter (const std::string& trans_cls,
175  const std::string& pers_cls)
176  : fTransClass (ToClass (trans_cls)),
177  fPersClass (ToClass (pers_cls)),
178  fCheckSum (CalculateCheckSum (fPersClass, fTransClass->GetName())),
179  fOldLast (-3),
180  fPersObj (0)
181 {
182  CheckClasses();
183 }
184 
185 
190 {
191  if (fTransClass == 0) {
192  if (fPersClass == 0)
193  Error ("TVirtualConverter",
194  "Both transient and persistent classes are null.");
195  else
196  Error ("TVirtualConverter",
197  "Transient class is null for persistent class `%s'",
198  fPersClass->GetName());
199  }
200  else if (fPersClass == 0)
201  Error ("TVirtualConverter",
202  "Persistent class is null for transient class `%s'",
203  fTransClass->GetName());
204 }
205 
206 
211 {
212  // If we made an instance of the persistent class, get rid of it here.
213  if (fPersObj)
215 }
216 
217 
222 {
223  return fTransClass;
224 }
225 
226 
231 {
232  return fPersClass;
233 }
234 
235 
240 {
241  return fCheckSum;
242 }
243 
244 
252 {
253  return fPersClass->New();
254 }
255 
256 
265 {
266  return fPersClass->Destructor (persobj);
267 }
268 
269 
284  void* obj,
285  Version_t version,
286  UInt_t R__s,
287  UInt_t R__c)
288 {
289  // Make sure that we've done automatic schema evolution on the
290  // persistent side.
292 
293  // Make an instance of the persistent class, if we haven't done so already.
294  if (fPersObj == 0)
295  fPersObj = NewPersObj();
296 
297  // Read in the object, as an instance of the persistent class.
298  fPersClass->ReadBuffer (b, fPersObj, version, R__s, R__c);
299 
300  // Convert to the transient representation.
302 }
303 
304 
311 TClass* TVirtualConverter::ToClass (const std::string& name)
312 {
313  return gROOT->GetClass (name.c_str());
314 }
315 
316 
323 TClass* TVirtualConverter::ToClass (const std::type_info& id)
324 {
325  TClass* cl = gROOT->GetClass (id);
326  if (cl) return cl;
327 
328  // This may fail if the dictionary hasn't been loaded yet,
329  // since we can auto-load only on the name.
330  // Make some attempt to get a name from the type_info.
331  const char* name = id.name();
332  cl = gROOT->GetClass (name);
333  if (cl) return cl;
334 
335  const char* n2 = name;
336  while (isdigit(*n2))
337  ++n2;
338  cl = gROOT->GetClass (n2);
339  if (cl) return cl;
340 
341  int errorCode = 0;
342  char* demname = nullptr;
343  {
344  // Protect against data race inside TClassEdit.
345  // https://github.com/root-project/root/issues/10353
346  // Should be fixed in root 6.26.02.
347  R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
348  demname = TClassEdit::DemangleTypeIdName (id, errorCode);
349  }
350  if (demname) {
351  cl = gROOT->GetClass (demname);
352  free (demname);
353  }
354  return cl;
355 }
356 
357 
370 {
371  // First check to see if the list of TStreamerInfo's for the transient
372  // class has changed since the last time we were called. If not,
373  // then don't do anything.
374  const TObjArray* trans_sis = fTransClass->GetStreamerInfos();
375  if (trans_sis->GetLast() != fOldLast) {
376  // There was a change. Compare the TStreamerInfo list for the
377  // persistent class and the transient class. Look for entries
378  // where the transient class has a TStreamerInfo but the persistent
379  // class does not.
380  //
381  // Note: don't do this for `version' -1.
382  // That should always be built from the internal dictionary.
383  // (Otherwise, root can crash.)
384  const TObjArray* pers_sis = fPersClass->GetStreamerInfos();
385  assert (trans_sis->LowerBound() == pers_sis->LowerBound());
386  for (Int_t v = trans_sis->LowerBound(); v <= trans_sis->GetLast(); ++v) {
387  if (v != -1 &&
388  trans_sis->At(v) != 0 &&
389  (v > pers_sis->GetLast() || pers_sis->At(v) == 0))
390  {
391  // Ok, at this index, the transient class has a TStreamerInfo
392  // but the persistent class does not. Copy the TStreamerInfo
393  // (changing the class that it applies to to the persistent
394  // class), and add it to the persistent class's list.
395  TStreamerInfo* new_si =(TStreamerInfo*)(trans_sis->At(v)->Clone());
396  new_si->SetClass (fPersClass);
397  fPersClass->RegisterStreamerInfo (new_si);
398  }
399  }
400 
401  // Remember how many entries there were in the list for next time.
402  fOldLast = trans_sis->GetLast();
403  }
404 }
405 
406 
414  : fTransClass (0),
415  fPersClass (0),
416  fCheckSum (0),
417  fOldLast (-3),
418  fPersObj (0)
419 {
420 }
421 
422 
431 void TVirtualConverter::SetCtorInfo (UInt_t checksum,
432  TClass* trans_cls,
433  TClass* pers_cls)
434 {
435  assert (fTransClass == 0);
436 
437  fCheckSum = checksum;
438  fTransClass = trans_cls;
439  fPersClass = pers_cls;
440  CheckClasses();
441 }
PlotCalibFromCool.il
il
Definition: PlotCalibFromCool.py:381
TVirtualConverter::GetPersClass
TClass * GetPersClass()
Return the persistent class, from which we're converting.
Definition: TVirtualConverter.cxx:230
TVirtualConverter::ToClass
static TClass * ToClass(const std::string &name)
Helper to convert a class name to a Root class pointer.
Definition: TVirtualConverter.cxx:311
yodamerge_tmp.dim
dim
Definition: yodamerge_tmp.py:239
TVirtualConverter::GetCheckSum
int GetCheckSum() const
Return the checksum of the class from which we're converting.
Definition: TVirtualConverter.cxx:239
TVirtualConverter::fOldLast
int fOldLast
Used by CheckStreamInfos: the length of the streamerinfo list that we saw on the last CheckStreamInfo...
Definition: TVirtualConverter.h:265
TVirtualConverter::TVirtualConverter
TVirtualConverter()
Default constructor.
Definition: TVirtualConverter.cxx:413
LArDigits2NtupleDumper.tdt
tdt
Definition: LArDigits2NtupleDumper.py:121
TVirtualConverter::~TVirtualConverter
virtual ~TVirtualConverter()
Destructor.
Definition: TVirtualConverter.cxx:210
TVirtualConverter::ReadBuffer
virtual void ReadBuffer(TBuffer &b, void *obj, Version_t version, UInt_t R__S, UInt_t R__c)
Read object in non-split mode.
Definition: TVirtualConverter.cxx:283
TVirtualConverter.h
Base class for Root converters.
TVirtualConverter::fCheckSum
UInt_t fCheckSum
The declared checksum.
Definition: TVirtualConverter.h:261
TVirtualConverter::fTransClass
TClass * fTransClass
The declared transient class.
Definition: TVirtualConverter.h:255
TVirtualConverter::fPersObj
void * fPersObj
The temporary persistent object instance, used for conversions (in non-split mode).
Definition: TVirtualConverter.h:271
TVirtualConverter::CheckClasses
void CheckClasses()
Helper to check that the classes have been defined properly.
Definition: TVirtualConverter.cxx:189
lumiFormat.i
int i
Definition: lumiFormat.py:92
TVirtualConverter::CheckStreamInfos
void CheckStreamInfos()
Helper to allow for automatic schema evolution for persistent classes.
Definition: TVirtualConverter.cxx:369
TVirtualConverter::GetTransClass
TClass * GetTransClass()
Return the transient class, to which we're converting.
Definition: TVirtualConverter.cxx:221
TVirtualConverter::fPersClass
TClass * fPersClass
The declared persistent class.
Definition: TVirtualConverter.h:258
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:194
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
python.PyAthena.v
v
Definition: PyAthena.py:157
get_generator_info.version
version
Definition: get_generator_info.py:33
TVirtualConverter::SetCtorInfo
void SetCtorInfo(UInt_t checksum, TClass *trans_cls, TClass *pers_cls)
Set the parameters that would normally be passed to the constructor.
Definition: TVirtualConverter.cxx:431
TVirtualConverter::NewPersObj
virtual void * NewPersObj()
Create a new instance of the persistent class.
Definition: TVirtualConverter.cxx:251
TVirtualConverter::DeletePersObj
virtual void DeletePersObj(void *persobj)
Destroy an instance of the persistent class.
Definition: TVirtualConverter.cxx:264
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
python.PyAthena.obj
obj
Definition: PyAthena.py:135
TVirtualConverter::ConvertVoid
virtual void ConvertVoid(void *transobj, const void *persobj)=0
Do the conversion.
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26