1
0
mirror of https://github.com/TREX-CoE/trexio.git synced 2024-08-25 06:31:43 +02:00

implement trexio_inquire function in front and back ends

This commit is contained in:
q-posev 2022-01-19 14:06:10 +01:00
parent e4073d0a8c
commit 550c5c3954
3 changed files with 161 additions and 44 deletions

View File

@ -1,5 +1,4 @@
#+TITLE: Front end API
break;
#+PROPERTY: comments org
#+SETUPFILE: ../../docs/theme.setup
# -*- mode: org -*-
@ -696,12 +695,15 @@ class File:
self.back_end = back_end
self.isOpen = False
self.exists = False
if pytrexio_s is None:
self.pytrexio_s = open(filename, mode, back_end)
self.pytrexio_s = _open(filename, mode, back_end)
self.isOpen = True
self.exists = True
else:
self.pytrexio_s = pytrexio_s
self.isOpen = None
self.exists = None
self.info = info
@ -710,17 +712,23 @@ class File:
"""Close a TREXIO File."""
if self.isOpen:
close(self.pytrexio_s)
_close(self.pytrexio_s)
self.isOpen = False
else:
raise Exception("TREXIO File object has not been opened.")
def inquire(self):
"""Inquire whether a TREXIO file exists."""
self.exists = _inquire(self.filename)
def __del__(self):
"""This is a TREXIO File destructor."""
if self.isOpen:
close(self.pytrexio_s)
_close(self.pytrexio_s)
elif self.isOpen is None:
raise Exception("[WIP]: TREXIO file handle provided but what if the file is already closed?")
else:
@ -972,7 +980,7 @@ end interface
*** Python
#+begin_src python :tangle basic_python.py
def open(file_name: str, mode: str, back_end: int):
def _open(file_name: str, mode: str, back_end: int):
"""Create TREXIO file or open existing one.
Parameters:
@ -1149,7 +1157,7 @@ end interface
*** Python
#+begin_src python :tangle basic_python.py
def close(trexio_file):
def _close(trexio_file):
"""Close TREXIO file.
Parameter is a ~trexio_file~ object that has been created by a call to ~open~ function.
@ -1163,6 +1171,77 @@ def close(trexio_file):
raise
#+end_src
** File existence
~trexio_inquire~ check whether TREXIO file exists.
input parameters:
~file_name~ - string containing file name
output:
~trexio_exit_code~ exit code.
*** C
#+begin_src c :tangle prefix_front.h :exports none
trexio_exit_code trexio_inquire(const char* file_name);
#+end_src
#+begin_src c :tangle prefix_front.c
trexio_exit_code
trexio_inquire (const char* file_name)
{
if (file_name == NULL || file_name[0] == '\0') return TREXIO_INVALID_ARG_1;
/* First check if the TREXIO file exists and if it is a directory */
trexio_exit_code rc_text = trexio_text_inquire(file_name);
#ifdef HAVE_HDF5
/* FILE_ERROR here means that the file exists but it is not a directory -> check with HDF5 */
if (rc_text == TREXIO_FILE_ERROR) {
trexio_exit_code rc_hdf5 = trexio_hdf5_inquire(file_name);
return rc_hdf5;
/* If rc_text is TREXIO_SUCCESS -> file is a TREXIO directory; TREXIO_FAILURE -> file/directory does not exist */
} else {
return rc_text;
}
#else
return rc_text;
#endif
}
#+end_src
*** Fortran
The function below is a C binding.
The front end Fortran function for ~trexio_inquire~ can be found in the ~Fortran helper/wrapper functions~.
#+begin_src f90 :tangle prefix_fortran.f90
interface
integer function trexio_inquire_c (filename) bind(C, name="trexio_inquire")
use, intrinsic :: iso_c_binding
import
character(kind=c_char), dimension(*) :: filename
end function trexio_inquire_c
end interface
#+end_src
*** Python
#+begin_src python :tangle basic_python.py
def _inquire(file_name: str) -> bool:
"""Check whether ~file_name~ TREXIO file exists.
"""
rc = pytr.trexio_inquire(trexio_file_name)
if rc == TREXIO_SUCCESS:
return True
elif rc == TREXIO_FAILURE:
return False
else:
raise Error(rc)
#+end_src
* Templates for front end
** Description
@ -1769,7 +1848,7 @@ trexio_write_$group_dset$_64 (trexio_t* const file, const $group_dset_dtype_doub
case TREXIO_HDF5:
#ifdef HAVE_HDF5
rc = trexio_hdf5_write_$group_dset$(file,
rc = trexio_hdf5_write_$group_dset$(file,
(const $group_dset_dtype_double$*) $group_dset$_p,
rank, dims);
break;
@ -2629,7 +2708,7 @@ trexio_write_$group_dset$(trexio_t* const file,
if (file->one_based) {
uint64_t index_size = rank * buffer_size;
int32_t* index_sparse_p = CALLOC(index_size, int32_t);
if (index_sparse_p == NULL) return TREXIO_ALLOCATION_FAILED;
@ -3801,6 +3880,23 @@ contains
end function trexio_open
#+end_src
The function below adapts the original C-based ~trexio_inquire~ for Fortran.
This is needed due to the same reasons as for ~trexio_open~ function.
Note, that Fortran interface calls the main ~TREXIO~ API, which is written in C.
#+begin_src f90 :tangle helper_fortran.f90
integer function trexio_inquire (filename)
use, intrinsic :: iso_c_binding
implicit none
character(len=*), intent(in) :: filename
character(len=len_trim(filename)+1) :: filename_c
filename_c = trim(filename) // c_null_char
trexio_inquire = trexio_inquire_c(filename_c)
end function trexio_inquire
#+end_src
The subroutine below transforms an array of Fortran strings into one big string using ~TREXIO_DELIM~ symbol
as a delimeter and adds ~NULL~ character in the end in order to properly pass the desired string to
C API. This is needed due to the fact that strings in C are terminated by ~NULL~ character ~\0~.

View File

@ -69,13 +69,29 @@ typedef struct trexio_hdf5_s {
} trexio_hdf5_t;
#+end_src
** Template for HDF5 init/deinit
#+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);
trexio_exit_code trexio_hdf5_inquire(const char* file_name);
#+end_src
** Template for HDF5 init/deinit
#+begin_src c :tangle basic_hdf5.c
trexio_exit_code
trexio_hdf5_inquire(const char* file_name)
{
/* H5Fis_hdf5 determines whether file is in HDF5 format */
htri_t rc = H5Fis_hdf5(file_name);
if (rc > 0 ) {
return TREXIO_SUCCESS; //exists and HDF5
} else if (rc == 0) {
return TREXIO_FILE_ERROR; //exists but not HDF5
} else {
return TREXIO_FAILURE; //does not exist or function fails
}
}
#+end_src
#+begin_src c :tangle basic_hdf5.c
trexio_exit_code
@ -134,7 +150,9 @@ trexio_hdf5_init (trexio_t* const file)
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle basic_hdf5.c
trexio_exit_code
trexio_hdf5_deinit (trexio_t* const file)
{

View File

@ -105,6 +105,33 @@ typedef struct trexio_text_s {
#+begin_src c :tangle basic_text.h :exports none
trexio_exit_code trexio_text_init(trexio_t* const file);
trexio_exit_code trexio_text_inquire(const char* file_name);
trexio_exit_code trexio_text_deinit(trexio_t* const file);
trexio_exit_code trexio_text_lock(trexio_t* const file);
trexio_exit_code trexio_text_unlock(trexio_t* const file);
#+end_src
#+begin_src c :tangle basic_text.c
trexio_exit_code
trexio_text_inquire (const char* file_name)
{
/* Check if the file with "file_name" exists and that it is a directory */
struct stat st;
int rc = stat(file_name, &st);
bool file_exists = rc == 0;
if (file_exists) {
bool is_a_directory = st.st_mode & S_IFDIR;
if (!is_a_directory) return TREXIO_FILE_ERROR;
return TREXIO_SUCCESS;
} else {
return TREXIO_FAILURE;
}
}
#+end_src
#+begin_src c :tangle basic_text.c
@ -119,30 +146,19 @@ trexio_text_init (trexio_t* const file)
/* Put all pointers to NULL but leave parent untouched */
memset(&(f->parent)+1,0,sizeof(trexio_text_t)-sizeof(trexio_t));
/* If directory doesn't exist, create it in write mode */
struct stat st;
/* Check if directory exists */
trexio_exit_code rc;
rc = trexio_text_inquire(file->file_name);
/* TREXIO file exists but is not a directory */
if (rc == TREXIO_FILE_ERROR) return rc;
/* If directory does not exist - create it in write mode */
if (rc == TREXIO_FAILURE) {
int rc = stat(file->file_name, &st);
if (file->mode == 'r') return TREXIO_READONLY;
bool file_exists = rc == 0;
int rc_dir = mkdir(file->file_name, 0777);
if (rc_dir != 0) return TREXIO_ERRNO;
if (file_exists) {
bool is_a_directory = st.st_mode & S_IFDIR;
if (!is_a_directory) {
return TREXIO_FILE_ERROR;
}
} else {
if (file->mode == 'r') {
return TREXIO_READONLY;
}
rc = mkdir(file->file_name, 0777);
if (rc != 0) {
return TREXIO_ERRNO;
}
}
/* Create the lock file in the directory */
@ -166,7 +182,7 @@ trexio_text_init (trexio_t* const file)
if (errno == EACCES) {
/* The directory is read-only and the lock file can't be written.
Create a dummy temporary file for dummy locking.
*/
,*/
char dirname[TREXIO_MAX_FILENAME_LENGTH] = "/tmp/trexio.XXXXXX";
if (mkdtemp(dirname) == NULL) return TREXIO_ERRNO;
strncpy (file_name, dirname, TREXIO_MAX_FILENAME_LENGTH);
@ -184,10 +200,6 @@ trexio_text_init (trexio_t* const file)
}
#+end_src
#+begin_src c :tangle basic_text.h :exports none
trexio_exit_code trexio_text_lock(trexio_t* const file);
#+end_src
#+begin_src c :tangle basic_text.c
trexio_exit_code trexio_text_lock(trexio_t* const file) {
if (file == NULL) return TREXIO_INVALID_ARG_1;
@ -210,15 +222,6 @@ trexio_exit_code trexio_text_lock(trexio_t* const file) {
}
#+end_src
#+begin_src c :tangle basic_text.h :exports none
trexio_exit_code trexio_text_deinit(trexio_t* const file);
#+end_src
#+begin_src c :tangle basic_text.h :exports none
trexio_exit_code trexio_text_unlock(trexio_t* const file);
#+end_src
#+begin_src c :tangle basic_text.c
trexio_exit_code
trexio_text_unlock (trexio_t* const file)