icedb  version 0.5.1
Snow particle scattering database API
Tables.cpp
Go to the documentation of this file.
1 #include <array>
2 #include "../icedb/Table.hpp"
3 #include "../icedb/Group.hpp"
4 #include "../private/Table_impl.hpp"
5 #include "../private/Attribute_impl.hpp"
6 #include "../private/hdf5_supplemental.hpp"
7 
8 namespace icedb {
9  namespace Tables {
11  Table::Table(const std::string &name) : name{ name } {}
12  // this->_setAttributeParent(_getTableSelf()); // Goes in implementation class.
13  bool Table::valid() const { if (_getTableSelf()) return true; return false; }
14 
15  size_t Table::getNumDimensions() const {
16  Expects(valid());
17  auto ptr = _getTableSelf();
18  return fs::hdf5::readDatasetNumDimensions(ptr.get());
19  }
20 
22  Expects(valid());
23  auto ptr = _getTableSelf();
25  fs::hdf5::readDatasetDimensions(ptr.get(), dims);
26  return dims;
27  }
28 
29  void Table::attachDimensionScale(size_t DimensionNumber, gsl::not_null<const Table *> scale) {
30  Expects(valid());
31  Expects(scale->valid());
32  Expects(DimensionNumber < getNumDimensions());
33  auto selfptr = _getTableSelf();
34  auto tblscaleptr = scale->_getTableSelf();
35  const herr_t res = H5DSattach_scale(selfptr->getId(), tblscaleptr->getId(), static_cast<unsigned int>(DimensionNumber));
36  assert(res == 0);
37  }
38 
39  void Table::detachDimensionScale(size_t DimensionNumber, gsl::not_null<const Table *> scale) {
40  Expects(valid());
41  Expects(scale->valid());
42  Expects(DimensionNumber < getNumDimensions());
43  auto selfptr = _getTableSelf();
44  auto tblscaleptr = scale->_getTableSelf();
45  const herr_t res = H5DSdetach_scale(selfptr->getId(), tblscaleptr->getId(), static_cast<unsigned int>(DimensionNumber));
46  assert(res == 0);
47  }
48 
49  /*
50  bool Table::hasDimensionScaleAttached(size_t DimensionNumber, gsl::not_null<const Table *> scale) const {
51  Expects(valid());
52  Expects(scale->valid());
53  Expects(DimensionNumber < getNumDimensions());
54  auto selfptr = _getTableSelf();
55  auto tblscaleptr = scale->_getTableSelf();
56  const herr_t res = H5DSis_attached(selfptr->getId(), tblscaleptr->getId(), DimensionNumber);
57  assert(res >= 0);
58  if (res > 0) return true;
59  return false;
60  }
61  */
62  /*
63  Table::Table_Type Table::readDimensionScale(size_t DimensionNumber) const {
64  Expects(valid());
65  Expects(DimensionNumber < getNumDimensions());
66  auto selfptr = _getTableSelf();
67 
68  }
69  */
70  /*
71  void Table::readAttachedDimensionScales() const {
72  Expects(valid());
73  auto selfptr = _getTableSelf();
74  size_t numDims = getNumDimensions();
75  int *idx = nullptr; // input the index to start iterating, output the next index. Start at NULL.
76  struct DimScaleInfo {
77  std::string name;
78  };
79  // Each dimension can have multiple scales attached.
80  typedef std::vector<std::vector<DimScaleInfo> > DimScaleInfo_vt;
81  DimScaleInfo_vt DimScaleInfo_v;
82  auto visitor = [](hid_t dimscaledataset, unsigned int dimnum, hid_t scale, void *visitor_data) ->herr_t {
83  DimScaleInfo_vt *vd = static_cast<DimScaleInfo_vt*>(visitor_data);
84 
85  return 0;
86  };
87  for (unsigned int dim = 0; dim < static_cast<unsigned int>(numDims); ++dim) {
88 
89  herr_t err = H5DSiterate_scales(selfptr->getId(), dim, idx, visitor, &DimScaleInfo_v);
90  }
91  }
92 
93  bool Table::hasDimensionScaleAttached(size_t DimensionNumber) const;
94 
95  bool Table::hasAllDimensionScalesAttached() const;
96  */
97  bool Table::isDimensionScale() const {
98  Expects(valid());
99  auto selfptr = _getTableSelf();
100  const htri_t res = H5DSis_scale(selfptr->getId());
101  assert(res >= 0);
102  if (res > 0) return true;
103  return false;
104  }
105 
106  void Table::setDimensionScale(const std::string &dimensionScaleName) {
107  Expects(valid());
108  Expects(!isDimensionScale());
109  auto selfptr = _getTableSelf();
110  const htri_t res = H5DSset_scale(selfptr->getId(), dimensionScaleName.c_str());
111  assert(res == 0);
112  }
113 
114  void Table::setDimensionScaleAxisLabel(size_t DimensionNumber, const std::string &label) {
115  Expects(valid());
116  Expects(DimensionNumber < getNumDimensions());
117  auto selfptr = _getTableSelf();
118  const htri_t res = H5DSset_label(selfptr->getId(), static_cast<unsigned int>(DimensionNumber), label.c_str());
119  assert(res == 0);
120  }
121 
122  std::string Table::getDimensionScaleAxisLabel(size_t DimensionNumber) const {
123  Expects(valid());
124  Expects(DimensionNumber < getNumDimensions());
125  auto selfptr = _getTableSelf();
126  constexpr size_t max_label_size = 1000;
127  std::array<char, max_label_size> label;
128  label.fill('\0');
129  const ssize_t res = H5DSget_label(selfptr->getId(), static_cast<unsigned int>(DimensionNumber), label.data(), max_label_size);
130  // res is the size of the label. The HDF5 documentation does not include whether the label is null-terminated,
131  // so I am terminating it manually.
132  label[max_label_size - 1] = '\0';
133  return std::string(label.data());
134  }
135 
136  std::string Table::getDimensionScaleName() const {
137  Expects(valid());
138  auto selfptr = _getTableSelf();
139  constexpr size_t max_label_size = 1000;
140  std::array<char, max_label_size> label;
141  label.fill('\0');
142  const ssize_t res = H5DSget_scale_name(selfptr->getId(), label.data(), max_label_size);
143  // res is the size of the label. The HDF5 documentation does not include whether the label is null-terminated,
144  // so I am terminating it manually.
145  label[max_label_size - 1] = '\0';
146  return std::string(label.data());
147  }
148 
149  std::type_index Table::getTableTypeId() const {
150  Expects(valid());
151  auto selfptr = _getTableSelf();
152  if (fs::hdf5::isType<uint64_t, H5::DataSet>(selfptr.get())) return (typeid(uint64_t));
153  if (fs::hdf5::isType<int64_t, H5::DataSet>(selfptr.get())) return (typeid(int64_t));
154  if (fs::hdf5::isType<uint32_t, H5::DataSet>(selfptr.get())) return (typeid(uint32_t));
155  if (fs::hdf5::isType<int32_t, H5::DataSet>(selfptr.get())) return (typeid(int32_t));
156  if (fs::hdf5::isType<uint16_t, H5::DataSet>(selfptr.get())) return (typeid(uint16_t));
157  if (fs::hdf5::isType<int16_t, H5::DataSet>(selfptr.get())) return (typeid(int16_t));
158  if (fs::hdf5::isType<uint8_t, H5::DataSet>(selfptr.get())) return (typeid(uint8_t));
159  if (fs::hdf5::isType<int8_t, H5::DataSet>(selfptr.get())) return (typeid(int8_t));
160  if (fs::hdf5::isType<double, H5::DataSet>(selfptr.get())) return (typeid(double));
161  if (fs::hdf5::isType<float, H5::DataSet>(selfptr.get())) return (typeid(float));
162  if (fs::hdf5::isType<char, H5::DataSet>(selfptr.get())) return (typeid(char));
163  if (fs::hdf5::isType<std::string, H5::DataSet>(selfptr.get())) return (typeid(std::string));
164  throw;
165  }
166 
167  template <class DataType, class ObjectType>
168  void pullData(
169  std::vector<size_t> &dims,
170  std::vector<DataType> &tdata,
171  gsl::not_null<ObjectType*> obj)
172  {
173  size_t sz = 1;
174  for (const auto &s : dims) sz *= s;
175  tdata.resize(sz);
176  icedb::fs::hdf5::readDatasetArray<DataType, H5::DataSet>(obj, tdata.data());
177  }
178 
179  template <class DataType>
181  std::vector<size_t> &dims,
182  std::vector<DataType> &data) const
183  {
184  Expects(valid());
185  auto selfptr = _getTableSelf();
186  fs::hdf5::readDatasetDimensions(selfptr.get(), dims);
187  size_t sz = 1;
188  for (const auto &s : dims) sz *= s;
189  data.resize(sz);
190 
191  pullData<DataType, H5::DataSet>(dims, data, selfptr.get());
192  }
193 
194  template <class DataType, class ObjectType>
195  void pushData(
196  const std::vector<size_t> &dims,
197  gsl::not_null<ObjectType*> obj,
198  const std::vector<DataType> &data)
199  {
200  size_t numElems = 1;
201  for (const auto &s : dims) numElems *= s;
202  Expects(numElems > 0);
203 
204  icedb::fs::hdf5::writeDatasetArray<DataType, ObjectType>(dims, obj, data.data());
205  }
206 
207  /*
208  template <class DataType>
209  void Table::writeAll(
210  const std::vector<DataType> &data) const
211  {
212  Expects(valid());
213  auto selfptr = _getTableSelf();
214  const auto dimensionality = getDimensions();
215  // Need to copy from the variant structure into an array of the exact data type
216  pushData<DataType, H5::DataSet>(dimensionality, selfptr.get(), data);
217  }
218  */
219 
220  template <class DataType>
221  void Table::writeAllInner(const gsl::span<const DataType> &outData) const {
222  Expects(valid());
223  Expects(isTableOfType<DataType>());
224  auto selfptr = _getTableSelf();
225  const auto dimensionality = getDimensions();
226  size_t sz = 1;
227  for (const auto &d : dimensionality) sz *= d;
228  Expects(outData.size() == sz);
229  icedb::fs::hdf5::writeDatasetArray<DataType, H5::DataSet>(dimensionality, selfptr.get(), outData.data());
230  }
231 
232 
233 #define INST_WRITE_TBL_INNER_TYPE(x) \
234  template void Table::writeAllInner<x>(const gsl::span<const x> &outData) const;
235 
237 
238 #define INST_READ_TBL_TYPE(x) \
239  template void Table::readAll<x>( \
240  std::vector<size_t> &dims, \
241  std::vector<x> &data) const;
242 
244 
247  bool CanHaveTables::valid() const { if (_getTablesParent()) return true; return false; }
248 
251  const std::string &tableName,
252  const std::type_index& type_id,
253  const std::vector<size_t> &dims,
254  const std::vector<size_t> &chunks)
255  {
256  Expects(valid());
257  std::vector<hsize_t> hdata;
258  for (const auto &d : dims) hdata.push_back(static_cast<hsize_t>(d));
259  std::vector<hsize_t> cdata;
260  for (const auto &c : chunks) cdata.push_back(static_cast<hsize_t>(c));
261 
262  //fs::hdf5::addDatasetArray
263  /* Turn on creation order tracking. */
264  //assert(H5Pset_attr_creation_order(plistid, H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED) >= 0);
265  std::shared_ptr<H5::DSetCreatPropList> plist = std::make_shared<H5::DSetCreatPropList>();
266  int fillvalue = -1;
267  plist->setFillValue(H5::PredType::NATIVE_INT, &fillvalue);
268  plist->setChunk(static_cast<int>(cdata.size()), cdata.data());
269  if (fs::hdf5::useZLIB()) {
270  plist->setDeflate(fs::hdf5::useZLIB());
271  }
272 #if ICEDB_H5_CREATEPROPLIST_SETATTRCRTORDER == 1
273  plist->setAttrCrtOrder(H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED);
274 #else
275  {
276  hid_t id = plist->getId();
277  herr_t e = H5Pset_attr_creation_order(id, H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED);
278  if (e < 0) throw;
279  }
280 #endif
281 
282  if (type_id == typeid(uint64_t))fs::hdf5::createDatasetRaw<uint64_t, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
283  else if (type_id == typeid(int64_t))fs::hdf5::createDatasetRaw<int64_t, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
284  else if (type_id == typeid(uint32_t))fs::hdf5::createDatasetRaw<uint32_t, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
285  else if (type_id == typeid(int32_t))fs::hdf5::createDatasetRaw<int32_t, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
286  else if (type_id == typeid(uint16_t))fs::hdf5::createDatasetRaw<uint16_t, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
287  else if (type_id == typeid(int16_t))fs::hdf5::createDatasetRaw<int16_t, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
288  else if (type_id == typeid(uint8_t))fs::hdf5::createDatasetRaw<uint8_t, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
289  else if (type_id == typeid(int8_t))fs::hdf5::createDatasetRaw<int8_t, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
290  else if (type_id == typeid(float))fs::hdf5::createDatasetRaw<float, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
291  else if (type_id == typeid(double))fs::hdf5::createDatasetRaw<double, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
292  else if (type_id == typeid(char))fs::hdf5::createDatasetRaw<char, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
293  else if (type_id == typeid(std::string))fs::hdf5::createDatasetRaw<std::string, H5::Group>(_getTablesParent().get(), tableName.c_str(), dims, plist);
294  else throw(std::invalid_argument("Unhandled data type"));
295  }
296 
297  std::set<std::string> CanHaveTables::getTableNames() const {
298  Expects(valid());
299  auto base = _getTablesParent();
300  auto objs = fs::hdf5::getGroupMembersTypes(*(base.get()));
301  std::set<std::string> res;
302  for (const auto &o : objs)
303  {
304  if (o.second == H5G_obj_t::H5G_DATASET) res.insert(o.first);
305  }
306  return res;
307  }
308 
309  bool CanHaveTables::doesTableExist(const std::string &tableName) const {
310  const auto tnames = getTableNames();
311  if (tnames.count(tableName)) return true;
312  return false;
313  }
314 
315  void CanHaveTables::unlinkTable(const std::string &tableName) {
316  Expects(valid());
317  auto base = _getTablesParent();
318  base->unlink(tableName.c_str());
319  }
320 
321  Table::Table_Type CanHaveTables::openTable(const std::string &tableName) {
322  Expects(valid());
323  const auto base = _getTablesParent();
324  const auto tbl = std::make_shared<H5::DataSet>(base->openDataSet(tableName));
325  Table::Table_Type res = std::make_unique<Table_impl>(tbl,tableName);
326  return res;
327  }
328 
329 
330 
331 
332  void Table_impl::_setTableSelf(std::shared_ptr<H5::DataSet> obj) { this->obj = obj; }
333  std::shared_ptr<H5::DataSet> Table_impl::_getTableSelf() const { return obj; }
335  Table_impl::Table_impl(std::shared_ptr<H5::DataSet> obj, const std::string &name) : Table{ name }, obj(obj) {
336  this->_setAttributeParent(obj);
337  }
338 
339 
340 
341 
342 
343  void CanHaveTables_impl::_setTablesParent(std::shared_ptr<H5::Group> newobj) { this->obj = newobj; }
344  std::shared_ptr<H5::Group> CanHaveTables_impl::_getTablesParent() const { return obj; }
347  }
348 }
size_t getNumDimensions() const
Returns the number of dimensions of a table.
Definition: Tables.cpp:15
void _setTableSelf(std::shared_ptr< H5::DataSet > obj) override
Associates the icedb table with the fundamental HDF5 DataSet. Only used internally.
Definition: Tables.cpp:332
void unlinkTable(const std::string &tableName)
Unlink a table. In HDF5, this is not the same as erasing a table, which never actually happens...
Definition: Tables.cpp:315
std::unique_ptr< Table > Table_Type
The preferred method of access of a Table is through std::unique_ptr.
Definition: Table.hpp:35
Table(const std::string &name="")
Default constructor, used by CanHaveTables.
Definition: Tables.cpp:11
const std::string name
The name of the Table.
Definition: Table.hpp:31
void setDimensionScale(const std::string &dimensionScaleName)
Designate this table as a dimension scale.
Definition: Tables.cpp:106
INST_ATTR(INST_WRITE_TBL_INNER_TYPE)
bool doesTableExist(const std::string &tableName) const
Does a table exist with the given name.
Definition: Tables.cpp:309
virtual void _setAttributeParent(std::shared_ptr< H5::H5Object > obj) override
Definition: Attributes.cpp:24
CanHaveTables()
Trivial constructor used when CanHaveTables is a virtual base class.
Definition: Tables.cpp:245
void readAll(std::vector< size_t > &dims, std::vector< DataType > &data) const
Read all of the data in the associated table.
Definition: Tables.cpp:180
void attachDimensionScale(size_t DimensionNumber, gsl::not_null< const Table *> scale)
Definition: Tables.cpp:29
virtual ~Table()
Definition: Tables.cpp:10
std::string getDimensionScaleName() const
Get the name of this table&#39;s defined dimension scale.
Definition: Tables.cpp:136
Table::Table_Type openTable(const std::string &tableName)
Definition: Tables.cpp:321
bool valid() const
Checks that the class is well-formed, constructed and activated. CanHaveTables needs post-constructor...
Definition: Tables.cpp:247
void _setTablesParent(std::shared_ptr< H5::Group > obj) override
CanHaveTables needs post-constructor setup. This sets the base HDF5 object that gets manipulated...
Definition: Tables.cpp:343
Dimensions_Type getDimensions() const
Returns a vector containing the dimensions of the table.
Definition: Tables.cpp:21
bool isDimensionScale() const
Is this Table used as a dimension scale?
Definition: Tables.cpp:97
std::shared_ptr< H5::DataSet > _getTableSelf() const override
Gets the fundamental HDF5 DataSet associated with the table. Only used internally.
Definition: Tables.cpp:333
void writeAllInner(const gsl::span< const DataType > &outData) const
Definition: Tables.cpp:221
std::vector< size_t > Dimensions_Type
The dimensions of a Table are expressed as a vector of unsigned integers.
Definition: Table.hpp:33
void readDatasetDimensions(gsl::not_null< H5::DataSet *> dataset, std::vector< size_t > &dims)
Table_impl(std::shared_ptr< H5::DataSet > obj, const std::string &name="")
Definition: Tables.cpp:335
#define INST_READ_TBL_TYPE(x)
Definition: Tables.cpp:238
bool valid() const
Checks that Table is well-formed during runtime. Only used internally.
Definition: Tables.cpp:13
std::shared_ptr< H5::Group > _getTablesParent() const override
Gets the base HDF5 object that is manipulated.
Definition: Tables.cpp:344
void setDimensionScaleAxisLabel(size_t DimensionNumber, const std::string &label)
Set the axis label for the dimension designated by DimensionNumber.
Definition: Tables.cpp:114
std::string getDimensionScaleAxisLabel(size_t DimensionNumber) const
Get the axis label for the dimension designated by DimensionNumber.
Definition: Tables.cpp:122
void pushData(const std::vector< size_t > &dims, gsl::not_null< ObjectType *> obj, const std::vector< DataType > &data)
Definition: Tables.cpp:195
std::shared_ptr< H5::DataSet > obj
Definition: Table_impl.hpp:13
void detachDimensionScale(size_t DimensionNumber, gsl::not_null< const Table *> scale)
Detaches a dimension scale from this table.
Definition: Tables.cpp:39
void _createTable(const std::string &tableName, const std::type_index &type, const std::vector< size_t > &dims, const std::vector< size_t > &chunks)
Internal function to create a table. Does not write data.
Definition: Tables.cpp:250
size_t readDatasetNumDimensions(gsl::not_null< H5::DataSet *> dataset)
std::map< std::string, H5G_obj_t > getGroupMembersTypes(const ICEDB_H5_GETNUMOBJS_OWNER &base)
std::set< std::string > getTableNames() const
Lists all table names that are children of this object.
Definition: Tables.cpp:297
#define INST_WRITE_TBL_INNER_TYPE(x)
Definition: Tables.cpp:233
void pullData(std::vector< size_t > &dims, std::vector< DataType > &tdata, gsl::not_null< ObjectType *> obj)
Definition: Tables.cpp:168
virtual std::shared_ptr< H5::DataSet > _getTableSelf() const =0
Gets the fundamental HDF5 DataSet associated with the table. Only used internally.
std::type_index getTableTypeId() const
Get the type of the table (i.e. int64_t, float, etc.)
Definition: Tables.cpp:149