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