1
0
mirror of https://github.com/TREX-CoE/trexio.git synced 2024-10-02 14:31:05 +02:00

Merge pull request #79 from TREX-CoE/add-unsafe-open-mode

Add unsafe open mode
This commit is contained in:
Anthony Scemama 2022-01-25 16:18:23 +01:00 committed by GitHub
commit bc92e139da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 877 additions and 150 deletions

View File

@ -94,6 +94,7 @@ TESTS_C = \
tests/io_safe_dset_float_text \
tests/io_str_text \
tests/io_dset_str_text \
tests/delete_group_text \
tests/overwrite_all_text \
tests/io_all
@ -107,6 +108,7 @@ TESTS_C += \
tests/io_safe_dset_float_hdf5 \
tests/io_str_hdf5 \
tests/io_dset_str_hdf5 \
tests/delete_group_hdf5 \
tests/overwrite_all_hdf5
endif

View File

@ -150,6 +150,41 @@ trexio.write_nucleus_label(test_file,labels)
del test_file
#==========================================================#
#========== DELETE THE GROUP FROM THE TEST FILE ===========#
#==========================================================#
unsafe_file = trexio.File(output_filename, 'u', TEST_TREXIO_BACKEND)
# overwrite existing data (only allowed in 'u' - unsafe mode)
trexio.write_nucleus_num(unsafe_file, nucleus_num)
trexio.write_nucleus_charge(unsafe_file, charges_np)
trexio.write_nucleus_coord(unsafe_file, coords)
trexio.write_nucleus_label(unsafe_file,labels)
trexio.write_nucleus_point_group(unsafe_file, point_group)
print("Overwriting the data in UNSAFE mode: checked")
# delete existing group (only allowed in 'u' - unsafe mode)
trexio.delete_nucleus(unsafe_file)
assert not trexio.has_nucleus_num(unsafe_file)
assert not trexio.has_nucleus_charge(unsafe_file)
assert not trexio.has_nucleus_coord(unsafe_file)
assert not trexio.has_nucleus_label(unsafe_file)
assert not trexio.has_nucleus_point_group(unsafe_file)
print("Deleting nucleus group in UNSAFE mode: checked")
# restore the deleted data
trexio.write_nucleus_num(unsafe_file, nucleus_num)
trexio.write_nucleus_charge(unsafe_file, charges_np)
trexio.write_nucleus_coord(unsafe_file, coords)
trexio.write_nucleus_label(unsafe_file,labels)
trexio.write_nucleus_point_group(unsafe_file, point_group)
del unsafe_file
#==========================================================#
#============ READ THE DATA FROM THE TEST FILE ============#
#==========================================================#
@ -159,12 +194,12 @@ test_file2 = trexio.File(output_filename, 'r', TEST_TREXIO_BACKEND)
assert test_file2.exists
# check for existence of some of the previously written variables
assert trexio.has_nucleus_num
assert trexio.has_nucleus_charge
assert trexio.has_nucleus_coord
assert trexio.has_nucleus_label
assert trexio.has_nucleus_point_group
assert trexio.has_mo_2e_int_eri
assert trexio.has_nucleus_num(test_file2)
assert trexio.has_nucleus_charge(test_file2)
assert trexio.has_nucleus_coord(test_file2)
assert trexio.has_nucleus_label(test_file2)
assert trexio.has_nucleus_point_group(test_file2)
assert trexio.has_mo_2e_int_eri(test_file2)
# read nucleus_num from file
rnum = trexio.read_nucleus_num(test_file2)

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;
}
@ -893,6 +903,7 @@ trexio_open(const char* file_name, const char mode,
break;
#else
if (rc_open != NULL) *rc_open = TREXIO_BACK_END_MISSING;
free(result);
return NULL;
#endif
/*
@ -925,6 +936,7 @@ trexio_open(const char* file_name, const char mode,
break;
#else
if (rc_open != NULL) *rc_open = TREXIO_BACK_END_MISSING;
free(result);
return NULL;
#endif
/*
@ -961,6 +973,7 @@ trexio_open(const char* file_name, const char mode,
break;
#else
if (rc_open != NULL) *rc_open = TREXIO_BACK_END_MISSING;
free(result);
return NULL;
#endif
@ -968,11 +981,51 @@ trexio_open(const char* file_name, const char mode,
}
if (rc != TREXIO_SUCCESS) {
if (rc_open != NULL) *rc_open = TREXIO_OPEN_ERROR;
if (rc_open != NULL) *rc_open = rc;
free(result);
return NULL;
}
/* Mark the file as unsafe upon opening in UNSAFE 'u' mode */
if (mode == 'u') {
rc = trexio_has_metadata_unsafe(result);
if (rc == TREXIO_FAILURE) {
if (rc_open != NULL) *rc_open = TREXIO_OPEN_ERROR;
free(result);
return NULL;
}
if (rc == TREXIO_HAS_NOT) {
int64_t unsafe_val = 1;
switch (back_end) {
case TREXIO_TEXT:
rc = trexio_text_write_metadata_unsafe(result, unsafe_val);
break;
case TREXIO_HDF5:
#ifdef HAVE_HDF5
rc = trexio_hdf5_write_metadata_unsafe(result, unsafe_val);
break;
#else
if (rc_open != NULL) *rc_open = TREXIO_BACK_END_MISSING;
free(result);
return NULL;
#endif
}
}
if (rc != TREXIO_SUCCESS) {
if (rc_open != NULL) *rc_open = rc;
free(result);
return NULL;
}
}
/* Exit upon success */
if (rc_open != NULL) *rc_open = TREXIO_SUCCESS;
@ -1429,7 +1482,7 @@ trexio_write_$group_num$_64 (trexio_t* const file, const $group_num_dtype_double
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
//if (num <= 0L) return TREXIO_INVALID_NUM; /* this line is uncommented by the generator for dimensioning variables; do NOT remove! */
if (trexio_has_$group_num$(file) == TREXIO_SUCCESS) return TREXIO_ATTR_ALREADY_EXISTS;
if (trexio_has_$group_num$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_ATTR_ALREADY_EXISTS;
switch (file->back_end) {
@ -1500,7 +1553,7 @@ trexio_write_$group_num$_32 (trexio_t* const file, const $group_num_dtype_single
if (file == NULL) return TREXIO_INVALID_ARG_1;
//if (num <= 0) return TREXIO_INVALID_NUM; /* this line is uncommented by the generator for dimensioning variables; do NOT remove! */
if (trexio_has_$group_num$(file) == TREXIO_SUCCESS) return TREXIO_ATTR_ALREADY_EXISTS;
if (trexio_has_$group_num$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_ATTR_ALREADY_EXISTS;
switch (file->back_end) {
@ -1848,7 +1901,7 @@ trexio_write_$group_dset$_64 (trexio_t* const file, const $group_dset_dtype_doub
assert(file->back_end < TREXIO_INVALID_BACK_END);
if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_DSET_ALREADY_EXISTS;
trexio_exit_code rc;
@ -2019,7 +2072,7 @@ trexio_write_$group_dset$_32 (trexio_t* const file, const $group_dset_dtype_sing
if (file == NULL) return TREXIO_INVALID_ARG_1;
if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_DSET_ALREADY_EXISTS;
trexio_exit_code rc;
int64_t $group_dset_dim$ = 0;
@ -2131,7 +2184,7 @@ trexio_write_safe_$group_dset$_32 (trexio_t* const file, const $group_dset_dtype
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset_in == NULL) return TREXIO_INVALID_ARG_2;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_DSET_ALREADY_EXISTS;
<<dimCheck>>
@ -2166,7 +2219,7 @@ trexio_write_safe_$group_dset$_64 (trexio_t* const file, const $group_dset_dtype
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset_in == NULL) return TREXIO_INVALID_ARG_2;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_DSET_ALREADY_EXISTS;
<<dimCheck>>
@ -3293,7 +3346,7 @@ trexio_write_$group_dset$_low (trexio_t* const file, char* dset_in, const int32_
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset_in == NULL) return TREXIO_INVALID_ARG_2;
if (max_str_len <= 0) return TREXIO_INVALID_ARG_3;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_DSET_ALREADY_EXISTS;
trexio_exit_code rc;
int64_t $group_dset_dim$ = 0;
@ -3377,7 +3430,7 @@ trexio_write_$group_dset$ (trexio_t* const file, const char** dset_in, const int
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset_in == NULL) return TREXIO_INVALID_ARG_2;
if (max_str_len <= 0) return TREXIO_INVALID_ARG_3;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_DSET_ALREADY_EXISTS;
assert(file->back_end < TREXIO_INVALID_BACK_END);
@ -3699,7 +3752,7 @@ trexio_write_$group_str$ (trexio_t* const file, const char* str, const int32_t m
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (str == NULL) return TREXIO_INVALID_ARG_2;
if (max_str_len <= 0) return TREXIO_INVALID_ARG_3;
if (trexio_has_$group_str$(file) == TREXIO_SUCCESS) return TREXIO_ATTR_ALREADY_EXISTS;
if (trexio_has_$group_str$(file) == TREXIO_SUCCESS && file->mode != 'u') return TREXIO_ATTR_ALREADY_EXISTS;
size_t len_write = strlen(str);
if ((size_t) max_str_len < len_write) return TREXIO_INVALID_STR_LEN;
@ -3909,6 +3962,87 @@ 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
* General helper functions
This section contains general helper functions like ~trexio_info~.
@ -3921,10 +4055,17 @@ def has_$group_str$(trexio_file) -> bool:
3) ~HDF5_VERSION~ [string] (optional, only if ~HAVE_HDF5~ is ~true~)
4) ~TREXIO_GIT_HASH~ [string]
~trexio_mark_safety~ checks if the file has been open in UNSAFE mode.
If it was, the ~metadata_unsafe~ attribute can be overwritten with the value provided in a second argument of the function.
Since ~metadata_unsafe~ is set to ~1~ (~true~) upon the first opening of the file in UNSAFE mode, this value is immutable.
However, if the user validated that the file is correct (e.g. using ~trexio-tools~),
then value of the ~metadata_unsafe~ attribute can be changed using the aforementioned function.
** C
#+begin_src c :tangle prefix_front.h :exports none
trexio_exit_code trexio_info(void);
trexio_exit_code trexio_mark_safety(trexio_t* const file, const int32_t safety_flag);
#+end_src
#+begin_src c :tangle prefix_front.c
@ -3951,6 +4092,21 @@ def has_$group_str$(trexio_file) -> bool:
}
#+end_src
#+begin_src c :tangle prefix_front.c
trexio_exit_code
trexio_mark_safety (trexio_t* const file, const int32_t safety_flag)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
/* 1 for true ; 0 for false */
if (safety_flag != 0 && safety_flag != 1) return TREXIO_INVALID_ARG_2;
/* Cannot mark the file in safe mode */
if (file->mode != 'u') return TREXIO_FAILURE;
return trexio_write_metadata_unsafe(file, safety_flag);
}
#+end_src
** Fortran
#+begin_src f90 :tangle prefix_fortran.f90

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);
@ -216,29 +218,38 @@ trexio_hdf5_write_$group_num$ (trexio_t* const file, const $group_num_dtype_doub
trexio_hdf5_t* const f = (trexio_hdf5_t*) file;
/* Write the dimensioning variables */
const hid_t dtype = H5Tcopy(H5T_$GROUP_NUM_H5_DTYPE$);
const hid_t dspace = H5Screate(H5S_SCALAR);
/* Delete the attribute if it exists and if the file is open in UNSAFE mode */
if (trexio_hdf5_has_$group_num$(file) == TREXIO_SUCCESS && file->mode == 'u') {
herr_t status_del = H5Adelete(f->$group$_group, $GROUP_NUM$_NAME);
if (status_del < 0) return TREXIO_FAILURE;
}
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);
/* Setup the dataspace */
const hid_t dtype_id = H5Tcopy(H5T_$GROUP_NUM_H5_DTYPE$);
if (dtype_id <= 0) return TREXIO_INVALID_ID;
const hid_t dspace_id = H5Screate(H5S_SCALAR);
if (dspace_id <= 0) {
H5Tclose(dtype_id);
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;
const hid_t num_id = H5Acreate(f->$group$_group,
$GROUP_NUM$_NAME,
dtype_id, dspace_id,
H5P_DEFAULT, H5P_DEFAULT);
if (num_id <= 0) {
H5Sclose(dspace_id);
H5Tclose(dtype_id);
return TREXIO_INVALID_ID;
}
H5Sclose(dspace);
const herr_t status = H5Awrite(num_id, dtype_id, &num);
H5Sclose(dspace_id);
H5Aclose(num_id);
H5Tclose(dtype);
H5Tclose(dtype_id);
if (status < 0) return TREXIO_FAILURE;
return TREXIO_SUCCESS;
}
@ -266,7 +277,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);
@ -338,30 +349,41 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$*
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_$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_$GROUP_DSET_H5_DTYPE$,
H5S_ALL, H5S_ALL, H5P_DEFAULT,
$group_dset$);
H5Dclose(dset_id);
if (status < 0) return TREXIO_FAILURE;
/*
Try to delete an existing dataset by unlinking it from the group (UNSAFE mode).
NOTE: In principle, HDF5 should see the deallocated (unused) file space and free it,
thus reducing the size of the HDF5 file. In practic, this is not always the case.
Consider using HDF5-native h5repack utility after deleting/overwriting big datasets.
,*/
if (H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME) == 1 && file->mode == 'u') {
herr_t status_del = H5Ldelete(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (status_del < 0) return TREXIO_FAILURE;
}
hid_t dspace_id = H5Screate_simple( (int) rank, (const hsize_t*) dims, NULL);
if (dspace_id <= 0) return TREXIO_INVALID_ID;
hid_t dset_id = H5Dcreate (f->$group$_group,
$GROUP_DSET$_NAME,
H5T_$GROUP_DSET_H5_DTYPE$,
dspace_id,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if (dset_id <= 0) {
H5Sclose(dspace_id);
return TREXIO_INVALID_ID;
}
herr_t status = H5Dwrite(dset_id,
H5T_$GROUP_DSET_H5_DTYPE$,
H5S_ALL,
dspace_id,
H5P_DEFAULT,
$group_dset$);
H5Dclose(dset_id);
H5Sclose(dspace_id);
if (status < 0) return TREXIO_FAILURE;
return TREXIO_SUCCESS;
}
@ -389,7 +411,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 +612,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);
@ -714,6 +736,18 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file, const char** $group_dset$,
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
/*
Try to delete an existing dataset by unlinking it from the group (UNSAFE mode).
NOTE: In principle, HDF5 should see the deallocated (unused) file space and free it,
thus reducing the size of the HDF5 file. In practic, this is not always the case.
Consider using HDF5-provided h5repack utility after deleting/overwriting big datasets.
,*/
if (H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME) == 1 && file->mode == 'u') {
herr_t status_del = H5Ldelete(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (status_del < 0) return TREXIO_FAILURE;
}
herr_t status;
hid_t dset_id;
@ -724,49 +758,30 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file, const char** $group_dset$,
status = H5Tset_size (memtype, H5T_VARIABLE);
if (status < 0) return TREXIO_FAILURE;
if ( H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME) != 1 ) {
hid_t dspace = H5Screate_simple( (int) rank, (const hsize_t*) dims, NULL);
if (dspace <= 0) return TREXIO_INVALID_ID;
/* code to create dataset */
hid_t filetype = H5Tcopy (H5T_FORTRAN_S1);
if (filetype <= 0) return TREXIO_INVALID_ID;
/* code to create dataset */
hid_t filetype = H5Tcopy (H5T_FORTRAN_S1);
if (filetype <= 0) return TREXIO_INVALID_ID;
status = H5Tset_size (filetype, H5T_VARIABLE);
if (status < 0) return TREXIO_FAILURE;
status = H5Tset_size (filetype, H5T_VARIABLE);
if (status < 0) return TREXIO_FAILURE;
hid_t dspace = H5Screate_simple( (int) rank, (const hsize_t*) dims, NULL);
if (dspace <= 0) return TREXIO_INVALID_ID;
dset_id = H5Dcreate (f->$group$_group, $GROUP_DSET$_NAME, filetype, dspace,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
dset_id = H5Dcreate (f->$group$_group, $GROUP_DSET$_NAME, filetype, dspace,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
status = H5Dwrite (dset_id, memtype,
H5S_ALL, H5S_ALL, H5P_DEFAULT,
$group_dset$);
status = H5Dwrite (dset_id, memtype,
H5S_ALL, H5S_ALL, H5P_DEFAULT,
$group_dset$);
H5Dclose (dset_id);
H5Sclose (dspace);
H5Tclose (filetype);
H5Tclose (memtype);
H5Dclose (dset_id);
H5Sclose (dspace);
H5Tclose (filetype);
H5Tclose (memtype);
if (status < 0) return TREXIO_FAILURE;
} else {
dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
/* code to write dataset */
status = H5Dwrite(dset_id, memtype,
H5S_ALL, H5S_ALL, H5P_DEFAULT,
$group_dset$);
H5Dclose(dset_id);
H5Tclose(memtype);
if (status < 0) return TREXIO_FAILURE;
}
if (status < 0) return TREXIO_FAILURE;
return TREXIO_SUCCESS;
@ -795,7 +810,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);
@ -855,8 +870,13 @@ trexio_hdf5_write_$group_str$ (trexio_t* const file, const char* str)
trexio_hdf5_t* const f = (trexio_hdf5_t*) file;
/* Delete the attribute if it exists and if the file is open in UNSAFE mode */
if (trexio_hdf5_has_$group_str$(file) == TREXIO_SUCCESS && file->mode == 'u') {
herr_t status_del = H5Adelete(f->$group$_group, $GROUP_STR$_NAME);
if (status_del < 0) return TREXIO_FAILURE;
}
/* Setup the dataspace */
/* Setup the datatype for variable length string */
const hid_t dtype_id = H5Tcopy(H5T_C_S1);
if (dtype_id <= 0) return TREXIO_INVALID_ID;
@ -869,12 +889,15 @@ trexio_hdf5_write_$group_str$ (trexio_t* const file, const char* str)
status = H5Tset_strpad(dtype_id, H5T_STR_NULLTERM);
if (status < 0) return TREXIO_FAILURE;
/* Setup the dataspace */
const hid_t dspace_id = H5Screate(H5S_SCALAR);
if (dspace_id <= 0) return TREXIO_INVALID_ID;
/* Create the $group_str$ attribute of $group$ group */
const hid_t str_id = H5Acreate(f->$group$_group, $GROUP_STR$_NAME, dtype_id, dspace_id,
H5P_DEFAULT, H5P_DEFAULT);
const hid_t str_id = H5Acreate(f->$group$_group,
$GROUP_STR$_NAME,
dtype_id, dspace_id,
H5P_DEFAULT, H5P_DEFAULT);
if (str_id <= 0) {
H5Sclose(dspace_id);
@ -883,18 +906,14 @@ trexio_hdf5_write_$group_str$ (trexio_t* const file, const char* str)
}
status = H5Awrite(str_id, dtype_id, str);
if (status < 0) {
H5Aclose(str_id);
H5Sclose(dspace_id);
H5Tclose(dtype_id);
return TREXIO_FAILURE;
}
H5Aclose(str_id);
H5Sclose(dspace_id);
H5Tclose(dtype_id);
return TREXIO_SUCCESS;
if (status < 0) return TREXIO_FAILURE;
return TREXIO_SUCCESS;
}
#+end_src
@ -919,7 +938,44 @@ 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, some space might remain occupied even after deleting the associated object in recent version.
To take the best use of the deleted file space, we recommend to write the deleted group within the same session
(i.e. before closing the TREXIO file).
In principle, one can use HDF5-provided ~h5repack~ binary, which copies all existing objects from one file into another.
Thus, any corrupted/lost file space will remain in the first file. The use of ~h5repack~ is highly encouraged.
#+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);
f->$group$_group = 0;
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,12 +574,11 @@ 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;
assert (file->parent.mode == 'w');
assert (file->parent.mode == 'w' || file->parent.mode == 'u');
FILE* f = fopen($group$->file_name, "w");
if (f == NULL) return TREXIO_INVALID_ARG_1;
@ -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

View File

@ -11,6 +11,7 @@ set(Tests_text
io_dset_int_text
io_num_text
io_str_text
delete_group_text
overwrite_all_text
)
@ -25,6 +26,7 @@ if(ENABLE_HDF5)
io_dset_int_hdf5
io_num_hdf5
io_str_hdf5
delete_group_hdf5
overwrite_all_hdf5
)

