GSI Object Oriented Online Offline (Go4) GO4-6.4.0
Loading...
Searching...
No Matches
TGo4HDF5DataHandle.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 "TGo4HDF5DataHandle.h"
16
17#include "TROOT.h"
18#include "TObjString.h"
19#include "TObjArray.h"
20#include "TDataType.h"
21
22#include "TGo4Log.h"
24#include "TGo4HDF5Source.h"
25
26#include <vector>
27
29
30TGo4HDF5DataHandle::TGo4HDF5DataHandle(const char *name, size_t datasize)
31 : fxTypeName(name), fxType(nullptr), fxDataSet(), fxDataSpace(nullptr), fxFileSpace(0), fiEntries(0),
32 fxData(nullptr), fiParentOffset(0), fiDataSize(datasize), fiReadOffset(0), fxEvent(nullptr),
33 fxParentSource(nullptr), fbDataSetExists(false), fbDataSetActive(false)
34
35{
36 fxType = new H5::CompType(datasize);
37 go4hdfdbg("TGo4HDF5DataHandle DDD created %s for size %ld \n", fxTypeName.Data(), datasize);
38}
39
41{
42 go4hdfdbg("TGo4HDF5DataHandle is deleted %s \n", fxTypeName.Data());
43
44 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
45 {
47 delete entry;
48 }
49 fxSubcomponents.clear();
50 fxDataSet.close();
51 delete fxDataSpace;
52 delete fxType;
53}
54
55void TGo4HDF5DataHandle::InsertTypeMember(const H5std_string &name, size_t offset, const H5::DataType &new_member)
56{
57 fxType->insertMember(name, offset, new_member);
58 if (fiReadOffset == 0)
59 fiReadOffset = offset; // keep location of first real data member
60 fbDataSetActive = kTRUE; // only work with handle if it has at least one member assigned to type
61}
62
63TGo4HDF5DataHandle *TGo4HDF5DataHandle::AddSubMember(const char *name, size_t datasize, const char *collectiontype)
64{
65 TGo4HDF5DataHandle *sub = fxFactory.CreateDataHandle(name, datasize, collectiontype);
66 fxSubcomponents.push_back(sub);
67 return sub;
68}
69
71 {
72 if (!name)
73 return nullptr;
74 // go4hdfdbg("TGo4HDF5DataHandle FindSubMember for name %s\n", name);
75 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) {
77 // go4hdfdbg("TGo4HDF5DataHandle FindSubMember %d compares with name %s\n",
78 // i, cursor ? cursor->GetTypeName() : "EMPTY CURSOR!");
79 if (strcmp(cursor->GetTypeName(), name) == 0)
80 return cursor;
81
82 // scan recursively name in possible subcomponents. do we need this?
83 TGo4HDF5DataHandle *subcursor = cursor->FindSubMember(name);
84 if (subcursor)
85 return subcursor;
86 }
87 return nullptr;
88 }
89
91 {
92 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) {
94 cursor->SetActive(on);
95 cursor->SetAllSubMembersActive(on);
96 }
97 }
98
100 {
101 fxData = (char *)(memptr) + fiParentOffset;
102 go4hdfdbg("TGo4HDF5DataHandle SetObjectPointer for %s with memptr 0x%lx and parentoffset 0x%lx has fxData:0x%lx\n",
103 fxTypeName.Data(), (unsigned long)memptr, (unsigned long)fiParentOffset, (unsigned long)fxData);
104
105 // now recursively do it for our components:
106 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
107 {
109 entry->SetObjectPointer(fxData);
110 }
111 }
112
114{
115 fxEvent = eve;
116 go4hdfdbg("TTTTTTTT TGo4HDF5DataHandle %s - SetTopEvent sets pointer to %ld \n", fxTypeName.Data(),
117 (unsigned long)eve);
118 // now recursively do it for our components:
119 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
120 {
122 entry->SetTopEvent(fxEvent);
123 }
124}
125
127{
128 fxEventClass = txt;
129 // go4hdfdbg("TGo4HDF5DataHandle::SetTopEventClass TTTTTTTT to %s \n",fxEventClass.Data());
130 // now recursively do it for our components:
131 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
132 {
134 entry->SetTopEventClass(txt);
135 }
136}
137
139{
140 // just recursively do it for our components:
141 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
142 {
144 entry->BuildReadDataset(file, parent);
145 }
146}
147
149 {
150 // just recursively do it for our components:
151 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) {
153 entry->BuildWriteDataset(file);
154 }
155 // actual dataset is build in subclass
156 }
157
158 void TGo4HDF5DataHandle::Read(hsize_t sequencenum, H5::H5File* file)
159 {
160 if(sequencenum>=fiEntries)
161 {
162 go4hdfdatahandlethrow( "TGo4HDF5DataHandle::Read - reached end of dataspace at %ld entries!\n", fiEntries);
163 }
164
165 //if(fbDataSetActive && fbDataSetExists)
167 {
168 hsize_t offset[1]= {sequencenum};
169 hsize_t onerow[1] ={1};
170 fxFileSpace.selectHyperslab( H5S_SELECT_SET, onerow, offset ); // one row of event object at last entry (offset is nextsize-1)
171 // idea: the go4 event is always at same location in memory, so we use the original data space as defined in BuildDataSet
172 // the data space in file for each event is of course increasing, so we need to extend the dataset and select
173 // a hyperslab to the write destination in the file.
174 go4hdfdbg("TGo4HDF5DataHandle::Read of %s has selected hyperslab for onerow:[%ld] offset:[%ld]\n",
175 fxTypeName.Data(),(unsigned long) onerow[0], (unsigned long) offset[0]);
176
177 // the actual reading from filespace is implemented in subclass!
178
179 }
180
181 // now recursively do it for our subcomponents :
182 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
183 {
185 entry->Read(sequencenum, file);
186 }
187 }
188
189void TGo4HDF5DataHandle::Write(hsize_t sequencenum, H5::H5File* file)
190{
191 //if(fbDataSetActive && fbDataSetExists)
193 {
194
195 go4hdfdbg("TGo4HDF5DataHandle::Write %s base function will extend dataset for %lld \n", fxTypeName.Data(), sequencenum);
196 hsize_t offset[1] = { sequencenum };
197 hsize_t nextsize[1] = { sequencenum + 1 };
198
199 fxDataSet.extend(nextsize);
200
201 fxFileSpace = fxDataSet.getSpace(); // dataspace in file
202 hsize_t onerow[1] = { 1 };
203 fxFileSpace.selectHyperslab(H5S_SELECT_SET, onerow, offset); // one row of event object at last entry (offset is nextsize-1)
204 // idea: the go4 event is always at same location in memory, so we use the original data space as defined in BuildDataSet
205 // the data space in file for each event is of course increasing, so we need to extend the dataset and select
206 // a hyperslab to the write destination in the file.
207
208 // the actual writing to filespace is implemented in subclass!
209
210 }
211 // now recursively do it for our subcomponents :
212 for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
213 {
215 entry->Write(sequencenum, file);
216 }
217
218}
219
221
222
223TGo4HDF5BasicDataHandle::TGo4HDF5BasicDataHandle(const char *name, size_t datasize) :
224 TGo4HDF5DataHandle(name, datasize), fxReadBuffer(nullptr)
225
226 {
227 go4hdfdbg("TGo4HDF5BasicDataHandle ctor\n");
228 }
229
230
232 {
233 go4hdfdbg("TGo4HDF5BasicDataHandle is deleted %s \n", fxTypeName.Data());
234 // delete [] fxReadBuffer; ???
235 }
236
237
239 {
240 if(fxReadBuffer && (size == fiDataSize)) return;
241 delete [] fxReadBuffer;
242 fxReadBuffer = new Char_t[size];
243 fiDataSize = size;
244 go4hdfdbg("TGo4HDF5DataHandle: AllocReadBuffer has created read buffer 0x%lx for size %ld \n",
245 (unsigned long) fxReadBuffer, fiDataSize);
246 }
247
249 {
250 if (!fbDataSetExists)// && fbDataSetActive)
251 {
252
253 fxParentSource=parent;
254
255 Int_t rank=1; // entries of the ntuple/tree
256 hsize_t dims[1] = { 1}; // dataset dimensions at creation
257 hsize_t maxdims[1] = {H5S_UNLIMITED}; // 1 ? only one entry maps to current event object -
258 fxDataSpace= new H5::DataSpace(rank, dims, maxdims);
259
260 // dataspace in memory covers only the current input event structure
261 hsize_t onerow[1] ={1};
262 hsize_t offset[1]= {0};
263 fxDataSpace->selectHyperslab( H5S_SELECT_SET, onerow, offset );
264
265 // get existing dataset from file and compare data with type of the target event
266 // we only allow datasets that match the memory structure concerning member names etc,
267
268 // NOTE that for reading back data, we first have to figure out our subcomponents from the file dataspace by name!
269 // TODO: when reading, scan all datasets in file
270 // for composite events, configgure the input event according the information in hdf5 file ????
271 // this means BuildDataType has to be done after we have scanned the input file and reconstructed the substructure setup
272 // not so easy, so constraint is currently that all substructures in code must match the status when hdf5 file was recorded
273
274 go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet will open set %s\n", fxTypeName.Data());
275 fxDataSet = file->openDataSet(fxTypeName.Data());
276
277 H5T_class_t type_class = fxDataSet.getTypeClass();
278 H5::CompType intype;
279 if( type_class == H5T_COMPOUND)
280 {
281 intype= fxDataSet.getCompType();
282 // size_t size = intype.getSize();
283 go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet finds in file compound type of size %ld \n", intype.getSize());
284 }
285 else if( type_class == H5T_VLEN)
286 {
287 H5::VarLenType vtype = fxDataSet.getVarLenType();
288 H5::DataType entrytype = vtype.getSuper();
289 //H5::DataType* entrytype = vtype.decode();
290 //size_t size = entrytype.getSize();
291 //size_t vsize = vtype.getSize();
292 H5T_class_t entry_class = entrytype.getClass();
293 go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet finds in file vlen type of size %ld, with entry class %d, size %ld \n",
294 vtype.getSize(), entry_class, entrytype.getSize());
295 if( entry_class == H5T_COMPOUND)
296 {
297
298 H5::DataType* ptype=&entrytype;
299 H5::CompType* entrycomp = static_cast<H5::CompType*>(ptype); // dynamic cast fails here?
300 if (entrycomp){
301 intype = *entrycomp;
302 go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet uses compound entry of vlen dtype %d \n", entry_class );
303 }
304 else
305 {
306 go4hdfdatahandlethrow("TGo4HDF5DataHandle: BuildReadDataSet - could not assign component entry of varlen data type !\n");
307 }
308 }
309 // TODO: treat vectors with simple data members here?
310 else
311 {
312 go4hdfdatahandlethrow( "TGo4HDF5DataHandle: BuildReadDataSet - varlen data type without compound, but contains class %d!\n", entry_class);
313 }
314 }
315 else
316 {
317 go4hdfdatahandlethrow("TGo4HDF5DataHandle: BuildReadDataSet - file contains no compound or varlen data type, but type %d!\n",type_class)
318 }
319
320
321 fxFileSpace = fxDataSet.getSpace();
322 int frank = fxFileSpace.getSimpleExtentNdims();
323 std::vector<hsize_t> dims_out(frank, 0);
324 fxFileSpace.getSimpleExtentDims(dims_out.data(), nullptr);
325 go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet file dataspace has rank %d, dimensions:%d, #1. dimension=%ld \n",
326 frank, fxFileSpace.getSimpleExtentDims(dims_out.data(), nullptr), (long) (dims_out[0]));
327 fiEntries = dims_out[0]; // events filled in this file, for leaving the read loop later.
328
329 #ifdef GO4HDF5_DEBUG
330 // check consistency of file dataset with input event structure:
331 int nfilemembers= intype.getNmembers ();
332 int neventmembers= fxType->getNmembers ();
333
334
335 go4hdfdbg("Type comparison: number of compound members: file %d, event %d\n",nfilemembers, neventmembers);
336
337 go4hdfdbg("Dump Type from file:\n");
338 for (int i = 0; i < nfilemembers; ++i)
339 {
340 H5::DataType mem_type=intype.getMemberDataType(i);
341 go4hdfdbg("\t %d: name:%s class:%s", i, intype.getMemberName(i).c_str(), mem_type.fromClass().c_str());
342 H5T_class_t mem_class = intype.getMemberClass(i);
343 if (mem_class == H5T_ARRAY)
344 {
345 H5::ArrayType artyp = intype.getMemberArrayType(i);
346 int ardim = artyp.getArrayNDims();
347 hsize_t dims[ardim];
348 artyp.getArrayDims(dims);
349 go4hdfdbg(" array dimensions:%d [", ardim);
350 for (int j = 0; j < ardim; ++j)
351 {
352 go4hdfdbg("%d", (int) dims[j]);
353 }
354 go4hdfdbg("]");
355 }
356 go4hdfdbg("\n");
357 }
358 go4hdfdbg("Dump Type from event structure:\n");
359 for (int i = 0; i < neventmembers; ++i)
360 {
361 H5::DataType mem_type=fxType->getMemberDataType(i);
362 go4hdfdbg("\t %d: name:%s class:%s", i, intype.getMemberName(i).c_str(), mem_type.fromClass().c_str());
363 H5T_class_t mem_class = fxType->getMemberClass(i);
364 if (mem_class == H5T_ARRAY)
365 {
366 H5::ArrayType artyp = fxType->getMemberArrayType(i);
367 int ardim = artyp.getArrayNDims();
368 hsize_t dims[ardim];
369 artyp.getArrayDims(dims);
370 go4hdfdbg("array dimensions:%d [", ardim);
371 for (int j = 0; j < ardim; ++j)
372 {
373 go4hdfdbg("%lu", (unsigned long) dims[j]);
374 }
375 go4hdfdbg("]");
376 }
377 go4hdfdbg("\n");
378 }
379
380 #endif
381
382 if(!(*fxType==intype))
383 {
384 TString msg= TString::Format( "BuildReadDataSet type mismatch between event structure(%s) and input from file (%s)\n",
385 fxType->fromClass().c_str(), intype.fromClass().c_str());
386 TGo4Log::Error("TGo4HDF5DataHandle: %s", msg.Data());
387 parent->SetErrMess(msg.Data());
388 throw TGo4EventSourceException(parent);
389
390 }
391
393
394 fbDataSetExists=kTRUE;
395
396 }
397
399
400 }
401
403 {
404
406 go4hdfdbg("TGo4HDF5BasicDataHandle: BuildWriteDataset for event set %s\n", fxTypeName.Data());
407 Int_t rank = 1; // entries of the ntuple/tree
408 hsize_t dims[1] = {1}; // dataset dimensions at creation
409 hsize_t maxdims[1] = {H5S_UNLIMITED};
410 fxDataSpace = new H5::DataSpace(rank, dims, maxdims);
411
412 H5::DSetCreatPropList cparms;
413 hsize_t chunk_dims[1] = {1};
414 cparms.setChunk(rank, chunk_dims);
415 cparms.setFillValue(*fxType, fxData);
416
417 fxDataSet = file->createDataSet(fxTypeName.Data(), *fxType, *fxDataSpace, cparms);
418 fbDataSetExists = kTRUE;
419 }
421 }
422
423 void TGo4HDF5BasicDataHandle::Read(hsize_t sequencenum, H5::H5File *file)
424 {
425 TGo4HDF5DataHandle::Read(sequencenum, file); // prepare dataspace and treat subcomponents
426 if (!fbDataSetActive)
427 return;
428
429 // we must not use actual eventclass directly,
430 // because hdf5 will destroy memory of not registered data members like pointer to eventsource and class info!
431 void *data = (void *)(fxReadBuffer);
432
433 // printf("TGo4HDF5Source: BuildEvent before read on data pointer 0x%lx \n",data);
434
435 fxDataSet.read(data, *fxType, *fxDataSpace, fxFileSpace);
436
437 // here copy data from our hdf5 bounce buffer to actual event object:
438 Char_t *target = (Char_t *)(fxData) + fiReadOffset;
439 Char_t *source = (Char_t *)(fxReadBuffer) + fiReadOffset;
440 size_t copylen = fiDataSize - fiReadOffset;
441 memcpy(target, source, copylen);
442
443#ifdef GO4HDF5_DEBUG
444 printf("Copy %ld bytes from %lx to %lx, fiReadOffset=%ld, fiDataSize=%ld \n", copylen, (long)source, (long)target,
446#endif
447 }
448
449 void TGo4HDF5BasicDataHandle::Write(hsize_t sequencenum, H5::H5File *file)
450 {
451 TGo4HDF5DataHandle::Write(sequencenum, file); // treat subcomponents here, extend dataset
452
453 if (!fbDataSetActive)
454 return;
455 // idea: the go4 event is always at same location in memory, so we use the original data space as defined in
456 // BuildDataSet the data space in file for each event is of course increasing, so we need to extend the dataset and
457 // select a hyperslab to the write destination in the file.
458 go4hdfdbg("TGo4HDF5BasicDataHandle::Write %s plain\n", fxTypeName.Data());
460 }
461
463
465 : TGo4HDF5BasicDataHandle(name, datasize)
466
467{
468 go4hdfdbg("TGo4HDF5CompositeDataHandle ctor use go4 composite event component\n");
469};
470
472{
473 go4hdfdbg("TGo4HDF5CompositeDataHandle is deleted %s \n", fxTypeName.Data());
474}
475
477{
479 // NOTE: currently we can not reconstruct the setup of the composite event from the information in hdf5 file
480 // we just rely that the user code has set up the input event accordingly and check if the types are consistent
481 // with information from hdf5 input
482 // later TODO?: evaluate substructure of composite event and dynamically create components of known class
483 // <- interpreter business. For the moment, do not follow this approach.
484}
485
487{
488 // same as plain set here. do we need different treatment?
489
491}
492
493void TGo4HDF5CompositeDataHandle::Read(hsize_t sequencenum, H5::H5File *file)
494{
495 TGo4HDF5BasicDataHandle::Read(sequencenum, file);
496 }
497
498 void TGo4HDF5CompositeDataHandle::Write(hsize_t sequencenum, H5::H5File *file)
499 {
500 TGo4HDF5BasicDataHandle::Write(sequencenum, file);
501 }
502
504
505TGo4HDF5VectorDataHandle::TGo4HDF5VectorDataHandle(const char *name, size_t datasize) :
506 TGo4HDF5BasicDataHandle(name, datasize), fxCollection(nullptr), fiElementSize(0)
507
508 {
509 go4hdfdbg("TGo4HDF5VectorDataHandle ctor \n");
510
511
512
513 // need to create comp type with hvl_t handle here!
514 //fxCollection = new H5::VarLenType(fxType); // this does not work, file is corrupt afterwards JAM 27-may-2019
515 fxCollection = new H5::CompType(sizeof(TGo4HDF5VarContainer));
516
517 fxCollection -> insertMember( fxTypeName.Data(), HOFFSET(TGo4HDF5VarContainer, fxArray), H5::VarLenType(fxType));
518
519 go4hdfdbg("TGo4HDF5VectorDataHandle ctor, typename is %s\n",
520 fxTypeName.Data());
521 }
522
523
525{
526 go4hdfdbg("TGo4HDF5VectorDataHandle is deleted %s \n", fxTypeName.Data());
527 delete fxCollection;
528}
529
531{
532
534
535 // depends on vector implementation! following is probably not true:
536 // struct std::vector<T>
537 // {
538 // size_t size;
539 // size_t cap;
540 // T* buffer;
541 // }
542 //
543 // maybe std::vector member in classlooks like this?
544 // struct vector { // Simple C struct as example (T is the type supplied by the template)
545 // T *begin; // vector::begin() probably returns this value
546 // T *end; // vector::end() probably returns this value
547 // T *end_capacity; // First non-valid address
548 // // Allocator state might be stored here (most allocators are stateless)
549 // };
550
551 char **p_collection = (char **) fxData;
552 char **p_begin_ptr = p_collection;
553 char **p_end_ptr = p_collection + 1;
554 //char **p_cap_ptr = p_collection + 2;
555
556 go4hdfdbg("TGo4HDF5VectorDataHandle SetObjectPointer has fxData=0x%lx elementsize=%ld\n",
557 (unsigned long) fxData, fiElementSize);
558
559 size_t len = (*p_end_ptr - *p_begin_ptr) / fiElementSize;
560 //size_t cap = (*p_cap_ptr - *p_begin_ptr) / fiElementSize;
561
562 fxVarHandle.fxArray.p = *p_begin_ptr;
563 fxVarHandle.fxArray.len = len;
564
565// SetActive((fxVarHandle.fxArray.p && (fxVarHandle.fxArray.len > 0)) ? true : false); // disable writing out empty vector
566
567#ifdef GO4HDF5_DEBUG
568 static unsigned debugcount = 0;
569 char **p_cap_ptr = p_collection + 2;
570 size_t cap = (*p_cap_ptr - *p_begin_ptr) / fiElementSize;
571 if (debugcount < 10000)
572 {
573 go4hdfdbg(
574 "TGo4HDF5VectorDataHandle SetObjectPointer for count %d has collection size: %ld capacity: %ld pointer to buffer 0x%lx, ACTIVE=%d\n",
575 debugcount, len, cap, (unsigned long) *p_begin_ptr, fbDataSetActive);
576 debugcount++;
577 }
578
579#endif
580
581// printf(
582// "TGo4HDF5VectorDataHandle %s - SetObjectPointer has collection size: %ld capacity: %ld pointer to buffer 0x%lx, fxData=0x%x\n",
583// fxTypeName.Data(), len, cap, (unsigned long) *p_begin_ptr, fxData);
584
585}
586
591
592
594 {
595 if(!fbDataSetExists) // && fbDataSetActive)
596 {
597 go4hdfdbg("TGo4HDF5VectorDataHandle: BuildWriteDataset for collection set %s \n",fxTypeName.Data());
598
599 Int_t rank=1; // entries of the ntuple/tree. vector dimension is handled by variable size type?
600 hsize_t dims[1] = { 1}; // dataset dimensions at creation
601 hsize_t maxdims[1] = {H5S_UNLIMITED};
602 fxDataSpace= new H5::DataSpace(rank, dims, maxdims);
603 H5::DSetCreatPropList cparms;
604 hsize_t chunk_dims[1] ={1};
605 cparms.setChunk( rank, chunk_dims );
606
607 cparms.setFillValue(H5::VarLenType(fxType), &fxVarHandle.fxArray);
608 fxDataSet = file->createDataSet( fxTypeName.Data(), H5::VarLenType(fxType), *fxDataSpace, cparms);
609
610 fbDataSetExists=kTRUE;
611 }
613
614}
615
616void TGo4HDF5VectorDataHandle::Read(hsize_t sequencenum, H5::H5File* file)
617{
618 TGo4HDF5DataHandle::Read(sequencenum, file); // prepare dataspaces and handle subcompoments
619 if(!fbDataSetActive) return;
620 go4hdfdbg("TGo4HDF5VectorDataHandle::Read %s collection \n", fxTypeName.Data());
621
622 // TODO: set varhandle to buffer - setobjectpointer has done this to actual vector in event object
623 // we need to resize this before we can directly fill it!
624// size_t vsize = fxDataSet.getVarLenType().getSize(); // this is just size in bytes, not #entries
625// go4hdfdbg("TGo4HDF5VectorDataHandle::Read FFFF tells us size of vlen type size is now %ld \n",
626// vsize);
627
628 // TODO: how to get from hdf5 length of vector _before_ reading it!!!?
629 // not necessary, since hdf5 will do allocation itself at hvl_t.p
630// int numentries = 5; //? get from filespace ?
631// size_t currentsize= fiElementSize * numentries;
632// AllocReadBuffer(currentsize);
634
635
636 fxVarHandle.fxArray.p = nullptr; //note: read will allocate the necessary buffer memory automatically!
637 fxDataSet.read(&fxVarHandle.fxArray, H5::VarLenType(fxType), *fxDataSpace, fxFileSpace);
638 go4hdfdbg("TGo4HDF5VectorDataHandle::Read LLLL length after reading is %ld, buffer is 0x%lx \n",
639 fxVarHandle.fxArray.len,
640 (unsigned long) fxVarHandle.fxArray.p);
641
642
644 // build interpreter command to resize our vector using handle on top event:
645// TString resizecom = TString::Format("%s * myevent= (%s *) %ld; myevent-> %s.resize(%ld)",
646// fxEventClass.Data(), fxEventClass.Data(), (unsigned long) fxEvent, fxMemberHandle.Data(), fxVarHandle.fxArray.len);
647//
648//
649//
650//
652// go4hdfdbg("TGo4HDF5VectorDataHandle::Read will use command: %s \n", resizecom.Data());
653// gROOT->ProcessLineFast(resizecom.Data());
654//
655// char **p_collection = (char **) fxData;
656// char **p_begin_ptr = p_collection;
657// char **p_end_ptr = p_collection + 1;
658// char **p_cap_ptr = p_collection + 2;
659//
660// size_t len = (*p_end_ptr - *p_begin_ptr) / fiElementSize;
661// size_t cap = (*p_cap_ptr - *p_begin_ptr) / fiElementSize;
662//
663// go4hdfdbg(
664// "TGo4HDF5VectorDataHandle::Read has collection size: %ld capacity: %ld pointer to buffer 0x%lx, end: 0x%lx cap: 0x%lx\n",
665// len, cap, (unsigned long) *p_begin_ptr, (unsigned long) *p_end_ptr, (unsigned long) *p_cap_ptr);
666// // here copy data from our hdf5 bounce buffer to actual event object:
667// Char_t *target = *p_begin_ptr;
668// Char_t *source = (Char_t*) fxVarHandle.fxArray.p; //(Char_t*) (fxReadBuffer);
669// size_t copylen = fxVarHandle.fxArray.len * fiElementSize;
670// go4hdfdbg(
671// "TGo4HDF5VectorDataHandle::Read before memcopy from 0x%x to 0x%x with length %ld (element size is :%ld)\n",
672// (unsigned long) source, (unsigned long) target, copylen, fiElementSize);
673//
674//
675// if(fxVarHandle.fxArray.len >0){
676// memcpy (target, source, copylen);
677//
678// go4hdfdbg(
679// "TGo4HDF5VectorDataHandle::Read AFTER COPY has collection size: %ld capacity: %ld pointer to buffer 0x%lx, end: 0x%lx cap: 0x%lx\n",
680// len, cap, (unsigned long) *p_begin_ptr, (unsigned long) *p_end_ptr, (unsigned long) *p_cap_ptr);
681//
682// }
683// NOTE: after doing this copy, the next clear on this vector will crash!
685
687 //dataVec.insert(dataVec.end(), &dataArray[0], &dataArray[dataArraySize]);
688
689 if(fxVarHandle.fxArray.len >0)
690 {
691 Char_t *first =(Char_t*) fxVarHandle.fxArray.p;
692 Char_t *last = (Char_t*) fxVarHandle.fxArray.p + (fxVarHandle.fxArray.len) * fiElementSize;
693
694 TString vectorhandle = TString::Format("myevent->%s",fxMemberHandle.Data());
695 TString copycom = TString::Format("%s * myevent= (%s *) %ld; %s.insert(%s.end(), (%s *) %ld, (%s *) %ld)",
696 fxEventClass.Data(), fxEventClass.Data(), (unsigned long) fxEvent, vectorhandle.Data(), vectorhandle.Data(),
697 fxMemberClass.Data(), (unsigned long) first, fxMemberClass.Data(),(unsigned long) last);
698
699 go4hdfdbg("TGo4HDF5VectorDataHandle::Read will use command: %s \n", copycom.Data());
700 gROOT->ProcessLineFast(copycom.Data());
701
702 // now check if vector has changed:
703#ifdef GO4HDF5_DEBUG
704
705 char **p_collection = (char **) fxData;
706 char **p_begin_ptr = p_collection;
707 char **p_end_ptr = p_collection + 1;
708 char **p_cap_ptr = p_collection + 2;
709
710 size_t len = (*p_end_ptr - *p_begin_ptr) / fiElementSize;
711 size_t cap = (*p_cap_ptr - *p_begin_ptr) / fiElementSize;
712
713 go4hdfdbg(
714 "TGo4HDF5VectorDataHandle::Read after INSERT has collection size: %ld capacity: %ld pointer to buffer 0x%lx, end: 0x%lx cap: 0x%lx\n",
715 len, cap, (unsigned long) *p_begin_ptr, (unsigned long) *p_end_ptr, (unsigned long) *p_cap_ptr);
716#endif
717
718 }
719
721}
722
723
724void TGo4HDF5VectorDataHandle::Write(hsize_t sequencenum, H5::H5File* file)
725{
726 SetActive((fxVarHandle.fxArray.p && (fxVarHandle.fxArray.len > 0)) ? true : false); // disable writing out empty vector
727
728 BuildWriteDataset(file); // dataset is no sooner created than we have really data to write in vector
729 TGo4HDF5DataHandle::Write(sequencenum, file);
730
732 {
733 //printf("TGo4HDF5VectorDataHandle::Write %s collection \n", fxTypeName.Data());
734 go4hdfdbg("TGo4HDF5VectorDataHandle::Write %s collection \n", fxTypeName.Data());
735 //TGo4HDF5DataHandle::Write(sequencenum, file);
736 fxDataSet.write(&fxVarHandle.fxArray, H5::VarLenType(fxType), *fxDataSpace, fxFileSpace);
737 // fxDataSet.write(fxVarHandle.fxArray.p, *fxType, *fxDataSpace, fspace); // test if we can write at lease first element in array? yes!
738 }
739 else
740 {
741 go4hdfdbg("TGo4HDF5VectorDataHandle::Write DO NOT WRITE inactive %s collection\n", fxTypeName.Data());
742 }
743
744}
745
747
748
749// this handle is a collection of vector elements with subelements
751 TGo4HDF5VectorDataHandle(name, datasize)
752
753{
754 go4hdfdbg("TGo4HDF5SubVectorDataHandle ctor \n");
755}
756
757
759{
760 go4hdfdbg("TGo4HDF5SubVectorDataHandle is deleted %s \n", fxTypeName.Data());
761}
762
764{
765
767 // still need to update recursively all vectors in this container
768
769 TDataType datatype(fxInnerClassName.Data());
770
771 size_t innersize=datatype.Size();
772
773 // need to find out which of the existing subhandles should not be written, because
774 // the corresponding entries in subervector are not existing for the current event.
775 SetAllSubMembersActive(false); // first disable all subcomponents if existing
776
777
778 for(unsigned int ix = 0; ix < fxVarHandle.fxArray.len; ++ix)
779 {
780 char *cursor = (char *) (fxVarHandle.fxArray.p) + ix * fiElementSize;
781 //TGo4HDF5VectorProxy* prox = (TGo4HDF5VectorProxy*) cursor;
782
783 TString fullname= TString::Format("%s[%d]", GetTypeName(), ix ); // full name of dataset
784 TString membername = TString::Format("%s[%d]",fxMemberHandle.Data(),ix); // local name to access member functions
785 // before adding it, look if we already have one TODO!
786 go4hdfdbg(
787 "TGo4HDF5SubVectorDataHandle SetObjectPointer updating element %s, inner class is %s\n",
788 fullname.Data(), fxInnerClassName.Data());
789
790// printf(
791// "TGo4HDF5SubVectorDataHandle SetObjectPointer updating element %s, inner class is %s\n",
792// fullname.Data(), fxInnerClassName.Data());
793
794 TString memberclass = TString::Format("vector<%s>",fxInnerClassName.Data());
795 TString searchname = TString::Format("%s[%s]",fullname.Data(), memberclass.Data());
796 TGo4HDF5DataHandle* subhandle =FindSubMember(searchname.Data());
797 if(subhandle)
798 {
799 go4hdfdbg(
800 "TGo4HDF5SubVectorDataHandle SetObjectPointer finds element %s, already in subcomponents\n",
801 searchname.Data());
802 subhandle->SetActive(true);
803 }
804 else
805 {
806 go4hdfdbg(
807 "TGo4HDF5SubVectorDataHandle SetObjectPointer creates new subcomponent %s \n",
808 fullname.Data());
809 //TString memberclass = TString::Format("vector<%s>",fxInnerClassName.Data());
810 subhandle = AddSubMember(fullname.Data(), innersize, memberclass.Data());
811 subhandle->SetMemberName(membername);
812 subhandle->SetMemberClass(fxInnerClassName.Data());
813
814 TGo4HDF5Adapter::FillTypeInfo(subhandle, fullname.Data(), fxInnerClassName.Data());
815 // newly created subcomponents will be set active at lazy creation of dataset later (when write or read is called).
816 subhandle->SetActive(true);
817 }
818
819 void *super = Data(); // everything is relative to immediate mother element
820 // pointer to the subvector is content of cursor:
821
822// char **psubvector = (char **)cursor;
823// char *subvector = *psubvector;
824// size_t delta = (char *) subvector - (char *) super;
825
826
827#ifdef GO4HDF5_DEBUG
828 char *subvector = cursor;
829#endif
830 size_t delta = (char *) cursor - (char *) super;
831 go4hdfdbg("TGo4HDF5SubVectorDataHandle SetObjectPointer sets parent offset %ld (subvector:0x%lx, super:0x%lx) cursor was 0x%lx\n",
832 delta, (unsigned long) subvector, (unsigned long) super, (unsigned long) cursor);
833
834 subhandle->SetParentOffset(delta);
835 subhandle->SetObjectPointer(super); // will internally set active only if subvector has real data
836
837 //subhandle->SetActive(false); // JAMDEBUG: disable all writing of subsubvectors
838
839 }
840
841}
842
844 {
846 SetActive(false);
847 }
848
849
851 {
852 // do nothing here until dataset is initalized lazy after set object pointer is done!
853 // TGo4HDF5DataHandle::BuildWriteDataset(file); // recursively do it for all subcomponents
854 // we do not build an own dataset to store the vector of vector in the file here.
855 // the actual data is stored in our subcomponents (i.e. regular TGo4HDF5VectorDataHandle objects)
856
857 go4hdfdbg("TGo4HDF5SubVectorDataHandle: BuildWriteDataset NOP for collection set %s \n",fxTypeName.Data());
858 SetActive(false); // mark to skip writing the vector of vector container itself.
859 }
860
861 void TGo4HDF5SubVectorDataHandle::Read(hsize_t sequencenum, H5::H5File* file)
862 {
863 // TODO here: for a consistent read back we would need to evaluate which of the subvectors are
864 // filled in the file for each entry.
865
866
868 TGo4HDF5DataHandle::Read(sequencenum, file); // recursively do it for all subcomponents
869 // we do not read the vector of vector from file here.
870 // the actual data is read into our subcomponents (i.e. regular TGo4HDF5VectorDataHandle objects)
871
872 go4hdfdbg("TGo4HDF5SubVectorDataHandle::Read %s collection \n", fxTypeName.Data());
873}
874
875void TGo4HDF5SubVectorDataHandle::Write(hsize_t sequencenum, H5::H5File* file)
876{
877 // need to dynamically setup new write datsets for variable subcomponents like vectors of vectors
878 //TGo4HDF5DataHandle::BuildWriteDataset(file);
879 TGo4HDF5DataHandle::Write(sequencenum, file);
880}
881
882
884
885TGo4HDF5DataHandle* TGo4HDF5DataHandleFactory::CreateDataHandle(const char *name, size_t datasize, const char *type)
886{
887 TGo4HDF5DataHandle* rev = nullptr;
888
889 if (strstr(type, "vector<vector"))
890 {
891 // add collectionclass to our datahandle name:
892 TString theName(name);
893 TString theCollection(type);
894 theName += "[";
895 theName = theName.Append(theCollection);
896 theName += "]";
897 TGo4HDF5SubVectorDataHandle* vrev = new TGo4HDF5SubVectorDataHandle(theName.Data(), datasize);
898 vrev->SetElementSize(datasize);
899 TObjArray *tokens = theCollection.Tokenize("<");
900 if (tokens)
901 {
902 TObjString* part = dynamic_cast<TObjString*>(tokens->At(2));
903 if (part)
904 {
905 TString rtype = part->GetString();
906 TObjArray *stokens = rtype.Tokenize(">");
907 if (stokens)
908 {
909 TObjString* spart = dynamic_cast<TObjString*>(stokens->At(0));
910 TString valuetype = spart->GetString();
911 vrev->SetInnerClassName(valuetype.Data());
912 go4hdfdbg("TGo4HDF5DataHandleFactory::CreateDataHandle for %s sets inner class name to %s\n", type,
913 valuetype.Data());
914 delete stokens;
915 }
916 else
917 {
918 go4hdfdbg("TGo4HDF5DataHandleFactory::CreateDataHandle for %s could not evaluate valuetype from %ss\n", type,
919 theCollection.Data());
920 }
921 }
922 else
923 {
924 go4hdfdbg("TGo4HDF5DataHandleFactory::CreateDataHandle for %s could not evaluate valuetype from %ss\n", type,
925 theCollection.Data());
926 }
927 delete tokens;
928 }
929 rev = vrev;
930 }
931 else if (strstr(type, "vector"))
932 {
933 // add collectionclass to our datahandle name:
934 TString theName(name);
935 TString theCollection(type);
936 theName += "[";
937 theName = theName.Append(theCollection);
938 theName += "]";
939 TGo4HDF5VectorDataHandle* vrev = new TGo4HDF5VectorDataHandle(theName.Data(), datasize);
940 vrev->SetElementSize(datasize);
941 rev = vrev;
942 }
943 else if (strstr(type, "Go4Comp"))
944 {
945 rev = new TGo4HDF5CompositeDataHandle(name, datasize);
946 rev->SetActive(true);
947 }
948 else
949 {
950 rev = new TGo4HDF5DataHandle(name, datasize);
951 rev->SetActive(true);
952 }
953
954 return rev;
955}
956
957
958
959
#define go4hdfdatahandlethrow(args ...)
Definition Go4HDF5.h:31
#define go4hdfdbg(args...)
Definition Go4HDF5.h:26
The abstract base class for the data elements of which the unpacked events (or detector structure dat...
void SetErrMess(const char *txt)
To be used for modification of the message by the event source implementation.
static void FillTypeInfo(TGo4HDF5DataHandle *handle, TClass *rootclass, const char *basename=nullptr)
evaluate h5 type information from root class streamer
void Write(hsize_t sequencenum, H5::H5File *file) override
Write event of sequence number from file.
void AllocReadBuffer(size_t size)
(Re-)allocate read buffer depending on the object size read from file
void BuildWriteDataset(H5::H5File *file) override
create datasets for writing memory structure of type into file.
Char_t * fxReadBuffer
secondary read bounce buffer for hdf5
void Read(hsize_t sequencenum, H5::H5File *file) override
Read event of sequence number from file.
TGo4HDF5BasicDataHandle(const char *name, size_t datasize)
create new data handle
void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent) override
create datasets and buffers for reading this structure from hdf5 file.
Handle object to access composite event type datasets in hdf5 formatted file with go4 event data.
void Read(hsize_t sequencenum, H5::H5File *file) override
Read event of sequence number from file.
void Write(hsize_t sequencenum, H5::H5File *file) override
Write event of sequence number from file.
void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent) override
create datasets and buffers for reading this structure from hdf5 file.
TGo4HDF5CompositeDataHandle(const char *name, size_t datasize)
create new data handle
void BuildWriteDataset(H5::H5File *file) override
create datasets for writing memory structure of type into file.
TGo4HDF5DataHandle * CreateDataHandle(const char *name, size_t datasize, const char *type)
create implementation of data handle by type
The base class to access a datatype with substructures in hdf5.
virtual void Write(hsize_t sequencenum, H5::H5File *file)
Write event of sequence number from file.
virtual void BuildWriteDataset(H5::H5File *file)
create datasets for writing memory structure of type into file.
void SetTopEventClass(const char *classname)
pass the top level event element class down the member hierarchy.
Bool_t fbDataSetExists
check on the fly if this handle has already created a dataset
virtual void Read(hsize_t sequencenum, H5::H5File *file)
Read event of sequence number from file.
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.
TGo4HDF5DataHandle(const char *name, size_t datasize)
create new data handle
virtual void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent)
create datasets and buffers for reading this structure from hdf5 file.
TGo4HDF5Source * fxParentSource
backpointer to parent source for exceptions
std::vector< TGo4HDF5DataHandle * > fxSubcomponents
collect sub-components of the referenced data object
TGo4HDF5DataHandle * FindSubMember(const char *name)
lookup if subcomponent of name already is in list.
void SetActive(Bool_t on)
const char * GetTypeName() const
TString fxEventClass
the top level event element classname to access the current data member from outside
void SetAllSubMembersActive(Bool_t on)
void SetMemberName(const char *name)
identifier for the member to access from outside using the top event handle
ULong_t fiEntries
number of event entries found in file dataspace
H5::DataSpace * fxDataSpace
dataspace in memory
Bool_t fbDataSetActive
we may disable this dataset temporarily from writing or reading useful for dynamic vector of vector c...
static TGo4HDF5DataHandleFactory fxFactory
TGo4HDF5DataHandle * AddSubMember(const char *name, size_t datasize, const char *collectiontype=nullptr)
create new subhandle for complex member component on heap.
TString fxMemberHandle
predefined interpreter access command e.g.
H5::DataSet fxDataSet
dataset containing the structure
H5::DataSpace fxFileSpace
dataspace in file
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
size_t fiReadOffset
begin of real eventdata payload after event object pointer
void SetParentOffset(size_t off)
remember location of this object relative to upper level object.
size_t fiDataSize
size of data structure in bytes, for redefining output dataset
size_t fiParentOffset
offset of this data structure relative to top level event object
TString fxMemberClass
classname of the entry for interpreter to operate e.g.
TString fxTypeName
identifier of the dataset
TGo4EventElement * fxEvent
the top level event element to access the current data member from outside
H5::CompType * fxType
component type representing the data structure
void * fxData
pointer to begin of data in memory
Event source which reads entries from a dataset in a hdf5 formatted file names of elements in hdf5 da...
Handle object to access datasets in hdf5 formatted file with go4 event data trial implementation for ...
void Read(hsize_t sequencenum, H5::H5File *file) override
Read event of sequence number from file.
TString fxInnerClassName
class that is contained in innermost vector
void Write(hsize_t sequencenum, H5::H5File *file) override
Write event of sequence number from file.
TGo4HDF5SubVectorDataHandle(const char *name, size_t datasize)
create new data handle
void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent) override
create datasets and buffers for reading this structure from hdf5 file.
void BuildWriteDataset(H5::H5File *file) override
create datasets for writing memory structure of type into file.
void SetObjectPointer(void *memptr) override
define location of corresponding object in memory.
void SetInnerClassName(const char *nm)
Handle object to access datasets in hdf5 formatted file with go4 event data implementation for std::v...
H5::CompType * fxCollection
collection type with fxType as entries
size_t fiElementSize
size of the (collection element) structure
void BuildWriteDataset(H5::H5File *file) override
create datasets for writing memory structure of type into file.
void SetElementSize(size_t len)
remember size of a single element (structure) in this collection, if it is one.
TGo4HDF5VarContainer fxVarHandle
handle for variable arrays
TGo4HDF5VectorDataHandle(const char *name, size_t datasize)
create new data handle
void Write(hsize_t sequencenum, H5::H5File *ile) override
Write event of sequence number from file.
void Read(hsize_t sequencenum, H5::H5File *file) override
Read event of sequence number from file.
void SetObjectPointer(void *memptr) override
define location of corresponding object in memory.
void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent) override
create datasets and buffers for reading this structure from hdf5 file.
static void Error(const char *text,...) GO4_PRINTF_ARGS
User shortcut for message with prio 3.
Definition TGo4Log.cxx:320
hdf5 needs structure containing the hvl_t to deal with it correctly