1
0
mirror of https://github.com/TREX-CoE/trexio.git synced 2024-11-03 20:54:07 +01:00

[WIP] add delete_group functions and unsafe trexio_open mode

This commit is contained in:
q-posev 2022-01-24 10:10:16 +01:00
parent ba2e0691ba
commit 6fe5a1eaa7
5 changed files with 178 additions and 19 deletions

View File

@ -190,6 +190,7 @@ __trexio_path__ = None
| ~TREXIO_BACK_END_MISSING~ | 26 | 'Requested back end is disabled' |
| ~TREXIO_INVALID_STR_LEN~ | 30 | 'Invalid max_str_len' |
| ~TREXIO_INT_SIZE_OVERFLOW~ | 31 | 'Possible integer overflow' |
| ~TREXIO_SAFE_MODE~ | 32 | 'Unsafe operation in safe mode' |
# We need to force Emacs not to indent the Python code:
# -*- org-src-preserve-indentation: t
@ -265,6 +266,7 @@ return '\n'.join(result)
#define TREXIO_BACK_END_MISSING ((trexio_exit_code) 26)
#define TREXIO_INVALID_STR_LEN ((trexio_exit_code) 30)
#define TREXIO_INT_SIZE_OVERFLOW ((trexio_exit_code) 31)
#define TREXIO_SAFE_MODE ((trexio_exit_code) 32)
#+end_src
#+begin_src f90 :tangle prefix_fortran.f90 :exports none
@ -298,6 +300,7 @@ return '\n'.join(result)
integer(trexio_exit_code), parameter :: TREXIO_BACK_END_MISSING = 26
integer(trexio_exit_code), parameter :: TREXIO_INVALID_STR_LEN = 30
integer(trexio_exit_code), parameter :: TREXIO_INT_SIZE_OVERFLOW = 31
integer(trexio_exit_code), parameter :: TREXIO_SAFE_MODE = 32
#+end_src
#+begin_src python :tangle prefix_python.py :exports none
@ -332,6 +335,7 @@ return '\n'.join(result)
TREXIO_BACK_END_MISSING = 26
TREXIO_INVALID_STR_LEN = 30
TREXIO_INT_SIZE_OVERFLOW = 31
TREXIO_SAFE_MODE = 32
#+end_src
:END:
@ -464,6 +468,9 @@ return '\n'.join(result)
case TREXIO_INT_SIZE_OVERFLOW:
return "Possible integer overflow";
break;
case TREXIO_SAFE_MODE:
return "Unsafe operation in safe mode";
break;
#+end_example
**** C source code
@ -776,6 +783,7 @@ struct trexio_back_end_s {
2) ~mode~ - character containing open mode (see below)
- ~'w'~ - (write) creates a new file as READWRITE (overwrite existing file)
- ~'r'~ - (read) opens existing file as READONLY
- ~'u'~ - (unsafe) opens existing file as READWRITE with the possibility to overwrite blocks and delete full groups.
3) ~back_end~ - integer number (or the corresponding global parameter) specifying the back end
- ~TREXIO_HDF5~ - for HDF5 back end (integer alternative: 0)
- ~TREXIO_TEXT~ - for TEXT back end (integer alternative: 1)
@ -783,7 +791,7 @@ struct trexio_back_end_s {
output:
~trexio_t~ file handle
Note: the ~file_name~ in TEXT back end actually corresponds to the
**Note:** the ~file_name~ in TEXT back end actually corresponds to the
name of the directory where ~.txt~ data files are stored. The
actual name of each ~.txt~ file corresponds to the group name
provided in ~trex.config~ (e.g. ~nucleus.txt~ for nuclei-related
@ -791,6 +799,8 @@ struct trexio_back_end_s {
are hard-coded), which is why the user should tend to avoid
renaming the ~.txt~ data files.
**Note:** internal consistency is not guaranteed once the file has been modified in ~'u'~ (unsafe) mode.
*** C
#+begin_src c :tangle prefix_front.h :exports none
@ -815,7 +825,7 @@ trexio_open(const char* file_name, const char mode,
return NULL;
}
if (mode != 'r' && mode != 'w') {
if (mode != 'r' && mode != 'w' && mode != 'u') {
if (rc_open != NULL) *rc_open = TREXIO_INVALID_ARG_2;
return NULL;
}
@ -3894,6 +3904,88 @@ def has_$group_str$(trexio_file) -> bool:
return False
#+end_src
** Templates for front end delete an entire group (UNSAFE MODE)
*** Introduction
This section concerns API calls related to string attributes.
| Function name | Description |
|-------------------------+-------------------------------------------|
| ~trexio_delete_$group$~ | Delete a given group from the TREXIO file |
*** C templates for front end
#+begin_src c :tangle delete_group_front.h :exports none
trexio_exit_code trexio_delete_$group$(trexio_t* const file);
#+end_src
#+begin_src c :tangle delete_group_front.c
trexio_exit_code
trexio_delete_$group$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (file->mode != 'u') return TREXIO_SAFE_MODE;
switch (file->back_end) {
case TREXIO_TEXT:
return trexio_text_delete_$group$(file);
case TREXIO_HDF5:
#ifdef HAVE_HDF5
return trexio_hdf5_delete_$group$(file);
#else
return TREXIO_BACK_END_MISSING;
#endif
/*
case TREXIO_JSON:
return trexio_json_delete_$group$(file);
break;
,*/
}
return TREXIO_FAILURE;
}
#+end_src
*** Fortran templates for front end
The ~Fortran~ templates that provide an access to the ~C~ API calls from Fortran.
These templates are based on the use of ~iso_c_binding~. Pointers have to be passed by value.
#+begin_src f90 :tangle delete_group_front_fortran.f90
interface
integer(trexio_exit_code) function trexio_delete_$group$ (trex_file) bind(C)
use, intrinsic :: iso_c_binding
import
integer(trexio_t), intent(in), value :: trex_file
end function trexio_delete_$group$
end interface
#+end_src
*** Python templates for front end
#+begin_src python :tangle delete_group_front.py
def delete_$group$(trexio_file) -> None:
"""Delete the entire $group$ group from the TREXIO file.
Parameters:
trexio_file:
TREXIO File object.
Raises:
- Exception from AssertionError if TREXIO return code ~rc~ is different from TREXIO_SUCCESS and prints the error message using trexio_string_of_error.
- Exception from some other error (e.g. RuntimeError).
"""
rc = pytr.trexio_delete_$group$(trexio_file.pytrexio_s)
if rc != TREXIO_SUCCESS:
raise Error(rc)
#+end_src
* Fortran helper/wrapper functions
The function below adapts the original C-based ~trexio_open~ for Fortran.

View File

@ -10,7 +10,9 @@ cat populated/pop_basic_hdf5.c >> trexio_hdf5.c
cat populated/pop_has_*.c >> trexio_hdf5.c
cat populated/pop_read_*.c >> trexio_hdf5.c
cat populated/pop_write_*.c >> trexio_hdf5.c
cat populated/pop_delete_group_hdf5.c >> trexio_hdf5.c
cat populated/pop_hrw_*.h >> trexio_hdf5.h
cat populated/pop_delete_group_hdf5.h >> trexio_hdf5.h
cat helpers_hdf5.c >> trexio_hdf5.c
cat suffix_hdf5.h >> trexio_hdf5.h

View File

@ -49,8 +49,7 @@
#+end_src
* HDF5 back end
** Template for HDF5 definitions
* Template for HDF5 definitions
#+begin_src c :tangle def_hdf5.c
#define $GROUP$_GROUP_NAME "$group$"
@ -59,7 +58,7 @@
#define $GROUP_STR$_NAME "$group_str$"
#+end_src
** Template for HDF5 structures
* Template for HDF5 structures
#+begin_src c :tangle struct_hdf5.h
typedef struct trexio_hdf5_s {
@ -69,7 +68,7 @@ typedef struct trexio_hdf5_s {
} trexio_hdf5_t;
#+end_src
** Template for HDF5 init/deinit
* Template for HDF5 init/deinit
#+begin_src c :tangle struct_hdf5.h :exports none
trexio_exit_code trexio_hdf5_init(trexio_t* const file);
@ -113,6 +112,7 @@ trexio_hdf5_init (trexio_t* const file)
// reading the existing file -> open as RDONLY
f->file_id = H5Fopen(file->file_name, H5F_ACC_RDONLY, H5P_DEFAULT);
break;
case 'u':
case 'w':
// writing the existing file -> open as RDWRITE
f->file_id = H5Fopen(file->file_name, H5F_ACC_RDWR, H5P_DEFAULT);
@ -125,6 +125,7 @@ trexio_hdf5_init (trexio_t* const file)
case 'r':
// reading non-existing file -> error
return TREXIO_FAILURE;
case 'u':
case 'w':
// writing non-existing file -> create it
f->file_id = H5Fcreate(file->file_name, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
@ -138,6 +139,7 @@ trexio_hdf5_init (trexio_t* const file)
case 'r':
f->$group$_group = H5Gopen(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT);
break;
case 'u':
case 'w':
if (f_exists == 1) {
f->$group$_group = H5Gopen(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT);
@ -170,7 +172,7 @@ trexio_hdf5_deinit (trexio_t* const file)
}
#+end_src
** Template for HDF5 has/read/write the numerical attribute
* Template for HDF5 has/read/write a numerical attribute
#+begin_src c :tangle hrw_attr_num_hdf5.h :exports none
trexio_exit_code trexio_hdf5_has_$group_num$ (trexio_t* const file);
@ -266,7 +268,7 @@ trexio_hdf5_has_$group_num$ (trexio_t* const file)
}
#+end_src
** Template for HDF5 has/read/write the dataset of numerical data
* Template for HDF5 has/read/write a dataset of numerical data
#+begin_src c :tangle hrw_dset_data_hdf5.h :exports none
trexio_exit_code trexio_hdf5_has_$group_dset$(trexio_t* const file);
@ -389,7 +391,7 @@ trexio_hdf5_has_$group_dset$ (trexio_t* const file)
}
#+end_src
** Template for HDF5 has/read/write the dataset of sparse data
* Template for HDF5 has/read/write a dataset of sparse data
Sparse data is stored using extensible datasets of HDF5. Extensibility is required
due to the fact that the sparse data will be written in chunks of user-defined size.
@ -590,7 +592,7 @@ trexio_hdf5_has_$group_dset$ (trexio_t* const file)
}
#+end_src
** Template for HDF5 has/read/write the dataset of strings
* Template for HDF5 has/read/write a dataset of strings
#+begin_src c :tangle hrw_dset_str_hdf5.h :exports none
trexio_exit_code trexio_hdf5_has_$group_dset$(trexio_t* const file);
@ -795,7 +797,7 @@ trexio_hdf5_has_$group_dset$ (trexio_t* const file)
}
#+end_src
** Template for HDF5 has/read/write the string attribute
* Template for HDF5 has/read/write a string attribute
#+begin_src c :tangle hrw_attr_str_hdf5.h :exports none
trexio_exit_code trexio_hdf5_has_$group_str$ (trexio_t* const file);
@ -919,7 +921,38 @@ trexio_hdf5_has_$group_str$ (trexio_t* const file)
}
#+end_src
** Helper functions
* Template for HDF5 delete a group (UNSAFE mode)
**Note:** in early versions of the HDF5 library (v < 1.10) unlinking an object was not working as expected
and the associated memory was not necessarily freed (see [[https://stackoverflow.com/questions/1124994/removing-data-from-a-hdf5-file][this StackOverflow discussion]] for example).
Nevertheless, we highly recommend to reopen the file in SAFE mode (e.g. ~'r'~ or ~'w'~) after deleting the data.
#+begin_src c :tangle delete_group_hdf5.h :exports none
trexio_exit_code trexio_hdf5_delete_$group$ (trexio_t* const file);
#+end_src
#+begin_src c :tangle delete_group_hdf5.c
trexio_exit_code
trexio_hdf5_delete_$group$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
// delete the link to the existing group: this should free the associated space
H5Gclose(f->$group$_group);
herr_t status = H5Ldelete(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT);
if (status < 0) return TREXIO_FAILURE;
// re-create the group (with the new link ?)
f->$group$_group = H5Gcreate(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if (f->$group$_group <= 0L) return TREXIO_INVALID_ID;
return TREXIO_SUCCESS;
}
#+end_src
* Helper functions
#+begin_src c :tangle helpers_hdf5.c
trexio_exit_code

View File

@ -13,9 +13,11 @@ cat basic_text.h >> trexio_text.h
cat populated/pop_free_group_text.c >> trexio_text.c
cat populated/pop_read_group_text.c >> trexio_text.c
cat populated/pop_flush_group_text.c >> trexio_text.c
cat populated/pop_delete_group_text.c >> trexio_text.c
cat populated/pop_free_group_text.h >> trexio_text.h
cat populated/pop_read_group_text.h >> trexio_text.h
cat populated/pop_flush_group_text.h >> trexio_text.h
cat populated/pop_delete_group_text.h >> trexio_text.h
cat populated/pop_has_dset_data_text.c >> trexio_text.c
cat populated/pop_has_dset_str_text.c >> trexio_text.c

View File

@ -265,7 +265,7 @@ trexio_text_deinit (trexio_t* const file)
}
#+end_src
** Template for text read struct
** Template for text read a group
#+begin_src c :tangle read_group_text.h :exports none
$group$_t* trexio_text_read_$group$(trexio_text_t* const file);
@ -558,7 +558,7 @@ trexio_text_read_$group$ (trexio_text_t* const file)
}
#+end_src
** Template for text flush struct
** Template for text flush a group
#+begin_src c :tangle flush_group_text.h :exports none
trexio_exit_code trexio_text_flush_$group$(trexio_text_t* const file);
@ -574,7 +574,6 @@ trexio_text_flush_$group$ (trexio_text_t* const file)
if (file->parent.mode == 'r') return TREXIO_READONLY;
$group$_t* $group$ = file->$group$;
if ($group$ == NULL) return TREXIO_SUCCESS;
if ($group$->to_flush == 0) return TREXIO_SUCCESS;
@ -663,12 +662,14 @@ trexio_text_free_$group$ (trexio_text_t* const file)
// END REPEAT GROUP_ATTR_STR
FREE ($group$);
file->$group$ = NULL;
return TREXIO_SUCCESS;
}
#+end_src
** Template for has/read/write the numerical attribute
** Template for has/read/write a numerical attribute
#+begin_src c :tangle hrw_attr_num_text.h :exports none
trexio_exit_code trexio_text_has_$group_num$ (trexio_t* const file);
@ -732,7 +733,7 @@ trexio_text_has_$group_num$ (trexio_t* const file)
}
#+end_src
** Template for has/read/write the dataset of numerical data
** Template for has/read/write a dataset of numerical data
The ~group_dset~ array is assumed allocated with the appropriate size.
@ -827,7 +828,7 @@ trexio_text_has_$group_dset$ (trexio_t* const file)
}
#+end_src
** Template for has/read/write the dataset of strings
** Template for has/read/write a dataset of strings
The ~group_dset~ array is assumed allocated with the appropriate size.
@ -927,7 +928,7 @@ trexio_text_has_$group_dset$ (trexio_t* const file)
}
#+end_src
** Template for has/read/write the string attribute
** Template for has/read/write a string attribute
#+begin_src c :tangle hrw_attr_str_text.h :exports none
trexio_exit_code trexio_text_has_$group_str$ (trexio_t* const file);
@ -1274,6 +1275,35 @@ trexio_exit_code trexio_text_has_$group_dset$(trexio_t* const file)
}
#+end_src
** Template for text delete a group (UNSAFE mode)
#+begin_src c :tangle delete_group_text.h :exports none
trexio_exit_code trexio_text_delete_$group$ (trexio_t* const file);
#+end_src
#+begin_src c :tangle delete_group_text.c
trexio_exit_code
trexio_text_delete_$group$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_text_t* f = (trexio_text_t*) file;
$group$_t* $group$ = trexio_text_read_$group$(f);
if ($group$ == NULL) return TREXIO_FAILURE;
int rc = remove($group$->file_name);
if (rc == -1) return TREXIO_FAILURE;
$group$->to_flush = 0;
trexio_exit_code rc_free = trexio_text_free_$group$(f);
if (rc_free != TREXIO_SUCCESS) return rc_free;
return TREXIO_SUCCESS;
}
#+end_src
* Constant file suffixes (not used by the generator) :noexport:
#+begin_src c :tangle suffix_text.h