#+TITLE: HDF5 back end #+PROPERTY: comments org #+SETUPFILE: ../../docs/theme.setup # -*- mode: org -*- * Constant file prefixes (not used by the generator) :noexport: #+begin_src emacs-lisp (setq-local org-babel-default-header-args:c '((:comments . "both"))) org-babel-default-header-args:c #+end_src #+RESULTS: : ((:comments . both)) #+NAME:header #+begin_src c /* This file was generated from the org-mode file. To generate it, open templator_hdf5.org file in Emacs and execute M-x org-babel-tangle */ #+end_src #+begin_src c :tangle prefix_hdf5.h :noweb yes <
> #ifndef TREXIO_HDF5_H #define TREXIO_HDF5_H #include "trexio.h" #include "trexio_private.h" #include "trexio_s.h" #include #include #include #include #include #include #include "hdf5.h" #include "hdf5_hl.h" // needed for high-level APIs like H5LT, requires additional linking in Makefile #+end_src #+begin_src c :tangle prefix_hdf5.c :noweb yes <
> #include "trexio_hdf5.h" #+end_src * HDF5 back end ** Template for HDF5 definitions #+begin_src c :tangle def_hdf5.c #define $GROUP$_GROUP_NAME "$group$" #define $GROUP_NUM$_NAME "$group_num$" #define $GROUP_DSET$_NAME "$group_dset$" #+end_src ** Template for HDF5 structures #+begin_src c :tangle struct_hdf5.h typedef struct trexio_hdf5_s { trexio_t parent ; hid_t file_id; hid_t $group$_group; const char* file_name; } trexio_hdf5_t; #+end_src #+begin_src c :tangle struct_hdf5.h :exports none trexio_exit_code trexio_hdf5_init(trexio_t* const file); trexio_exit_code trexio_hdf5_deinit(trexio_t* const file); #+end_src ** Template for HDF5 init/deinit #+begin_src c :tangle basic_hdf5.c 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 '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': // reading 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) { case 'r': 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; } #+end_src ** Template for HDF5 has/read/write a number #+begin_src c :tangle hrw_num_hdf5.h :exports none trexio_exit_code trexio_hdf5_has_$group_num$ (trexio_t* const file); trexio_exit_code trexio_hdf5_read_$group_num$ (trexio_t* const file, uint64_t* const num); trexio_exit_code trexio_hdf5_write_$group_num$(trexio_t* const file, const uint64_t num); #+end_src #+begin_src c :tangle read_num_hdf5.c 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; } #+end_src #+begin_src c :tangle write_num_hdf5.c 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; } } #+end_src #+begin_src c :tangle has_num_hdf5.c 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; } } #+end_src ** Template for HDF5 has/read/write a dataset #+begin_src c :tangle hrw_dset_hdf5.h :exports none trexio_exit_code trexio_hdf5_has_$group_dset$(trexio_t* const file); trexio_exit_code trexio_hdf5_read_$group_dset$(trexio_t* const file, $group_dset_dtype$* const $group_dset$, const uint32_t rank, const uint64_t* dims); trexio_exit_code trexio_hdf5_write_$group_dset$(trexio_t* const file, const $group_dset_dtype$* $group_dset$, const uint32_t rank, const uint64_t* dims); #+end_src #+begin_src c :tangle read_dset_hdf5.c trexio_exit_code trexio_hdf5_read_$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_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_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$group$_group, $GROUP_DSET$_NAME, H5T_NATIVE_$GROUP_DSET_H5_DTYPE$, $group_dset$); if (status < 0) return TREXIO_FAILURE; return TREXIO_SUCCESS; } #+end_src #+begin_src c :tangle write_dset_hdf5.c trexio_exit_code trexio_hdf5_write_$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_DSET$_NAME) != 1 ) { const herr_t status = H5LTmake_dataset(f->$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_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; } #+end_src #+begin_src c :tangle has_dset_hdf5.c trexio_exit_code trexio_hdf5_has_$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_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; } } #+end_src * Constant file suffixes (not used by the generator) :noexport: #+begin_src c :tangle suffix_hdf5.h #endif #+end_src