GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
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 
27 
28 TGo4HDF5DataHandle::TGo4HDF5DataHandle(const char *name, size_t datasize)
29  : fxTypeName(name), fxType(nullptr), fxDataSet(), fxDataSpace(nullptr), fxFileSpace(0), fiEntries(0),
30  fxData(nullptr), fiParentOffset(0), fiDataSize(datasize), fiReadOffset(0), fxEvent(nullptr),
31  fxParentSource(nullptr), fbDataSetExists(false), fbDataSetActive(false)
32 
33 {
34  fxType = new H5::CompType(datasize);
35  go4hdfdbg("TGo4HDF5DataHandle DDD created %s for size %ld \n", fxTypeName.Data(), datasize);
36 }
37 
39 {
40  go4hdfdbg("TGo4HDF5DataHandle is deleted %s \n", fxTypeName.Data());
41 
42  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
43  {
45  delete entry;
46  }
47  fxSubcomponents.clear();
48  fxDataSet.close();
49  delete fxDataSpace;
50  delete fxType;
51 }
52 
53 void TGo4HDF5DataHandle::InsertTypeMember(const H5std_string &name, size_t offset, const H5::DataType &new_member)
54 {
55  fxType->insertMember(name, offset, new_member);
56  if (fiReadOffset == 0)
57  fiReadOffset = offset; // keep location of first real data member
58  fbDataSetActive = kTRUE; // only work with handle if it has at least one member assigned to type
59 }
60 
61 TGo4HDF5DataHandle *TGo4HDF5DataHandle::AddSubMember(const char *name, size_t datasize, const char *collectiontype)
62 {
63  TGo4HDF5DataHandle *sub = fxFactory.CreateDataHandle(name, datasize, collectiontype);
64  fxSubcomponents.push_back(sub);
65  return sub;
66 }
67 
69  {
70  if (!name)
71  return nullptr;
72  // go4hdfdbg("TGo4HDF5DataHandle FindSubMember for name %s\n", name);
73  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) {
75  // go4hdfdbg("TGo4HDF5DataHandle FindSubMember %d compares with name %s\n",
76  // i, cursor ? cursor->GetTypeName() : "EMPTY CURSOR!");
77  if (strcmp(cursor->GetTypeName(), name) == 0)
78  return cursor;
79 
80  // scan recursively name in possible subcomponents. do we need this?
81  TGo4HDF5DataHandle *subcursor = cursor->FindSubMember(name);
82  if (subcursor)
83  return subcursor;
84  }
85  return nullptr;
86  }
87 
89  {
90  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) {
92  cursor->SetActive(on);
93  cursor->SetAllSubMembersActive(on);
94  }
95  }
96 
98  {
99  fxData = (char *)(memptr) + fiParentOffset;
100  go4hdfdbg("TGo4HDF5DataHandle SetObjectPointer for %s with memptr 0x%lx and parentoffset 0x%lx has fxData:0x%lx\n",
101  fxTypeName.Data(), (unsigned long)memptr, (unsigned long)fiParentOffset, (unsigned long)fxData);
102 
103  // now recursively do it for our components:
104  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
105  {
107  entry->SetObjectPointer(fxData);
108  }
109  }
110 
112 {
113  fxEvent = eve;
114  go4hdfdbg("TTTTTTTT TGo4HDF5DataHandle %s - SetTopEvent sets pointer to %ld \n", fxTypeName.Data(),
115  (unsigned long)eve);
116  // now recursively do it for our components:
117  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
118  {
120  entry->SetTopEvent(fxEvent);
121  }
122 }
123 
125 {
126  fxEventClass = txt;
127  // go4hdfdbg("TGo4HDF5DataHandle::SetTopEventClass TTTTTTTT to %s \n",fxEventClass.Data());
128  // now recursively do it for our components:
129  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
130  {
132  entry->SetTopEventClass(txt);
133  }
134 }
135 
137 {
138  // just recursively do it for our components:
139  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
140  {
142  entry->BuildReadDataset(file, parent);
143  }
144 }
145 
147  {
148  // just recursively do it for our components:
149  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) {
151  entry->BuildWriteDataset(file);
152  }
153  // actual dataset is build in subclass
154  }
155 
156  void TGo4HDF5DataHandle::Read(hsize_t sequencenum, H5::H5File* file)
157  {
158  if(sequencenum>=fiEntries)
159  {
160  go4hdfdatahandlethrow( "TGo4HDF5DataHandle::Read - reached end of dataspace at %ld entries!\n", fiEntries);
161  }
162 
163  //if(fbDataSetActive && fbDataSetExists)
164  if(fbDataSetExists)
165  {
166  hsize_t offset[1]= {sequencenum};
167  hsize_t onerow[1] ={1};
168  fxFileSpace.selectHyperslab( H5S_SELECT_SET, onerow, offset ); // one row of event object at last entry (offset is nextsize-1)
169  // idea: the go4 event is always at same location in memory, so we use the original data space as defined in BuildDataSet
170  // the data space in file for each event is of course increasing, so we need to extend the dataset and select
171  // a hyperslab to the write destination in the file.
172  go4hdfdbg("TGo4HDF5DataHandle::Read of %s has selected hyperslab for onerow:[%ld] offset:[%ld]\n",
173  fxTypeName.Data(),(unsigned long) onerow[0], (unsigned long) offset[0]);
174 
175  // the actual reading from filespace is implemented in subclass!
176 
177  }
178 
179  // now recursively do it for our subcomponents :
180  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
181  {
183  entry->Read(sequencenum, file);
184  }
185  }
186 
187 void TGo4HDF5DataHandle::Write(hsize_t sequencenum, H5::H5File* file)
188 {
189  //if(fbDataSetActive && fbDataSetExists)
190  if(fbDataSetExists)
191  {
192 
193  go4hdfdbg("TGo4HDF5DataHandle::Write %s base function will extend dataset for %lld \n", fxTypeName.Data(), sequencenum);
194  hsize_t offset[1] = { sequencenum };
195  hsize_t nextsize[1] = { sequencenum + 1 };
196 
197  fxDataSet.extend(nextsize);
198 
199  fxFileSpace = fxDataSet.getSpace(); // dataspace in file
200  hsize_t onerow[1] = { 1 };
201  fxFileSpace.selectHyperslab(H5S_SELECT_SET, onerow, offset); // one row of event object at last entry (offset is nextsize-1)
202  // idea: the go4 event is always at same location in memory, so we use the original data space as defined in BuildDataSet
203  // the data space in file for each event is of course increasing, so we need to extend the dataset and select
204  // a hyperslab to the write destination in the file.
205 
206  // the actual writing to filespace is implemented in subclass!
207 
208  }
209  // now recursively do it for our subcomponents :
210  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
211  {
213  entry->Write(sequencenum, file);
214  }
215 
216 }
217 
219 
220 
221 TGo4HDF5BasicDataHandle::TGo4HDF5BasicDataHandle(const char *name, size_t datasize) :
222  TGo4HDF5DataHandle(name, datasize), fxReadBuffer(nullptr)
223 
224  {
225  go4hdfdbg("TGo4HDF5BasicDataHandle ctor\n");
226  }
227 
228 
230  {
231  go4hdfdbg("TGo4HDF5BasicDataHandle is deleted %s \n", fxTypeName.Data());
232  // delete [] fxReadBuffer; ???
233  }
234 
235 
237  {
238  if(fxReadBuffer && (size == fiDataSize)) return;
239  delete [] fxReadBuffer;
240  fxReadBuffer = new Char_t[size];
241  fiDataSize = size;
242  go4hdfdbg("TGo4HDF5DataHandle: AllocReadBuffer has created read buffer 0x%lx for size %ld \n",
243  (unsigned long) fxReadBuffer, fiDataSize);
244  }
245 
247  {
248  if (!fbDataSetExists)// && fbDataSetActive)
249  {
250 
251  fxParentSource=parent;
252 
253  Int_t rank=1; // entries of the ntuple/tree
254  hsize_t dims[1] = { 1}; // dataset dimensions at creation
255  hsize_t maxdims[1] = {H5S_UNLIMITED}; // 1 ? only one entry maps to current event object -
256  fxDataSpace= new H5::DataSpace(rank, dims, maxdims);
257 
258  // dataspace in memory covers only the current input event structure
259  hsize_t onerow[1] ={1};
260  hsize_t offset[1]= {0};
261  fxDataSpace->selectHyperslab( H5S_SELECT_SET, onerow, offset );
262 
263  // get existing dataset from file and compare data with type of the target event
264  // we only allow datasets that match the memory structure concerning member names etc,
265 
266  // NOTE that for reading back data, we first have to figure out our subcomponents from the file dataspace by name!
267  // TODO: when reading, scan all datasets in file
268  // for composite events, configgure the input event according the information in hdf5 file ????
269  // this means BuildDataType has to be done after we have scanned the input file and reconstructed the substructure setup
270  // not so easy, so constraint is currently that all substructures in code must match the status when hdf5 file was recorded
271 
272  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet will open set %s\n", fxTypeName.Data());
273  fxDataSet = file->openDataSet(fxTypeName.Data());
274 
275  H5T_class_t type_class = fxDataSet.getTypeClass();
276  H5::CompType intype;
277  if( type_class == H5T_COMPOUND)
278  {
279  intype= fxDataSet.getCompType();
280  // size_t size = intype.getSize();
281  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet finds in file compound type of size %ld \n", intype.getSize());
282  }
283  else if( type_class == H5T_VLEN)
284  {
285  H5::VarLenType vtype = fxDataSet.getVarLenType();
286  H5::DataType entrytype = vtype.getSuper();
287  //H5::DataType* entrytype = vtype.decode();
288  //size_t size = entrytype.getSize();
289  //size_t vsize = vtype.getSize();
290  H5T_class_t entry_class = entrytype.getClass();
291  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet finds in file vlen type of size %ld, with entry class %d, size %ld \n",
292  vtype.getSize(), entry_class, entrytype.getSize());
293  if( entry_class == H5T_COMPOUND)
294  {
295 
296  H5::DataType* ptype=&entrytype;
297  H5::CompType* entrycomp = static_cast<H5::CompType*>(ptype); // dynamic cast fails here?
298  if (entrycomp){
299  intype = *entrycomp;
300  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet uses compound entry of vlen dtype %d \n", entry_class );
301  }
302  else
303  {
304  go4hdfdatahandlethrow("TGo4HDF5DataHandle: BuildReadDataSet - could not assign component entry of varlen data type !\n");
305  }
306  }
307  // TODO: treat vectors with simple data members here?
308  else
309  {
310  go4hdfdatahandlethrow( "TGo4HDF5DataHandle: BuildReadDataSet - varlen data type without compound, but contains class %d!\n", entry_class);
311  }
312  }
313  else
314  {
315  go4hdfdatahandlethrow("TGo4HDF5DataHandle: BuildReadDataSet - file contains no compound or varlen data type, but type %d!\n",type_class)
316  }
317 
318 
319  fxFileSpace = fxDataSet.getSpace();
320  int frank = fxFileSpace.getSimpleExtentNdims();
321  hsize_t dims_out[frank];
322  fxFileSpace.getSimpleExtentDims( dims_out, nullptr);
323  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet file dataspace has rank %d, dimensions:%d, #1. dimension=%ld \n",
324  frank ,
325  fxFileSpace.getSimpleExtentDims(dims_out, nullptr),
326  (unsigned 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,
445  fiReadOffset, fiDataSize);
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 
493 void 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 
505 TGo4HDF5VectorDataHandle::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 
588 {
590 }
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 
616 void 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 
724 void 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 
731  if(fbDataSetActive)
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 
875 void 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 
885 TGo4HDF5DataHandle* 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 
void SetInnerClassName(const char *nm)
void SetActive(Bool_t on)
void Read(hsize_t sequencenum, H5::H5File *file) override
void Write(hsize_t sequencenum, H5::H5File *file) override
virtual void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent)
static void FillTypeInfo(TGo4HDF5DataHandle *handle, TClass *rootclass, const char *basename=nullptr)
H5::DataSpace * fxDataSpace
void InsertTypeMember(const H5std_string &name, size_t offset, const H5::DataType &new_member)
void AllocReadBuffer(size_t size)
void BuildWriteDataset(H5::H5File *file) override
TGo4HDF5DataHandle * CreateDataHandle(const char *name, size_t datasize, const char *type)
TGo4EventElement * fxEvent
void Read(hsize_t sequencenum, H5::H5File *file) override
void Read(hsize_t sequencenum, H5::H5File *file) override
void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent) override
void BuildWriteDataset(H5::H5File *file) override
void SetAllSubMembersActive(Bool_t on)
void SetObjectPointer(void *memptr) override
void Write(hsize_t sequencenum, H5::H5File *file) override
void BuildWriteDataset(H5::H5File *file) override
H5::DataSpace fxFileSpace
void SetErrMess(const char *txt)
void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent) override
std::vector< TGo4HDF5DataHandle * > fxSubcomponents
virtual void Read(hsize_t sequencenum, H5::H5File *file)
virtual void Write(hsize_t sequencenum, H5::H5File *file)
void Write(hsize_t sequencenum, H5::H5File *ile) override
void Write(hsize_t sequencenum, H5::H5File *file) override
#define go4hdfdbg(args...)
Definition: Go4HDF5.h:26
void Read(hsize_t sequencenum, H5::H5File *file) override
void SetTopEventClass(const char *classname)
void SetTopEvent(TGo4EventElement *eve)
void BuildWriteDataset(H5::H5File *file) override
#define go4hdfdatahandlethrow(args ...)
Definition: Go4HDF5.h:31
TGo4HDF5CompositeDataHandle(const char *name, size_t datasize)
void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent) override
TGo4HDF5BasicDataHandle(const char *name, size_t datasize)
static void Error(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:320
TGo4HDF5Source * fxParentSource
virtual void BuildWriteDataset(H5::H5File *file)
TGo4HDF5SubVectorDataHandle(const char *name, size_t datasize)
TGo4HDF5DataHandle(const char *name, size_t datasize)
TGo4HDF5DataHandle * FindSubMember(const char *name)
virtual void SetObjectPointer(void *memptr)
void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent) override
static TGo4HDF5DataHandleFactory fxFactory
void SetObjectPointer(void *memptr) override
TGo4HDF5VectorDataHandle(const char *name, size_t datasize)
const char * GetTypeName() const
TGo4HDF5VarContainer fxVarHandle
TGo4HDF5DataHandle * AddSubMember(const char *name, size_t datasize, const char *collectiontype=nullptr)
void SetMemberName(const char *name)
void SetElementSize(size_t len)
string msg
Definition: go4init.py:11