GSI Object Oriented Online Offline (Go4)  GO4-6.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TGo4HDF5DataHandle.cxx
Go to the documentation of this file.
1 // $Id: TGo4HDF5DataHandle.cxx 3376 2021-11-30 14:04:38Z linev $
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 
15 #include "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) : fxTypeName(name),
29  fxType(0),fxDataSet(), fxDataSpace(0), fxFileSpace(0), fiEntries(0),
30  fxData(0), fiParentOffset(0),fiDataSize(datasize), fiReadOffset(0),
31  fxEvent(0), fxParentSource(0), 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  };
38 
40  {
41  go4hdfdbg("TGo4HDF5DataHandle is deleted %s \n", fxTypeName.Data());
42 
43  for(unsigned int i=0; i<fxSubcomponents.size();++i) // raterecord index
44  {
46  delete entry;
47  }
48  fxSubcomponents.clear();
49  fxDataSet.close();
50  delete fxDataSpace;
51  delete fxType;
52  }
53 
54 
55  void 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) fiReadOffset=offset; // keep location of first real data member
59  fbDataSetActive=kTRUE; // only work with handle if it has at least one member assigned to type
60  }
61 
62  TGo4HDF5DataHandle* TGo4HDF5DataHandle::AddSubMember(const char* name, size_t datasize, const char* collectiontype)
63  {
64  TGo4HDF5DataHandle* sub= fxFactory.CreateDataHandle(name,datasize,collectiontype);
65  fxSubcomponents.push_back(sub);
66  return sub;
67  }
68 
69 
71  {
72  if(name==0) return 0;
73  //go4hdfdbg("TGo4HDF5DataHandle FindSubMember for name %s\n", name);
74  for(unsigned int i=0; i< fxSubcomponents.size(); ++i)
75  {
77 // go4hdfdbg("TGo4HDF5DataHandle FindSubMember %d compares with name %s\n",
78 // i, cursor ? cursor->GetTypeName() : "EMPTY CURSOR!");
79  if(strcmp(cursor->GetTypeName(),name)==0) return cursor;
80 
81  // scan recursively name in possible subcomponents. do we need this?
82  TGo4HDF5DataHandle* subcursor = cursor->FindSubMember(name);
83  if (subcursor) return subcursor;
84  }
85  return 0;
86  }
87 
88 
90  {
91  for(unsigned int i=0; i< fxSubcomponents.size(); ++i)
92  {
94  cursor->SetActive(on);
95  cursor->SetAllSubMembersActive(on);
96  }
97  }
98 
99 
101 {
102  fxData = (char*) (memptr) + fiParentOffset;
103  go4hdfdbg("TGo4HDF5DataHandle SetObjectPointer for %s with memptr 0x%lx and parentoffset 0x%lx has fxData:0x%lx\n",
104  fxTypeName.Data(), (unsigned long) memptr, (unsigned long) fiParentOffset, (unsigned long) fxData);
105 
106  // now recursively do it for our components:
107  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
108  {
110  entry->SetObjectPointer(fxData);
111  }
112 
113 }
114 
115 
117  {
118  fxEvent=eve;
119  go4hdfdbg(
120  "TTTTTTTT TGo4HDF5DataHandle %s - SetTopEvent sets pointer to %ld \n",
121  fxTypeName.Data(), (unsigned long) eve);
122  // now recursively do it for our components:
123  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
124  {
126  entry->SetTopEvent(fxEvent);
127  }
128  }
129 
131  {
132 
133  fxEventClass=txt;
134  //go4hdfdbg("TGo4HDF5DataHandle::SetTopEventClass TTTTTTTT to %s \n",fxEventClass.Data());
135  // now recursively do it for our components:
136  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
137  {
139  entry->SetTopEventClass(txt);
140  }
141  }
142 
143 
145  {
146  // just recursively do it for our components:
147  for(unsigned int i=0; i<fxSubcomponents.size();++i) // raterecord index
148  {
150  entry->BuildReadDataset(file, parent);
151  }
152  }
153 
154 
155 
157  {
158  // just recursively do it for our components:
159  for(unsigned int i=0; i<fxSubcomponents.size();++i)
160  {
162  entry->BuildWriteDataset(file);
163  }
164  // actual dataset is build in subclass
165  }
166 
167 
168 
169 
170 
171 
172  void TGo4HDF5DataHandle::Read(hsize_t sequencenum, H5::H5File* file)
173  {
174  if(sequencenum>=fiEntries)
175  {
176  go4hdfdatahandlethrow( "TGo4HDF5DataHandle::Read - reached end of dataspace at %ld entries!\n", fiEntries);
177  }
178 
179  //if(fbDataSetActive && fbDataSetExists)
180  if(fbDataSetExists)
181  {
182  hsize_t offset[1]= {sequencenum};
183  hsize_t onerow[1] ={1};
184  fxFileSpace.selectHyperslab( H5S_SELECT_SET, onerow, offset ); // one row of event object at last entry (offset is nextsize-1)
185  // idea: the go4 event is always at same location in memory, so we use the original data space as defined in BuildDataSet
186  // the data space in file for each event is of course increasing, so we need to extend the dataset and select
187  // a hyperslab to the write destination in the file.
188  go4hdfdbg("TGo4HDF5DataHandle::Read of %s has selected hyperslab for onerow:[%ld] offset:[%ld]\n",
189  fxTypeName.Data(),(unsigned long) onerow[0], (unsigned long) offset[0]);
190 
191  // the actual reading from filespace is implemented in subclass!
192 
193  }
194 
195  // now recursively do it for our subcomponents :
196  for(unsigned int i=0; i<fxSubcomponents.size();++i) // raterecord index
197  {
199  entry->Read(sequencenum, file);
200  }
201 
202 
203 
204 
205 
206 
207 
208  }
209 
210 void TGo4HDF5DataHandle::Write(hsize_t sequencenum, H5::H5File* file)
211 {
212  //if(fbDataSetActive && fbDataSetExists)
213  if(fbDataSetExists)
214  {
215 
216  go4hdfdbg("TGo4HDF5DataHandle::Write %s base function will extend dataset for %lld \n", fxTypeName.Data(), sequencenum);
217  hsize_t offset[1] = { sequencenum };
218  hsize_t nextsize[1] = { sequencenum + 1 };
219 
220  fxDataSet.extend(nextsize);
221 
222  fxFileSpace = fxDataSet.getSpace(); // dataspace in file
223  hsize_t onerow[1] = { 1 };
224  fxFileSpace.selectHyperslab(H5S_SELECT_SET, onerow, offset); // one row of event object at last entry (offset is nextsize-1)
225  // idea: the go4 event is always at same location in memory, so we use the original data space as defined in BuildDataSet
226  // the data space in file for each event is of course increasing, so we need to extend the dataset and select
227  // a hyperslab to the write destination in the file.
228 
229  // the actual writing to filespace is implemented in subclass!
230 
231  }
232  // now recursively do it for our subcomponents :
233  for (unsigned int i = 0; i < fxSubcomponents.size(); ++i) // raterecord index
234  {
236  entry->Write(sequencenum, file);
237  }
238 
239 
240 
241 }
242 
243 
245 
246 
247 TGo4HDF5BasicDataHandle::TGo4HDF5BasicDataHandle(const char* name, size_t datasize) :
248  TGo4HDF5DataHandle(name, datasize), fxReadBuffer(0)
249 
250  {
251  go4hdfdbg("TGo4HDF5BasicDataHandle ctor\n");
252  }
253 
254 
256  {
257  go4hdfdbg("TGo4HDF5BasicDataHandle is deleted %s \n", fxTypeName.Data());
258  // delete [] fxReadBuffer; ???
259  }
260 
261 
263  {
264  if(fxReadBuffer && (size == fiDataSize)) return;
265  delete [] fxReadBuffer;
266  fxReadBuffer = new Char_t[size];
267  fiDataSize=size;
268  go4hdfdbg("TGo4HDF5DataHandle: AllocReadBuffer has created read buffer 0x%lx for size %ld \n",
269  (unsigned long) fxReadBuffer, fiDataSize);
270  }
271 
272 
273 
275  {
276  if (!fbDataSetExists)// && fbDataSetActive)
277  {
278 
279  fxParentSource=parent;
280 
281  Int_t rank=1; // entries of the ntuple/tree
282  hsize_t dims[1] = { 1}; // dataset dimensions at creation
283  hsize_t maxdims[1] = {H5S_UNLIMITED}; // 1 ? only one entry maps to current event object -
284  fxDataSpace= new H5::DataSpace(rank, dims, maxdims);
285 
286  // dataspace in memory covers only the current input event structure
287  hsize_t onerow[1] ={1};
288  hsize_t offset[1]= {0};
289  fxDataSpace->selectHyperslab( H5S_SELECT_SET, onerow, offset );
290 
291 
292 
293 
294  // get existing dataset from file and compare data with type of the target event
295  // we only allow datasets that match the memory structure concerning member names etc,
296 
297  // NOTE that for reading back data, we first have to figure out our subcomponents from the file dataspace by name!
298  // TODO: when reading, scan all datasets in file
299  // for composite events, configgure the input event according the information in hdf5 file ????
300  // this means BuildDataType has to be done after we have scanned the input file and reconstructed the substructure setup
301  // not so easy, so constraint is currently that all substructures in code must match the status when hdf5 file was recorded
302 
303  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet will open set %s\n", fxTypeName.Data());
304  fxDataSet = file->openDataSet(fxTypeName.Data());
305 
306  H5T_class_t type_class = fxDataSet.getTypeClass();
307  H5::CompType intype;
308  if( type_class == H5T_COMPOUND)
309  {
310  intype= fxDataSet.getCompType();
311  // size_t size = intype.getSize();
312  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet finds in file compound type of size %ld \n", intype.getSize());
313  }
314  else if( type_class == H5T_VLEN)
315  {
316  H5::VarLenType vtype = fxDataSet.getVarLenType();
317  H5::DataType entrytype = vtype.getSuper();
318  //H5::DataType* entrytype = vtype.decode();
319  //size_t size = entrytype.getSize();
320  //size_t vsize = vtype.getSize();
321  H5T_class_t entry_class = entrytype.getClass();
322  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet finds in file vlen type of size %ld, with entry class %d , size %ld \n",
323  vtype.getSize(), entry_class, entrytype.getSize());
324  if( entry_class == H5T_COMPOUND)
325  {
326 
327  H5::DataType* ptype=&entrytype;
328  H5::CompType* entrycomp = static_cast<H5::CompType*>(ptype); // dynamic cast fails here?
329  if (entrycomp){
330  intype = *entrycomp;
331  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet uses compound entry of vlen dtype %d \n", entry_class );
332  }
333  else
334  {
335  go4hdfdatahandlethrow("TGo4HDF5DataHandle: BuildReadDataSet - could not assign component entry of varlen data type !\n");
336  }
337  }
338  // TODO: treat vectors with simple data members here?
339  else
340  {
341  go4hdfdatahandlethrow( "TGo4HDF5DataHandle: BuildReadDataSet - varlen data type without compound, but contains class %d!\n", entry_class);
342  }
343  }
344  else
345  {
346  go4hdfdatahandlethrow("TGo4HDF5DataHandle: BuildReadDataSet - file contains no compound or varlen data type, but type %d!\n",type_class)
347  }
348 
349 
350  fxFileSpace = fxDataSet.getSpace();
351  int frank = fxFileSpace.getSimpleExtentNdims();
352  hsize_t dims_out[frank];
353  fxFileSpace.getSimpleExtentDims( dims_out, NULL);
354  go4hdfdbg("TGo4HDF5DataHandle::BuildReadDataSet file dataspace has rank %d, dimensions:%d, #1. dimension=%ld \n",
355  frank ,
356  fxFileSpace.getSimpleExtentDims( dims_out, NULL),
357  (unsigned long)(dims_out[0]));
358  fiEntries=dims_out[0]; // events filled in this file, for leaving the read loop later.
359 
360  #ifdef GO4HDF5_DEBUG
361  // check consistency of file dataset with input event structure:
362  int nfilemembers= intype.getNmembers ();
363  int neventmembers= fxType->getNmembers ();
364 
365 
366  go4hdfdbg("Type comparison: number of compound members: file %d, event %d\n",nfilemembers, neventmembers);
367 
368  go4hdfdbg("Dump Type from file:\n");
369  for (int i = 0; i < nfilemembers; ++i)
370  {
371  H5::DataType mem_type=intype.getMemberDataType(i);
372  go4hdfdbg("\t %d: name:%s class:%s", i, intype.getMemberName(i).c_str(), mem_type.fromClass().c_str());
373  H5T_class_t mem_class = intype.getMemberClass(i);
374  if (mem_class == H5T_ARRAY)
375  {
376  H5::ArrayType artyp = intype.getMemberArrayType(i);
377  int ardim = artyp.getArrayNDims();
378  hsize_t dims[ardim];
379  artyp.getArrayDims(dims);
380  go4hdfdbg(" array dimensions:%d [", ardim);
381  for (int j = 0; j < ardim; ++j)
382  {
383  go4hdfdbg("%d", (int) dims[j]);
384  }
385  go4hdfdbg("]");
386  }
387  go4hdfdbg("\n");
388  }
389  go4hdfdbg("Dump Type from event structure:\n");
390  for (int i = 0; i < neventmembers; ++i)
391  {
392  H5::DataType mem_type=fxType->getMemberDataType(i);
393  go4hdfdbg("\t %d: name:%s class:%s", i, intype.getMemberName(i).c_str(), mem_type.fromClass().c_str());
394  H5T_class_t mem_class = fxType->getMemberClass(i);
395  if (mem_class == H5T_ARRAY)
396  {
397  H5::ArrayType artyp = fxType->getMemberArrayType(i);
398  int ardim = artyp.getArrayNDims();
399  hsize_t dims[ardim];
400  artyp.getArrayDims(dims);
401  go4hdfdbg("array dimensions:%d [", ardim);
402  for (int j = 0; j < ardim; ++j)
403  {
404  go4hdfdbg("%lu", (unsigned long) dims[j]);
405  }
406  go4hdfdbg("]");
407  }
408  go4hdfdbg("\n");
409  }
410 
411  #endif
412 
413  if(!(*fxType==intype))
414  {
415  TString msg= TString::Format( "BuildReadDataSet type mismatch between event structure(%s) and input from file (%s)\n",
416  fxType->fromClass().c_str(), intype.fromClass().c_str());
417  TGo4Log::Error("TGo4HDF5DataHandle: %s", msg.Data());
418  parent->SetErrMess(msg.Data());
419  throw TGo4EventSourceException(parent);
420 
421  }
422 
424 
425  fbDataSetExists=kTRUE;
426 
427  }
428 
430 
431  }
432 
433 
435 {
436 
438  {
439  go4hdfdbg("TGo4HDF5BasicDataHandle: BuildWriteDataset for event set %s\n", fxTypeName.Data());
440  Int_t rank = 1; // entries of the ntuple/tree
441  hsize_t dims[1] = { 1 }; // dataset dimensions at creation
442  hsize_t maxdims[1] = { H5S_UNLIMITED };
443  fxDataSpace = new H5::DataSpace(rank, dims, maxdims);
444 
445  H5::DSetCreatPropList cparms;
446  hsize_t chunk_dims[1] = { 1 };
447  cparms.setChunk(rank, chunk_dims);
448  cparms.setFillValue(*fxType, fxData);
449 
450  fxDataSet = file->createDataSet(fxTypeName.Data(), *fxType, *fxDataSpace, cparms);
451  fbDataSetExists = kTRUE;
452  }
454 
455 }
456 
457 
458 
459 
460 
461 
462  void TGo4HDF5BasicDataHandle::Read(hsize_t sequencenum, H5::H5File* file)
463  {
464  TGo4HDF5DataHandle::Read(sequencenum, file); // prepare dataspace and treat subcomponents
465  if(!fbDataSetActive) return;
466 
467  // we must not use actual eventclass directly,
468  // because hdf5 will destroy memory of not registered data members like pointer to eventsource and class info!
469  void* data= (void*)(fxReadBuffer);
470 
471  // printf("TGo4HDF5Source: BuildEvent before read on data pointer 0x%lx \n",data);
472 
473  fxDataSet.read( data, *fxType, *fxDataSpace, fxFileSpace );
474 
475 
476  // here copy data from our hdf5 bounce buffer to actual event object:
477  Char_t* target = (Char_t*) (fxData) + fiReadOffset;
478  Char_t* source = (Char_t*) (fxReadBuffer) + fiReadOffset;
479  size_t copylen = fiDataSize - fiReadOffset;
480  memcpy (target, source, copylen);
481 
482  #ifdef GO4HDF5_DEBUG
483  printf("Copy %ld bytes from %lx to %lx, fiReadOffset=%ld, fiDataSize=%ld \n",
484  copylen, (long) source, (long)target, fiReadOffset, fiDataSize);
485  #endif
486 
487  }
488 
489 void TGo4HDF5BasicDataHandle::Write(hsize_t sequencenum, H5::H5File* file)
490 {
491  TGo4HDF5DataHandle::Write(sequencenum, file); // treat subcomponents here, extend dataset
492 
493  if(!fbDataSetActive) return;
494  // idea: the go4 event is always at same location in memory, so we use the original data space as defined in BuildDataSet
495  // the data space in file for each event is of course increasing, so we need to extend the dataset and select
496  // a hyperslab to the write destination in the file.
497  go4hdfdbg("TGo4HDF5BasicDataHandle::Write %s plain\n", fxTypeName.Data());
499 
500 }
501 
502 
503 
504 
505 
506 
508 
509 
511  TGo4HDF5BasicDataHandle(name, datasize)
512 
513  {
514  go4hdfdbg("TGo4HDF5CompositeDataHandle ctor use go4 composite event component\n");
515  };
516 
517 
519  {
520  go4hdfdbg("TGo4HDF5CompositeDataHandle is deleted %s \n", fxTypeName.Data());
521  }
522 
523 
524 
525 
527  {
529  // NOTE: currently we can not reconstruct the setup of the composite event from the information in hdf5 file
530  // we just rely that the user code has set up the input event accordingly and check if the types are consistent
531  // with information from hdf5 input
532  // later TODO?: evaluate substructure of composite event and dynamically create components of known class
533  // <- interpreter business. For the moment, do not follow this approach.
534 
535  }
536 
537 
539  {
540  // same as plain set here. do we need different treatment?
541 
543 
544  }
545 
546 
547 
548 
549 
550 
551  void TGo4HDF5CompositeDataHandle::Read(hsize_t sequencenum, H5::H5File* file)
552  {
553  TGo4HDF5BasicDataHandle::Read(sequencenum, file);
554 
555 
556 
557  }
558 
559 void TGo4HDF5CompositeDataHandle::Write(hsize_t sequencenum, H5::H5File* file)
560 {
561  TGo4HDF5BasicDataHandle::Write(sequencenum, file);
562 
563 
564 
565 }
566 
567 
570 
571 
572 
573 TGo4HDF5VectorDataHandle::TGo4HDF5VectorDataHandle(const char* name, size_t datasize) :
574  TGo4HDF5BasicDataHandle(name, datasize), fxCollection(0), fiElementSize(0)
575 
576  {
577  go4hdfdbg("TGo4HDF5VectorDataHandle ctor \n");
578 
579 
580 
581  // need to create comp type with hvl_t handle here!
582  //fxCollection = new H5::VarLenType(fxType); // this does not work, file is corrupt afterwards JAM 27-may-2019
583  fxCollection = new H5::CompType(sizeof(TGo4HDF5VarContainer));
584 
585  fxCollection -> insertMember( fxTypeName.Data(), HOFFSET(TGo4HDF5VarContainer, fxArray), H5::VarLenType(fxType));
586 
587  go4hdfdbg("TGo4HDF5VectorDataHandle ctor, typename is %s\n",
588  fxTypeName.Data());
589  }
590 
591 
592 
593 
594 
595 
597  {
598  go4hdfdbg("TGo4HDF5VectorDataHandle is deleted %s \n", fxTypeName.Data());
599  delete fxCollection;
600  }
601 
602 
603 
605 {
606 
608 
609  // depends on vector implementation! following is probably not true:
610  // struct std::vector<T>
611  // {
612  // size_t size;
613  // size_t cap;
614  // T* buffer;
615  // }
616  //
617  // maybe std::vector member in classlooks like this?
618  // struct vector { // Simple C struct as example (T is the type supplied by the template)
619  // T *begin; // vector::begin() probably returns this value
620  // T *end; // vector::end() probably returns this value
621  // T *end_capacity; // First non-valid address
622  // // Allocator state might be stored here (most allocators are stateless)
623  // };
624 
625  char** p_collection = (char**) fxData;
626  char** p_begin_ptr = p_collection;
627  char** p_end_ptr = p_collection + 1;
628  //char** p_cap_ptr = p_collection + 2;
629 
630  go4hdfdbg("TGo4HDF5VectorDataHandle SetObjectPointer has fxData=0x%lx elementsize=%ld\n",
631  (unsigned long) fxData, fiElementSize);
632 
633  size_t len = (*p_end_ptr - *p_begin_ptr) / fiElementSize;
634  //size_t cap = (*p_cap_ptr - *p_begin_ptr) / fiElementSize;
635 
636  fxVarHandle.fxArray.p = *p_begin_ptr;
637  fxVarHandle.fxArray.len = len;
638 
639 // SetActive(((fxVarHandle.fxArray.p!=0) && (fxVarHandle.fxArray.len>0)) ? true : false); // disable writing out empty vector
640 
641 #ifdef GO4HDF5_DEBUG
642  static unsigned debugcount = 0;
643  char** p_cap_ptr = p_collection + 2;
644  size_t cap = (*p_cap_ptr - *p_begin_ptr) / fiElementSize;
645  if (debugcount < 10000)
646  {
647  go4hdfdbg(
648  "TGo4HDF5VectorDataHandle SetObjectPointer for count %d has collection size: %ld capacity: %ld pointer to buffer 0x%lx, ACTIVE=%d\n",
649  debugcount, len, cap, (unsigned long) *p_begin_ptr, fbDataSetActive);
650  debugcount++;
651  }
652 
653 #endif
654 
655 // printf(
656 // "TGo4HDF5VectorDataHandle %s - SetObjectPointer has collection size: %ld capacity: %ld pointer to buffer 0x%lx, fxData=0x%x\n",
657 // fxTypeName.Data(), len, cap, (unsigned long) *p_begin_ptr, fxData);
658 
659 }
660 
661 
663  {
665 
666  }
667 
668 
670  {
671  if(!fbDataSetExists) // && fbDataSetActive)
672  {
673  go4hdfdbg("TGo4HDF5VectorDataHandle: BuildWriteDataset for collection set %s \n",fxTypeName.Data());
674 
675  Int_t rank=1; // entries of the ntuple/tree. vector dimension is handled by variable size type?
676  hsize_t dims[1] = { 1}; // dataset dimensions at creation
677  hsize_t maxdims[1] = {H5S_UNLIMITED};
678  fxDataSpace= new H5::DataSpace(rank, dims, maxdims);
679  H5::DSetCreatPropList cparms;
680  hsize_t chunk_dims[1] ={1};
681  cparms.setChunk( rank, chunk_dims );
682 
683  cparms.setFillValue(H5::VarLenType(fxType), &fxVarHandle.fxArray);
684  fxDataSet = file->createDataSet( fxTypeName.Data(), H5::VarLenType(fxType), *fxDataSpace, cparms);
685 
686  fbDataSetExists=kTRUE;
687  }
689 
690 
691 
692  }
693 
694 
695 
696 
697 
698 
699  void TGo4HDF5VectorDataHandle::Read(hsize_t sequencenum, H5::H5File* file)
700  {
701  TGo4HDF5DataHandle::Read(sequencenum, file); // prepare dataspaces and handle subcompoments
702  if(!fbDataSetActive) return;
703  go4hdfdbg("TGo4HDF5VectorDataHandle::Read %s collection \n", fxTypeName.Data());
704 
705  // TODO: set varhandle to buffer - setobjectpointer has done this to actual vector in event object
706  // we need to resize this before we can directly fill it!
707 // size_t vsize = fxDataSet.getVarLenType().getSize(); // this is just size in bytes, not #entries
708 // go4hdfdbg("TGo4HDF5VectorDataHandle::Read FFFF tells us size of vlen type size is now %ld \n",
709 // vsize);
710 
711  // TODO: how to get from hdf5 length of vector _before_ reading it!!!?
712  // not necessary, since hdf5 will do allocation itself at hvl_t.p
713 // int numentries = 5; //? get from filespace ?
714 // size_t currentsize= fiElementSize * numentries;
715 // AllocReadBuffer(currentsize);
717 
718 
719  fxVarHandle.fxArray.p=0; //note: read will allocate the necessary buffer memory automatically!
720  fxDataSet.read(&fxVarHandle.fxArray, H5::VarLenType(fxType), *fxDataSpace, fxFileSpace);
721  go4hdfdbg("TGo4HDF5VectorDataHandle::Read LLLL length after reading is %ld, buffer is 0x%lx \n",
722  fxVarHandle.fxArray.len,
723  (unsigned long) fxVarHandle.fxArray.p);
724 
725 
727  // build interpreter command to resize our vector using handle on top event:
728 // TString resizecom = TString::Format("%s * myevent= (%s *) %ld; myevent-> %s.resize(%ld)",
729 // fxEventClass.Data(), fxEventClass.Data(), (unsigned long) fxEvent, fxMemberHandle.Data(), fxVarHandle.fxArray.len);
730 //
731 //
732 //
733 //
735 // go4hdfdbg("TGo4HDF5VectorDataHandle::Read will use command: %s \n", resizecom.Data());
736 // gROOT->ProcessLineFast(resizecom.Data());
737 //
738 // char** p_collection = (char**) fxData;
739 // char** p_begin_ptr = p_collection;
740 // char** p_end_ptr = p_collection + 1;
741 // char** p_cap_ptr = p_collection + 2;
742 //
743 // size_t len = (*p_end_ptr - *p_begin_ptr) / fiElementSize;
744 // size_t cap = (*p_cap_ptr - *p_begin_ptr) / fiElementSize;
745 //
746 // go4hdfdbg(
747 // "TGo4HDF5VectorDataHandle::Read has collection size: %ld capacity: %ld pointer to buffer 0x%lx, end: 0x%lx cap: 0x%lx\n",
748 // len, cap, (unsigned long) *p_begin_ptr, (unsigned long) *p_end_ptr, (unsigned long) *p_cap_ptr);
749 // // here copy data from our hdf5 bounce buffer to actual event object:
750 // Char_t* target = *p_begin_ptr;
751 // Char_t* source = (Char_t*) fxVarHandle.fxArray.p; //(Char_t*) (fxReadBuffer);
752 // size_t copylen = fxVarHandle.fxArray.len * fiElementSize;
753 // go4hdfdbg(
754 // "TGo4HDF5VectorDataHandle::Read before memcopy from 0x%x to 0x%x with length %ld (element size is :%ld)\n",
755 // (unsigned long) source, (unsigned long) target, copylen, fiElementSize);
756 //
757 //
758 // if(fxVarHandle.fxArray.len >0){
759 // memcpy (target, source, copylen);
760 //
761 // go4hdfdbg(
762 // "TGo4HDF5VectorDataHandle::Read AFTER COPY has collection size: %ld capacity: %ld pointer to buffer 0x%lx, end: 0x%lx cap: 0x%lx\n",
763 // len, cap, (unsigned long) *p_begin_ptr, (unsigned long) *p_end_ptr, (unsigned long) *p_cap_ptr);
764 //
765 // }
766 // NOTE: after doing this copy, the next clear on this vector will crash!
768 
770  //dataVec.insert(dataVec.end(), &dataArray[0], &dataArray[dataArraySize]);
771 
772  if(fxVarHandle.fxArray.len >0)
773  {
774  Char_t* first =(Char_t*) fxVarHandle.fxArray.p;
775  Char_t* last = (Char_t*) fxVarHandle.fxArray.p + (fxVarHandle.fxArray.len) * fiElementSize;
776 
777  TString vectorhandle = TString::Format("myevent->%s",fxMemberHandle.Data());
778  TString copycom = TString::Format("%s * myevent= (%s *) %ld; %s.insert(%s.end(), (%s *) %ld, (%s *) %ld)",
779  fxEventClass.Data(), fxEventClass.Data(), (unsigned long) fxEvent, vectorhandle.Data(), vectorhandle.Data(),
780  fxMemberClass.Data(), (unsigned long) first, fxMemberClass.Data(),(unsigned long) last);
781 
782  go4hdfdbg("TGo4HDF5VectorDataHandle::Read will use command: %s \n", copycom.Data());
783  gROOT->ProcessLineFast(copycom.Data());
784 
785  // now check if vector has changed:
786 #ifdef GO4HDF5_DEBUG
787 
788  char** p_collection = (char**) fxData;
789  char** p_begin_ptr = p_collection;
790  char** p_end_ptr = p_collection + 1;
791  char** p_cap_ptr = p_collection + 2;
792 
793  size_t len = (*p_end_ptr - *p_begin_ptr) / fiElementSize;
794  size_t cap = (*p_cap_ptr - *p_begin_ptr) / fiElementSize;
795 
796  go4hdfdbg(
797  "TGo4HDF5VectorDataHandle::Read after INSERT has collection size: %ld capacity: %ld pointer to buffer 0x%lx, end: 0x%lx cap: 0x%lx\n",
798  len, cap, (unsigned long) *p_begin_ptr, (unsigned long) *p_end_ptr, (unsigned long) *p_cap_ptr);
799 #endif
800 
801  }
802 
804 
805  }
806 
807 
808 
809 
810 void TGo4HDF5VectorDataHandle::Write(hsize_t sequencenum, H5::H5File* file)
811 {
812  SetActive(((fxVarHandle.fxArray.p!=0) && (fxVarHandle.fxArray.len>0)) ? true : false); // disable writing out empty vector
813 
814  BuildWriteDataset(file); // dataset is no sooner created than we have really data to write in vector
815  TGo4HDF5DataHandle::Write(sequencenum, file);
816 
817  if(fbDataSetActive)
818  {
819  //printf("TGo4HDF5VectorDataHandle::Write %s collection \n", fxTypeName.Data());
820  go4hdfdbg("TGo4HDF5VectorDataHandle::Write %s collection \n", fxTypeName.Data());
821  //TGo4HDF5DataHandle::Write(sequencenum, file);
822  fxDataSet.write(&fxVarHandle.fxArray, H5::VarLenType(fxType), *fxDataSpace, fxFileSpace);
823  // fxDataSet.write(fxVarHandle.fxArray.p, *fxType, *fxDataSpace, fspace); // test if we can write at lease first element in array? yes!
824  }
825  else
826  {
827  go4hdfdbg("TGo4HDF5VectorDataHandle::Write DO NOT WRITE inactive %s collection\n", fxTypeName.Data());
828  }
829 
830 }
831 
832 
833 
834 
835 
836 
839 
840 
841 // this handle is a collection of vector elements with subelements
843  TGo4HDF5VectorDataHandle(name, datasize)
844 
845  {
846  go4hdfdbg("TGo4HDF5SubVectorDataHandle ctor \n");
847 
848 
849  }
850 
851 
852 
853 
854 
855 
857  {
858  go4hdfdbg("TGo4HDF5SubVectorDataHandle is deleted %s \n", fxTypeName.Data());
859  }
860 
861 
862 
864 {
865 
867 
868 
869  // still need to update recursively all vectors in this container
870 
871  TDataType datatype(fxInnerClassName.Data());
872 
873  size_t innersize=datatype.Size();
874 
875  // need to find out which of the existing subhandles should not be written, because
876  // the corresponding entries in subervector are not exisiting for the current event.
877  SetAllSubMembersActive(false); // first disable all subcomponents if existing
878 
879 
880  for(unsigned int ix=0; ix< fxVarHandle.fxArray.len; ++ix)
881  {
882  char* cursor = (char*)(fxVarHandle.fxArray.p) + ix * fiElementSize;
883  //TGo4HDF5VectorProxy* prox = (TGo4HDF5VectorProxy*) cursor;
884 
885  TString fullname= TString::Format("%s[%d]", GetTypeName(), ix ); // full name of dataset
886  TString membername = TString::Format("%s[%d]",fxMemberHandle.Data(),ix); // local name to access member functions
887  // before adding it, look if we already have one TODO!
888  go4hdfdbg(
889  "TGo4HDF5SubVectorDataHandle SetObjectPointer updating element %s , inner class is %s\n",
890  fullname.Data(), fxInnerClassName.Data());
891 
892 // printf(
893 // "TGo4HDF5SubVectorDataHandle SetObjectPointer updating element %s , inner class is %s\n",
894 // fullname.Data(), fxInnerClassName.Data());
895 
896  TString memberclass = TString::Format("vector<%s>",fxInnerClassName.Data());
897  TString searchname = TString::Format("%s[%s]",fullname.Data(), memberclass.Data());
898  TGo4HDF5DataHandle* subhandle =FindSubMember(searchname.Data());
899  if(subhandle)
900  {
901  go4hdfdbg(
902  "TGo4HDF5SubVectorDataHandle SetObjectPointer finds element %s , already in subcomponents\n",
903  searchname.Data());
904  subhandle->SetActive(true);
905  }
906  else
907  {
908  go4hdfdbg(
909  "TGo4HDF5SubVectorDataHandle SetObjectPointer creates new subcomponent %s \n",
910  fullname.Data());
911  //TString memberclass = TString::Format("vector<%s>",fxInnerClassName.Data());
912  subhandle = AddSubMember(fullname.Data(), innersize, memberclass.Data());
913  subhandle->SetMemberName(membername);
914  subhandle->SetMemberClass(fxInnerClassName.Data());
915 
916  TGo4HDF5Adapter::FillTypeInfo(subhandle, fullname.Data(), fxInnerClassName.Data());
917  // newly created subcomponents will be set active at lazy creation of dataset later (when write or read is called).
918  subhandle->SetActive(true);
919  }
920 
921  void* super=Data(); // everything is relative to immediate mother element
922  // pointer to the subvector is content of cursor:
923 
924 // char** psubvector = (char**) cursor;
925 // char* subvector = *psubvector;
926 // size_t delta= (char*) subvector - (char*) super;
927 
928 
929 #ifdef GO4HDF5_DEBUG
930  char* subvector = cursor;
931 #endif
932  size_t delta= (char*) cursor - (char*) super;
933  go4hdfdbg("TGo4HDF5SubVectorDataHandle SetObjectPointer sets parent offset %ld (subvector:0x%lx, super:0x%lx) cursor was 0x%lx\n",
934  delta, (unsigned long) subvector, (unsigned long) super, (unsigned long) cursor);
935 
936  subhandle->SetParentOffset(delta);
937  subhandle->SetObjectPointer(super); // will internally set active only if subvector has real data
938 
939  //subhandle->SetActive(false); // JAMDEBUG: disable all writing of subsubvectors
940 
941  } // for(unsigned int ix=0; ix< fxVarHandle.fxArray.len; ++ix)
942 
943 
944 }
945 
946 
948  {
950  SetActive(false);
951  }
952 
953 
955  {
956  // do nothing here until dataset is initalized lazy after set object pointer is done!
957  // TGo4HDF5DataHandle::BuildWriteDataset(file); // recursively do it for all subcomponents
958  // we do not build an own dataset to store the vector of vector in the file here.
959  // the actual data is stored in our subcomponents (i.e. regular TGo4HDF5VectorDataHandle objects)
960 
961  go4hdfdbg("TGo4HDF5SubVectorDataHandle: BuildWriteDataset NOP for collection set %s \n",fxTypeName.Data());
962  SetActive(false); // mark to skip writing the vector of vector container itself.
963 
964 
965  }
966 
967 
968 
969 
970 
971 
972  void TGo4HDF5SubVectorDataHandle::Read(hsize_t sequencenum, H5::H5File* file)
973  {
974  // TODO here: for a consistent read back we would need to evaluate which of the subvectors are
975  // filled in the file for each entry.
976 
977 
979  TGo4HDF5DataHandle::Read(sequencenum, file); // recursively do it for all subcomponents
980  // we do not read the vector of vector from file here.
981  // the actual data is read into our subcomponents (i.e. regular TGo4HDF5VectorDataHandle objects)
982 
983  go4hdfdbg("TGo4HDF5SubVectorDataHandle::Read %s collection \n", fxTypeName.Data());
984 
985 
986 
987 
988  }
989 
990 
991 
992 
993 void TGo4HDF5SubVectorDataHandle::Write(hsize_t sequencenum, H5::H5File* file)
994 {
995  // need to dynamically setup new write datsets for variable subcomponents like vectors of vectors
996  //TGo4HDF5DataHandle::BuildWriteDataset(file);
997  TGo4HDF5DataHandle::Write(sequencenum, file);
998 
999 
1000 }
1001 
1002 
1003 
1004 
1005 
1006 
1007 
1008 
1009 
1010 
1011 
1012 
1013 
1014 
1016 
1017 
1018 TGo4HDF5DataHandle* TGo4HDF5DataHandleFactory::CreateDataHandle(const char* name, size_t datasize, const char* type)
1019 {
1020  TGo4HDF5DataHandle* rev = 0;
1021 
1022  if (strstr(type, "vector<vector") != 0)
1023  {
1024  // add collectionclass to our datahandle name:
1025  TString theName(name);
1026  TString theCollection(type);
1027  theName += "[";
1028  theName = theName.Append(theCollection);
1029  theName += "]";
1030  TGo4HDF5SubVectorDataHandle* vrev = new TGo4HDF5SubVectorDataHandle(theName.Data(), datasize);
1031  vrev->SetElementSize(datasize);
1032  TObjArray* tokens = theCollection.Tokenize("<");
1033  if (tokens)
1034  {
1035  TObjString* part = dynamic_cast<TObjString*>(tokens->At(2));
1036  if (part)
1037  {
1038  TString rtype = part->GetString();
1039  TObjArray* stokens = rtype.Tokenize(">");
1040  if (stokens)
1041  {
1042  TObjString* spart = dynamic_cast<TObjString*>(stokens->At(0));
1043  TString valuetype = spart->GetString();
1044  vrev->SetInnerClassName(valuetype.Data());
1045  go4hdfdbg("TGo4HDF5DataHandleFactory::CreateDataHandle for %s sets inner class name to %s\n", type,
1046  valuetype.Data());
1047  delete stokens;
1048  }
1049  else
1050  {
1051  go4hdfdbg("TGo4HDF5DataHandleFactory::CreateDataHandle for %s could not evaluate valuetype from %ss\n", type,
1052  theCollection.Data());
1053  }
1054  }
1055  else
1056  {
1057  go4hdfdbg("TGo4HDF5DataHandleFactory::CreateDataHandle for %s could not evaluate valuetype from %ss\n", type,
1058  theCollection.Data());
1059  }
1060  delete tokens;
1061  }
1062  rev = vrev;
1063  }
1064  else if (strstr(type, "vector") != 0)
1065  {
1066  // add collectionclass to our datahandle name:
1067  TString theName(name);
1068  TString theCollection(type);
1069  theName += "[";
1070  theName = theName.Append(theCollection);
1071  theName += "]";
1072  TGo4HDF5VectorDataHandle* vrev = new TGo4HDF5VectorDataHandle(theName.Data(), datasize);
1073  vrev->SetElementSize(datasize);
1074  rev = vrev;
1075  }
1076  else if (strstr(type, "Go4Comp") != 0)
1077  {
1078  rev = new TGo4HDF5CompositeDataHandle(name, datasize);
1079  rev->SetActive(true);
1080  }
1081  else
1082  {
1083  rev = new TGo4HDF5DataHandle(name, datasize);
1084  rev->SetActive(true);
1085  }
1086 
1087  return rev;
1088 }
1089 
1090 
1091 
1092 
void SetInnerClassName(const char *nm)
void SetActive(Bool_t on)
virtual void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent)
H5::DataSpace * fxDataSpace
virtual void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent)
void InsertTypeMember(const H5std_string &name, size_t offset, const H5::DataType &new_member)
void AllocReadBuffer(size_t size)
TGo4HDF5DataHandle * CreateDataHandle(const char *name, size_t datasize, const char *type)
TGo4EventElement * fxEvent
#define go4hdfdatahandlethrow(args...)
Definition: Go4HDF5.h:31
void Read(hsize_t sequencenum, H5::H5File *file)
virtual void Write(hsize_t sequencenum, H5::H5File *ile)
virtual void BuildWriteDataset(H5::H5File *file)
virtual void SetObjectPointer(void *memptr)
static void FillTypeInfo(TGo4HDF5DataHandle *handle, TClass *rootclass, const char *basename=0)
virtual void Read(hsize_t sequencenum, H5::H5File *file)
virtual void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent)
void SetAllSubMembersActive(Bool_t on)
virtual void BuildWriteDataset(H5::H5File *file)
H5::DataSpace fxFileSpace
virtual void Write(hsize_t sequencenum, H5::H5File *file)
virtual void Read(hsize_t sequencenum, H5::H5File *file)
void SetErrMess(const char *txt)
std::vector< TGo4HDF5DataHandle * > fxSubcomponents
virtual void Read(hsize_t sequencenum, H5::H5File *file)
virtual void Write(hsize_t sequencenum, H5::H5File *file)
virtual void Write(hsize_t sequencenum, H5::H5File *file)
virtual void BuildWriteDataset(H5::H5File *file)
void BuildWriteDataset(H5::H5File *file)
#define go4hdfdbg(args...)
Definition: Go4HDF5.h:26
void SetTopEventClass(const char *classname)
const char * GetTypeName()
void SetTopEvent(TGo4EventElement *eve)
TGo4HDF5CompositeDataHandle(const char *name, size_t datasize)
TGo4HDF5BasicDataHandle(const char *name, size_t datasize)
virtual void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent)
TGo4HDF5Source * fxParentSource
virtual void BuildWriteDataset(H5::H5File *file)
TGo4HDF5SubVectorDataHandle(const char *name, size_t datasize)
void Write(hsize_t sequencenum, H5::H5File *file)
TGo4HDF5DataHandle(const char *name, size_t datasize)
TGo4HDF5DataHandle * FindSubMember(const char *name)
virtual void SetObjectPointer(void *memptr)
virtual void Read(hsize_t sequencenum, H5::H5File *file)
virtual void SetObjectPointer(void *memptr)
static TGo4HDF5DataHandleFactory fxFactory
TGo4HDF5VectorDataHandle(const char *name, size_t datasize)
TGo4HDF5VarContainer fxVarHandle
TGo4HDF5DataHandle * AddSubMember(const char *name, size_t datasize, const char *collectiontype=0)
static void Error(const char *text,...)
Definition: TGo4Log.cxx:323
void BuildReadDataset(H5::H5File *file, TGo4HDF5Source *parent)
void SetMemberName(const char *name)
void SetElementSize(size_t len)
string msg
Definition: go4init.py:11