diff --git a/.github/workflows/netcdf.yml b/.github/workflows/netcdf.yml
index 30b37bf8e65..0c396588cb0 100644
--- a/.github/workflows/netcdf.yml
+++ b/.github/workflows/netcdf.yml
@@ -74,6 +74,7 @@ jobs:
repository: unidata/netcdf-c
path: netcdf-c
+
- name: Test netCDF
run: |
cd netcdf-c
diff --git a/doxygen/dox/H5.format.2.0.dox b/doxygen/dox/H5.format.2.0.dox
index ab6d48b6aa8..bd2c1fecd78 100644
--- a/doxygen/dox/H5.format.2.0.dox
+++ b/doxygen/dox/H5.format.2.0.dox
@@ -143,7 +143,7 @@ Values for all fields in this document should be treated as unsigned integers, u
the description of a field. Additionally, all metadata fields are stored in little-endian byte order.
All checksums used in the format are computed with the
-Jenkins’ lookup3 algorithm.
+Jenkins’ lookup3 algorithm.
Whenever a bit flag or field is mentioned for an entry, bits are numbered from the lowest bit position
in the entry.
diff --git a/doxygen/dox/H5.format.3.0.dox b/doxygen/dox/H5.format.3.0.dox
index 36b37fff16a..353b0b4f64a 100644
--- a/doxygen/dox/H5.format.3.0.dox
+++ b/doxygen/dox/H5.format.3.0.dox
@@ -170,7 +170,7 @@ Values for all fields in this document should be treated as unsigned integers, u
the description of a field. Additionally, all metadata fields are stored in little-endian byte order.
All checksums used in the format are computed with the
-Jenkins’ lookup3 algorithm.
+Jenkins’ lookup3 algorithm.
Whenever a bit flag or field is mentioned for an entry, bits are numbered from the lowest bit position
in the entry.
diff --git a/doxygen/examples/tables/volAPIs.dox b/doxygen/examples/tables/volAPIs.dox
index 88299960ea6..b4167988ea0 100644
--- a/doxygen/examples/tables/volAPIs.dox
+++ b/doxygen/examples/tables/volAPIs.dox
@@ -52,7 +52,11 @@
|
-| #H5Dread_chunk |
+#H5Dread_chunk1 |
+ |
+
+
+| #H5Dread_chunk2 |
|
@@ -461,7 +465,7 @@
| #H5VL_NATIVE_DATASET_GET_CHUNK_INFO_BY_COORD |
-| #H5Dread_chunk |
+#H5Dread_chunk1 / #H5Dread_chunk2 |
#H5VL_NATIVE_DATASET_CHUNK_READ |
diff --git a/fortran/src/H5Dff.F90 b/fortran/src/H5Dff.F90
index da7efd7a98e..34529824086 100644
--- a/fortran/src/H5Dff.F90
+++ b/fortran/src/H5Dff.F90
@@ -203,6 +203,12 @@ MODULE H5D
INTEGER(HID_T) :: mem_type_id
END FUNCTION h5dfill_c
END INTERFACE
+
+ INTERFACE h5dread_chunk_f
+ MODULE PROCEDURE h5dread_chunk1_f
+ MODULE PROCEDURE h5dread_chunk2_f
+ END INTERFACE
+
#endif
CONTAINS
@@ -1780,6 +1786,62 @@ CONTAINS
INTEGER(HID_T), INTENT(IN) :: space_id
END SUBROUTINE h5dfill_f
+!>
+!! \ingroup FH5D
+!!
+!! \brief Reads a raw data chunk directly from a dataset in a file into a buffer.
+!!
+!! \param dset_id Identifier of the dataset to read from
+!! \param offset Logical position of the chunk's first element in the dataspace, \Bold{0-based indices}
+!! \param filters Mask for identifying the filters in use
+!! \param buf Buffer containing data to be read from the chunk, if passed \p C_NULL_PTR then returns the
+!! needed size of \p buf in \p buf_size
+!! \param buf_size Size of \p buf in bytes
+!! \param hdferr \fortran_error
+!! \param dxpl_id Dataset transfer property list identifier
+!!
+!! See C API: @ref H5Dread_chunk2()
+!!
+ SUBROUTINE h5dread_chunk_f(dset_id, offset, filters, buf, buf_size, hdferr, dxpl_id)
+ IMPLICIT NONE
+
+ INTEGER(HID_T) , INTENT(IN) :: dset_id
+ INTEGER(HSIZE_T) , INTENT(IN), DIMENSION(:) :: offset
+ INTEGER , INTENT(INOUT) :: filters
+ TYPE(C_PTR) :: buf
+ INTEGER(SIZE_T) , INTENT(INOUT) :: buf_size
+ INTEGER , INTENT(OUT) :: hdferr
+ INTEGER(HID_T) , INTENT(IN), OPTIONAL :: dxpl_id
+ END SUBROUTINE h5dread_chunk_f
+
+!>
+!! \ingroup FH5D
+!!
+!! \important If HDF5 was built without deprecated symbols, the API \p h5dread_chunk_f will return an error
+!! since there is no equivalent C API to call.
+!!
+!! \brief Reads a raw data chunk directly from a dataset in a file into a buffer.
+!!
+!! \param dset_id Identifier of the dataset to read from
+!! \param offset Logical position of the chunk's first element in the dataspace, \Bold{0-based indices}
+!! \param filters Mask for identifying the filters in use
+!! \param buf Buffer containing data to be read from the chunk
+!! \param hdferr \fortran_error
+!! \param dxpl_id Dataset transfer property list identifier
+!!
+!! See C API: Deprecated @ref H5Dread_chunk1()
+!!
+ SUBROUTINE h5dread_chunk_f(dset_id, offset, filters, buf, hdferr, dxpl_id)
+ IMPLICIT NONE
+
+ INTEGER(HID_T) , INTENT(IN) :: dset_id
+ INTEGER(HSIZE_T) , INTENT(IN), DIMENSION(:) :: offset
+ INTEGER , INTENT(INOUT) :: filters
+ TYPE(C_PTR) :: buf
+ INTEGER , INTENT(OUT) :: hdferr
+ INTEGER(HID_T) , INTENT(IN), OPTIONAL :: dxpl_id
+ END SUBROUTINE h5dread_chunk_f
+
#else
SUBROUTINE h5dwrite_reference_obj(dset_id, mem_type_id, buf, dims, hdferr, &
@@ -2266,6 +2328,138 @@ CONTAINS
END SUBROUTINE h5dfill_char
+ SUBROUTINE h5dread_chunk2_f(dset_id, offset, filters, buf, buf_size, hdferr, dxpl_id)
+ IMPLICIT NONE
+
+ INTEGER(HID_T) , INTENT(IN) :: dset_id
+ INTEGER(HSIZE_T) , INTENT(IN), DIMENSION(:) :: offset
+ INTEGER , INTENT(INOUT) :: filters
+ TYPE(C_PTR) :: buf
+ INTEGER(SIZE_T) , INTENT(INOUT) :: buf_size
+ INTEGER , INTENT(OUT) :: hdferr
+ INTEGER(HID_T) , INTENT(IN), OPTIONAL :: dxpl_id
+
+ INTEGER(HID_T) :: dxpl_id_default
+ INTEGER(HSIZE_T), DIMENSION(:), ALLOCATABLE :: c_offset
+ INTEGER(HSIZE_T) :: i, rank
+ INTEGER(C_INT32_T) :: c_filters
+ INTEGER(C_SIZE_T) :: cbuf_size
+
+ INTERFACE
+ INTEGER(C_INT) FUNCTION H5Dread_chunk2(dset_id, dxpl_id, offset, filters, buf, buf_size) &
+ BIND(C, NAME='H5Dread_chunk2')
+ IMPORT :: SIZE_T, HSIZE_T, HID_T
+ IMPORT :: C_PTR, C_INT32_T, C_INT, C_SIZE_T
+ IMPLICIT NONE
+ INTEGER(HID_T) , VALUE :: dset_id
+ INTEGER(HID_T) , VALUE :: dxpl_id
+ INTEGER(HSIZE_T) , DIMENSION(*) :: offset
+ INTEGER(C_INT32_T) :: filters
+ TYPE(C_PTR) , VALUE :: buf
+ INTEGER(C_SIZE_T) :: buf_size
+ END FUNCTION H5Dread_chunk2
+ END INTERFACE
+
+ dxpl_id_default = H5P_DEFAULT_F
+ IF (PRESENT(dxpl_id)) dxpl_id_default = dxpl_id
+
+ c_filters = INT(filters, KIND=C_INT32_T)
+
+ rank = SIZE(offset, KIND=HSIZE_T)
+
+ ALLOCATE(c_offset(rank), STAT=hdferr)
+ IF (hdferr .NE. 0 ) THEN
+ hdferr = -1
+ RETURN
+ ENDIF
+
+ !
+ ! Reverse dimensions due to C-FORTRAN storage order
+ !
+ DO i = 1, rank
+ c_offset(i) = offset(rank - i + 1)
+ ENDDO
+
+ IF(.NOT. C_ASSOCIATED(buf) )THEN
+ cbuf_size = 0_C_SIZE_T
+ hdferr = INT(H5Dread_chunk2(dset_id, dxpl_id_default, c_offset, c_filters, C_NULL_PTR, cbuf_size))
+ buf_size = INT(cbuf_size, SIZE_T)
+ RETURN
+ ELSE
+ cbuf_size = INT(buf_size, C_SIZE_T)
+ ENDIF
+
+ hdferr = INT(H5Dread_chunk2(dset_id, dxpl_id_default, c_offset, c_filters, buf, cbuf_size))
+
+ filters = INT(c_filters)
+ buf_size = INT(cbuf_size, SIZE_T)
+
+ DEALLOCATE(c_offset)
+
+ END SUBROUTINE h5dread_chunk2_f
+
+ SUBROUTINE h5dread_chunk1_f(dset_id, offset, filters, buf, hdferr, dxpl_id)
+ IMPLICIT NONE
+
+ INTEGER(HID_T) , INTENT(IN) :: dset_id
+ INTEGER(HSIZE_T) , INTENT(IN), DIMENSION(:) :: offset
+ INTEGER , INTENT(INOUT) :: filters
+ TYPE(C_PTR) :: buf
+ INTEGER , INTENT(OUT) :: hdferr
+ INTEGER(HID_T) , INTENT(IN), OPTIONAL :: dxpl_id
+
+#ifdef H5_NO_DEPRECATED_SYMBOLS
+ buf = C_NULL_PTR
+ hdferr = -1
+ RETURN
+#else
+ INTEGER(HID_T) :: dxpl_id_default
+ INTEGER(HSIZE_T), DIMENSION(:), ALLOCATABLE :: c_offset
+ INTEGER(HSIZE_T) :: i, rank
+ INTEGER(C_INT32_T) :: c_filters
+
+ INTERFACE
+ INTEGER(C_INT) FUNCTION H5Dread_chunk1(dset_id, dxpl_id, offset, filters, buf) &
+ BIND(C, NAME='H5Dread_chunk1')
+ IMPORT :: SIZE_T, HSIZE_T, HID_T
+ IMPORT :: C_PTR, C_INT32_T, C_INT
+ IMPLICIT NONE
+ INTEGER(HID_T) , VALUE :: dset_id
+ INTEGER(HID_T) , VALUE :: dxpl_id
+ INTEGER(HSIZE_T) , DIMENSION(*) :: offset
+ INTEGER(C_INT32_T) :: filters
+ TYPE(C_PTR) , VALUE :: buf
+ END FUNCTION H5Dread_chunk1
+ END INTERFACE
+
+ dxpl_id_default = H5P_DEFAULT_F
+ IF (PRESENT(dxpl_id)) dxpl_id_default = dxpl_id
+
+ c_filters = INT(filters, KIND=C_INT32_T)
+
+ rank = SIZE(offset, KIND=HSIZE_T)
+
+ ALLOCATE(c_offset(rank), STAT=hdferr)
+ IF (hdferr .NE. 0 ) THEN
+ hdferr = -1
+ RETURN
+ ENDIF
+
+ !
+ ! Reverse dimensions due to C-FORTRAN storage order
+ !
+ DO i = 1, rank
+ c_offset(i) = offset(rank - i + 1)
+ ENDDO
+
+ hdferr = INT(H5Dread_chunk1(dset_id, dxpl_id_default, c_offset, c_filters, buf))
+
+ filters = INT(c_filters)
+
+ DEALLOCATE(c_offset)
+#endif
+ END SUBROUTINE h5dread_chunk1_f
+
#endif
!>
@@ -2376,77 +2570,6 @@ CONTAINS
END SUBROUTINE h5dwrite_multi_f
-!>
-!! \ingroup FH5D
-!!
-!! \brief Reads a raw data chunk directly from a dataset in a file into a buffer.
-!!
-!! \param dset_id Identifier of the dataset to read from
-!! \param offset Logical position of the chunk's first element in the dataspace, \Bold{0-based indices}
-!! \param filters Mask for identifying the filters in use
-!! \param buf Buffer containing data to be read from the chunk
-!! \param hdferr \fortran_error
-!! \param dxpl_id Dataset transfer property list identifier
-!!
-!! See C API: @ref H5Dread_chunk()
-!!
- SUBROUTINE h5dread_chunk_f(dset_id, offset, filters, buf, hdferr, dxpl_id)
- IMPLICIT NONE
-
- INTEGER(HID_T) , INTENT(IN) :: dset_id
- INTEGER(HSIZE_T) , INTENT(IN), DIMENSION(:) :: offset
- INTEGER , INTENT(INOUT) :: filters
- TYPE(C_PTR) :: buf
- INTEGER , INTENT(OUT) :: hdferr
- INTEGER(HID_T) , INTENT(IN), OPTIONAL :: dxpl_id
-
- INTEGER(HID_T) :: dxpl_id_default
- INTEGER(HSIZE_T), DIMENSION(:), ALLOCATABLE :: c_offset
- INTEGER(HSIZE_T) :: i, rank
- INTEGER(C_INT32_T) :: c_filters
-
- INTERFACE
- INTEGER(C_INT) FUNCTION H5Dread_chunk(dset_id, dxpl_id, offset, filters, buf) &
- BIND(C, NAME='H5Dread_chunk')
- IMPORT :: SIZE_T, HSIZE_T, HID_T
- IMPORT :: C_PTR, C_INT32_T, C_INT
- IMPLICIT NONE
- INTEGER(HID_T) , VALUE :: dset_id
- INTEGER(HID_T) , VALUE :: dxpl_id
- INTEGER(HSIZE_T) , DIMENSION(*) :: offset
- INTEGER(C_INT32_T) :: filters
- TYPE(C_PTR) , VALUE :: buf
- END FUNCTION H5Dread_chunk
- END INTERFACE
-
- dxpl_id_default = H5P_DEFAULT_F
- IF (PRESENT(dxpl_id)) dxpl_id_default = dxpl_id
-
- c_filters = INT(filters, KIND=C_INT32_T)
-
- rank = SIZE(offset, KIND=HSIZE_T)
-
- ALLOCATE(c_offset(rank), STAT=hdferr)
- IF (hdferr .NE. 0 ) THEN
- hdferr = -1
- RETURN
- ENDIF
-
- !
- ! Reverse dimensions due to C-FORTRAN storage order
- !
- DO i = 1, rank
- c_offset(i) = offset(rank - i + 1)
- ENDDO
-
- hdferr = INT(H5Dread_chunk(dset_id, dxpl_id_default, c_offset, c_filters, buf))
-
- filters = INT(c_filters)
-
- DEALLOCATE(c_offset)
-
- END SUBROUTINE h5dread_chunk_f
-
!>
!! \ingroup FH5D
!!
diff --git a/fortran/src/hdf5_fortrandll.def.in b/fortran/src/hdf5_fortrandll.def.in
index 5bc4a274c42..8a51a15928f 100644
--- a/fortran/src/hdf5_fortrandll.def.in
+++ b/fortran/src/hdf5_fortrandll.def.in
@@ -103,7 +103,8 @@ H5D_mp_H5DWRITE_MULTI_F
H5D_mp_H5DWRITE_ASYNC_F
H5D_mp_H5DREAD_ASYNC_F
H5D_mp_H5DWRITE_CHUNK_F
-H5D_mp_H5DREAD_CHUNK_F
+H5D_mp_H5DREAD_CHUNK1_F
+H5D_mp_H5DREAD_CHUNK2_F
; H5E
H5E_mp_H5ECLEAR_F
H5E_mp_H5EPRINT1_F
diff --git a/fortran/test/tH5D.F90 b/fortran/test/tH5D.F90
index 59b69db7e7f..d5c5355c5d3 100644
--- a/fortran/test/tH5D.F90
+++ b/fortran/test/tH5D.F90
@@ -32,7 +32,6 @@
#include
-!
MODULE TH5D
USE HDF5 ! This module contains all necessary modules
@@ -1013,6 +1012,7 @@ CONTAINS
INTEGER(HSIZE_T), DIMENSION(2) :: offset
INTEGER(HSIZE_T), DIMENSION(2) :: dims = (/DIM0,DIM1/)
INTEGER, DIMENSION(CHUNK0,CHUNK1), TARGET :: wdata1, rdata1, wdata2, rdata2
+ INTEGER, DIMENSION(:), ALLOCATABLE, TARGET :: buf_alloc
INTEGER(HSIZE_T), DIMENSION(2) :: chunk = (/CHUNK0, CHUNK1/)
INTEGER :: i, j, n
INTEGER :: error
@@ -1020,6 +1020,7 @@ CONTAINS
INTEGER :: filters
INTEGER(SIZE_T) :: sizeINT
INTEGER(HID_T) :: dxpl
+ INTEGER(SIZE_T) :: buf_size
!
!Create a new file using default properties.
@@ -1107,6 +1108,9 @@ CONTAINS
filters = 99
offset(1:2) = (/0, 0/)
CALL H5Dread_chunk_f(dset_id, offset, filters, f_ptr, error)
+#ifdef H5_NO_DEPRECATED_SYMBOLS
+ CALL VERIFY("H5Dread_chunk_f",error,-1,total_error)
+#else
CALL check("H5Dread_chunk_f",error,total_error)
! Verify that the data read was correct.
@@ -1118,10 +1122,14 @@ CONTAINS
ENDDO
CALL VERIFY("H5Dread_chunk_f",filters, 0, total_error)
+#endif
f_ptr = C_LOC(rdata2)
offset(1:2) = (/0, 16/)
CALL H5Dread_chunk_f(dset_id, offset, filters, f_ptr, error, dxpl)
+#ifdef H5_NO_DEPRECATED_SYMBOLS
+ CALL VERIFY("H5Dread_chunk_f",error,-1,total_error)
+#else
CALL check("H5Dread_chunk_f",error,total_error)
! Verify that the data read was correct.
@@ -1133,6 +1141,33 @@ CONTAINS
ENDDO
CALL VERIFY("H5Dread_chunk_f",filters, 0, total_error)
+#endif
+
+ !
+ ! check version of H5Dread_chunk_f with buf_size parameter
+ !
+ offset(1:2) = (/0, 16/)
+
+ CALL H5Dread_chunk_f(dset_id, offset, filters, C_NULL_PTR, buf_size, error, dxpl)
+ CALL check("H5Dread_chunk_f",error,total_error)
+ CALL VERIFY("H5Dread_chunk_f", buf_size, 256_SIZE_T, total_error)
+
+ ALLOCATE(buf_alloc(1:buf_size/sizeINT))
+ f_ptr = C_LOC(buf_alloc(1))
+
+ CALL H5Dread_chunk_f(dset_id, offset, filters, f_ptr, buf_size, error, dxpl)
+ CALL check("H5Dread_chunk_f",error,total_error)
+ CALL VERIFY("H5Dread_chunk_f", buf_size, 256_SIZE_T, total_error)
+
+ rdata2 = RESHAPE(buf_alloc,(/CHUNK0, CHUNK1/))
+ DO i = 1, CHUNK0
+ DO j = 1, CHUNK1
+ CALL VERIFY("H5Dread_chunk_f", rdata2(i,j), wdata2(i,j), total_error)
+ IF(total_error.NE.0) EXIT
+ ENDDO
+ ENDDO
+
+ DEALLOCATE(buf_alloc)
CALL h5dclose_f(dset_id, error)
CALL check("h5dclose_f",error,total_error)
diff --git a/hl/src/H5DO.c b/hl/src/H5DO.c
index 5e72b2b2645..cf827181870 100644
--- a/hl/src/H5DO.c
+++ b/hl/src/H5DO.c
@@ -60,7 +60,7 @@ herr_t
H5DOread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters, void *buf)
{
/* Call underlying H5D function */
- if (H5Dread_chunk(dset_id, dxpl_id, offset, filters, buf) < 0)
+ if (H5Dread_chunk1(dset_id, dxpl_id, offset, filters, buf) < 0)
return FAIL;
else
return SUCCEED;
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 60748b42e0b..910f647c74c 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -200,6 +200,32 @@ New Features
Library:
--------
+
+ - The H5Dread_chunk() signature has changed
+
+ A new parameter, nalloc, has been added to H5Dread_chunk(). This parameter
+ contains a pointer to a variable that holds the size of the buffer buf. If
+ *nalloc is not large enough to hold the entire chunk being read, no data
+ is read. On exit, the value of this variable is set to the buffer size
+ needed to read the chunk.
+
+ The old signature has been renamed to H5Dread_chunk1() and is considered
+ deprecated:
+
+ herr_t H5Dread_chunk1(hid_t dset_id, hid_t dxpl_id,
+ const hsize_t *offset, uint32_t *filters,
+ void *buf);
+
+ The new signature is H5Dread_chunk2(). All code should be updated to use
+ this version:
+
+ herr_t H5Dread_chunk2(hid_t dset_id, hid_t dxpl_id,
+ const hsize_t *offset, uint32_t *filters,
+ void *buf, size_t *nalloc);
+
+ H5Dread_chunk() will map to the new signature unless the library is
+ explicitly configured to use an older version of the API.
+
- Replaced the ROS3 VFD's S3 backend based on libcurl with a new backend
based on the aws-c-s3 library (https://github.com/awslabs/aws-c-s3)
@@ -282,6 +308,7 @@ New Features
H5_FCTESTDLL(VAR) --> H5FC_TEST_DLL(VAR)
HDF5_HL_F90CSTUBDLL(VAR) --> H5FC_HL_DLL(VAR)
+
- The H5Iregister_type() signature has changed
The hash_size parameter has not been used since early versions of HDF5
diff --git a/src/H5D.c b/src/H5D.c
index 711a257712a..394d9a3f569 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -1169,7 +1169,7 @@ done:
} /* end H5Dread_multi_async() */
/*-------------------------------------------------------------------------
- * Function: H5Dread_chunk
+ * Function: H5Dread_chunk2
*
* Purpose: Reads an entire chunk from the file directly.
*
@@ -1178,7 +1178,8 @@ done:
*---------------------------------------------------------------------------
*/
herr_t
-H5Dread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters, void *buf /*out*/)
+H5Dread_chunk2(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters /*out*/,
+ void *buf /*out*/, size_t *buf_size)
{
H5VL_object_t *vol_obj; /* Dataset for this operation */
H5VL_optional_args_t vol_cb_args; /* Arguments to VOL callback */
@@ -1190,12 +1191,12 @@ H5Dread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *fil
/* Check arguments */
if (NULL == (vol_obj = H5VL_vol_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID");
- if (!buf)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf cannot be NULL");
if (!offset)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offset cannot be NULL");
if (!filters)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "filters cannot be NULL");
+ if (!buf_size)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf_size cannot be NULL");
/* Get the default dataset transfer property list if the user didn't provide one */
if (H5P_DEFAULT == dxpl_id)
@@ -1204,11 +1205,12 @@ H5Dread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *fil
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dxpl_id is not a dataset transfer property list ID");
/* Set up VOL callback arguments */
- dset_opt_args.chunk_read.offset = offset;
- dset_opt_args.chunk_read.filters = 0;
- dset_opt_args.chunk_read.buf = buf;
- vol_cb_args.op_type = H5VL_NATIVE_DATASET_CHUNK_READ;
- vol_cb_args.args = &dset_opt_args;
+ dset_opt_args.chunk_read.offset = offset;
+ dset_opt_args.chunk_read.filters = 0;
+ dset_opt_args.chunk_read.buf = buf;
+ dset_opt_args.chunk_read.buf_size = buf_size;
+ vol_cb_args.op_type = H5VL_NATIVE_DATASET_CHUNK_READ;
+ vol_cb_args.args = &dset_opt_args;
/* Read the raw chunk */
if (H5VL_dataset_optional(vol_obj, &vol_cb_args, dxpl_id, H5_REQUEST_NULL) < 0)
@@ -1219,7 +1221,7 @@ H5Dread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *fil
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Dread_chunk() */
+} /* end H5Dread_chunk2() */
/*-------------------------------------------------------------------------
* Function: H5D__write_api_common
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 23e0cf11ba9..4c2dfc2fa2a 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -483,7 +483,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D__chunk_direct_read(const H5D_t *dset, hsize_t *offset, uint32_t *filters, void *buf)
+H5D__chunk_direct_read(const H5D_t *dset, hsize_t *offset, uint32_t *filters, void *buf, size_t *nalloc)
{
const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /* raw data chunk cache */
@@ -497,7 +497,7 @@ H5D__chunk_direct_read(const H5D_t *dset, hsize_t *offset, uint32_t *filters, vo
assert(dset && H5D_CHUNKED == layout->type);
assert(offset);
assert(filters);
- assert(buf);
+ assert(buf || nalloc);
*filters = 0;
@@ -553,10 +553,18 @@ H5D__chunk_direct_read(const H5D_t *dset, hsize_t *offset, uint32_t *filters, vo
if (!H5_addr_defined(udata.chunk_block.offset))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined");
- /* Read the chunk data into the supplied buffer */
- if (H5F_shared_block_read(H5F_SHARED(dset->oloc.file), H5FD_MEM_DRAW, udata.chunk_block.offset,
- udata.chunk_block.length, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk");
+ /* If nalloc is provided, check if *nalloc is large enough. If not provided, assume it is large enough
+ * (this is the insecure older behaviour that is disallowed by H5Dread_chunk2(), but we must support it
+ * here for the deprecated H5Dreach_chunk1()). */
+ if (udata.chunk_block.length > 0 && buf && (!nalloc || *nalloc >= udata.chunk_block.length))
+ /* Read the chunk data into the supplied buffer */
+ if (H5F_shared_block_read(H5F_SHARED(dset->oloc.file), H5FD_MEM_DRAW, udata.chunk_block.offset,
+ udata.chunk_block.length, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk");
+
+ /* Return the size of the chunk block in *nalloc if nalloc is provided */
+ if (nalloc)
+ *nalloc = udata.chunk_block.length;
/* Return the filter mask */
*filters = udata.filter_mask;
diff --git a/src/H5Ddeprec.c b/src/H5Ddeprec.c
index 0b98a5e726a..dff60e3110a 100644
--- a/src/H5Ddeprec.c
+++ b/src/H5Ddeprec.c
@@ -335,4 +335,61 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Dvlen_reclaim() */
+/*-------------------------------------------------------------------------
+ * Function: H5Dread_chunk1
+ *
+ * Purpose: Reads an entire chunk from the file directly.
+ *
+ * Note: Deprecated in favor of H5Dread_chunk2
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5Dread_chunk1(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters /*out*/,
+ void *buf /*out*/)
+{
+ H5VL_object_t *vol_obj; /* Dataset for this operation */
+ H5VL_optional_args_t vol_cb_args; /* Arguments to VOL callback */
+ H5VL_native_dataset_optional_args_t dset_opt_args; /* Arguments for optional operation */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+
+ /* Check arguments */
+ if (NULL == (vol_obj = H5VL_vol_object_verify(dset_id, H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID");
+ if (!buf)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf cannot be NULL");
+ if (!offset)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offset cannot be NULL");
+ if (!filters)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "filters cannot be NULL");
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if (H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else if (true != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dxpl_id is not a dataset transfer property list ID");
+
+ /* Set up VOL callback arguments */
+ dset_opt_args.chunk_read.offset = offset;
+ dset_opt_args.chunk_read.filters = 0;
+ dset_opt_args.chunk_read.buf = buf;
+ dset_opt_args.chunk_read.buf_size = NULL;
+ vol_cb_args.op_type = H5VL_NATIVE_DATASET_CHUNK_READ;
+ vol_cb_args.args = &dset_opt_args;
+
+ /* Read the raw chunk */
+ if (H5VL_dataset_optional(vol_obj, &vol_cb_args, dxpl_id, H5_REQUEST_NULL) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read unprocessed chunk data");
+
+ /* Set return value */
+ *filters = dset_opt_args.chunk_read.filters;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Dread_chunk1() */
+
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index d7dbf23ce1a..a7adbc4f2e5 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -750,7 +750,8 @@ H5_DLL herr_t H5D__chunk_delete(H5F_t *f, H5O_t *oh, H5O_storage_t *store);
H5_DLL herr_t H5D__chunk_get_offset_copy(const H5D_t *dset, const hsize_t *offset, hsize_t *offset_copy);
H5_DLL herr_t H5D__chunk_direct_write(H5D_t *dset, uint32_t filters, hsize_t *offset, uint32_t data_size,
const void *buf);
-H5_DLL herr_t H5D__chunk_direct_read(const H5D_t *dset, hsize_t *offset, uint32_t *filters, void *buf);
+H5_DLL herr_t H5D__chunk_direct_read(const H5D_t *dset, hsize_t *offset, uint32_t *filters, void *buf,
+ size_t *nalloc);
#ifdef H5D_CHUNK_DEBUG
H5_DLL herr_t H5D__chunk_stats(const H5D_t *dset, bool headers);
#endif /* H5D_CHUNK_DEBUG */
diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h
index f307be7f176..da69d5153ae 100644
--- a/src/H5Dpublic.h
+++ b/src/H5Dpublic.h
@@ -1221,14 +1221,14 @@ H5_DLL herr_t H5Dwrite_multi_async(size_t count, hid_t dset_id[], hid_t mem_type
* \p buf is the memory buffer containing data to be written to
* the chunk in the file.
*
- * \attention Exercise caution when using H5Dread_chunk() and
+ * \attention Exercise caution when using H5Dread_chunk2() and
* H5Dwrite_chunk(), as they read and write data chunks directly
* in a file. H5Dwrite_chunk() bypasses hyperslab selection, the
* conversion of data from one datatype to another, and the filter
* pipeline to write the chunk. Developers should have experience
* with these processes before using this function.
*
- * \note H5Dread_chunk() and H5Dwrite_chunk() are currently not supported
+ * \note H5Dread_chunk2() and H5Dwrite_chunk() are currently not supported
* with parallel HDF5 and do not support variable-length types.
*
* \since 1.10.2
@@ -1250,10 +1250,11 @@ H5_DLL herr_t H5Dwrite_chunk(hid_t dset_id, hid_t dxpl_id, uint32_t filters, con
* dataspace
* \param[in,out] filters Mask for identifying the filters in use
* \param[out] buf Buffer containing data to be read from the chunk
+ * \param[in,out] buf_size Size of buf in bytes
*
* \return \herr_t
*
- * \details H5Dread_chunk() reads a raw data chunk as specified by
+ * \details H5Dread_chunk2() reads a raw data chunk as specified by
* its logical offset \p offset in a chunked dataset \p dset_id
* from the dataset in the file into the application memory
* buffer \p buf. The data in \p buf is read directly from the
@@ -1276,7 +1277,16 @@ H5_DLL herr_t H5Dwrite_chunk(hid_t dset_id, hid_t dxpl_id, uint32_t filters, con
* \p buf is the memory buffer containing the chunk read from
* the dataset in the file.
*
- * \attention Exercise caution when using H5Dread_chunk() and
+ * \p buf_size must be passed as a pointer to a variable holding the
+ * allocated size, in bytes, of the memory buffer \p buf. On exit,
+ * \p *buf_size is set to the buffer size needed to read the chunk, which
+ * is the same as the size of the chunk on disk. If the value of
+ * \p *buf_size passed in was insufficient to read the entire, chunk, no
+ * data is read. \p buf may be passed as NULL as long as \p *buf_size
+ * is 0. \p filters is always set by this function even if the chunk
+ * was not read.
+ *
+ * \attention Exercise caution when using H5Dread_chunk2() and
* H5Dwrite_chunk(), as they read and write data chunks directly
* in a file. H5Dwrite_chunk() bypasses hyperslab selection, the
* conversion of data from one datatype to another, and the filter
@@ -1284,14 +1294,14 @@ H5_DLL herr_t H5Dwrite_chunk(hid_t dset_id, hid_t dxpl_id, uint32_t filters, con
* with these processes before using this function. Please see
* \ref subsec_hldo_direct_chunk_using for more information.
*
- * \note H5Dread_chunk() and H5Dwrite_chunk() are currently not supported
+ * \note H5Dread_chunk2() and H5Dwrite_chunk() are currently not supported
* with parallel HDF5 and do not support variable-length datatypes.
*
- * \since 1.10.2
+ * \since 2.0.0
*
*/
-H5_DLL herr_t H5Dread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters,
- void *buf);
+H5_DLL herr_t H5Dread_chunk2(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters,
+ void *buf, size_t *buf_size);
/**
* --------------------------------------------------------------------------
@@ -1890,6 +1900,75 @@ H5_DLL herr_t H5Dextend(hid_t dset_id, const hsize_t size[]);
*
*/
H5_DLL herr_t H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t dxpl_id, void *buf);
+/**
+ * --------------------------------------------------------------------------
+ * \ingroup H5D
+ *
+ * \brief Reads a raw data chunk directly from a dataset in a file into
+ * a buffer
+ *
+ * \dset_id
+ * \dxpl_id
+ * \param[in] offset Logical position of the chunk's first element in the
+ * dataspace
+ * \param[in,out] filters Mask for identifying the filters in use
+ * \param[out] buf Buffer containing data to be read from the chunk
+ *
+ * \return \herr_t
+ *
+ * \deprecation_note{H5Dread_chunk2() or the macro H5Dread_chunk()}
+ *
+ * \details H5Dread_chunk1() reads a raw data chunk as specified by
+ * its logical offset \p offset in a chunked dataset \p dset_id
+ * from the dataset in the file into the application memory
+ * buffer \p buf. The data in \p buf is read directly from the
+ * file bypassing the library's internal data transfer pipeline,
+ * including filters.
+ *
+ * \p offset is an array specifying the logical position of the
+ * first element of the chunk in the dataset's dataspace. The
+ * length of the \p offset array must equal the number of dimensions,
+ * or rank, of the dataspace. The values in \p offset must not exceed
+ * the dimension limits and must specify a point that falls on
+ * a dataset chunk boundary.
+ *
+ * The mask \p filters indicates which filters were used when the
+ * chunk was written. A zero value (all bits 0) indicates that all
+ * enabled filters are applied on the chunk. A filter is skipped if
+ * the bit corresponding to the filter's position in the pipeline
+ * (0 ≤ position < 32) is turned on.
+ *
+ * \p buf is the memory buffer containing the chunk read from
+ * the dataset in the file.
+ *
+ * \attention It is strongly recommended to use H5Dread_chunk2() instead of this
+ * function due to the potential for memory corruption. During the
+ * typical usage pattern of this function, the application has no way
+ * of knowing the size of the chunk on disk, or even a maximum size
+ * (filters can increase the size of a chunk). The library also has no
+ * way of knowing the size of \p buf, so there is a potential for the
+ * library to write past the end of the buffer. The only general way to
+ * avoid this problem, besides upgrading to H5Dread_chunk2(), is to
+ * query the chunk size beforehand, which can be expensive.
+ *
+ * \attention Exercise caution when using H5Dread_chunk1() and
+ * H5Dwrite_chunk(), as they read and write data chunks directly
+ * in a file. H5Dwrite_chunk() bypasses hyperslab selection, the
+ * conversion of data from one datatype to another, and the filter
+ * pipeline to write the chunk. Developers should have experience
+ * with these processes before using this function. Please see
+ * \ref subsec_hldo_direct_chunk_using for more information.
+ *
+ * \note H5Dread_chunk1() and H5Dwrite_chunk() are currently not supported
+ * with parallel HDF5 and do not support variable-length datatypes.
+ *
+ * \version 2.0.0 Function was deprecated
+ *
+ * \since 1.10.2
+ *
+ */
+H5_DLL herr_t H5Dread_chunk1(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters,
+ void *buf);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/src/H5VLnative.h b/src/H5VLnative.h
index 6b1cc5652ec..c6ec4d5118c 100644
--- a/src/H5VLnative.h
+++ b/src/H5VLnative.h
@@ -84,6 +84,7 @@ typedef struct H5VL_native_dataset_chunk_read_t {
const hsize_t *offset;
uint32_t filters;
void *buf;
+ size_t *buf_size;
} H5VL_native_dataset_chunk_read_t;
/* Parameters for native connector's dataset 'chunk write' operation */
diff --git a/src/H5VLnative_dataset.c b/src/H5VLnative_dataset.c
index 415a67a7ead..db0e974fca2 100644
--- a/src/H5VLnative_dataset.c
+++ b/src/H5VLnative_dataset.c
@@ -732,8 +732,8 @@ H5VL__native_dataset_optional(void *obj, H5VL_optional_args_t *args, hid_t dxpl_
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "failure to copy offset array");
/* Read the raw chunk */
- if (H5D__chunk_direct_read(dset, offset_copy, &chunk_read_args->filters, chunk_read_args->buf) <
- 0)
+ if (H5D__chunk_direct_read(dset, offset_copy, &chunk_read_args->filters, chunk_read_args->buf,
+ chunk_read_args->buf_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read unprocessed chunk data");
break;
diff --git a/src/H5vers.txt b/src/H5vers.txt
index de65f1298c1..e11c10c42d6 100644
--- a/src/H5vers.txt
+++ b/src/H5vers.txt
@@ -44,6 +44,7 @@ FUNCTION: H5Acreate; ; v10, v18
FUNCTION: H5Aiterate; H5A_operator; v10, v18
FUNCTION: H5Dcreate; ; v10, v18
FUNCTION: H5Dopen; ; v10, v18
+FUNCTION: H5Dread_chunk; ; v110, v200
FUNCTION: H5Eclear; ; v10, v18
FUNCTION: H5Eget_auto; ; v10, v18
FUNCTION: H5Eprint; ; v10, v18
diff --git a/src/H5version.h b/src/H5version.h
index 55b2e22ff55..92206293022 100644
--- a/src/H5version.h
+++ b/src/H5version.h
@@ -368,6 +368,10 @@
#define H5Dopen_vers 2
#endif /* !defined(H5Dopen_vers) */
+#if !defined(H5Dread_chunk_vers)
+ #define H5Dread_chunk_vers 1
+#endif /* !defined(H5Dread_chunk_vers) */
+
#if !defined(H5Eclear_vers)
#define H5Eclear_vers 2
#endif /* !defined(H5Eclear_vers) */
@@ -548,6 +552,10 @@
#define H5Dopen_vers 2
#endif /* !defined(H5Dopen_vers) */
+#if !defined(H5Dread_chunk_vers)
+ #define H5Dread_chunk_vers 1
+#endif /* !defined(H5Dread_chunk_vers) */
+
#if !defined(H5Eclear_vers)
#define H5Eclear_vers 2
#endif /* !defined(H5Eclear_vers) */
@@ -728,6 +736,10 @@
#define H5Dopen_vers 2
#endif /* !defined(H5Dopen_vers) */
+#if !defined(H5Dread_chunk_vers)
+ #define H5Dread_chunk_vers 1
+#endif /* !defined(H5Dread_chunk_vers) */
+
#if !defined(H5Eclear_vers)
#define H5Eclear_vers 2
#endif /* !defined(H5Eclear_vers) */
@@ -908,6 +920,10 @@
#define H5Dopen_vers 2
#endif /* !defined(H5Dopen_vers) */
+#if !defined(H5Dread_chunk_vers)
+ #define H5Dread_chunk_vers 2
+#endif /* !defined(H5Dread_chunk_vers) */
+
#if !defined(H5Eclear_vers)
#define H5Eclear_vers 2
#endif /* !defined(H5Eclear_vers) */
@@ -1123,6 +1139,17 @@
#error "H5Dopen_vers set to invalid value"
#endif /* H5Dopen_vers */
+#if !defined(H5Dread_chunk_vers) || H5Dread_chunk_vers == 2
+ #ifndef H5Dread_chunk_vers
+ #define H5Dread_chunk_vers 2
+ #endif /* H5Dread_chunk_vers */
+ #define H5Dread_chunk H5Dread_chunk2
+#elif H5Dread_chunk_vers == 1
+ #define H5Dread_chunk H5Dread_chunk1
+#else /* H5Dread_chunk_vers */
+ #error "H5Dread_chunk_vers set to invalid value"
+#endif /* H5Dread_chunk_vers */
+
#if !defined(H5Eclear_vers) || H5Eclear_vers == 2
#ifndef H5Eclear_vers
#define H5Eclear_vers 2
diff --git a/test/chunk_info.c b/test/chunk_info.c
index 6fd3b9ba09e..3c05d9234ed 100644
--- a/test/chunk_info.c
+++ b/test/chunk_info.c
@@ -325,11 +325,18 @@ verify_selected_chunks(hid_t dset, hid_t plist, const hsize_t *start, const hsiz
chk_index = 0;
for (ii = start[0]; ii < end[0]; ii++)
for (jj = start[1]; jj < end[1]; jj++, chk_index++) {
+ size_t tmp_buf_size;
+
offset[0] = ii * CHUNK_NX;
offset[1] = jj * CHUNK_NY;
/* Read the current chunk */
- if (H5Dread_chunk(dset, plist, offset, &read_flt_msk, read_buf) < 0)
+ tmp_buf_size = sizeof(read_buf);
+ if (H5Dread_chunk2(dset, plist, offset, &read_flt_msk, read_buf, &tmp_buf_size) < 0)
+ TEST_ERROR;
+
+ /* Check if buffer wasn't big enough */
+ if (tmp_buf_size > sizeof(read_buf))
TEST_ERROR;
/* Verify that read chunk is the same as the corresponding written one */
@@ -2060,12 +2067,18 @@ test_flt_msk_with_skip_compress(hid_t fapl)
if (read_buf_size != CHK_SIZE)
TEST_ERROR;
- /* Read the raw chunk back with H5Dread_chunk */
- memset(&read_direct_buf, 0, sizeof(read_direct_buf));
- if (H5Dread_chunk(dset, H5P_DEFAULT, offset, &read_flt_msk, read_direct_buf) < 0)
- TEST_ERROR;
- if (read_flt_msk != flt_msk)
- TEST_ERROR;
+ /* Read the raw chunk back with H5Dread_chunk2 */
+ {
+ size_t tmp_buf_size = sizeof(read_direct_buf);
+
+ memset(&read_direct_buf, 0, sizeof(read_direct_buf));
+ if (H5Dread_chunk2(dset, H5P_DEFAULT, offset, &read_flt_msk, read_direct_buf, &tmp_buf_size) < 0)
+ TEST_ERROR;
+ if (tmp_buf_size > sizeof(read_direct_buf))
+ TEST_ERROR;
+ if (read_flt_msk != flt_msk)
+ TEST_ERROR;
+ }
/* Check that the direct chunk read is the same as the chunk written */
for (ii = 0; ii < CHUNK_NX; ii++)
diff --git a/test/direct_chunk.c b/test/direct_chunk.c
index 9afdb47e95b..9aa18ada1dc 100644
--- a/test/direct_chunk.c
+++ b/test/direct_chunk.c
@@ -41,6 +41,10 @@
#endif
#define DATASETNAME11 "unallocated_chunk"
#define DATASETNAME12 "unfiltered_data"
+#define DATASETNAME13 "buf_size"
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+#define DATASETNAME14 "deprec"
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
#define RANK 2
#define NX 16
@@ -525,7 +529,7 @@ test_skip_compress_write1(hid_t file)
hsize_t count[2]; /* Block count */
hsize_t block[2]; /* Block sizes */
- TESTING("skipping compression filter for H5Dwrite_chunk/H5Dread_chunk");
+ TESTING("skipping compression filter for H5Dwrite_chunk/H5Dread_chunk2");
/*
* Create the data space with unlimited dimensions.
@@ -622,10 +626,17 @@ test_skip_compress_write1(hid_t file)
/* Read the raw chunk back */
memset(&read_direct_buf, 0, sizeof(read_direct_buf));
- if ((status = H5Dread_chunk(dataset, H5P_DEFAULT, offset, &read_filter_mask, read_direct_buf)) < 0)
+ if ((status =
+ H5Dread_chunk2(dataset, H5P_DEFAULT, offset, &read_filter_mask, read_direct_buf, &buf_size)) < 0)
goto error;
- if (read_filter_mask != filter_mask)
+ if (buf_size > read_buf_size) {
+ fprintf(stderr, "insufficient buffer size\n");
goto error;
+ }
+ if (read_filter_mask != filter_mask) {
+ fprintf(stderr, "incorrect filter mask returned\n");
+ goto error;
+ }
/* Check that the direct chunk read is the same as the chunk written */
for (i = 0; i < CHUNK_NX; i++) {
@@ -888,12 +899,101 @@ test_skip_compress_write2(hid_t file)
if (read_buf_size != buf_size)
goto error;
+ /* Zero out read buffer and filter mask */
+ memset(read_direct_buf, 0, sizeof(read_direct_buf));
+ read_filter_mask = 0;
+
+ /* Try reading with no buffer */
+ buf_size = 0;
+ if ((status = H5Dread_chunk2(dataset, H5P_DEFAULT, offset, &read_filter_mask, NULL, &buf_size)) < 0)
+ goto error;
+ if (buf_size != read_buf_size) {
+ fprintf(stderr, "insufficient buffer size\n");
+ goto error;
+ }
+ if (read_filter_mask != filter_mask) {
+ fprintf(stderr, "incorrect filter mask returned\n");
+ goto error;
+ }
+
+ /* Verify no data was read */
+ for (i = 0; i < CHUNK_NX; i++) {
+ for (j = 0; j < CHUNK_NY; j++) {
+ if (read_direct_buf[i][j] != 0) {
+ printf(" 1. Values read when buffer too small.");
+ printf(" At index %d,%d\n", i, j);
+ printf(" read_direct_buf=%d\n", read_direct_buf[i][j]);
+ goto error;
+ }
+ }
+ }
+
+ /* Try reading with buffer but 0 buf_size */
+ buf_size = 0;
+ read_filter_mask = 0;
+ if ((status =
+ H5Dread_chunk2(dataset, H5P_DEFAULT, offset, &read_filter_mask, read_direct_buf, &buf_size)) < 0)
+ goto error;
+ if (buf_size != read_buf_size) {
+ fprintf(stderr, "insufficient buffer size\n");
+ goto error;
+ }
+ if (read_filter_mask != filter_mask) {
+ fprintf(stderr, "incorrect filter mask returned\n");
+ goto error;
+ }
+
+ /* Verify no data was read */
+ for (i = 0; i < CHUNK_NX; i++) {
+ for (j = 0; j < CHUNK_NY; j++) {
+ if (read_direct_buf[i][j] != 0) {
+ printf(" 1. Values read when buffer too small.");
+ printf(" At index %d,%d\n", i, j);
+ printf(" read_direct_buf=%d\n", read_direct_buf[i][j]);
+ goto error;
+ }
+ }
+ }
+
+ /* Try reading with buffer but insufficient buf_size */
+ buf_size = read_buf_size - 1;
+ read_filter_mask = 0;
+ if ((status =
+ H5Dread_chunk2(dataset, H5P_DEFAULT, offset, &read_filter_mask, read_direct_buf, &buf_size)) < 0)
+ goto error;
+ if (buf_size != read_buf_size) {
+ fprintf(stderr, "insufficient buffer size\n");
+ goto error;
+ }
+ if (read_filter_mask != filter_mask) {
+ fprintf(stderr, "incorrect filter mask returned\n");
+ goto error;
+ }
+
+ /* Verify no data was read */
+ for (i = 0; i < CHUNK_NX; i++) {
+ for (j = 0; j < CHUNK_NY; j++) {
+ if (read_direct_buf[i][j] != 0) {
+ printf(" 1. Values read when buffer too small.");
+ printf(" At index %d,%d\n", i, j);
+ printf(" read_direct_buf=%d\n", read_direct_buf[i][j]);
+ goto error;
+ }
+ }
+ }
+
/* Read the raw chunk back */
- memset(&read_direct_buf, 0, sizeof(read_direct_buf));
- if ((status = H5Dread_chunk(dataset, H5P_DEFAULT, offset, &read_filter_mask, read_direct_buf)) < 0)
+ if ((status =
+ H5Dread_chunk2(dataset, H5P_DEFAULT, offset, &read_filter_mask, read_direct_buf, &buf_size)) < 0)
goto error;
- if (read_filter_mask != filter_mask)
+ if (buf_size > read_buf_size) {
+ fprintf(stderr, "insufficient buffer size\n");
goto error;
+ }
+ if (read_filter_mask != filter_mask) {
+ fprintf(stderr, "incorrect filter mask returned\n");
+ goto error;
+ }
/* Check that the direct chunk read is the same as the chunk written */
for (i = 0; i < CHUNK_NX; i++) {
@@ -969,7 +1069,7 @@ test_data_conv(hid_t file)
uint32_t filter_mask = 0;
src_type_t direct_buf[CHUNK_NX][CHUNK_NY];
dst_type_t check_chunk[CHUNK_NX][CHUNK_NY];
- src_type_t read_chunk[CHUNK_NX][CHUNK_NY]; /* For H5Dread_chunk */
+ src_type_t read_chunk[CHUNK_NX][CHUNK_NY]; /* For H5Dread_chunk2 */
hsize_t offset[2] = {0, 0};
size_t buf_size = CHUNK_NX * CHUNK_NY * sizeof(src_type_t);
@@ -979,7 +1079,7 @@ test_data_conv(hid_t file)
hsize_t count[2]; /* Block count */
hsize_t block[2]; /* Block sizes */
- TESTING("data conversion for H5Dwrite_chunk/H5Dread_chunk");
+ TESTING("data conversion for H5Dwrite_chunk/H5Dread_chunk2");
/*
* Create the data space with unlimited dimensions.
@@ -1063,9 +1163,17 @@ test_data_conv(hid_t file)
if ((dataset = H5Dopen2(file, DATASETNAME4, H5P_DEFAULT)) < 0)
goto error;
- /* Use H5Dread_chunk() to read the uncompressed data */
- if ((status = H5Dread_chunk(dataset, dxpl, offset, &filter_mask, read_chunk)) < 0)
- goto error;
+ /* Use H5Dread_chunk2() to read the uncompressed data */
+ {
+ size_t tmp_buf_size = buf_size;
+
+ if ((status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, read_chunk, &tmp_buf_size)) < 0)
+ goto error;
+ if (tmp_buf_size > buf_size) {
+ fprintf(stderr, "insufficient buffer size\n");
+ goto error;
+ }
+ }
/* Check that the values read are the same as the values written */
for (i = 0; i < CHUNK_NX; i++) {
@@ -1170,7 +1278,7 @@ error:
/*-------------------------------------------------------------------------
* Function: test_invalid_parameters
*
- * Purpose: Test invalid parameters for H5Dwrite_chunk and H5Dread_chunk
+ * Purpose: Test invalid parameters for H5Dwrite_chunk and H5Dread_chunk2
*
* Return: Success: 0
* Failure: 1
@@ -1190,13 +1298,12 @@ test_invalid_parameters(hid_t file)
uint32_t filter_mask = 0;
int direct_buf[CHUNK_NX][CHUNK_NY];
- hsize_t offset[2] = {0, 0};
- size_t buf_size = CHUNK_NX * CHUNK_NY * sizeof(int);
- int aggression = 9; /* Compression aggression setting */
+ hsize_t offset[2] = {0, 0};
+ size_t buf_size = CHUNK_NX * CHUNK_NY * sizeof(int);
hsize_t chunk_nbytes; /* Chunk size */
- TESTING("invalid parameters for H5Dwrite_chunk/H5Dread_chunk");
+ TESTING("invalid parameters for H5Dwrite_chunk/H5Dread_chunk2");
/*
* Create the data space with unlimited dimensions.
@@ -1213,8 +1320,12 @@ test_invalid_parameters(hid_t file)
if ((cparms = H5Pcreate(H5P_DATASET_CREATE)) < 0)
goto error;
+ /* Set early allocation time so unallocated data doesn't cause failures that mask an unexpected success */
+ if (H5Pset_alloc_time(cparms, H5D_ALLOC_TIME_EARLY) < 0)
+ goto error;
+
/*
- * Create a new contiguous dataset to verify H5Dwrite_chunk/H5Dread_chunk doesn't work
+ * Create a new contiguous dataset to verify H5Dwrite_chunk/H5Dread_chunk2 doesn't work
*/
if ((dataset =
H5Dcreate2(file, DATASETNAME5, H5T_NATIVE_INT, dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT)) < 0)
@@ -1248,10 +1359,12 @@ test_invalid_parameters(hid_t file)
}
H5E_END_TRY
- /* Try to H5Dread_chunk from the contiguous dataset. It should fail */
+ /* Try to H5Dread_chunk2 from the contiguous dataset. It should fail */
H5E_BEGIN_TRY
{
- if ((status = H5Dread_chunk(dataset, dxpl, offset, &filter_mask, direct_buf)) != FAIL)
+ size_t tmp_buf_size = buf_size;
+
+ if ((status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, direct_buf, &tmp_buf_size)) != FAIL)
goto error;
}
H5E_END_TRY
@@ -1259,12 +1372,17 @@ test_invalid_parameters(hid_t file)
if (H5Dclose(dataset) < 0)
goto error;
- /* Create a chunked dataset with compression filter */
+ /* Create a chunked dataset with compression filter (if available) */
if ((status = H5Pset_chunk(cparms, RANK, chunk_dims)) < 0)
goto error;
- if ((status = H5Pset_deflate(cparms, (unsigned)aggression)) < 0)
- goto error;
+#ifdef H5_HAVE_FILTER_DEFLATE
+ {
+ unsigned aggression = 9; /* Compression aggression setting */
+ if ((status = H5Pset_deflate(cparms, aggression)) < 0)
+ goto error;
+ }
+#endif /* H5_HAVE_FILTER_DEFLATE */
/*
* Create a new dataset within the file using cparms
@@ -1274,7 +1392,7 @@ test_invalid_parameters(hid_t file)
H5Dcreate2(file, DATASETNAME6, H5T_NATIVE_INT, dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT)) < 0)
goto error;
- /* Check invalid dataset ID for H5Dwrite_chunk and H5Dread_chunk */
+ /* Check invalid dataset ID for H5Dwrite_chunk and H5Dread_chunk2 */
H5E_BEGIN_TRY
{
if ((status = H5Dwrite_chunk((hid_t)H5I_INVALID_HID, dxpl, filter_mask, offset, buf_size,
@@ -1285,12 +1403,15 @@ test_invalid_parameters(hid_t file)
H5E_BEGIN_TRY
{
- if ((status = H5Dread_chunk((hid_t)H5I_INVALID_HID, dxpl, offset, &filter_mask, direct_buf)) != FAIL)
+ size_t tmp_buf_size = buf_size;
+
+ if ((status = H5Dread_chunk2((hid_t)H5I_INVALID_HID, dxpl, offset, &filter_mask, direct_buf,
+ &tmp_buf_size)) != FAIL)
goto error;
}
H5E_END_TRY
- /* Check invalid DXPL ID for H5Dwrite_chunk and H5Dread_chunk */
+ /* Check invalid DXPL ID for H5Dwrite_chunk and H5Dread_chunk2 */
H5E_BEGIN_TRY
{
if ((status = H5Dwrite_chunk(dataset, (hid_t)H5I_INVALID_HID, filter_mask, offset, buf_size,
@@ -1301,13 +1422,15 @@ test_invalid_parameters(hid_t file)
H5E_BEGIN_TRY
{
- if ((status = H5Dread_chunk(dataset, (hid_t)H5I_INVALID_HID, offset, &filter_mask, direct_buf)) !=
- FAIL)
+ size_t tmp_buf_size = buf_size;
+
+ if ((status = H5Dread_chunk2(dataset, (hid_t)H5I_INVALID_HID, offset, &filter_mask, direct_buf,
+ &tmp_buf_size)) != FAIL)
goto error;
}
H5E_END_TRY
- /* Check invalid OFFSET for H5Dwrite_chunk and H5Dread_chunk */
+ /* Check invalid OFFSET for H5Dwrite_chunk and H5Dread_chunk2 */
H5E_BEGIN_TRY
{
if ((status = H5Dwrite_chunk(dataset, dxpl, filter_mask, NULL, buf_size, direct_buf)) != FAIL)
@@ -1317,12 +1440,14 @@ test_invalid_parameters(hid_t file)
H5E_BEGIN_TRY
{
- if ((status = H5Dread_chunk(dataset, dxpl, NULL, &filter_mask, direct_buf)) != FAIL)
+ size_t tmp_buf_size = buf_size;
+
+ if ((status = H5Dread_chunk2(dataset, dxpl, NULL, &filter_mask, direct_buf, &tmp_buf_size)) != FAIL)
goto error;
}
H5E_END_TRY
- /* Check when OFFSET is out of dataset range for H5Dwrite_chunk and H5Dread_chunk */
+ /* Check when OFFSET is out of dataset range for H5Dwrite_chunk and H5Dread_chunk2 */
offset[0] = NX + 1;
offset[1] = NY;
H5E_BEGIN_TRY
@@ -1334,12 +1459,14 @@ test_invalid_parameters(hid_t file)
H5E_BEGIN_TRY
{
- if ((status = H5Dread_chunk(dataset, dxpl, offset, &filter_mask, direct_buf)) != FAIL)
+ size_t tmp_buf_size = buf_size;
+
+ if ((status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, direct_buf, &tmp_buf_size)) != FAIL)
goto error;
}
H5E_END_TRY
- /* Check when OFFSET is not on chunk boundary for H5Dwrite_chunk and H5Dread_chunk */
+ /* Check when OFFSET is not on chunk boundary for H5Dwrite_chunk and H5Dread_chunk2 */
offset[0] = CHUNK_NX;
offset[1] = CHUNK_NY + 1;
H5E_BEGIN_TRY
@@ -1351,7 +1478,9 @@ test_invalid_parameters(hid_t file)
H5E_BEGIN_TRY
{
- if ((status = H5Dread_chunk(dataset, dxpl, offset, &filter_mask, direct_buf)) != FAIL)
+ size_t tmp_buf_size = buf_size;
+
+ if ((status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, direct_buf, &tmp_buf_size)) != FAIL)
goto error;
}
H5E_END_TRY
@@ -1367,7 +1496,7 @@ test_invalid_parameters(hid_t file)
}
H5E_END_TRY
- /* Check invalid data buffer for H5Dwrite_chunk and H5Dread_chunk */
+ /* Check invalid data buffer for H5Dwrite_chunk only */
buf_size = CHUNK_NX * CHUNK_NY * sizeof(int);
H5E_BEGIN_TRY
{
@@ -1376,9 +1505,17 @@ test_invalid_parameters(hid_t file)
}
H5E_END_TRY
+ /* Check invalid buffer size pointer for H5Dread_chunk2, with and without data buffer */
H5E_BEGIN_TRY
{
- if ((status = H5Dread_chunk(dataset, dxpl, offset, &filter_mask, NULL)) != FAIL)
+ if ((status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, direct_buf, NULL)) != FAIL)
+ goto error;
+ }
+ H5E_END_TRY
+
+ H5E_BEGIN_TRY
+ {
+ if ((status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, NULL, NULL)) != FAIL)
goto error;
}
H5E_END_TRY
@@ -1389,10 +1526,14 @@ test_invalid_parameters(hid_t file)
/*
* Close/release resources.
*/
- H5Sclose(mem_space);
- H5Sclose(dataspace);
- H5Pclose(cparms);
- H5Pclose(dxpl);
+ if (H5Sclose(mem_space) < 0)
+ goto error;
+ if (H5Sclose(dataspace) < 0)
+ goto error;
+ if (H5Pclose(cparms) < 0)
+ goto error;
+ if (H5Pclose(dxpl) < 0)
+ goto error;
PASSED();
return 0;
@@ -1415,7 +1556,7 @@ error:
/*-------------------------------------------------------------------------
* Function: test_direct_chunk_read_no_cache
*
- * Purpose: Test the basic functionality of H5Dread_chunk with the
+ * Purpose: Test the basic functionality of H5Dread_chunk2 with the
* chunk cache disabled.
*
* Return: Success: 0
@@ -1438,10 +1579,10 @@ test_direct_chunk_read_no_cache(hid_t file)
int data[NX][NY];
int i, j, k, l, n; /* local index variables */
- uint32_t filter_mask = 0; /* filter mask returned from H5Dread_chunk */
+ uint32_t filter_mask = 0; /* filter mask returned from H5Dread_chunk2 */
int direct_buf[CHUNK_NX][CHUNK_NY]; /* chunk read with H5Dread and manually decompressed */
int check_chunk[CHUNK_NX][CHUNK_NY]; /* chunk read with H5Dread */
- hsize_t offset[2]; /* chunk offset used for H5Dread_chunk */
+ hsize_t offset[2]; /* chunk offset used for H5Dread_chunk2 */
size_t buf_size = CHUNK_NX * CHUNK_NY * sizeof(int);
Bytef *z_src = NULL; /* source buffer */
@@ -1456,7 +1597,7 @@ test_direct_chunk_read_no_cache(hid_t file)
hsize_t count[2]; /* Block count */
hsize_t block[2]; /* Block sizes */
- TESTING("basic functionality of H5Dread_chunk (chunk cache disabled)");
+ TESTING("basic functionality of H5Dread_chunk2 (chunk cache disabled)");
/* Create the data space with unlimited dimensions. */
if ((dataspace = H5Screate_simple(RANK, dims, maxdims)) < 0)
@@ -1500,9 +1641,11 @@ test_direct_chunk_read_no_cache(hid_t file)
outbuf = malloc(z_src_nbytes);
z_src = (Bytef *)outbuf;
- /* For each chunk in the dataset, compare the result of H5Dread and H5Dread_chunk. */
+ /* For each chunk in the dataset, compare the result of H5Dread and H5Dread_chunk2. */
for (i = 0; i < NX / CHUNK_NX; i++) {
for (j = 0; j < NY / CHUNK_NY; j++) {
+ size_t tmp_buf_size;
+
/* Select hyperslab for one chunk in the file */
start[0] = (hsize_t)i * CHUNK_NX;
start[1] = (hsize_t)j * CHUNK_NY;
@@ -1525,14 +1668,23 @@ test_direct_chunk_read_no_cache(hid_t file)
offset[0] = (hsize_t)i * CHUNK_NX;
offset[1] = (hsize_t)j * CHUNK_NY;
/* Read the compressed chunk back using the direct read function. */
- if ((status = H5Dread_chunk(dataset, dxpl, offset, &filter_mask, outbuf)) < 0)
+ tmp_buf_size = buf_size;
+ if ((status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, outbuf, &tmp_buf_size)) < 0)
goto error;
+ /* Check if buffer wasn't big enough */
+ if (tmp_buf_size > buf_size) {
+ fprintf(stderr, "insufficient buffer size\n");
+ goto error;
+ }
+
/* Check filter mask return value */
- if (filter_mask != 0)
+ if (filter_mask != 0) {
+ fprintf(stderr, "incorrect filter mask returned\n");
goto error;
+ }
- /* Perform decompression from the source to the destination buffer */
+ /* Perform decompression from the source to the destination buffer */
#if defined(H5_HAVE_ZLIBNG_H)
ret = zng_uncompress(z_dst, &z_dst_nbytes, z_src, z_src_nbytes);
#else
@@ -1620,10 +1772,10 @@ test_direct_chunk_read_cache(hid_t file, bool flush)
int data[NX][NY];
int i, j, k, l, n; /* local index variables */
- uint32_t filter_mask = 0; /* filter mask returned from H5Dread_chunk */
+ uint32_t filter_mask = 0; /* filter mask returned from H5Dread_chunk2 */
int direct_buf[CHUNK_NX][CHUNK_NY]; /* chunk read with H5Dread and manually decompressed */
int check_chunk[CHUNK_NX][CHUNK_NY]; /* chunk read with H5Dread */
- hsize_t offset[2]; /* chunk offset used for H5Dread_chunk */
+ hsize_t offset[2]; /* chunk offset used for H5Dread_chunk2 */
size_t buf_size = CHUNK_NX * CHUNK_NY * sizeof(int);
Bytef *z_src = NULL; /* source buffer */
@@ -1640,10 +1792,10 @@ test_direct_chunk_read_cache(hid_t file, bool flush)
hsize_t block[2]; /* Block sizes */
if (flush) {
- TESTING("basic functionality of H5Dread_chunk (flush chunk cache)");
+ TESTING("basic functionality of H5Dread_chunk2 (flush chunk cache)");
}
else {
- TESTING("basic functionality of H5Dread_chunk (does not flush chunk cache)");
+ TESTING("basic functionality of H5Dread_chunk2 (does not flush chunk cache)");
}
/* Create the data space with unlimited dimensions. */
@@ -1688,9 +1840,11 @@ test_direct_chunk_read_cache(hid_t file, bool flush)
outbuf = malloc(z_src_nbytes);
z_src = (Bytef *)outbuf;
- /* For each chunk in the dataset, compare the result of H5Dread and H5Dread_chunk. */
+ /* For each chunk in the dataset, compare the result of H5Dread and H5Dread_chunk2. */
for (i = 0; i < NX / CHUNK_NX; i++) {
for (j = 0; j < NY / CHUNK_NY; j++) {
+ size_t tmp_buf_size;
+
/* Select hyperslab for one chunk in the file */
start[0] = (hsize_t)i * CHUNK_NX;
start[1] = (hsize_t)j * CHUNK_NY;
@@ -1720,14 +1874,23 @@ test_direct_chunk_read_cache(hid_t file, bool flush)
goto error;
/* Read the compressed chunk back using the direct read function. */
- if ((status = H5Dread_chunk(dataset, dxpl, offset, &filter_mask, outbuf)) < 0)
+ tmp_buf_size = buf_size;
+ if ((status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, outbuf, &tmp_buf_size)) < 0)
goto error;
+ /* Check if buffer wasn't big enough */
+ if (tmp_buf_size > buf_size) {
+ fprintf(stderr, "insufficient buffer size\n");
+ goto error;
+ }
+
/* Check filter mask return value */
- if (filter_mask != 0)
+ if (filter_mask != 0) {
+ fprintf(stderr, "incorrect filter mask returned\n");
goto error;
+ }
- /* Perform decompression from the source to the destination buffer */
+ /* Perform decompression from the source to the destination buffer */
#if defined(H5_HAVE_ZLIBNG_H)
ret = zng_uncompress(z_dst, &z_dst_nbytes, z_src, z_src_nbytes);
#else
@@ -1801,7 +1964,7 @@ error:
/*-------------------------------------------------------------------------
* Function: test_read_unfiltered_dset
*
- * Purpose: Test the basic functionality of H5Dread_chunk on a dataset
+ * Purpose: Test the basic functionality of H5Dread_chunk2 on a dataset
* without no filters applied.
*
* Return: Success: 0
@@ -1834,7 +1997,7 @@ test_read_unfiltered_dset(hid_t file)
hsize_t count[2]; /* Block count */
hsize_t block[2]; /* Block sizes */
- TESTING("basic functionality of H5Dread_chunk on unfiltered datasets");
+ TESTING("basic functionality of H5Dread_chunk2 on unfiltered datasets");
/* Create the data space with unlimited dimensions. */
if ((dataspace = H5Screate_simple(RANK, dims, maxdims)) < 0)
@@ -1863,16 +2026,18 @@ test_read_unfiltered_dset(hid_t file)
/* Write the data for the dataset.
* It should stay in the chunk cache and will be evicted/flushed by
- * the H5Dread_chunk function call. */
+ * the H5Dread_chunk2 function call. */
if ((status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl, data)) < 0)
goto error;
if (H5Fflush(dataset, H5F_SCOPE_LOCAL) < 0)
goto error;
- /* For each chunk in the dataset, compare the result of H5Dread and H5Dread_chunk. */
+ /* For each chunk in the dataset, compare the result of H5Dread and H5Dread_chunk2. */
for (i = 0; i < NX / CHUNK_NX; i++) {
for (j = 0; j < NY / CHUNK_NY; j++) {
+ size_t tmp_buf_size;
+
/* Select hyperslab for one chunk in the file */
start[0] = (hsize_t)i * CHUNK_NX;
start[1] = (hsize_t)j * CHUNK_NY;
@@ -1903,13 +2068,22 @@ test_read_unfiltered_dset(hid_t file)
offset[1] = (hsize_t)j * CHUNK_NY;
/* Read the raw chunk back */
memset(&direct_buf, 0, sizeof(direct_buf));
- filter_mask = UINT_MAX;
- if ((status = H5Dread_chunk(dataset, dxpl, offset, &filter_mask, direct_buf)) < 0)
+ filter_mask = UINT_MAX;
+ tmp_buf_size = buf_size;
+ if ((status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, direct_buf, &tmp_buf_size)) < 0)
goto error;
- /* Check filter mask return value */
- if (filter_mask != 0)
+ /* Check if buffer wasn't big enough */
+ if (tmp_buf_size > buf_size) {
+ fprintf(stderr, "insufficient buffer size\n");
goto error;
+ }
+
+ /* Check filter mask return value */
+ if (filter_mask != 0) {
+ fprintf(stderr, "incorrect filter mask returned\n");
+ goto error;
+ }
/* Check that the decompressed values match those read from H5Dread */
for (k = 0; k < CHUNK_NX; k++) {
@@ -1953,7 +2127,7 @@ error:
/*-------------------------------------------------------------------------
* Function: test_read_unallocated_chunk
*
- * Purpose: Tests the H5Dread_chunk and H5Dget_chunk_storage_size with valid
+ * Purpose: Tests the H5Dread_chunk2 and H5Dget_chunk_storage_size with valid
* offsets to chunks that have not been written to the dataset and are
* not allocated in the chunk storage on disk.
*
@@ -1976,11 +2150,11 @@ test_read_unallocated_chunk(hid_t file)
herr_t status; /* status from H5 function calls */
hsize_t i, j; /* local index variables */
- uint32_t filter_mask = 0; /* filter mask returned from H5Dread_chunk */
+ uint32_t filter_mask = 0; /* filter mask returned from H5Dread_chunk2 */
int direct_buf[CHUNK_NX][CHUNK_NY]; /* chunk read with H5Dread and manually decompressed */
- hsize_t offset[2]; /* chunk offset used for H5Dread_chunk */
+ hsize_t offset[2]; /* chunk offset used for H5Dread_chunk2 */
- TESTING("H5Dread_chunk with unallocated chunks");
+ TESTING("H5Dread_chunk2 with unallocated chunks");
/* Create the data space with unlimited dimensions. */
if ((dataspace = H5Screate_simple(RANK, dims, maxdims)) < 0)
@@ -2011,8 +2185,8 @@ test_read_unallocated_chunk(hid_t file)
FAIL_STACK_ERROR;
/* Attempt to read each chunk in the dataset. Chunks are not allocated,
- * therefore we expect the result of H5Dread_chunk to fail. Chunk idx starts
- * at 1, since one chunk was written to init the chunk storage. */
+ * therefore we expect the result of H5Dread_chunk2 to fail. Chunk idx
+ * starts at 1, since one chunk was written to init the chunk storage. */
for (i = 1; i < NX / CHUNK_NX; i++) {
for (j = 0; j < NY / CHUNK_NY; j++) {
@@ -2022,7 +2196,9 @@ test_read_unallocated_chunk(hid_t file)
/* Read a non-existent chunk using the direct read function. */
H5E_BEGIN_TRY
{
- status = H5Dread_chunk(dataset, dxpl, offset, &filter_mask, &direct_buf);
+ size_t tmp_buf_size = sizeof(direct_buf);
+
+ status = H5Dread_chunk2(dataset, dxpl, offset, &filter_mask, &direct_buf, &tmp_buf_size);
}
H5E_END_TRY
@@ -2076,6 +2252,283 @@ error:
return 1;
} /* test_read_unallocated_chunk() */
+/*-------------------------------------------------------------------------
+ * Function: test_direct_chunk_read_buf_size
+ *
+ * Purpose: Test buffer size parameter/query for H5Dread_chunk2
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_direct_chunk_read_buf_size(hid_t fid)
+{
+ hid_t sid = H5I_INVALID_HID; /* Dataspace ID */
+ hid_t did = H5I_INVALID_HID; /* Dataset ID */
+ hid_t dcpl = H5I_INVALID_HID; /* Dataset creation property list */
+ hsize_t dims[2] = {DIM0, DIM1}; /* Dimension sizes */
+ hsize_t chunk[2] = {CHUNK0, CHUNK1}; /* Chunk dimension sizes */
+ hsize_t offset[2] = {0, 0}; /* Offset for writing */
+ uint32_t filters; /* Filter mask out */
+ size_t tmp_buf_size; /* Size of buffer as passed to H5Dread_chunk2 */
+ int wdata[DIM0][DIM1]; /* Write buffer */
+ int rdata[DIM0][DIM1]; /* Read buffer */
+ int i, j; /* Local index variable */
+
+ TESTING("Read buffer size parameter");
+
+ /* Initialize data */
+ for (i = 0; i < DIM0; i++)
+ for (j = 0; j < DIM1; j++)
+ wdata[i][j] = j / CHUNK0;
+
+ /* Create dataspace */
+ if ((sid = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR;
+
+ /* Create the dataset creation property list and set the chunk size */
+ if ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ if (H5Pset_chunk(dcpl, 2, chunk) < 0)
+ TEST_ERROR;
+
+ /* Create the dataset */
+ if ((did = H5Dcreate2(fid, DATASETNAME13, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Write the data directly to the dataset */
+ if (H5Dwrite_chunk(did, H5P_DEFAULT, 0, offset, CHUNK0 * CHUNK1 * sizeof(int), (void *)wdata) < 0)
+ TEST_ERROR;
+
+ /* Zero out read buffer */
+ memset(rdata, 0, sizeof(rdata));
+
+ /* Test with no buffer and 0 tmp_buf_size */
+ tmp_buf_size = 0;
+ if (H5Dread_chunk2(did, H5P_DEFAULT, offset, &filters, NULL, &tmp_buf_size) < 0)
+ TEST_ERROR;
+
+ /* Verify correct buffer size returned */
+ if (tmp_buf_size != sizeof(rdata))
+ TEST_ERROR;
+
+ /* Verify returned filter mask */
+ if (filters != 0)
+ TEST_ERROR;
+
+ /* Verify no data was read */
+ for (i = 0; i < DIM0; i++)
+ for (j = 0; j < DIM1; j++)
+ if (rdata[i][j] != 0)
+ TEST_ERROR;
+
+ /* Test with no buffer and nonzero tmp_buf_size */
+ tmp_buf_size = 2112;
+ if (H5Dread_chunk2(did, H5P_DEFAULT, offset, &filters, NULL, &tmp_buf_size) < 0)
+ TEST_ERROR;
+
+ /* Verify correct buffer size returned */
+ if (tmp_buf_size != sizeof(rdata))
+ TEST_ERROR;
+
+ /* Verify returned filter mask */
+ if (filters != 0)
+ TEST_ERROR;
+
+ /* Verify no data was read */
+ for (i = 0; i < DIM0; i++)
+ for (j = 0; j < DIM1; j++)
+ if (rdata[i][j] != 0)
+ TEST_ERROR;
+
+ /* Test with buffer but 0 tmp_buf_size */
+ tmp_buf_size = 0;
+ if (H5Dread_chunk2(did, H5P_DEFAULT, offset, &filters, rdata, &tmp_buf_size) < 0)
+ TEST_ERROR;
+
+ /* Verify correct buffer size returned */
+ if (tmp_buf_size != sizeof(rdata))
+ TEST_ERROR;
+
+ /* Verify returned filter mask */
+ if (filters != 0)
+ TEST_ERROR;
+
+ /* Verify no data was read */
+ for (i = 0; i < DIM0; i++)
+ for (j = 0; j < DIM1; j++)
+ if (rdata[i][j] != 0)
+ TEST_ERROR;
+
+ /* Test with buffer but insufficient tmp_buf_size */
+ tmp_buf_size = sizeof(rdata) - 1;
+ if (H5Dread_chunk2(did, H5P_DEFAULT, offset, &filters, rdata, &tmp_buf_size) < 0)
+ TEST_ERROR;
+
+ /* Verify correct buffer size returned */
+ if (tmp_buf_size != sizeof(rdata))
+ TEST_ERROR;
+
+ /* Verify returned filter mask */
+ if (filters != 0)
+ TEST_ERROR;
+
+ /* Verify no data was read */
+ for (i = 0; i < DIM0; i++)
+ for (j = 0; j < DIM1; j++)
+ if (rdata[i][j] != 0)
+ TEST_ERROR;
+
+ /* Read the data directly */
+ if (H5Dread_chunk2(did, H5P_DEFAULT, offset, &filters, rdata, &tmp_buf_size) < 0)
+ TEST_ERROR;
+
+ /* Check if buffer wasn't big enough */
+ if (tmp_buf_size > sizeof(rdata))
+ TEST_ERROR;
+
+ /* Verify returned filter mask */
+ if (filters != 0)
+ TEST_ERROR;
+
+ /* Verify that the data read was correct. */
+ for (i = 0; i < DIM0; i++)
+ for (j = 0; j < DIM1; j++)
+ if (rdata[i][j] != wdata[i][j])
+ TEST_ERROR;
+
+ /*
+ * Close and release resources
+ */
+ if (H5Pclose(dcpl) < 0)
+ TEST_ERROR;
+ if (H5Sclose(sid) < 0)
+ TEST_ERROR;
+ if (H5Dclose(did) < 0)
+ TEST_ERROR;
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Dclose(did);
+ H5Sclose(sid);
+ H5Pclose(dcpl);
+ }
+ H5E_END_TRY
+
+ H5_FAILED();
+ return 1;
+} /* end test_direct_chunk_read_buf_size() */
+
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+/*-------------------------------------------------------------------------
+ * Function: test_deprec
+ *
+ * Purpose: Test deprecated symbols
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_deprec(hid_t fid)
+{
+ hid_t sid = H5I_INVALID_HID; /* Dataspace ID */
+ hid_t did = H5I_INVALID_HID; /* Dataset ID */
+ hid_t dcpl = H5I_INVALID_HID; /* Dataset creation property list */
+ hsize_t dims[2] = {DIM0, DIM1}; /* Dimension sizes */
+ hsize_t chunk[2] = {CHUNK0, CHUNK1}; /* Chunk dimension sizes */
+ hsize_t offset[2] = {0, 0}; /* Offset for writing */
+ uint32_t filters; /* Filter mask out */
+ int wdata[DIM0][DIM1]; /* Write buffer */
+ int rdata[DIM0][DIM1]; /* Read buffer */
+ int i, j; /* Local index variable */
+
+ TESTING("Deprecated symbols");
+
+ /* Initialize data */
+ for (i = 0; i < DIM0; i++)
+ for (j = 0; j < DIM1; j++)
+ wdata[i][j] = j / CHUNK0;
+
+ /* Create dataspace */
+ if ((sid = H5Screate_simple(2, dims, NULL)) < 0)
+ TEST_ERROR;
+
+ /* Create the dataset creation property list and set the chunk size */
+ if ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR;
+ if (H5Pset_chunk(dcpl, 2, chunk) < 0)
+ TEST_ERROR;
+
+ /* Create the dataset */
+ if ((did = H5Dcreate2(fid, DATASETNAME14, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR;
+
+ /* Write the data directly to the dataset */
+ if (H5Dwrite_chunk(did, H5P_DEFAULT, 0, offset, CHUNK0 * CHUNK1 * sizeof(int), (void *)wdata) < 0)
+ TEST_ERROR;
+
+ /* Zero out read buffer */
+ memset(rdata, 0, sizeof(rdata));
+
+ /* Try reading with no buffer */
+ H5E_BEGIN_TRY
+ {
+ herr_t ret;
+ ret = H5Dread_chunk1(did, H5P_DEFAULT, offset, &filters, NULL);
+ if (ret >= 0)
+ TEST_ERROR;
+ }
+ H5E_END_TRY
+
+ /* Read the data directly */
+ if (H5Dread_chunk1(did, H5P_DEFAULT, offset, &filters, rdata) < 0)
+ TEST_ERROR;
+
+ /* Verify returned filter mask */
+ if (filters != 0)
+ TEST_ERROR;
+
+ /* Verify that the data read was correct. */
+ for (i = 0; i < DIM0; i++)
+ for (j = 0; j < DIM1; j++)
+ if (rdata[i][j] != wdata[i][j])
+ TEST_ERROR;
+
+ /*
+ * Close and release resources
+ */
+ if (H5Pclose(dcpl) < 0)
+ TEST_ERROR;
+ if (H5Sclose(sid) < 0)
+ TEST_ERROR;
+ if (H5Dclose(did) < 0)
+ TEST_ERROR;
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY
+ {
+ H5Dclose(did);
+ H5Sclose(sid);
+ H5Pclose(dcpl);
+ }
+ H5E_END_TRY
+
+ H5_FAILED();
+ return 1;
+} /* end test_deprec() */
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
/*-------------------------------------------------------------------------
* Function: test_single_chunk
*
@@ -2149,7 +2602,7 @@ test_single_chunk(unsigned config)
if (config & CONFIG_DIRECT_WRITE) {
/* Write the data directly to the dataset */
- if (H5Dwrite_chunk(did, H5P_DEFAULT, 0, offset, CHUNK0 * CHUNK1 * 4, (void *)wdata) < 0)
+ if (H5Dwrite_chunk(did, H5P_DEFAULT, 0, offset, CHUNK0 * CHUNK1 * sizeof(int), (void *)wdata) < 0)
FAIL_STACK_ERROR;
} /* end if */
else
@@ -2186,9 +2639,15 @@ test_single_chunk(unsigned config)
FAIL_STACK_ERROR;
if (config & CONFIG_DIRECT_READ) {
+ size_t tmp_buf_size = sizeof(rdata);
+
/* Read the data directly */
- if (H5Dread_chunk(did, H5P_DEFAULT, offset, &filters, rdata) < 0)
- FAIL_STACK_ERROR;
+ if (H5Dread_chunk2(did, H5P_DEFAULT, offset, &filters, rdata, &tmp_buf_size) < 0)
+ TEST_ERROR;
+
+ /* Check if buffer wasn't big enough */
+ if (tmp_buf_size > sizeof(rdata))
+ TEST_ERROR;
/* Verify returned filter mask */
if (filters != 0)
@@ -2231,13 +2690,13 @@ error:
H5_FAILED();
return 1;
-} /* test_single_chunk_latest() */
+} /* test_single_chunk() */
/*-------------------------------------------------------------------------
* Function: Main function
*
* Purpose: Test direct chunk write function H5Dwrite_chunk and
- * chunk direct read function H5Dread_chunk
+ * chunk direct read function H5Dread_chunk2
*
* Return: Success: 0
* Failure: 1
@@ -2275,6 +2734,10 @@ main(void)
#endif /* H5_HAVE_FILTER_DEFLATE */
nerrors += test_read_unfiltered_dset(file_id);
nerrors += test_read_unallocated_chunk(file_id);
+ nerrors += test_direct_chunk_read_buf_size(file_id);
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ nerrors += test_deprec(file_id);
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
/* Loop over test configurations */
for (config = 0; config < CONFIG_END; config++) {