GSI Object Oriented Online Offline (Go4)  GO4-6.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TGo4HDF5Adapter.cxx
Go to the documentation of this file.
1 // $Id: TGo4HDF5Adapter.cxx 2723 2020-03-13 08:19:44Z linev $
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 
15 #include "TGo4HDF5Adapter.h"
16 
17 #include "TList.h"
18 #include "TDataMember.h"
19 #include "TVirtualCollectionProxy.h"
20 #include "TBaseClass.h"
21 
22 #include "TGo4Log.h"
23 #include "TGo4EventElement.h"
24 #include "TGo4CompositeEvent.h"
25 
26 const char* TGo4HDF5Adapter::fgcFILESUF = ".h5";
27 
28 
30 {
31  if(fxFile==0) return;
32  delete fxFile;
33  fxFile=0;
34 }
35 
36 
38 {
39  if(fbDataSetExists)
40  delete fxHandle;
41  fbDataSetExists=kFALSE;
42 }
43 
45 {
46  if (event==0) return 0;
47  TClass* evclass=event->Class();
48  TClass* actualclass=evclass->GetActualClass(event);
49  size_t rev=actualclass->Size();
50  go4hdfdbg("TGo4HDF5Adapter: ScanEventSize for class %s with object size %ld\n",
51  actualclass->GetName(), rev);
52  return rev;
53 }
54 
55 void TGo4HDF5Adapter::AddSubHandle(TGo4HDF5DataHandle* handle, const char* name, const char* type, size_t size,
56  size_t memberoffset, const char* membername, const char* classname, TClass* valueclass)
57 {
58  TGo4HDF5DataHandle* subhandle = handle->AddSubMember(name, size, type);
59  subhandle->SetParentOffset(memberoffset);
60  subhandle->SetMemberName(membername);
61  subhandle->SetMemberClass(classname);
62  TGo4HDF5SubVectorDataHandle* subvector = dynamic_cast<TGo4HDF5SubVectorDataHandle*> (subhandle);
63  if(subvector)
64  {
65  TString containerclass = "TGo4HDF5VectorProxy";
66  FillTypeInfo(subhandle, name, containerclass.Data());
67 
68  }
69  else
70  {
71  if (valueclass)
72  FillTypeInfo(subhandle, valueclass, name);
73  else
74  FillTypeInfo(subhandle, name, classname);
75  }
76 }
77 
78 
79 
80 
81 void TGo4HDF5Adapter::FillTypeInfo(TGo4HDF5DataHandle* handle, TClass* rootclass, const char* basename)
82 {
83  if(handle==0 || rootclass==0) return;
84  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo CCCC - for class %s \n", rootclass->GetName());
85  // first check here baseclass members:
86  // otherwise will not store complete object
87  // and we have the problem of the bounce buffer with offset when reading back (first implementation!)
88  TIter baseiter(rootclass->GetListOfBases());
89  TObject* obj = 0;
90  while ((obj=baseiter()) != 0) {
91  //printf("TGo4HDF5Adapter::FillTypeInfo - baseiter object 0x%x of name %s , class:%s\n", obj, (obj ? obj->GetName() : "No base class"), (obj ? obj->IsA()->GetName() : "No type"));
92  TBaseClass* base = dynamic_cast<TBaseClass*>(obj);
93  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo - base class 0x%lx %s \n", (unsigned long) base, (base ? base->GetName() : "No base class"));
94  if (base==0) continue;
95  TClass* bclass=base->GetClassPointer();
96  if(bclass==0) continue;
97  FillTypeInfo(handle, bclass, basename);
98  }
99 
100  // skip base class members not necessary for our dataset:G
101  if(strcmp(rootclass->GetName(),"TObject")==0) return;
102  if(strcmp(rootclass->GetName(),"TNamed")==0) return;
103  if(strcmp(rootclass->GetName(),"TGo4EventElement")==0) return;
104 
105  if(strcmp(rootclass->GetName(),"TGo4CompositeEvent")==0)
106  {
107  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo COMP detects go4 composite event. Assign fMaxIndex member...\n");
108  TDataMember* member=rootclass->GetDataMember("fMaxIndex");
109  if (member==0) return;
110  size_t memberoffset = member->GetOffset();
111  const char* memtypename = member->GetFullTypeName();
112  TString fullname= (basename ? TString::Format("%s_%s", basename, member->GetName()) : TString(member->GetName()));
113  const char* membername = fullname.Data();
114  Int_t arraydim = member->GetArrayDim();
115  FillTypeInfo(handle, membername, memtypename, memberoffset, arraydim, member);
116  return;
117  // avoid that reading back the event will overwrite our objectarray pointers, since it is inside the fiReadOffset range!
118  // for composite events without own members, however, need the fMaxIndex as dummy to produce a hdf5 dataset
119  }
120 
121 
122 
123 
124  // follows the members of our class
125  TIter iter(rootclass->GetListOfDataMembers());
126 
127  //TObject* obj = 0;
128  while ((obj=iter()) != 0) {
129  TDataMember* member = dynamic_cast<TDataMember*>(obj);
130  if (member==0) continue;
131  const char* memtypename = member->GetFullTypeName();
132  TString fullname= (basename ? TString::Format("%s_%s", basename, member->GetName()) : TString(member->GetName()));
133  const char* membername = fullname.Data();
134  size_t memberoffset = member->GetOffset();
135  Int_t arraydim = member->GetArrayDim();
136  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo *** sees member %s of type %s, offset=%ld , arraydim=%d\n",
137  membername, memtypename, memberoffset, arraydim);
138  //continue; // DEBUG IT
139 
140  if (arraydim>2) continue;
141 // hsize_t maxindex1(1), maxindex2(1);
142 // H5::DataType theType;
143  // do not edit IsA info
144  if(strstr(memtypename,"TClass")) // handles TClass* and atomic_TClass_ptr of ROOT6
145  continue;
146  if(strstr(membername,"fgIsA")!=0) // paranoidly redundant, never come here
147  continue;
148 
149  if(member->Property() & kIsStatic)
150  {
151  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo ignored static member.\n");
152  continue;
153  }
154 
155 
156  // first check if we have a collection member.
157  TClass* innerclass=TClass::GetClass(memtypename);
158  TVirtualCollectionProxy* cprox = (innerclass ? innerclass->GetCollectionProxy() : 0);
159  if(cprox)
160  {
161  TClass* collectionclass=cprox->GetCollectionClass();
162  TClass* valueclass=cprox->GetValueClass();
163  EDataType valuetype=cprox->GetType();
164  // Int_t colltype=cprox->GetCollectionType();
165  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo *** has collection proxy, type:%d, valueclass=0x%lx, valuetype=%d\n",
166  cprox->GetCollectionType(),
167  (unsigned long) valueclass, valuetype);
168  size_t innersize=0;
169  size_t collsize=0;
170  TString typenm;
171  TString colltypnm;
172 
173  //continue; // JAM DEBUG - leave out collections to test composite event io first! OK, this works
174 
175 
176  if(valueclass)
177  {
178  collsize=collectionclass->Size();
179  innersize=valueclass->Size();
180  typenm=valueclass->GetName();
181  colltypnm= collectionclass->GetName();
182  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo has collection proxy for type %d, collectionclass %s, class %s, size:%ld, collsize:%ld\n",
183  collectionclass->GetCollectionType(), colltypnm.Data(), typenm.Data(), innersize, collsize);//, cprox->Size() needs real collection object set to proxy);
184 
185  }
186  else if (valuetype)
187  {
188  TDataType* datatype=TDataType::GetDataType(valuetype);
189  typenm=datatype->GetTypeName();
190  innersize=datatype->Size();
191 
192  // will not work, since basic type do not have class object in ROOT!
193  //valueclass=TClass::GetClass(typenm.Data());
194  //go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo sees valueclass %s\n",(valueclass? valueclass->GetName() :"NO CLASS"));
195 
196  colltypnm=memtypename; // get the vector<double> here!
197  collectionclass=TClass::GetClass(memtypename);
198  if(collectionclass)
199  collsize= collectionclass->Size();
200  else
201  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo could not get class for collection %s \n",memtypename);
202  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo has collection proxy for value %d, type %s, size:%ld, collsize:%ld\n",
203  collectionclass->GetCollectionType(), typenm.Data(), innersize, collsize);
204  }
205  else
206  {
207  continue;
208  }
209 
211 
212  // now evaluate the subhandles depending on the array dimension:
213  // here treat special case of array of vectors (poland example)
214  Int_t maxindex1=0, maxindex2=0;
215  switch(arraydim)
216  {
217 
218  default:
219  // plain collection that is not part of another array:
220  AddSubHandle(handle, membername, colltypnm.Data(), innersize, memberoffset, member->GetName(), typenm.Data(), valueclass);
221  break;
222 
223  case 1:
224  maxindex1 = member->GetMaxIndex(0);
225  for(int x=0; x<maxindex1; ++x)
226  {
227  TString arraymember=TString::Format("%s[%d]",membername,x); // contains supermembers as prefix for full name
228  TString memberhandle=TString::Format("%s[%d]",member->GetName(),x); // only local member for pointer handle
229  AddSubHandle(handle, arraymember.Data(), colltypnm.Data(), innersize, memberoffset, memberhandle.Data(), typenm.Data(), valueclass);
230  memberoffset+=collsize;
231  }
232  break;
233 
234  case 2:
235  maxindex1 = member->GetMaxIndex(0);
236  maxindex2 = member->GetMaxIndex(1);
237  for(int x=0; x<maxindex1; ++x)
238  for(int y=0; y<maxindex2; ++y)
239  {
240  TString arraymember=TString::Format("%s[%d][%d]",membername,x,y); // contains supermembers as prefix for full name
241  TString memberhandle=TString::Format("%s[%d][%d]",member->GetName(),x,y); // only local member for pointer handle
242  AddSubHandle(handle, arraymember.Data(), colltypnm.Data(), innersize, memberoffset, memberhandle.Data(), typenm.Data(), valueclass);
243  memberoffset+=collsize;
244  }
245  break;
246 
247 
248  }; // switch(arraydim)
249  continue;
250  }
251 
252  FillTypeInfo(handle, membername, memtypename, memberoffset, arraydim, member);
253 
254  } // while ((obj=iter()) != 0) {
255 
256 }
257 
258 
260  const char* membername, const char* memtypename, size_t memberoffset,
261  Int_t arraydim, TDataMember* member)
262  {
263  H5::DataType theType;
264  hsize_t maxindex1(1), maxindex2(1);
265 
266  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo begins for type %s ...\n",memtypename);
267 
268 
269  if ((strcmp(memtypename,"Char_t")==0) || (strcmp(memtypename,"char")==0))
270  theType=H5::PredType::NATIVE_CHAR;
271  else if ((strcmp(memtypename,"UChar_t")==0) || (strcmp(memtypename,"unsigned char")==0))
272  theType=H5::PredType::NATIVE_UCHAR;
273  else if ((strcmp(memtypename,"Short_t")==0) || (strcmp(memtypename,"short")==0))
274  theType=H5::PredType::NATIVE_SHORT;
275  else if ((strcmp(memtypename,"UShort_t")==0) || (strcmp(memtypename,"unsigned short")==0))
276  theType=H5::PredType::NATIVE_USHORT;
277  else if ((strcmp(memtypename,"Int_t")==0) || (strcmp(memtypename,"int")==0))
278  theType=H5::PredType::NATIVE_INT;
279  else if ((strcmp(memtypename,"UInt_t")==0) || (strcmp(memtypename,"unsigned int")==0))
280  theType=H5::PredType::NATIVE_UINT;
281  else if ((strcmp(memtypename,"ULong_t")==0) || (strcmp(memtypename,"unsigned long")==0))
282  theType=H5::PredType::NATIVE_ULONG;
283  else if ((strcmp(memtypename,"Double_t")==0)|| (strcmp(memtypename,"double")==0))
284  theType=H5::PredType::NATIVE_DOUBLE;
285  else if ((strcmp(memtypename,"Float_t")==0) || (strcmp(memtypename,"float")==0))
286  theType=H5::PredType::NATIVE_FLOAT;
287  else if ((strcmp(memtypename,"Bool_t")==0)|| (strcmp(memtypename,"bool")==0))
288  theType=H5::PredType::NATIVE_HBOOL;
289 
290 
291  else if((strcmp(memtypename,"TString")==0) || (strstr(memtypename,"string")!=0))
292  {
293  return; // skip for the moment names and text information TODO!
294  }
295 
296  else if(strcmp(memtypename,"TGo4HDF5VectorProxy")==0)
297  {
298  // this is dummy class to represent vector of vector entry, handle it manually without root
299  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo handles explicitly vector entry %s\n",memtypename);
300 
301  TString innermemname;
302  TGo4HDF5DataHandle innercomp(memtypename,sizeof(TGo4HDF5VectorProxy));
303  innermemname= TString::Format("%s_fx_Begin_ptr",membername);
304  innercomp.InsertTypeMember(innermemname.Data(), HOFFSET(TGo4HDF5VectorProxy, fx_Begin_ptr), H5::PredType::NATIVE_ULONG);
305  innermemname= TString::Format("%s_fx_End_ptr",membername);
306  innercomp.InsertTypeMember(innermemname.Data(), HOFFSET(TGo4HDF5VectorProxy, fx_End_ptr), H5::PredType::NATIVE_ULONG);
307  innermemname= TString::Format("%s_fx_Cap_ptr",membername);
308  innercomp.InsertTypeMember(innermemname.Data(), HOFFSET(TGo4HDF5VectorProxy, fx_Cap_ptr), H5::PredType::NATIVE_ULONG);
309  theType= *(innercomp.GetType());
310  }
311 
312 
313 
314 
315  else {
316  // evaluate structure components here
317  TClass* innerclass=TClass::GetClass(memtypename);
318 
319  if(innerclass==0) return;
320  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo finds root class info for type %s\n",memtypename);
321 
322  size_t innersize=innerclass->Size();
323  // temporary datahandle just to extract the type components
324  TGo4HDF5DataHandle innercomp(memtypename,innersize);
325  FillTypeInfo(&innercomp, innerclass, membername);
326  theType= *(innercomp.GetType());
327  }
328 
329  const H5std_string theMEMBER(membername);
330 
331  switch(arraydim) {
332  case 1:
333  {
334  maxindex1 = member->GetMaxIndex(0);
335  hsize_t dims[1]={maxindex1};
336  H5::ArrayType theArray(theType, arraydim, dims);
337  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo inserts array member %s, type %s dimension %d, maxindex:%lld , offset:%ld\n",
338  membername,memtypename, arraydim,maxindex1, memberoffset);
339  handle->InsertTypeMember( theMEMBER, memberoffset, theArray);
340  break;
341  }
342  case 2:
343  {
344  maxindex1 = member->GetMaxIndex(0);
345  maxindex2 = member->GetMaxIndex(1);
346  hsize_t dims[2]={maxindex1, maxindex2};
347  H5::ArrayType theArray(theType, arraydim, dims);
348  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo inserts array member %s, type %s dimension %d, maxindex:%lld , offset:%ld\n",
349  membername,memtypename, arraydim,maxindex1, memberoffset);
350 
351  handle->InsertTypeMember( theMEMBER, memberoffset, theArray);
352  break;
353 
354  }
355 
356 
357  default:
358  go4hdfdbg("TGo4HDF5Adapter::FillTypeInfo inserts simple member %s, type %s dimension %d, maxindex:%lld , offset:%ld\n",
359  membername, memtypename, arraydim,maxindex1, memberoffset);
360 
361  handle->InsertTypeMember(theMEMBER, memberoffset, theType);
362  break;
363 
364  } // switch()
365  }
366 
367 
368 
370 {
371  TClass* evclass=event->Class();
372  if(!evclass)
373  {
374  TGo4Log::Error("TGo4HDF5Adapter::BuildDataType can not find an event class\n");
375  return;
376  }
377  TClass* actualclass=evclass->GetActualClass(event);
378  TString actualclassname= actualclass->GetName();
379  size_t eventsize=ScanEventSize(event);
380  TGo4HDF5DataHandle* theHandle=0;
381  go4hdfdbg("TGo4HDF5Adapter::BuildDataType for class %s\n",
382  actualclassname.Data());
383  if(parent==0)
384  {
385  // top level event, components are scanned recursively:
386  fxHandle=new TGo4HDF5BasicDataHandle(actualclassname.Data(), eventsize);
387  fxHandle->SetObjectPointer(event);
388  FillTypeInfo(fxHandle, actualclass, actualclassname.Data());
389  theHandle=fxHandle;
390  fxHandle->SetTopEvent(event);
391  fxHandle->SetTopEventClass(actualclassname.Data());
392 
393  }
394  else
395  {
396  // component of a composite event: belongs to the parent handle
397  TString compname=TString::Format("%s_%s(%d)",parent->GetTypeName(), actualclassname.Data(), index);
398  TString comptype="Go4CompEv"; // do we need to tag the subhandles here?
399  theHandle=parent->AddSubMember(compname.Data(), eventsize, comptype.Data());
400  void* super=parent->Data(); // everything is relative to immediate mother element
401  size_t delta= (char*) event - (char*) super;
402  go4hdfdbg("TGo4HDF5Adapter::BuildDataType sets parent offset %ld (event:0x%lx, super:0x%lx)\n",
403  delta, (unsigned long) event, (unsigned long) super);
404  theHandle->SetParentOffset(delta);
405  theHandle->SetObjectPointer(super);
406  // prepend here the parent name to our subhandle:
407  FillTypeInfo(theHandle, actualclass, theHandle->GetTypeName());
408 
409  // for reading back component data, each composite subevent has to override the top level parent event:
410  theHandle->SetTopEvent(event);
411  theHandle->SetTopEventClass(actualclassname.Data());
412 
413  }
414 
415 // need to scan components of composite event here:
416  TGo4CompositeEvent* comp= dynamic_cast<TGo4CompositeEvent*>(event);
417  if(comp)
418  {
419  go4hdfdbg("TGo4HDF5Adapter::BuildDataType evaluates members of Go4 composite event %s\n",
420  comp->GetName());
421  Short_t numSubEvents=comp->getNElements();
422  for (int i = 0; i < numSubEvents ; ++i)
423  {
424  TGo4EventElement* sub = comp->getEventElement(i);
425  if(sub==0) continue;
426  BuildDataType(sub,theHandle, i);
427  }
428  }
429 
430  // finally, set reference pointers for all evaluated subcomponents:
431  if(parent==0)
432  {
433  theHandle->SetObjectPointer(event); // set it here, because parentoffsets of subcomponents may have changed at recursive evaluation
434  }
435 
436 }
437 
438 
439 
441 {
442  UInt_t h5flags=0;
443 
444  switch(flags)
445  {
446  case GO4_H5F_ACC_NONE:
447  case GO4_H5F_ACC_TRUNC:
448  h5flags=H5F_ACC_TRUNC;
449  break;
450  case GO4_H5F_ACC_EXCL:
451  h5flags=H5F_ACC_EXCL;
452  break;
453  case GO4_H5F_ACC_RDONLY:
454  h5flags=H5F_ACC_RDONLY;
455  break;
456  case GO4_H5F_ACC_RDWR:
457  h5flags=H5F_ACC_RDWR;
458  break;
459  default:
460  h5flags=H5F_ACC_TRUNC;
461  break;
462  }
463  return h5flags;
464 }
static const char * fgcFILESUF
void InsertTypeMember(const H5std_string &name, size_t offset, const H5::DataType &new_member)
H5::H5File * fxFile
UInt_t ConvertFileMode(Go4_H5_File_Flags flags)
Short_t getNElements() const
static void FillTypeInfo(TGo4HDF5DataHandle *handle, TClass *rootclass, const char *basename=0)
void BuildDataType(TGo4EventElement *event, TGo4HDF5DataHandle *parent=0, Int_t index=0)
H5::CompType * GetType()
#define go4hdfdbg(args...)
Definition: Go4HDF5.h:26
size_t ScanEventSize(TGo4EventElement *event)
static void AddSubHandle(TGo4HDF5DataHandle *handle, const char *name, const char *type, size_t size, size_t memberoffset, const char *membername, const char *classname, TClass *valueclass)
virtual void DeleteDataSet()
void SetTopEventClass(const char *classname)
Go4_H5_File_Flags
Definition: Go4HDF5.h:41
const char * GetTypeName()
void SetTopEvent(TGo4EventElement *eve)
TGo4EventElement * getEventElement(Int_t idx)
virtual void SetObjectPointer(void *memptr)
void SetParentOffset(size_t off)
virtual void CloseFile()
TGo4HDF5DataHandle * AddSubMember(const char *name, size_t datasize, const char *collectiontype=0)
static void Error(const char *text,...)
Definition: TGo4Log.cxx:323
void SetMemberName(const char *name)
TGo4HDF5DataHandle * fxHandle
void SetMemberClass(const char *clname)