89
tests/delete_group_hdf5.c Normal file
View File

@ -0,0 +1,89 @@
#include "trexio.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define TEST_BACKEND TREXIO_HDF5
#define TREXIO_FILE "test_del.h5"
#define RM_COMMAND "rm -f -- " TREXIO_FILE
static int test_write_delete_group (const char* file_name, const back_end_t backend) {
/* Try to write a dimensioning attribute (num variable) into the TREXIO file */
trexio_t* file = NULL;
trexio_exit_code rc;
// parameters to be written
int num = 12;
double coord[36] = {
0.00000000 , 1.39250319 , 0.00000000 ,
-1.20594314 , 0.69625160 , 0.00000000 ,
-1.20594314 , -0.69625160 , 0.00000000 ,
0.00000000 , -1.39250319 , 0.00000000 ,
1.20594314 , -0.69625160 , 0.00000000 ,
1.20594314 , 0.69625160 , 0.00000000 ,
-2.14171677 , 1.23652075 , 0.00000000 ,
-2.14171677 , -1.23652075 , 0.00000000 ,
0.00000000 , -2.47304151 , 0.00000000 ,
2.14171677 , -1.23652075 , 0.00000000 ,
2.14171677 , 1.23652075 , 0.00000000 ,
0.00000000 , 2.47304151 , 0.00000000 ,
};
/*================= START OF TEST ==================*/
// open file in 'write' mode
file = trexio_open(file_name, 'w', backend, &rc);
assert (file != NULL);
// write numerical attribute in an empty file
rc = trexio_write_nucleus_num(file, num);
assert (rc == TREXIO_SUCCESS);
// write numerical dataset in a file
rc = trexio_write_nucleus_coord(file, coord);
assert (rc == TREXIO_SUCCESS);
// write numerical attribute ao_cartesian as 0
rc = trexio_write_ao_cartesian(file, 0);
assert (rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
// open file in 'unsafe' mode
file = trexio_open(file_name, 'u', backend, &rc);
assert (file != NULL);
// delete a previously written group
rc = trexio_delete_nucleus(file);
assert (rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
/*================= END OF TEST ==================*/
return 0;
}
int main(void) {
/*============== Test launcher ================*/
int rc;
rc = system(RM_COMMAND);
assert (rc == 0);
test_write_delete_group (TREXIO_FILE, TEST_BACKEND);
rc = system(RM_COMMAND);
assert (rc == 0);
return 0;
}

89
tests/delete_group_text.c Normal file
View File

@ -0,0 +1,89 @@
#include "trexio.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define TEST_BACKEND TREXIO_TEXT
#define TREXIO_FILE "test_del.dir"
#define RM_COMMAND "rm -rf " TREXIO_FILE
static int test_write_delete_group (const char* file_name, const back_end_t backend) {
/* Try to write a dimensioning attribute (num variable) into the TREXIO file */
trexio_t* file = NULL;
trexio_exit_code rc;
// parameters to be written
int num = 12;
double coord[36] = {
0.00000000 , 1.39250319 , 0.00000000 ,
-1.20594314 , 0.69625160 , 0.00000000 ,
-1.20594314 , -0.69625160 , 0.00000000 ,
0.00000000 , -1.39250319 , 0.00000000 ,
1.20594314 , -0.69625160 , 0.00000000 ,
1.20594314 , 0.69625160 , 0.00000000 ,
-2.14171677 , 1.23652075 , 0.00000000 ,
-2.14171677 , -1.23652075 , 0.00000000 ,
0.00000000 , -2.47304151 , 0.00000000 ,
2.14171677 , -1.23652075 , 0.00000000 ,
2.14171677 , 1.23652075 , 0.00000000 ,
0.00000000 , 2.47304151 , 0.00000000 ,
};
/*================= START OF TEST ==================*/
// open file in 'write' mode
file = trexio_open(file_name, 'w', backend, &rc);
assert (file != NULL);
// write numerical attribute in an empty file
rc = trexio_write_nucleus_num(file, num);
assert (rc == TREXIO_SUCCESS);
// write numerical dataset in a file
rc = trexio_write_nucleus_coord(file, coord);
assert (rc == TREXIO_SUCCESS);
// write numerical attribute ao_cartesian as 0
rc = trexio_write_ao_cartesian(file, 0);
assert (rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
// open file in 'unsafe' mode
file = trexio_open(file_name, 'u', backend, &rc);
assert (file != NULL);
// delete a previously written group
rc = trexio_delete_nucleus(file);
assert (rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
/*================= END OF TEST ==================*/
return 0;
}
int main(void) {
/*============== Test launcher ================*/
int rc;
rc = system(RM_COMMAND);
assert (rc == 0);
test_write_delete_group (TREXIO_FILE, TEST_BACKEND);
rc = system(RM_COMMAND);
assert (rc == 0);
return 0;
}

View File

@ -2,10 +2,11 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEST_BACKEND TREXIO_HDF5
#define TREXIO_FILE "test_over.h5"
#define RM_COMMAND "rm -rf " TREXIO_FILE
#define RM_COMMAND "rm -f -- " TREXIO_FILE
static int test_write (const char* file_name, const back_end_t backend) {
@ -56,13 +57,13 @@ static int test_write (const char* file_name, const back_end_t backend) {
rc = trexio_write_nucleus_coord(file, coord);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_point_group(file, sym, 4);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_label(file, labels, 2);
assert (rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
@ -73,9 +74,61 @@ static int test_write (const char* file_name, const back_end_t backend) {
}
static int test_overwrite (const char* file_name, const back_end_t backend) {
static int test_overwrite_unsafe (const char* file_name, const back_end_t backend) {
/* Try to overwrite the data that already exists in the TREXIO file */
/* Try to overwrite the data that already exists in the TREXIO file which is open in UNSAFE mode*/
trexio_t* file = NULL;
trexio_exit_code rc;
// parameters to be written
int num = 5;
double coord[15] = {
0.00000000 , 666.666 , 0.00000000 ,
-1.20594314 , 0.69625160 , 0.00000000 ,
-1.20594314 , -0.69625160 , 0.00000000 ,
0.00000000 , -1.39250319 , 0.00000000 ,
1.20594314 , -0.69625160 , 0.00000000
};
const char* sym = "Unknown";
const char* labels[] = {"Ru" ,
"U" ,
"Cl" ,
"Na" ,
"H" };
/*================= START OF TEST ==================*/
// open file in 'write' mode
file = trexio_open(file_name, 'u', backend, &rc);
assert (file != NULL);
// check that the previously written data cannot be overwritten
rc = trexio_write_nucleus_num(file, num);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_coord(file, coord);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_point_group(file, sym, 16);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_label(file, labels, 4);
assert (rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
/*================= END OF TEST ==================*/
return 0;
}
static int test_overwrite_safe (const char* file_name, const back_end_t backend) {
/* Try to overwrite the data that already exists in the TREXIO file which is open in SAFE mode*/
trexio_t* file = NULL;
trexio_exit_code rc;
@ -104,10 +157,10 @@ static int test_overwrite (const char* file_name, const back_end_t backend) {
rc = trexio_write_nucleus_coord(file, coord);
assert (rc == TREXIO_DSET_ALREADY_EXISTS);
rc = trexio_write_nucleus_point_group(file, sym, 16);
assert (rc == TREXIO_ATTR_ALREADY_EXISTS);
rc = trexio_write_nucleus_label(file, labels, 4);
assert (rc == TREXIO_DSET_ALREADY_EXISTS);
@ -121,6 +174,78 @@ static int test_overwrite (const char* file_name, const back_end_t backend) {
}
int test_read(const char* file_name, const back_end_t backend) {
/*========= Test read ===========*/
trexio_t* file = NULL;
trexio_exit_code rc;
int num;
double* coord;
char** label;
char* point_group;
/*================= START OF TEST ==================*/
// open existing file on 'read' mode
file = trexio_open(file_name, 'r', backend, &rc);
assert (file != NULL);
// read nucleus_num
rc = trexio_read_nucleus_num(file,&num);
assert (rc == TREXIO_SUCCESS);
assert (num == 5);
// read nucleus_coord
coord = (double*) calloc(3*num, sizeof(double));
rc = trexio_read_nucleus_coord(file,coord);
assert (rc == TREXIO_SUCCESS);
double x = coord[1] - 666.666;
assert( x*x < 1.e-14);
free(coord);
// read nucleus_label
label = (char**) malloc(num*sizeof(char*));
for (int i=0; i<num; i++){
label[i] = (char*) malloc(32*sizeof(char));
}
rc = trexio_read_nucleus_label(file, label, 2);
assert (rc == TREXIO_SUCCESS);
assert (strcmp(label[0], "Ru") == 0);
assert (strcmp(label[3], "Na") == 0);
for (int i=0; i<num; i++){
free(label[i]);
}
free(label);
point_group = (char*) malloc(32*sizeof(char));
rc = trexio_read_nucleus_point_group(file, point_group, 10);
assert (rc == TREXIO_SUCCESS);
char * pch;
pch = strtok(point_group, " ");
assert (strcmp(pch, "Unknown") == 0);
/* alternative test when 3 symbols are read from the file to point_group */
/*rc = trexio_read_nucleus_point_group(file, point_group, 3);
assert (rc == TREXIO_SUCCESS);
assert (strcmp(point_group, "B3U") == 0 );*/
free(point_group);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
/*================= END OF TEST =====================*/
return 0;
}
int main(void) {
/*============== Test launcher ================*/
@ -129,13 +254,13 @@ int main(void) {
rc = system(RM_COMMAND);
assert (rc == 0);
test_write (TREXIO_FILE, TEST_BACKEND);
test_overwrite (TREXIO_FILE, TEST_BACKEND);
test_write (TREXIO_FILE, TEST_BACKEND);
test_overwrite_safe (TREXIO_FILE, TEST_BACKEND);
test_overwrite_unsafe (TREXIO_FILE, TEST_BACKEND);
test_read (TREXIO_FILE, TEST_BACKEND);
rc = system(RM_COMMAND);
assert (rc == 0);
return 0;
}

View File

@ -2,6 +2,7 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEST_BACKEND TREXIO_TEXT
#define TREXIO_FILE "test_over.dir"
@ -56,13 +57,13 @@ static int test_write (const char* file_name, const back_end_t backend) {
rc = trexio_write_nucleus_coord(file, coord);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_point_group(file, sym, 4);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_label(file, labels, 2);
assert (rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
@ -73,9 +74,61 @@ static int test_write (const char* file_name, const back_end_t backend) {
}
static int test_overwrite (const char* file_name, const back_end_t backend) {
static int test_overwrite_unsafe (const char* file_name, const back_end_t backend) {
/* Try to overwrite the data that already exists in the TREXIO file */
/* Try to overwrite the data that already exists in the TREXIO file which is open in UNSAFE mode*/
trexio_t* file = NULL;
trexio_exit_code rc;
// parameters to be written
int num = 5;
double coord[15] = {
0.00000000 , 666.666 , 0.00000000 ,
-1.20594314 , 0.69625160 , 0.00000000 ,
-1.20594314 , -0.69625160 , 0.00000000 ,
0.00000000 , -1.39250319 , 0.00000000 ,
1.20594314 , -0.69625160 , 0.00000000
};
const char* sym = "Unknown";
const char* labels[] = {"Ru" ,
"U" ,
"Cl" ,
"Na" ,
"H" };
/*================= START OF TEST ==================*/
// open file in 'write' mode
file = trexio_open(file_name, 'u', backend, &rc);
assert (file != NULL);
// check that the previously written data cannot be overwritten
rc = trexio_write_nucleus_num(file, num);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_coord(file, coord);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_point_group(file, sym, 16);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_label(file, labels, 4);
assert (rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
/*================= END OF TEST ==================*/
return 0;
}
static int test_overwrite_safe (const char* file_name, const back_end_t backend) {
/* Try to overwrite the data that already exists in the TREXIO file which is open in SAFE mode*/
trexio_t* file = NULL;
trexio_exit_code rc;
@ -104,10 +157,10 @@ static int test_overwrite (const char* file_name, const back_end_t backend) {
rc = trexio_write_nucleus_coord(file, coord);
assert (rc == TREXIO_DSET_ALREADY_EXISTS);
rc = trexio_write_nucleus_point_group(file, sym, 16);
assert (rc == TREXIO_ATTR_ALREADY_EXISTS);
rc = trexio_write_nucleus_label(file, labels, 4);
assert (rc == TREXIO_DSET_ALREADY_EXISTS);
@ -121,6 +174,78 @@ static int test_overwrite (const char* file_name, const back_end_t backend) {
}
int test_read(const char* file_name, const back_end_t backend) {
/*========= Test read ===========*/
trexio_t* file = NULL;
trexio_exit_code rc;
int num;
double* coord;
char** label;
char* point_group;
/*================= START OF TEST ==================*/
// open existing file on 'read' mode
file = trexio_open(file_name, 'r', backend, &rc);
assert (file != NULL);
// read nucleus_num
rc = trexio_read_nucleus_num(file,&num);
assert (rc == TREXIO_SUCCESS);
assert (num == 5);
// read nucleus_coord
coord = (double*) calloc(3*num, sizeof(double));
rc = trexio_read_nucleus_coord(file,coord);
assert (rc == TREXIO_SUCCESS);
double x = coord[1] - 666.666;
assert( x*x < 1.e-14);
free(coord);
// read nucleus_label
label = (char**) malloc(num*sizeof(char*));
for (int i=0; i<num; i++){
label[i] = (char*) malloc(32*sizeof(char));
}
rc = trexio_read_nucleus_label(file, label, 2);
assert (rc == TREXIO_SUCCESS);
assert (strcmp(label[0], "Ru") == 0);
assert (strcmp(label[3], "Na") == 0);
for (int i=0; i<num; i++){
free(label[i]);
}
free(label);
point_group = (char*) malloc(32*sizeof(char));
rc = trexio_read_nucleus_point_group(file, point_group, 10);
assert (rc == TREXIO_SUCCESS);
char * pch;
pch = strtok(point_group, " ");
assert (strcmp(pch, "Unknown") == 0);
/* alternative test when 3 symbols are read from the file to point_group */
/*rc = trexio_read_nucleus_point_group(file, point_group, 3);
assert (rc == TREXIO_SUCCESS);
assert (strcmp(point_group, "B3U") == 0 );*/
free(point_group);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
/*================= END OF TEST =====================*/
return 0;
}
int main(void) {
/*============== Test launcher ================*/
@ -129,13 +254,13 @@ int main(void) {
rc = system(RM_COMMAND);
assert (rc == 0);
test_write (TREXIO_FILE, TEST_BACKEND);
test_overwrite (TREXIO_FILE, TEST_BACKEND);
test_write (TREXIO_FILE, TEST_BACKEND);
test_overwrite_safe (TREXIO_FILE, TEST_BACKEND);
test_overwrite_unsafe (TREXIO_FILE, TEST_BACKEND);
test_read (TREXIO_FILE, TEST_BACKEND);
rc = system(RM_COMMAND);
assert (rc == 0);
return 0;
}

View File

@ -62,8 +62,13 @@ for fname in files_todo['dset_str']:
for fname in files_todo['dset_sparse']:
recursive_populate_file(fname, template_paths, detailed_dsets_sparse)
# populate group-related functions with mixed (iterative+recursive) scheme [text backend]
# populate group-related functions with mixed scheme
for fname in files_todo['group']:
special_populate_text_group(fname, template_paths, group_dict, detailed_dsets, detailed_nums, detailed_strs)
# recursive scheme for delete_group functions
if 'delete' in fname:
recursive_populate_file(fname, template_paths, group_dict)
# mixed (iterative+recursive) scheme [text backend]
else:
special_populate_text_group(fname, template_paths, group_dict, detailed_dsets, detailed_nums, detailed_strs)
# --------------------------------------------------------------------------- #

View File

@ -37,14 +37,16 @@ def get_files_todo(source_files: dict) -> dict:
all_files += source_files[key]
files_todo = {}
#files_todo['all'] = list(filter(lambda x: 'read' in x or 'write' in x or 'has' in x or 'hrw' in x or 'flush' in x or 'free' in x, all_files))
files_todo['all'] = [f for f in all_files if 'read' in f or 'write' in f or 'has' in f or 'flush' in f or 'free' in f or 'hrw' in f]
files_todo['all'] = [f for f in all_files if 'read' in f or 'write' in f or 'has' in f or 'flush' in f or 'free' in f or 'hrw' in f or 'delete' in f]
for key in ['dset_data', 'dset_str', 'dset_sparse', 'attr_num', 'attr_str', 'group']:
files_todo[key] = list(filter(lambda x: key in x, files_todo['all']))
files_todo['group'].append('struct_text_group_dset.h')
# files that correspond to iterative population (e.g. the code is repeated within the function body but the function itself is unique)
files_todo['auxiliary'] = ['def_hdf5.c', 'basic_hdf5.c', 'basic_text_group.c', 'struct_hdf5.h', 'struct_text_group.h']
files_todo['auxiliary'] = [
'def_hdf5.c', 'basic_hdf5.c', 'struct_hdf5.h',
'basic_text_group.c', 'struct_text_group.h'
]
return files_todo
@ -92,7 +94,7 @@ def recursive_populate_file(fname: str, paths: dict, detailed_source: dict) -> N
Parameters:
filename (str) : template file to be populated
paths (dict) : dictionary of paths per source directory
detailed_source (dict) : dictionary of variables with substitution details (usually either datasets or numbers)
detailed_source (dict) : dictionary of variables with substitution details
Returns:
None
@ -456,7 +458,7 @@ def get_group_dict (configuration: dict) -> dict:
"""
group_dict = {}
for k in configuration.keys():
group_dict[k] = 0
group_dict[k] = {'group' : k}
return group_dict

View File

@ -57,6 +57,12 @@ fetched using multiple function calls to perform I/O on buffers.
| ~author~ | ~str~ | ~(metadata.author_num)~ | Names of the authors of the file |
| ~package_version~ | ~str~ | | TREXIO version used to produce the file |
| ~description~ | ~str~ | | Text describing the content of file |
| ~unsafe~ | ~int~ | | ~1~: true, ~0~: false |
**Note:** ~unsafe~ attribute of the ~metadata~ group indicates whether the file has been previously opened with ~'u'~ mode.
It is automatically written in the file upon the first unsafe opening.
If the user has checked that the TREXIO file is valid (e.g. using ~trexio-tools~) after unsafe operations,
then the ~unsafe~ attribute value can be manually overwritten (in unsafe mode) from ~1~ to ~0~.
#+CALL: json(data=metadata, title="metadata")
#+RESULTS:
@ -69,6 +75,7 @@ fetched using multiple function calls to perform I/O on buffers.
, "author" : [ "str", [ "metadata.author_num" ] ]
, "package_version" : [ "str", [] ]
, "description" : [ "str", [] ]
, "unsafe" : [ "int", [] ]
} ,
#+end_src
:END: