HDF5 back end
Table of Contents
1 HDF5 back end
1.1 Template for HDF5 definitions
#define $GROUP$_GROUP_NAME "$group$" #define $GROUP_NUM$_NAME "$group_num$" #define $GROUP$_$GROUP_DSET$_NAME "$group_dset$"
1.2 Template for HDF5 structures
typedef struct trexio_hdf5_s { trexio_t parent ; hid_t file_id; hid_t $group$_group; const char* file_name; } trexio_hdf5_t;
1.3 Template for HDF5 init/deinit
trexio_exit_code trexio_hdf5_init (trexio_t* const file) { trexio_hdf5_t* const f = (trexio_hdf5_t*) file; /* If file doesn't exist, create it */ int f_exists = 0; struct stat st; if (stat(file->file_name, &st) == 0) f_exists = 1; if (f_exists == 1) { switch (file->mode) { case 'r': // reading the existing file -> open as RDONLY f->file_id = H5Fopen(file->file_name, H5F_ACC_RDONLY, H5P_DEFAULT); break; case 'a': // appending the existing file -> open as RDWR f->file_id = H5Fopen(file->file_name, H5F_ACC_RDWR, H5P_DEFAULT); break; case 'w': // writing the existing file -> overwrite it (_TRUNC) [_EXCL | H5F_ACC_DEBUG as an alternative] f->file_id = H5Fcreate(file->file_name, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); break; } } else { switch (file->mode) { case 'r': case 'a': // reading or appending non-existing file -> error return TREXIO_FAILURE; case 'w': // writing non-existing file -> create it f->file_id = H5Fcreate(file->file_name, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); break; } } /* Create or open groups in the hdf5 file assuming that they exist if file exists */ switch (file->mode) { // the switch for 'r'/'a' is reached only if file exists case 'r': case 'a': f->$group$_group = H5Gopen(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT); break; case 'w': f->$group$_group = H5Gcreate(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); break; } if (f->$group$_group <= 0L) return TREXIO_INVALID_ID; return TREXIO_SUCCESS; } trexio_exit_code trexio_hdf5_deinit (trexio_t* const file) { trexio_hdf5_t* f = (trexio_hdf5_t*) file; H5Gclose(f->$group$_group); f->$group$_group = 0; H5Fclose(f->file_id); f->file_id = 0; return TREXIO_SUCCESS; }
1.4 Template for HDF5 has/read/write a number
trexio_exit_code trexio_hdf5_read_$group_num$ (trexio_t* const file, uint64_t* const num) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (num == NULL) return TREXIO_INVALID_ARG_2; const trexio_hdf5_t* f = (const trexio_hdf5_t*) file; /* Quit if the dimensioning attribute is missing in the file */ if (H5Aexists(f->$group$_group, $GROUP_NUM$_NAME) == 0) return TREXIO_FAILURE; /* Read the nucleus_num attribute of nucleus group */ const hid_t num_id = H5Aopen(f->$group$_group, $GROUP_NUM$_NAME, H5P_DEFAULT); if (num_id <= 0) return TREXIO_INVALID_ID; const herr_t status = H5Aread(num_id, H5T_NATIVE_UINT64, num); if (status < 0) return TREXIO_FAILURE; return TREXIO_SUCCESS; }
trexio_exit_code trexio_hdf5_write_$group_num$ (trexio_t* const file, const uint64_t num) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (num == 0L ) return TREXIO_INVALID_ARG_2; trexio_hdf5_t* const f = (trexio_hdf5_t*) file; if (H5Aexists(f->$group$_group, $GROUP_NUM$_NAME) == 0) { /* Write the dimensioning variables */ const hid_t dtype = H5Tcopy(H5T_NATIVE_UINT64); const hid_t dspace = H5Screate(H5S_SCALAR); const hid_t num_id = H5Acreate(f->$group$_group, $GROUP_NUM$_NAME, dtype, dspace, H5P_DEFAULT, H5P_DEFAULT); if (num_id <= 0) { H5Sclose(dspace); H5Tclose(dtype); return TREXIO_INVALID_ID; } const herr_t status = H5Awrite(num_id, dtype, &(num)); if (status < 0) { H5Aclose(num_id); H5Sclose(dspace); H5Tclose(dtype); return TREXIO_FAILURE; } H5Sclose(dspace); H5Aclose(num_id); H5Tclose(dtype); return TREXIO_SUCCESS; } else { uint64_t infile_num; trexio_exit_code rc = trexio_hdf5_read_$group_num$(file, &(infile_num)); if (rc != TREXIO_SUCCESS) return rc; if (infile_num != num) { if (infile_num != 0) { return TREXIO_NUM_ALREADY_EXISTS; } else { const hid_t dtype = H5Tcopy(H5T_NATIVE_UINT64); const hid_t num_id = H5Aopen(f->$group$_group, $GROUP_NUM$_NAME, H5P_DEFAULT); if (num_id <= 0) return TREXIO_INVALID_ID; const herr_t status = H5Awrite(num_id, dtype, &(num)); if (status < 0) return TREXIO_FAILURE; H5Aclose(num_id); H5Tclose(dtype); } } return TREXIO_SUCCESS; } }
trexio_exit_code trexio_hdf5_has_$group_num$ (trexio_t* const file) { if (file == NULL) return TREXIO_INVALID_ARG_1; const trexio_hdf5_t* f = (const trexio_hdf5_t*) file; htri_t status = H5Aexists(f->$group$_group, $GROUP_NUM$_NAME); /* H5Aexists returns positive value if attribute exists, 0 if does not, negative if error */ if (status > 0){ return TREXIO_SUCCESS; } else if (status == 0) { return TREXIO_HAS_NOT; } else { return TREXIO_FAILURE; } }
1.5 Template for HDF5 has/read/write a dataset
trexio_exit_code trexio_hdf5_read_$group$_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $group_dset$, const uint32_t rank, const uint64_t* dims) { if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; const trexio_hdf5_t* f = (const trexio_hdf5_t*) file; herr_t status; int rrank; // get the rank of the dataset in a file status = H5LTget_dataset_ndims (f->$group$_group, $GROUP$_$GROUP_DSET$_NAME, &rrank); if (status < 0) return TREXIO_FAILURE; if (rrank != (int) rank) return TREXIO_INVALID_ARG_3; // open the dataset to get its dimensions hid_t dset_id = H5Dopen(f->$group$_group, $GROUP$_$GROUP_DSET$_NAME, H5P_DEFAULT); if (dset_id <= 0) return TREXIO_INVALID_ID; // allocate space for the dimensions to be read hsize_t* ddims = CALLOC( (int) rank, hsize_t); if (ddims == NULL) return TREXIO_FAILURE; // read dimensions from the existing dataset status = H5LDget_dset_dims(dset_id, ddims); H5Dclose(dset_id); if (status < 0) { free(ddims); return TREXIO_FAILURE; } for (uint32_t i=0; i<rank; ++i){ if (ddims[i] != dims[i]) { free(ddims); return TREXIO_INVALID_ARG_4; } } free(ddims); /* High-level H5LT API. No need to deal with dataspaces and datatypes */ status = H5LTread_dataset(f->$group$_group, $GROUP$_$GROUP_DSET$_NAME, H5T_NATIVE_$GROUP_DSET_H5_DTYPE$, $group_dset$); if (status < 0) return TREXIO_FAILURE; return TREXIO_SUCCESS; }
trexio_exit_code trexio_hdf5_write_$group$_$group_dset$ (trexio_t* const file, const $group_dset_dtype$* $group_dset$, const uint32_t rank, const uint64_t* dims) { if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; trexio_exit_code rc; uint64_t $group_dset_dim$; // error handling for rc is added by the generator rc = trexio_hdf5_read_$group_dset_dim$(file, &($group_dset_dim$)); if ($group_dset_dim$ == 0L) return TREXIO_INVALID_NUM; trexio_hdf5_t* f = (trexio_hdf5_t*) file; if ( H5LTfind_dataset(f->$group$_group, $GROUP$_$GROUP_DSET$_NAME) != 1 ) { const herr_t status = H5LTmake_dataset(f->$group$_group, $GROUP$_$GROUP_DSET$_NAME, (int) rank, (const hsize_t*) dims, H5T_NATIVE_$GROUP_DSET_H5_DTYPE$, $group_dset$); if (status < 0) return TREXIO_FAILURE; } else { hid_t dset_id = H5Dopen(f->$group$_group, $GROUP$_$GROUP_DSET$_NAME, H5P_DEFAULT); if (dset_id <= 0) return TREXIO_INVALID_ID; const herr_t status = H5Dwrite(dset_id, H5T_NATIVE_$GROUP_DSET_H5_DTYPE$, H5S_ALL, H5S_ALL, H5P_DEFAULT, $group_dset$); H5Dclose(dset_id); if (status < 0) return TREXIO_FAILURE; } return TREXIO_SUCCESS; }
trexio_exit_code trexio_hdf5_has_$group$_$group_dset$ (trexio_t* const file) { if (file == NULL) return TREXIO_INVALID_ARG_1; trexio_hdf5_t* f = (trexio_hdf5_t*) file; herr_t status = H5LTfind_dataset(f->$group$_group, $GROUP$_$GROUP_DSET$_NAME); /* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */ if (status == 1){ return TREXIO_SUCCESS; } else if (status == 0) { return TREXIO_HAS_NOT; } else { return TREXIO_FAILURE; } }