Skip to content

Commit 9b56bd6

Browse files
committed
add ability to write HDF5 soft links
1 parent 5b3b7e3 commit 9b56bd6

File tree

7 files changed

+82
-17
lines changed

7 files changed

+82
-17
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ include(cmake/compiler_find.cmake)
55

66
project(h5fortran
77
LANGUAGES C Fortran
8-
VERSION 3.4.2
8+
VERSION 3.4.3
99
DESCRIPTION "thin, light object-oriented HDF5 Fortran interface"
1010
HOMEPAGE_URL https://github.com/geospace-code/h5fortran)
1111

Examples.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ call h5f%write('/value1', 123.)
2626
call h5f%finalize()
2727
```
2828

29+
## create soft links to actual variable
30+
31+
HDF5 soft link variables: arbitrarily many soft-linked variable names can point to an actual variable, which need not yet exist.
32+
33+
```fortran
34+
call h5f%write("/x", 42)
35+
call h5f%softlink("/x", "/y")
36+
call h5f%softlink("/x", "/z")
37+
```
38+
39+
/z and /y are soft links to /x, which need not yet exist.
40+
2941
## ensure all files are flushed to disk at end of program
3042

3143
If your program opens lots of HDF5 files and you're worried about being sure they're all flushed to disk, make this call near the very end of the program.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ as well as **character (string)**.
4040
* **Array slicing on read and write** is supported, that is, reading or writing part of a disk HDF5 array into a variable matching the slice shape.
4141
* Mismatched datatypes are coerced as per standard Fortran rules. For example, reading a float HDF5 variable into an integer Fortran variable: 42.3 => 42
4242
* Zlib (deflate) compression / decompression -- h5fortran will work without Zlib, but will save/load uncompressed data only.
43+
* create HDF5 soft link variables--arbitrarily many soft-linked variable names can point to an actual variable, which need not yet exist.
4344

4445
Tested on systems with HDF5 1.8, 1.10 and 1.12 including:
4546

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
project('h5fortran', 'fortran',
22
meson_version : '>=0.52.0',
3-
version : '3.4.2',
3+
version : '3.4.3',
44
default_options : ['default_library=static', 'buildtype=release', 'warning_level=3'])
55

66
subdir('meson')

src/interface.f90

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ module h5fortran
5151
ndims => hdf_get_ndims, &
5252
shape => hdf_get_shape, layout => hdf_get_layout, chunks => hdf_get_chunk, &
5353
exist => hdf_check_exist, exists => hdf_check_exist, &
54-
is_contig => hdf_is_contig, is_chunked => hdf_is_chunked
54+
is_contig => hdf_is_contig, is_chunked => hdf_is_chunked, &
55+
softlink => create_softlink
5556

5657
!> below are procedure that need generic mapping (type or rank agnostic)
5758

@@ -123,6 +124,24 @@ module subroutine hdf_create(self, dname, dtype, dims, sid, did, chunk_size, ist
123124
integer, intent(in), optional :: chunk_size(:), istart(:), iend(:), stride(:)
124125
!! keep istart, iend, stride for future slice shape check
125126
end subroutine hdf_create
127+
128+
module subroutine hdf_open_group(self, gname, ierr)
129+
class(hdf5_file), intent(inout) :: self
130+
character(*), intent(in) :: gname
131+
integer, intent(out), optional :: ierr
132+
end subroutine hdf_open_group
133+
134+
module subroutine hdf_close_group(self, ierr)
135+
class(hdf5_file), intent(inout) :: self
136+
integer, intent(out), optional :: ierr
137+
end subroutine hdf_close_group
138+
139+
module subroutine create_softlink(self, target, link)
140+
class(hdf5_file), intent(inout) :: self
141+
character(*), intent(in) :: target, & !< target path to link
142+
link !< soft link path to create
143+
end subroutine create_softlink
144+
126145
end interface
127146

128147
interface !< writer_lt.f90
@@ -399,19 +418,6 @@ module subroutine hdf_read_7d(self, dname, value, ierr, istart, iend, stride)
399418
end subroutine hdf_read_7d
400419
end interface
401420

402-
interface
403-
module subroutine hdf_open_group(self, gname, ierr)
404-
class(hdf5_file), intent(inout) :: self
405-
character(*), intent(in) :: gname
406-
integer, intent(out), optional :: ierr
407-
end subroutine hdf_open_group
408-
409-
module subroutine hdf_close_group(self, ierr)
410-
class(hdf5_file), intent(inout) :: self
411-
integer, intent(out), optional :: ierr
412-
end subroutine hdf_close_group
413-
end interface
414-
415421

416422
interface !< attributes.f90
417423

src/tests/test_exist.f90

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ program exist_tests
1111
call test_exist()
1212
print *, 'OK: exist'
1313

14+
call test_softlink()
15+
print *, "OK: softlink"
16+
1417
call test_scratch()
1518
print *, 'OK: scratch'
1619

@@ -59,6 +62,35 @@ subroutine test_exist()
5962
end subroutine test_exist
6063

6164

65+
subroutine test_softlink()
66+
type(hdf5_file) :: h
67+
character(*), parameter :: fn = 'soft.h5'
68+
integer :: y
69+
70+
call h%initialize(fn, status="new")
71+
72+
call h%write("/actual", 142)
73+
call h%softlink("/actual", "/additional")
74+
call h%read("/additional", y)
75+
76+
if (.not.h%exist("/additional")) error stop "softlink not present"
77+
78+
if (y /= 142) error stop "did not read softlink correctly"
79+
80+
!> test dangling link
81+
82+
call h%softlink("/not_here", "/not_yet")
83+
if (h%exist("/not_yet")) error stop "dangling softlink"
84+
85+
call h%write("/not_here", 36)
86+
call h%read("/not_yet", y)
87+
if (y /= 36) error stop "finalizing dangling link failed"
88+
89+
call h%finalize()
90+
91+
end subroutine test_softlink
92+
93+
6294
subroutine test_scratch()
6395
logical :: e
6496
type(hdf5_file) :: h

src/write.f90

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
h5screate_f, H5S_SCALAR_F, &
55
h5dcreate_f, &
66
h5pset_chunk_f, h5pset_deflate_f, h5pset_shuffle_f, h5pset_fletcher32_f, h5pcreate_f, H5P_DATASET_CREATE_F, h5pclose_f, &
7-
h5gopen_f
7+
h5gopen_f, &
8+
H5Lcreate_soft_f
89

910
use H5LT, only: h5ltmake_dataset_string_f, h5ltpath_valid_f
1011

@@ -109,6 +110,19 @@
109110
end procedure hdf_create
110111

111112

113+
module procedure create_softlink
114+
!! HDF5 soft link -- to variables in same file
115+
!! target need not exist (dangling link)
116+
!! linking to external files requires an external link (different function required)
117+
118+
integer :: ierr
119+
120+
call H5Lcreate_soft_f(target, self%lid, link, ierr)
121+
if (check(ierr, self%filename)) return
122+
123+
end procedure create_softlink
124+
125+
112126
subroutine set_deflate(self, dims, pid, ierr, chunk_size)
113127
class(hdf5_file), intent(inout) :: self
114128
integer(HSIZE_T), intent(in) :: dims(:)

0 commit comments

Comments
 (0)