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