Skip to content

Commit

Permalink
Use wrappers of HDF5 functions.
Browse files Browse the repository at this point in the history
This commit continues the work to introduce a layer between HDF5 and
HighFive. By wrapping all HDF5 functions we gain control over when we
call into HDF5. We can use this to introduce error checking without
repeating ourselves; or eventually for thread-safety.
  • Loading branch information
1uc committed Nov 23, 2023
1 parent 28e5958 commit 6ffefcd
Show file tree
Hide file tree
Showing 31 changed files with 1,641 additions and 507 deletions.
20 changes: 9 additions & 11 deletions include/highfive/H5DataType.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
#include "bits/string_padding.hpp"
#include "H5PropertyList.hpp"

#include "bits/h5_wrapper.hpp"
#include "bits/h5t_wrapper.hpp"

namespace HighFive {


Expand Down Expand Up @@ -236,21 +239,16 @@ class CompoundType: public DataType {
ss << "hid " << _hid << " does not refer to a compound data type";
throw DataTypeException(ss.str());
}
int result = H5Tget_nmembers(_hid);
if (result < 0) {
throw DataTypeException("Could not get members of compound datatype");
}
size_t n_members = static_cast<size_t>(result);
size_t n_members = static_cast<size_t>(detail::h5t_get_nmembers(_hid));
members.reserve(n_members);
for (unsigned i = 0; i < n_members; i++) {
char* name = H5Tget_member_name(_hid, i);
size_t offset = H5Tget_member_offset(_hid, i);
hid_t member_hid = H5Tget_member_type(_hid, i);
char* name = detail::h5t_get_member_name(_hid, i);
size_t offset = detail::h5t_get_member_offset(_hid, i);
hid_t member_hid = detail::h5t_get_member_type(_hid, i);
DataType member_type{member_hid};
members.emplace_back(std::string(name), member_type, offset);
if (H5free_memory(name) < 0) {
throw DataTypeException("Could not free names from the compound datatype");
}

detail::h5_free_memory(name);
}
}

Expand Down
9 changes: 9 additions & 0 deletions include/highfive/H5Exception.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ class PropertyException: public Exception {
: Exception(err_msg) {}
};

///
/// \brief Exception specific to HighFive Link interface
///
class LinkException: public Exception {
public:
LinkException(const std::string& err_msg)
: Exception(err_msg) {}
};

///
/// \brief Exception specific to HighFive Reference interface
///
Expand Down
12 changes: 7 additions & 5 deletions include/highfive/H5Utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

#pragma once

#include <H5Epublic.h>
#include <functional>
#include <string>
#include <iostream>

#include "bits/h5e_wrapper.hpp"
#include "bits/H5Friends.hpp"

