libSplash
DCDataSet.cpp
1 
25 #include <string>
26 #include <sstream>
27 #include <cassert>
28 
29 #include "splash/sdc_defines.hpp"
30 
31 #include "splash/core/DCDataSet.hpp"
32 #include "splash/core/DCAttribute.hpp"
33 #include "splash/core/DCHelper.hpp"
34 #include "splash/core/logging.hpp"
35 #include "splash/DCException.hpp"
36 #include "splash/basetypes/ColTypeDim.hpp"
37 
38 namespace splash
39 {
40 
41  std::string DCDataSet::getExceptionString(std::string msg)
42  {
43  return (std::string("Exception for DCDataSet [") + name + std::string("] ") +
44  msg);
45  }
46 
47  void DCDataSet::splitPath(const std::string fullName, std::string &path, std::string &name)
48  {
49  std::string::size_type pos = fullName.find_last_of('/');
50 
51  if (pos == std::string::npos || (pos == fullName.size() - 1))
52  {
53  path = "";
54  name = fullName;
55  } else
56  {
57  path.assign(fullName.c_str(), fullName.c_str() + pos);
58  name.assign(fullName.c_str() + pos + 1);
59  }
60  }
61 
62  void DCDataSet::getFullDataPath(const std::string fullUserName,
63  const std::string pathBase, uint32_t id, std::string &path, std::string &name)
64  {
65  splitPath(fullUserName, path, name);
66 
67  std::stringstream group_id_name;
68  group_id_name << pathBase << "/" << id;
69  if (path.size() > 0)
70  group_id_name << "/" << path;
71 
72  path.assign(group_id_name.str());
73  }
74 
75  DCDataSet::DCDataSet(const std::string name) :
76  dataset(-1),
77  datatype(-1),
78  logicalSize(),
79  ndims(0),
80  name(name),
81  opened(false),
82  isReference(false),
83  checkExistence(true),
84  compression(false),
85  dimType()
86  {
87  dsetProperties = H5Pcreate(H5P_DATASET_CREATE);
88  dsetWriteProperties = H5P_DEFAULT;
89  dsetReadProperties = H5P_DEFAULT;
90  }
91 
92  DCDataSet::~DCDataSet()
93  {
94  H5Pclose(dsetProperties);
95  }
96 
97  Dimensions DCDataSet::getSize() const
98  {
99  return logicalSize;
100  }
101 
102  Dimensions& DCDataSet::getLogicalSize()
103  {
104  return logicalSize;
105  }
106 
107  Dimensions DCDataSet::getPhysicalSize()
108  {
109  Dimensions result(logicalSize);
110  result.swapDims(ndims);
111  return result;
112  }
113 
114  bool DCDataSet::open(hid_t group)
115  throw (DCException)
116  {
117  if (checkExistence && !H5Lexists(group, name.c_str(), H5P_LINK_ACCESS_DEFAULT))
118  return false;
119 
120  dataset = H5Dopen(group, name.c_str(), H5P_DATASET_ACCESS_DEFAULT);
121 
122  if (dataset < 0)
123  throw DCException(getExceptionString("open: Failed to open dataset"));
124 
125  datatype = H5Dget_type(dataset);
126  if (datatype < 0)
127  {
128  H5Dclose(dataset);
129  throw DCException(getExceptionString("open: Failed to get type of dataset"));
130  }
131 
132  dataspace = H5Dget_space(dataset);
133  if (dataspace < 0)
134  {
135  H5Dclose(dataset);
136  throw DCException(getExceptionString("open: Failed to open dataspace"));
137  }
138 
139  int dims_result = H5Sget_simple_extent_ndims(dataspace);
140  if (dims_result < 0)
141  {
142  close();
143  throw DCException(getExceptionString("open: Failed to get dimensions"));
144  }
145 
146  ndims = dims_result;
147 
148  getLogicalSize().set(1, 1, 1);
149  if (H5Sget_simple_extent_dims(dataspace, getLogicalSize().getPointer(), NULL) < 0)
150  {
151  close();
152  throw DCException(getExceptionString("open: Failed to get sizes"));
153  }
154 
155  getLogicalSize().swapDims(ndims);
156 
157  opened = true;
158 
159  return true;
160  }
161 
162  void DCDataSet::setChunking(size_t typeSize)
163  throw (DCException)
164  {
165  if (getPhysicalSize().getScalarSize() != 0)
166  {
167  // get chunking dimensions
168  hsize_t chunk_dims[ndims];
169  DCHelper::getOptimalChunkDims(getPhysicalSize().getPointer(), ndims,
170  typeSize, chunk_dims);
171 
172  if (H5Pset_chunk(this->dsetProperties, ndims, chunk_dims) < 0)
173  {
174  for (size_t i = 0; i < ndims; ++i)
175  {
176  log_msg(1, "chunk_dims[%llu] = %llu",
177  (long long unsigned) i, (long long unsigned) (chunk_dims[i]));
178  }
179  throw DCException(getExceptionString("setChunking: Failed to set chunking"));
180  }
181  }
182  }
183 
184  void DCDataSet::setCompression()
185  throw (DCException)
186  {
187  if (this->compression && getPhysicalSize().getScalarSize() != 0)
188  {
189  // shuffling reorders bytes for better compression
190  // set gzip compression level (1=lowest - 9=highest)
191  if (H5Pset_shuffle(this->dsetProperties) < 0 ||
192  H5Pset_deflate(this->dsetProperties, 1) < 0)
193  throw DCException(getExceptionString("setCompression: Failed to set compression"));
194  }
195  }
196 
197  void DCDataSet::create(const CollectionType& colType,
198  hid_t group, const Dimensions size, uint32_t ndims,
199  bool compression, bool extensible)
200  throw (DCException)
201  {
202  log_msg(2, "DCDataSet::create (%s, size %s)", name.c_str(), size.toString().c_str());
203 
204  if (opened)
205  throw DCException(getExceptionString("create: dataset is already open"));
206 
207  // if the dataset already exists, remove/unlink it
208  // note that this won't free the memory occupied by this
209  // dataset, however, there currently is no function to delete
210  // a dataset
211  if (!checkExistence || (checkExistence && H5Lexists(group, name.c_str(), H5P_LINK_ACCESS_DEFAULT)))
212  H5Ldelete(group, name.c_str(), H5P_LINK_ACCESS_DEFAULT);
213 
214  this->ndims = ndims;
215  this->compression = compression;
216  this->datatype = colType.getDataType();
217 
218  getLogicalSize().set(size);
219 
220  setChunking(colType.getSize());
221  setCompression();
222 
223  if (getPhysicalSize().getScalarSize() != 0)
224  {
225  hsize_t *max_dims = new hsize_t[ndims];
226  for (size_t i = 0; i < ndims; ++i)
227  {
228  if (extensible)
229  max_dims[i] = H5F_UNLIMITED;
230  else
231  max_dims[i] = getPhysicalSize()[i];
232  }
233 
234  dataspace = H5Screate_simple(ndims, getPhysicalSize().getPointer(), max_dims);
235 
236  delete[] max_dims;
237  max_dims = NULL;
238  } else
239  dataspace = H5Screate(H5S_NULL);
240 
241 
242 
243  if (dataspace < 0)
244  throw DCException(getExceptionString("create: Failed to create dataspace"));
245 
246  // create the new dataset
247  dataset = H5Dcreate(group, this->name.c_str(), this->datatype, dataspace,
248  H5P_DEFAULT, dsetProperties, H5P_DEFAULT);
249 
250  if (dataset < 0)
251  throw DCException(getExceptionString("create: Failed to create dataset"));
252 
253  isReference = false;
254  opened = true;
255  }
256 
257  void DCDataSet::createReference(hid_t refGroup,
258  hid_t srcGroup,
259  DCDataSet &srcDataSet)
260  throw (DCException)
261  {
262  if (opened)
263  throw DCException(getExceptionString("createReference: dataset is already open"));
264 
265  if (checkExistence && H5Lexists(refGroup, name.c_str(), H5P_LINK_ACCESS_DEFAULT))
266  throw DCException(getExceptionString("createReference: this reference already exists"));
267 
268  getLogicalSize().set(srcDataSet.getLogicalSize());
269  this->ndims = srcDataSet.getNDims();
270 
271  if (H5Rcreate(&regionRef, srcGroup, srcDataSet.getName().c_str(), H5R_OBJECT, -1) < 0)
272  throw DCException(getExceptionString("createReference: failed to create region reference"));
273 
274  hsize_t ndims = 1;
275  dataspace = H5Screate_simple(1, &ndims, NULL);
276  if (dataspace < 0)
277  throw DCException(getExceptionString("createReference: failed to create dataspace for reference"));
278 
279  dataset = H5Dcreate(refGroup, name.c_str(), H5T_STD_REF_OBJ,
280  dataspace, H5P_DEFAULT, dsetProperties, H5P_DEFAULT);
281 
282  if (dataset < 0)
283  throw DCException(getExceptionString("createReference: failed to create dataset for reference"));
284 
285  if (H5Dwrite(dataset, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL,
286  dsetWriteProperties, &regionRef) < 0)
287  throw DCException(getExceptionString("createReference: failed to write reference"));
288 
289  isReference = true;
290  opened = true;
291  }
292 
293  void DCDataSet::createReference(hid_t refGroup,
294  hid_t srcGroup,
295  DCDataSet &srcDataSet,
296  Dimensions count,
297  Dimensions offset,
298  Dimensions stride)
299  throw (DCException)
300  {
301  if (opened)
302  throw DCException(getExceptionString("createReference: dataset is already open"));
303 
304  if (checkExistence && H5Lexists(refGroup, name.c_str(), H5P_LINK_ACCESS_DEFAULT))
305  throw DCException(getExceptionString("createReference: this reference already exists"));
306 
307  getLogicalSize().set(count);
308  this->ndims = srcDataSet.getNDims();
309 
310  count.swapDims(this->ndims);
311  offset.swapDims(this->ndims);
312  stride.swapDims(this->ndims);
313 
314  // select region hyperslab in source dataset
315  if (H5Sselect_hyperslab(srcDataSet.getDataSpace(), H5S_SELECT_SET,
316  offset.getPointer(), stride.getPointer(),
317  count.getPointer(), NULL) < 0 ||
318  H5Sselect_valid(srcDataSet.getDataSpace()) <= 0)
319  throw DCException(getExceptionString("createReference: failed to select hyperslap for reference"));
320 
321  if (H5Rcreate(&regionRef, srcGroup, srcDataSet.getName().c_str(), H5R_DATASET_REGION,
322  srcDataSet.getDataSpace()) < 0)
323  throw DCException(getExceptionString("createReference: failed to create region reference"));
324 
325  hsize_t ndims = 1;
326  dataspace = H5Screate_simple(1, &ndims, NULL);
327  if (dataspace < 0)
328  throw DCException(getExceptionString("createReference: failed to create dataspace for reference"));
329 
330  dataset = H5Dcreate(refGroup, name.c_str(), H5T_STD_REF_DSETREG,
331  dataspace, H5P_DEFAULT, dsetProperties, H5P_DEFAULT);
332 
333  if (dataset < 0)
334  throw DCException(getExceptionString("createReference: failed to create dataset for reference"));
335 
336  if (H5Dwrite(dataset, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL,
337  dsetWriteProperties, &regionRef) < 0)
338  throw DCException(getExceptionString("createReference: failed to write reference"));
339 
340  isReference = true;
341  opened = true;
342  }
343 
344  void DCDataSet::close()
345  throw (DCException)
346  {
347  opened = false;
348  isReference = false;
349 
350  if (H5Dclose(dataset) < 0 || H5Sclose(dataspace) < 0)
351  throw DCException(getExceptionString("close: Failed to close dataset"));
352  }
353 
354  size_t DCDataSet::getNDims()
355  {
356  return ndims;
357  }
358 
359  hid_t DCDataSet::getDataSpace()
360  throw (DCException)
361  {
362  if (!opened)
363  throw DCException(getExceptionString("getDataSpace: dataset is not opened"));
364 
365  return dataspace;
366  }
367 
368  DCDataType DCDataSet::getDCDataType() throw (DCException)
369  {
370  if (!opened)
371  throw DCException(getExceptionString("getDCDataType: dataset is not opened"));
372 
373  DCDataType result = DCDT_UNKNOWN;
374 
375  H5T_class_t type_class = H5Tget_class(datatype);
376  size_t type_size = H5Tget_size(datatype);
377  H5T_sign_t type_signed = H5Tget_sign(datatype);
378 
379  if (type_class == H5T_INTEGER)
380  {
381  if (type_signed == H5T_SGN_NONE)
382  {
383  if (type_size == sizeof (uint64_t))
384  result = DCDT_UINT64;
385  else
386  result = DCDT_UINT32;
387  } else
388  {
389  if (type_size == sizeof (int64_t))
390  result = DCDT_INT64;
391  else
392  result = DCDT_INT32;
393  }
394  } else
395  if (type_class == H5T_FLOAT)
396  {
397  // float or double
398  if (type_size == sizeof (float))
399  result = DCDT_FLOAT32;
400  else
401  if (type_size == sizeof (double))
402  result = DCDT_FLOAT64;
403  }
404 
405  return result;
406  }
407 
408  size_t DCDataSet::getDataTypeSize()
409  throw (DCException)
410  {
411  if (!opened)
412  throw DCException(getExceptionString("getDataTypeSize: dataset is not opened"));
413 
414  size_t size = H5Tget_size(this->datatype);
415  if (size == 0)
416  throw DCException(getExceptionString("getDataTypeSize: could not get size of datatype"));
417 
418  return size;
419  }
420 
421  std::string DCDataSet::getName()
422  {
423  return name;
424  }
425 
426  void DCDataSet::read(Dimensions dstBuffer,
427  Dimensions dstOffset,
428  Dimensions &sizeRead,
429  uint32_t& srcNDims,
430  void* dst)
431  throw (DCException)
432  {
433  read(dstBuffer, dstOffset, getLogicalSize(), Dimensions(0, 0, 0),
434  sizeRead, srcNDims, dst);
435  }
436 
437  void DCDataSet::read(Dimensions dstBuffer,
438  Dimensions dstOffset,
439  Dimensions srcSize,
440  Dimensions srcOffset,
441  Dimensions& sizeRead,
442  uint32_t& srcNDims,
443  void* dst)
444  throw (DCException)
445  {
446  log_msg(2, "DCDataSet::read (%s)", name.c_str());
447 
448  if (!opened)
449  throw DCException(getExceptionString("read: Dataset has not been opened/created"));
450 
451  if (dstBuffer.getScalarSize() == 0)
452  dstBuffer.set(srcSize);
453 
454  // dst buffer is allowed to be NULL
455  // in this case, only the size of the dataset is returned
456  // if the dataset is empty, return just its size as there is nothing to read
457  if (getNDims() > 0)
458  {
459  log_msg(3,
460  "\n ndims = %llu\n"
461  " logical_size = %s\n"
462  " physical_size = %s\n"
463  " dstBuffer = %s\n"
464  " dstOffset = %s\n"
465  " srcSize = %s\n"
466  " srcOffset = %s\n",
467  (long long unsigned) ndims,
468  getLogicalSize().toString().c_str(),
469  getPhysicalSize().toString().c_str(),
470  dstBuffer.toString().c_str(),
471  dstOffset.toString().c_str(),
472  srcSize.toString().c_str(),
473  srcOffset.toString().c_str());
474 
475  dstBuffer.swapDims(ndims);
476  dstOffset.swapDims(ndims);
477  srcSize.swapDims(ndims);
478  srcOffset.swapDims(ndims);
479 
480  hid_t dst_dataspace = H5Screate_simple(ndims, dstBuffer.getPointer(), NULL);
481  if (dst_dataspace < 0)
482  throw DCException(getExceptionString("read: Failed to create target dataspace"));
483 
484  if (!dst) {
485  H5Sselect_none(dst_dataspace);
486  } else {
487  if (H5Sselect_hyperslab(dst_dataspace, H5S_SELECT_SET, dstOffset.getPointer(), NULL,
488  srcSize.getPointer(), NULL) < 0 ||
489  H5Sselect_valid(dst_dataspace) <= 0)
490  throw DCException(getExceptionString("read: Target dataspace hyperslab selection is not valid!"));
491  }
492 
493  if (!dst || srcSize.getScalarSize() == 0) {
494  H5Sselect_none(dataspace);
495  } else {
496  if (H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, srcOffset.getPointer(), NULL,
497  srcSize.getPointer(), NULL) < 0 ||
498  H5Sselect_valid(dataspace) <= 0)
499  throw DCException(getExceptionString("read: Source dataspace hyperslab selection is not valid!"));
500  }
501 
502  if (H5Dread(dataset, this->datatype, dst_dataspace, dataspace, dsetReadProperties, dst) < 0)
503  throw DCException(getExceptionString("read: Failed to read dataset"));
504 
505  H5Sclose(dst_dataspace);
506 
507  srcSize.swapDims(ndims);
508  }
509 
510  // swap dimensions if necessary
511  sizeRead.set(srcSize);
512  srcNDims = this->ndims;
513 
514  log_msg(3, " returns ndims = %llu", (long long unsigned) ndims);
515  log_msg(3, " returns sizeRead = %s", sizeRead.toString().c_str());
516  }
517 
518  void DCDataSet::write(
519  Selection srcSelect,
520  Dimensions dstOffset,
521  const void* data)
522  throw (DCException)
523  {
524  log_msg(2, "DCDataSet::write (%s)", name.c_str());
525 
526  if (!opened)
527  throw DCException(getExceptionString("write: Dataset has not been opened/created"));
528 
529  log_msg(3,
530  "\n ndims = %llu\n"
531  " logical_size = %s\n"
532  " physical_size = %s\n"
533  " src_select = %s\n"
534  " dst_offset = %s\n",
535  (long long unsigned) ndims,
536  getLogicalSize().toString().c_str(),
537  getPhysicalSize().toString().c_str(),
538  srcSelect.toString().c_str(),
539  dstOffset.toString().c_str());
540 
541  // swap dimensions if necessary
542  srcSelect.swapDims(ndims);
543  dstOffset.swapDims(ndims);
544 
545  // dataspace to read from
546  hid_t dsp_src;
547 
548  if (getLogicalSize().getScalarSize() != 0)
549  {
550  dsp_src = H5Screate_simple(ndims, srcSelect.size.getPointer(), NULL);
551  if (dsp_src < 0)
552  throw DCException(getExceptionString("write: Failed to create source dataspace"));
553 
554  // select hyperslap only if necessary
555  if ((srcSelect.offset.getScalarSize() != 0) || (srcSelect.count != srcSelect.size) ||
556  (srcSelect.stride.getScalarSize() != 1))
557  {
558  if (H5Sselect_hyperslab(dsp_src, H5S_SELECT_SET, srcSelect.offset.getPointer(),
559  srcSelect.stride.getPointer(), srcSelect.count.getPointer(), NULL) < 0 ||
560  H5Sselect_valid(dsp_src) <= 0)
561  throw DCException(getExceptionString("write: Invalid source hyperslap selection"));
562  }
563 
564  if (srcSelect.count.getScalarSize() == 0)
565  H5Sselect_none(dsp_src);
566 
567  // dataspace to write to
568  // select hyperslap only if necessary
569  if ((dstOffset.getScalarSize() != 0) || (srcSelect.count != getPhysicalSize()))
570  {
571  if (H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, dstOffset.getPointer(),
572  NULL, srcSelect.count.getPointer(), NULL) < 0 ||
573  H5Sselect_valid(dataspace) <= 0)
574  throw DCException(getExceptionString("write: Invalid target hyperslap selection"));
575  }
576 
577  if (!data || (srcSelect.count.getScalarSize() == 0))
578  {
579  H5Sselect_none(dataspace);
580  data = NULL;
581  }
582 
583  // write data to the dataset
584 
585  if (H5Dwrite(dataset, this->datatype, dsp_src, dataspace, dsetWriteProperties, data) < 0)
586  throw DCException(getExceptionString("write: Failed to write dataset"));
587 
588  H5Sclose(dsp_src);
589  }
590  }
591 
592  void DCDataSet::append(size_t count, size_t offset, size_t stride, const void* data)
593  throw (DCException)
594  {
595  log_msg(2, "DCDataSet::append");
596 
597  if (!opened)
598  throw DCException(getExceptionString("append: Dataset has not been opened/created."));
599 
600  log_msg(3, "logical_size = %s", getLogicalSize().toString().c_str());
601 
602  Dimensions target_offset(getLogicalSize());
603  // extend size (dataspace) of existing dataset with count elements
604  getLogicalSize()[0] += count;
605 
606  hsize_t * max_dims = new hsize_t[ndims];
607  for (size_t i = 0; i < ndims; ++i)
608  max_dims[i] = H5F_UNLIMITED;
609 
610  if (H5Sset_extent_simple(dataspace, 1, getLogicalSize().getPointer(), max_dims) < 0)
611  throw DCException(getExceptionString("append: Failed to set new extent"));
612 
613  delete[] max_dims;
614  max_dims = NULL;
615 
616  log_msg(3, "logical_size = %s", getLogicalSize().toString().c_str());
617 
618  if (H5Dset_extent(dataset, getLogicalSize().getPointer()) < 0)
619  throw DCException(getExceptionString("append: Failed to extend dataset"));
620 
621  // select the region in the target DataSpace to write to
622  Dimensions dim_data(count, 1, 1);
623  if (H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, target_offset.getPointer(),
624  NULL, dim_data.getPointer(), NULL) < 0 ||
625  H5Sselect_valid(dataspace) < 0)
626  throw DCException(getExceptionString("append: Invalid target hyperslap selection"));
627 
628  // append data to the dataset.
629  // select the region in the source DataSpace to read from
630  Dimensions dim_src(offset + count * stride, 1, 1);
631  hid_t dsp_src = H5Screate_simple(1, dim_src.getPointer(), NULL);
632  if (dsp_src < 0)
633  throw DCException(getExceptionString("append: Failed to create src dataspace while appending"));
634 
635  if (H5Sselect_hyperslab(dsp_src, H5S_SELECT_SET, Dimensions(offset, 0, 0).getPointer(),
636  Dimensions(stride, 1, 1).getPointer(), dim_data.getPointer(), NULL) < 0 ||
637  H5Sselect_valid(dsp_src) < 0)
638  throw DCException(getExceptionString("append: Invalid source hyperslap selection"));
639 
640  if (!data || (count == 0))
641  {
642  H5Sselect_none(dataspace);
643  data = NULL;
644  }
645 
646  if (H5Dwrite(dataset, this->datatype, dsp_src, dataspace, dsetWriteProperties, data) < 0)
647  throw DCException(getExceptionString("append: Failed to append dataset"));
648 
649  H5Sclose(dsp_src);
650  }
651 
652 }
EXTERN void log_msg(int level, const char *fmt,...)
Definition: logging.cpp:56
void read(const CollectionType &colType, void *buf)