namespace HighFive {
Expand All @@ -25,13 +25,15 @@ class SilenceHDF5 {
public:
inline SilenceHDF5(bool enable = true)
: _client_data(nullptr) {
H5Eget_auto2(H5E_DEFAULT, &_func, &_client_data);
if (enable)
H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
detail::nothrow::h5e_get_auto2(H5E_DEFAULT, &_func, &_client_data);

if (enable) {
detail::nothrow::h5e_set_auto2(H5E_DEFAULT, nullptr, nullptr);
}
}

inline ~SilenceHDF5() {
H5Eset_auto2(H5E_DEFAULT, _func, _client_data);
detail::nothrow::h5e_set_auto2(H5E_DEFAULT, _func, _client_data);
}

private:
Expand Down
60 changes: 20 additions & 40 deletions include/highfive/bits/H5Annotate_traits_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,20 @@

#include "H5Attribute_misc.hpp"
#include "H5Iterables_misc.hpp"
#include "h5a_wrapper.hpp"

namespace HighFive {

template <typename Derivate>
inline Attribute AnnotateTraits<Derivate>::createAttribute(const std::string& attribute_name,
const DataSpace& space,
const DataType& dtype) {
auto attr_id = H5Acreate2(static_cast<Derivate*>(this)->getId(),
attribute_name.c_str(),
dtype.getId(),
space.getId(),
H5P_DEFAULT,
H5P_DEFAULT);
if (attr_id < 0) {
HDF5ErrMapper::ToException<AttributeException>(
std::string("Unable to create the attribute \"") + attribute_name + "\":");
}
auto attr_id = detail::h5a_create2(static_cast<Derivate*>(this)->getId(),
attribute_name.c_str(),
dtype.getId(),
space.getId(),
H5P_DEFAULT,
H5P_DEFAULT);
return detail::make_attribute(attr_id);
}

Expand All @@ -57,30 +54,20 @@ inline Attribute AnnotateTraits<Derivate>::createAttribute(const std::string& at

template <typename Derivate>
inline void AnnotateTraits<Derivate>::deleteAttribute(const std::string& attribute_name) {
if (H5Adelete(static_cast<const Derivate*>(this)->getId(), attribute_name.c_str()) < 0) {
HDF5ErrMapper::ToException<AttributeException>(
std::string("Unable to delete attribute \"") + attribute_name + "\":");
}
detail::h5a_delete(static_cast<const Derivate*>(this)->getId(), attribute_name.c_str());
}

template <typename Derivate>
inline Attribute AnnotateTraits<Derivate>::getAttribute(const std::string& attribute_name) const {
const auto attr_id =
H5Aopen(static_cast<const Derivate*>(this)->getId(), attribute_name.c_str(), H5P_DEFAULT);
if (attr_id < 0) {
HDF5ErrMapper::ToException<AttributeException>(
std::string("Unable to open the attribute \"") + attribute_name + "\":");
}
const auto attr_id = detail::h5a_open(static_cast<const Derivate*>(this)->getId(),
attribute_name.c_str(),
H5P_DEFAULT);
return detail::make_attribute(attr_id);
}

template <typename Derivate>
inline size_t AnnotateTraits<Derivate>::getNumberAttributes() const {
int res = H5Aget_num_attrs(static_cast<const Derivate*>(this)->getId());
if (res < 0) {
HDF5ErrMapper::ToException<AttributeException>(
std::string("Unable to count attributes in existing group or file"));
}
int res = detail::h5a_get_num_attrs(static_cast<const Derivate*>(this)->getId());
return static_cast<size_t>(res);
}

Expand All @@ -92,27 +79,20 @@ inline std::vector<std::string> AnnotateTraits<Derivate>::listAttributeNames() c
size_t num_objs = getNumberAttributes();
names.reserve(num_objs);

if (H5Aiterate2(static_cast<const Derivate*>(this)->getId(),
H5_INDEX_NAME,
H5_ITER_INC,
NULL,
&details::internal_high_five_iterate<H5A_info_t>,
static_cast<void*>(&iterateData)) < 0) {
HDF5ErrMapper::ToException<AttributeException>(
std::string("Unable to list attributes in group"));
}
detail::h5a_iterate2(static_cast<const Derivate*>(this)->getId(),
H5_INDEX_NAME,
H5_ITER_INC,
nullptr,
&details::internal_high_five_iterate<H5A_info_t>,
static_cast<void*>(&iterateData));

// TODO catch and rethrow with a better message.
return names;
}

template <typename Derivate>
inline bool AnnotateTraits<Derivate>::hasAttribute(const std::string& attr_name) const {
int res = H5Aexists(static_cast<const Derivate*>(this)->getId(), attr_name.c_str());
if (res < 0) {
HDF5ErrMapper::ToException<AttributeException>(
std::string("Unable to check for attribute in group"));
}
return res;
return detail::h5a_exists(static_cast<const Derivate*>(this)->getId(), attr_name.c_str());
}

} // namespace HighFive
26 changes: 11 additions & 15 deletions include/highfive/bits/H5Attribute_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,36 @@
#include <sstream>
#include <string>

#include <H5Apublic.h>
#include <H5Ppublic.h>

#include "../H5DataSpace.hpp"
#include "H5Converter_misc.hpp"
#include "H5ReadWrite_misc.hpp"
#include "H5Utils.hpp"
#include "h5a_wrapper.hpp"
#include "h5d_wrapper.hpp"
#include "h5t_wrapper.hpp"

namespace HighFive {

inline std::string Attribute::getName() const {
return details::get_name(
[&](char* buffer, size_t length) { return H5Aget_name(_hid, length, buffer); });
[&](char* buffer, size_t length) { return detail::h5a_get_name(_hid, length, buffer); });
}

inline size_t Attribute::getStorageSize() const {
return static_cast<size_t>(H5Aget_storage_size(_hid));
return static_cast<size_t>(detail::h5a_get_storage_size(_hid));
}

inline DataType Attribute::getDataType() const {
DataType res;
res._hid = H5Aget_type(_hid);
res._hid = detail::h5a_get_type(_hid);
return res;
}

inline DataSpace Attribute::getSpace() const {
DataSpace space;
if ((space._hid = H5Aget_space(_hid)) < 0) {
HDF5ErrMapper::ToException<AttributeException>("Unable to get DataSpace out of Attribute");
}
space._hid = detail::h5a_get_space(_hid);
return space;
}

Expand Down Expand Up @@ -94,10 +94,10 @@ inline void Attribute::read(T& array) const {
if (c == DataTypeClass::VarLen || t.isVariableStr()) {
#if H5_VERSION_GE(1, 12, 0)
// This one have been created in 1.12.0
(void) H5Treclaim(t.getId(), mem_space.getId(), H5P_DEFAULT, r.getPointer());
(void) detail::h5t_reclaim(t.getId(), mem_space.getId(), H5P_DEFAULT, r.getPointer());
#else
// This one is deprecated since 1.12.0
(void) H5Dvlen_reclaim(t.getId(), mem_space.getId(), H5P_DEFAULT, r.getPointer());
(void) detail::h5d_vlen_reclaim(t.getId(), mem_space.getId(), H5P_DEFAULT, r.getPointer());
#endif
}
}
Expand All @@ -107,9 +107,7 @@ inline void Attribute::read(T* array, const DataType& mem_datatype) const {
static_assert(!std::is_const<T>::value,
"read() requires a non-const structure to read data into");

if (H5Aread(getId(), mem_datatype.getId(), static_cast<void*>(array)) < 0) {
HDF5ErrMapper::ToException<AttributeException>("Error during HDF5 Read: ");
}
detail::h5a_read(getId(), mem_datatype.getId(), static_cast<void*>(array));
}

template <typename T>
Expand Down Expand Up @@ -147,9 +145,7 @@ inline void Attribute::write(const T& buffer) {

template <typename T>
inline void Attribute::write_raw(const T* buffer, const DataType& mem_datatype) {
if (H5Awrite(getId(), mem_datatype.getId(), buffer) < 0) {
HDF5ErrMapper::ToException<DataSetException>("Error during HDF5 Write: ");
}
detail::h5a_write(getId(), mem_datatype.getId(), buffer);
}

template <typename T>
Expand Down
21 changes: 6 additions & 15 deletions include/highfive/bits/H5DataSet_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,24 @@
#include <sstream>
#include <string>

#include <H5Dpublic.h>
#include <H5Ppublic.h>

#include "h5d_wrapper.hpp"
#include "H5Utils.hpp"

namespace HighFive {

inline uint64_t DataSet::getStorageSize() const {
return H5Dget_storage_size(_hid);
return detail::h5d_get_storage_size(_hid);
}

inline DataType DataSet::getDataType() const {
return DataType(H5Dget_type(_hid));
return DataType(detail::h5d_get_type(_hid));
}

inline DataSpace DataSet::getSpace() const {
DataSpace space;
if ((space._hid = H5Dget_space(_hid)) < 0) {
HDF5ErrMapper::ToException<DataSetException>("Unable to get DataSpace out of DataSet");
}
space._hid = detail::h5d_get_space(_hid);
return space;
}

Expand All @@ -42,11 +40,7 @@ inline DataSpace DataSet::getMemSpace() const {
}

inline uint64_t DataSet::getOffset() const {
uint64_t addr = H5Dget_offset(_hid);
if (addr == HADDR_UNDEF) {
HDF5ErrMapper::ToException<DataSetException>("Cannot get offset of DataSet.");
}
return addr;
return static_cast<uint64_t>(detail::h5d_get_offset(_hid));
}

inline void DataSet::resize(const std::vector<size_t>& dims) {
Expand All @@ -58,10 +52,7 @@ inline void DataSet::resize(const std::vector<size_t>& dims) {
}

std::vector<hsize_t> real_dims(dims.begin(), dims.end());

if (H5Dset_extent(getId(), real_dims.data()) < 0) {
HDF5ErrMapper::ToException<DataSetException>("Could not resize dataset.");
}
detail::h5d_set_extent(getId(), real_dims.data());
}

} // namespace HighFive

0 comments on commit 6ffefcd

Please sign in to comment.