Multi Dataset (#2120)

* Fix bug with cross platform compatibility of references within vlens.
No testing yet.

* Merge from multi_rd_wd_coll_io to a more recent branch from develop.
Untested, probably does not work yet.

* Committing clang-format changes

* Committing clang-format changes

* Fix many bugs in multi dataset branch.  Mostly works, some issues in
SWMR tests.

* Committing clang-format changes

* Disable test in swmr.c that was failing due to bug in HDF5 unrelated to
multi dataset.

* Committing clang-format changes

* Fixed fortran multi-dataset tests

* Fixed xlf errors

* Added benchmark code for multi-datasets

* loops over datasets

* added missing error arg.

* Added gnuplot formatting

* Jonathan Kim original MD benchmarking code

* updated MD benchmarking code

* code clean-up

* Only make files in feature test mode

* misc clean-up

* removed TEST_MDSET_NO_LAST_DSET_2ND_PROC option

* Committing clang-format changes

* Change multi dataset API to use arrays of individual parameters instead
of the parameter struct.

* Committing clang-format changes

* Update to new multi dataset Fortran API and tests. (#1724)

* Update to new multi dataset Fortran API and tests.
* Sync Fortran with develop.
* skipping h5pget_mpio_actual_io_mode_f for now

* Fixed issue with dxpl_id, changed to variable size dim. (#1770)

* Remove "is_coll_broken" field from H5D_io_info_t struct

* Committing clang-format changes

* Minor cleanup in multi dataset code.

* Committing clang-format changes

* Clean up in multi dataset code.

* Committing clang-format changes

* Committing clang-format changes

* Fix speeling

* Fix bug in parallel compression. Switch base_maddr in io_info to be a
union.

* Committing clang-format changes

* Implement selection I/O support with multi dataset.  Will be broken in
parallel until PR 1803 is merged to develop then the MDS branch.

* Committing clang-format changes

* Spelling

* Fix bug in multi dataset that could cause errors when only some of the
datasets in the multi dataset I/O used type conversion.

* Committing clang-format changes

* Integrate multi dataset APIs with VOL layer.  Add async versions of
multi dataset APIs.

* Committing clang-format changes

* Spelling fixes

* Fix bug in non-parallel HDF5 compilation.

* Committing clang-format changes

* Fix potential memory/free list error. Minor performance fix. Other minor
changes.

* Committing clang-format changes

* Fix memory leak with memory dataspace for I/O.

* Committing clang-format changes

* Fix stack variables too large.  Rename H5D_dset_info_t to
H5D_dset_io_info_t.

* Committing clang-format changes

* Remove mem_space_alloc field from H5D_dset_io_info_t.  Each function is
now responsible for freeing any spaces it adds to dset_info.

* Committing clang-format changes

* fixed _multi Fortran declaration

* Refactor various things in (mostly) the serial I/O code path to make
things more maintainable.

* Committing clang-format changes

* updated to array based, doxygen, and examples

* Reinstate H5D_chunk_map_t, stored (via pointer) inside
H5D_dset_io_info_t.

* Change from calloc to malloc for H5D_dset_io_info_t and H5D_chunk_map_t.
Switch temporary dset_infos to be local stack variables.

* Committing clang-format changes

* format cleanup

* format cleanup

* added coll and ind

* Modify all parallel I/O paths to take dset_info instead of assuming
dset_info[0].

* Committing clang-format changes

* fixed output

* Rework parallel I/O code to work properly with multi dataset in more
cases.  Fix bug in parallel compression.

* Committing clang-format changes

* Prevent H5D__multi_chunk_collective_io() from messing up collective opt
property for other datasets in I/O.  Other minor cleanup.  Add new test
case to t_pmulti_dset.c for H5FD_MPIO_INDIVIDUAL_IO, disabled for now
due to failures apparently unrelated to multi dataset code.

* Fix spelling

* Committing clang-format changes

* Replace N log N algorithm for finding chunk in
H5D__multi_chunk_collective_io() with O(N) algorithm, and remove use of
io_info->sel_pieces in that function.

* Committing clang-format changes

* Replace sel_pieces skiplist in io_info with flat array of pointers, use
qsort in I/O routine only when necessary.

* Committing clang-format changes

* Add new test case to mdset.c

* Committing clang-format changes

* Fix spelling

* Very minor fix in H5VL__native_dataset_read()

* Fix bug that could affect filtered parallel multi-dataset I/O.

* Add RM entries for H5Dread_multi(), H5Dread_multi_async(),
H5Dwrite_multi(), and H5Dwrite_multi_async()

* Unskip test in swmr.c

* Committing clang-format changes

* Eliminate H5D__pre_read and H5D__pre_write

* Remove examples/ph5mdsettest.c. Will fix and re-add as a test.

* Enable hyperslab combinations in mdset test

* Committing clang-format changes

* Clarify H5Dread/write_multi documentation.

* Fix bugs in multi-dataset I/O.  Expand serial multi dataset test.
Update macro in parallel multi dataset test.

* Committing clang-format changes

* Spelling

* Remove obsolete entry in bin/trace

* Rework type conversion buffer allocation. Only one buffer is shared
between datasets in mdset mode, and it is malloced instead of calloced.

* Committing clang-format changes

* Fix bug in error handling in H5D__read/write

* added multi-dataset fortran check with optional dataset creation id (#2150)

* removed dup. dll entry

* Address comments from code review.

* Remove spurious changes in H5Fmpi.c

* Fix issue with reading unallocated datasets in multi-dataset mode.
Address other comments from code review.

* Committing clang-format changes

* Delay chunk index lookup from io_init to mdio_init so it doesn't add
overhead to single dataset I/O.

* Committing clang-format changes

* Fix inappropriate use of piece_count

* updated copyright on new file, removed benchmark from testing dir.

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: M. Scot Breitenfeld <brtnfld@hdfgroup.org>
Co-authored-by: Dana Robinson <43805+derobins@users.noreply.github.com>
This commit is contained in:
Neil Fortner
2022-10-19 09:13:15 -07:00
committed by GitHub
co-authored by github-actions M. Scot Breitenfeld Dana Robinson
parent a898cef6c2
commit 93754cae33
40 changed files with 6493 additions and 2975 deletions
+103 -1
View File
@@ -1098,7 +1098,7 @@ CONTAINS
!>
!! \ingroup FH5D
!!
!! \brief Writes raw data from a dataset into a buffer.
!! \brief Writes raw data from a buffer to a dataset.
!!
!! \attention \fortran_approved
!!
@@ -1762,6 +1762,108 @@ CONTAINS
CALL h5dfill_ptr(f_ptr_fill_value, fill_type_id, f_ptr_buf, mem_type_id, space_id, hdferr)
END SUBROUTINE h5dfill_char
!>
!! \ingroup FH5D
!!
!! \brief Reads data from a file to memory buffers for multiple datasets.
!!
!! \param count Number of datasets to write to.
!! \param dset_id Identifier of the dataset to write to.
!! \param mem_type_id Identifier of the memory datatype.
!! \param mem_space_id Identifier of the memory dataspace.
!! \param file_space_id Identifier of the dataset&apos;s dataspace in the file.
!! \param buf Buffer with data to be written to the file.
!! \param hdferr \fortran_error
!! \param xfer_prp Identifier of a transfer property list for this I/O operation.
!!
SUBROUTINE H5Dread_multi_f(count, dset_id, mem_type_id, mem_space_id, file_space_id, buf, hdferr, xfer_prp)
IMPLICIT NONE
INTEGER(SIZE_T), INTENT(IN) :: count
INTEGER(HID_T), INTENT(IN), DIMENSION(*) :: dset_id
INTEGER(HID_T), INTENT(IN), DIMENSION(*) :: mem_type_id
INTEGER(HID_T), INTENT(IN), DIMENSION(*) :: mem_space_id
INTEGER(HID_T), INTENT(IN), DIMENSION(*) :: file_space_id
TYPE(C_PTR), DIMENSION(*) :: buf
INTEGER, INTENT(OUT) :: hdferr
INTEGER(HID_T), INTENT(IN), OPTIONAL :: xfer_prp
INTEGER(HID_T) :: xfer_prp_default
INTERFACE
INTEGER FUNCTION H5Dread_multi(count, dset_id, mem_type_id, mem_space_id, file_space_id, xfer_prp, buf) &
BIND(C, NAME='H5Dread_multi')
IMPORT :: SIZE_T
IMPORT :: HID_T
IMPORT :: C_PTR
IMPLICIT NONE
INTEGER(SIZE_T), VALUE :: count
INTEGER(HID_T), DIMENSION(*) :: dset_id
INTEGER(HID_T), DIMENSION(*) :: mem_type_id
INTEGER(HID_T), DIMENSION(*) :: mem_space_id
INTEGER(HID_T), DIMENSION(*) :: file_space_id
INTEGER(HID_T), VALUE :: xfer_prp
TYPE(C_PTR), DIMENSION(*) :: buf
END FUNCTION H5Dread_multi
END INTERFACE
xfer_prp_default = H5P_DEFAULT_F
IF (PRESENT(xfer_prp)) xfer_prp_default = xfer_prp
hdferr = H5Dread_multi(count, dset_id, mem_type_id, mem_space_id, file_space_id, xfer_prp_default, buf)
END SUBROUTINE H5Dread_multi_f
!>
!! \ingroup FH5D
!!
!! \brief Writes data in memory to a file for multiple datasets.
!!
!! \param count Number of datasets to write to.
!! \param dset_id Identifier of the dataset to write to.
!! \param mem_type_id Identifier of the memory datatype.
!! \param mem_space_id Identifier of the memory dataspace.
!! \param file_space_id Identifier of the dataset&apos;s dataspace in the file.
!! \param buf Buffer with data to be written to the file.
!! \param hdferr \fortran_error
!! \param xfer_prp Identifier of a transfer property list for this I/O operation.
!!
SUBROUTINE H5Dwrite_multi_f(count, dset_id, mem_type_id, mem_space_id, file_space_id, buf, hdferr, xfer_prp)
IMPLICIT NONE
INTEGER(SIZE_T), INTENT(IN) :: count
INTEGER(HID_T), INTENT(IN), DIMENSION(*) :: dset_id
INTEGER(HID_T), INTENT(IN), DIMENSION(*) :: mem_type_id
INTEGER(HID_T), INTENT(IN), DIMENSION(*) :: mem_space_id
INTEGER(HID_T), INTENT(IN), DIMENSION(*) :: file_space_id
TYPE(C_PTR), DIMENSION(*) :: buf
INTEGER, INTENT(OUT) :: hdferr
INTEGER(HID_T), INTENT(IN), OPTIONAL :: xfer_prp
INTEGER(HID_T) :: xfer_prp_default
INTERFACE
INTEGER FUNCTION H5Dwrite_multi(count, dset_id, mem_type_id, mem_space_id, file_space_id, xfer_prp, buf) &
BIND(C, NAME='H5Dwrite_multi')
IMPORT :: SIZE_T
IMPORT :: HID_T
IMPORT :: C_PTR
IMPLICIT NONE
INTEGER(SIZE_T), VALUE :: count
INTEGER(HID_T), DIMENSION(*) :: dset_id
INTEGER(HID_T), DIMENSION(*) :: mem_type_id
INTEGER(HID_T), DIMENSION(*) :: mem_space_id
INTEGER(HID_T), DIMENSION(*) :: file_space_id
INTEGER(HID_T), VALUE :: xfer_prp
TYPE(C_PTR), DIMENSION(*) :: buf
END FUNCTION H5Dwrite_multi
END INTERFACE
xfer_prp_default = H5P_DEFAULT_F
IF (PRESENT(xfer_prp)) xfer_prp_default = xfer_prp
hdferr = H5Dwrite_multi(count, dset_id, mem_type_id, mem_space_id, file_space_id, xfer_prp_default, buf)
END SUBROUTINE H5Dwrite_multi_f
#endif
+2
View File
@@ -80,6 +80,8 @@ H5D_mp_H5DGET_ACCESS_PLIST_F
H5D_mp_H5DWRITE_PTR
H5D_mp_H5DREAD_PTR
H5D_mp_H5DVLEN_RECLAIM_F
H5D_mp_H5DREAD_MULTI_F
H5D_mp_H5DWRITE_MULTI_F
; H5E
H5E_mp_H5ECLEAR_F
H5E_mp_H5EPRINT_F
+4
View File
@@ -151,6 +151,10 @@ PROGRAM fortranlibtest_F03
CALL test_h5p_file_image(ret_total_error)
CALL write_test_status(ret_total_error, ' Testing h5pset/get file image', total_error)
ret_total_error = 0
CALL multiple_dset_rw(ret_total_error)
CALL write_test_status(ret_total_error, ' Testing multi-dataset reads and writes', total_error)
! write(*,*)
! write(*,*) '========================================='
! write(*,*) 'Testing OBJECT interface '
+254
View File
@@ -3407,4 +3407,258 @@ SUBROUTINE t_enum_conv(total_error)
END SUBROUTINE t_enum_conv
! Tests the reading and writing of multiple datasets using H5Dread_multi and
! H5Dwrite_multi
SUBROUTINE multiple_dset_rw(total_error)
!-------------------------------------------------------------------------
! Subroutine: multiple_dset_rw
!
! Purpose: Tests the reading and writing of multiple datasets
! using H5Dread_multi and H5Dwrite_multi
!
! Return: Success: 0
! Failure: number of errors
!
! Programmer: M. Scot Breitenfeld
! April 2, 2014
!
!-------------------------------------------------------------------------
!
USE iso_c_binding
USE hdf5
IMPLICIT NONE
INTEGER, INTENT(INOUT) :: total_error ! number of errors
INTEGER :: error ! HDF hdferror flag
INTEGER(SIZE_T), PARAMETER :: ndset = 5 ! Number of data sets
INTEGER(HID_T), DIMENSION(:), ALLOCATABLE :: dset_id
INTEGER(HID_T), DIMENSION(:), ALLOCATABLE :: mem_type_id
INTEGER(HID_T), DIMENSION(:), ALLOCATABLE :: mem_space_id
INTEGER(HID_T), DIMENSION(:), ALLOCATABLE :: file_space_id
INTEGER, PARAMETER :: idim=10, idim2=5, idim3=3 ! size of integer array
INTEGER, PARAMETER :: rdim=5 ! size of real array
INTEGER, PARAMETER :: cdim=3 ! size of character array
INTEGER, PARAMETER :: sdim=2 ! length of character string
INTEGER, PARAMETER :: ddim=2 ! size of derived type array
INTEGER :: i,j,k
TYPE(C_PTR), ALLOCATABLE, DIMENSION(:) :: buf_md ! array to hold the multi-datasets
INTEGER, DIMENSION(1:idim), TARGET :: wbuf_int ! integer write buffer
INTEGER, DIMENSION(1:idim,idim2,idim3), TARGET :: wbuf_intmd
REAL, DIMENSION(1:rdim), TARGET :: wbuf_real ! real write buffer
CHARACTER(LEN=sdim), DIMENSION(1:cdim), TARGET :: wbuf_chr ! character write buffer
INTEGER, DIMENSION(1:idim), TARGET :: rbuf_int ! integer read buffer
INTEGER, DIMENSION(1:idim,idim2,idim3), TARGET :: rbuf_intmd ! integer read buffer
REAL, DIMENSION(1:rdim), TARGET :: rbuf_real ! real read buffer
CHARACTER(LEN=sdim), DIMENSION(1:cdim), TARGET :: rbuf_chr ! character read buffer
TYPE derived
REAL :: r
INTEGER :: i
CHARACTER(LEN=sdim) :: c
END TYPE derived
TYPE(derived), DIMENSION(1:ddim), TARGET :: wbuf_derived ! derived type write buffer
TYPE(derived), DIMENSION(1:ddim), TARGET :: rbuf_derived ! derived type read buffer
INTEGER(HSIZE_T), DIMENSION(1:1) :: dims ! dimension of the spaces
INTEGER(HSIZE_T), DIMENSION(1:3) :: dimsmd ! dimension of the spaces
INTEGER(HID_T) :: file_id, strtype ! handles
INTEGER(SIZE_T) :: obj_count
ALLOCATE(buf_md(1:ndset),stat=error)
IF (error .NE. 0) THEN
WRITE(*,*) 'allocate error'
total_error = total_error + 1
RETURN
ENDIF
ALLOCATE(dset_id(1:ndset),stat=error)
IF (error .NE. 0) THEN
WRITE(*,*) 'allocate error'
total_error = total_error + 1
RETURN
ENDIF
ALLOCATE(mem_type_id(1:ndset),stat=error)
IF (error .NE. 0) THEN
WRITE(*,*) 'allocate error'
total_error = total_error + 1
RETURN
ENDIF
ALLOCATE(mem_space_id(1:ndset),stat=error)
IF (error .NE. 0) THEN
WRITE(*,*) 'allocate error'
total_error = total_error + 1
RETURN
ENDIF
ALLOCATE(file_space_id(1:ndset),stat=error)
IF (error .NE. 0) THEN
WRITE(*,*) 'allocate error'
total_error = total_error + 1
RETURN
ENDIF
CALL h5fcreate_f("multidset_rw.h5", H5F_ACC_TRUNC_F, file_id, error)
CALL check("h5fcreate_f", error, total_error)
!
! Create real dataset
!
wbuf_real(1:rdim) = (/(i,i=1,rdim)/)
dims(1) = rdim
buf_md(1) = C_LOC(wbuf_real(1))
mem_type_id(1) = H5T_NATIVE_REAL
CALL h5screate_simple_f(1, dims, file_space_id(1), error)
CALL check("h5screate_simple_f", error, total_error)
CALL h5dcreate_f(file_id, "ds real", mem_type_id(1), file_space_id(1), dset_id(1), error)
CALL check("h5dcreate_f", error, total_error)
mem_space_id(1) = file_space_id(1)
! Create integer dataset (1D)
wbuf_int(1:idim) = (/(i,i=1,idim)/)
dims(1) = idim
buf_md(2) = C_LOC(wbuf_int(1))
mem_type_id(2) = H5T_NATIVE_INTEGER
CALL h5screate_simple_f(1, dims, file_space_id(2), error)
CALL check("h5screate_simple_f", error, total_error)
CALL h5dcreate_f(file_id, "ds int", mem_type_id(2), file_space_id(2), dset_id(2), error)
CALL check("h5dcreate_f", error, total_error)
mem_space_id(2) = file_space_id(2)
! Create character dataset
wbuf_chr(1:cdim) = (/'ab','cd','ef'/)
dims(1) = cdim
buf_md(3) = C_LOC(wbuf_chr(1)(1:1))
CALL H5Tcopy_f(H5T_FORTRAN_S1, mem_type_id(3), error)
CALL check("H5Tcopy_f", error, total_error)
CALL H5Tset_size_f(mem_type_id(3), INT(sdim,SIZE_T), error)
CALL check("H5Tset_size_f", error, total_error)
CALL h5screate_simple_f(1, dims, file_space_id(3), error)
CALL check("h5screate_simple_f", error, total_error)
CALL h5dcreate_f(file_id, "ds chr", mem_type_id(3), file_space_id(3), dset_id(3), error)
CALL check("h5dcreate_f", error, total_error)
mem_space_id(3) = file_space_id(3)
! Create derived type dataset
wbuf_derived(1:ddim)%r = (/10.,20./)
wbuf_derived(1:ddim)%i = (/30,40/)
wbuf_derived(1:ddim)%c = (/'wx','yz'/)
buf_md(4) = C_LOC(wbuf_derived(1)%r)
CALL h5tcreate_f(H5T_COMPOUND_F, H5OFFSETOF(C_LOC(wbuf_derived(1)), C_LOC(wbuf_derived(2))), mem_type_id(4), error)
CALL check("h5tcreate_f", error, total_error)
CALL h5tinsert_f(mem_type_id(4), "real", &
H5OFFSETOF(C_LOC(wbuf_derived(1)),C_LOC(wbuf_derived(1)%r)), H5T_NATIVE_REAL, error)
CALL check("h5tinsert_f", error, total_error)
CALL h5tinsert_f(mem_type_id(4), "int", &
H5OFFSETOF(C_LOC(wbuf_derived(1)),C_LOC(wbuf_derived(1)%i)), H5T_NATIVE_INTEGER, error)
CALL check("h5tinsert_f", error, total_error)
CALL h5tcopy_f(H5T_NATIVE_CHARACTER, strtype, error)
CALL check("h5tcopy_f", error, total_error)
CALL h5tset_size_f(strtype, INT(sdim,size_t), error)
CALL check("h5tset_size_f", error, total_error)
CALL h5tinsert_f(mem_type_id(4), "chr", &
H5OFFSETOF(C_LOC(wbuf_derived(1)),C_LOC(wbuf_derived(1)%c(1:1))), strtype, error)
CALL check("h5tinsert_f", error, total_error)
dims(1) = ddim
CALL h5screate_simple_f(1, dims, file_space_id(4), error)
CALL check("h5screate_simple_f", error, total_error)
CALL h5dcreate_f(file_id, "ds derived", mem_type_id(4), file_space_id(4), dset_id(4), error)
CALL check("h5dcreate_f", error, total_error)
mem_space_id(4) = file_space_id(4)
! Create integer dataset (3D)
DO i = 1, idim
DO j = 1, idim2
DO k = 1, idim3
wbuf_intmd(i,j,k) = i*j
ENDDO
ENDDO
ENDDO
dimsmd(1:3) = (/idim,idim2,idim3/)
buf_md(5) = C_LOC(wbuf_intmd(1,1,1))
mem_type_id(5) = H5T_NATIVE_INTEGER
CALL h5screate_simple_f(3, dimsmd, file_space_id(5), error)
CALL check("h5screate_simple_f", error, total_error)
CALL h5dcreate_f(file_id, "ds int 3d", mem_type_id(5), file_space_id(5), dset_id(5), error)
CALL check("h5dcreate_f", error, total_error)
mem_space_id(5) = file_space_id(5)
! write all the datasets
CALL h5dwrite_multi_f(ndset, dset_id, mem_type_id, mem_space_id, file_space_id, buf_md, error)
CALL check("h5dwrite_multi_f", error, total_error)
! point to read buffers
buf_md(1) = C_LOC(rbuf_real(1))
buf_md(2) = C_LOC(rbuf_int(1))
buf_md(3) = C_LOC(rbuf_chr(1)(1:1))
buf_md(4) = C_LOC(rbuf_derived(1)%r)
buf_md(5) = C_LOC(rbuf_intmd(1,1,1))
! read all the datasets
CALL h5dread_multi_f(ndset, dset_id, mem_type_id, mem_space_id, file_space_id, buf_md, error)
CALL check("h5dread_multi_f", error, total_error)
! check the written and read in values
DO i = 1, rdim
IF(rbuf_real(i).NE.wbuf_real(i))THEN
total_error = total_error + 1
END IF
END DO
DO i = 1, idim
IF(rbuf_int(i).NE.wbuf_int(i))THEN
total_error = total_error + 1
END IF
END DO
DO i = 1, cdim
IF(rbuf_chr(i).NE.wbuf_chr(i))THEN
total_error = total_error + 1
END IF
END DO
DO i = 1, ddim
IF(rbuf_derived(i)%r.NE.wbuf_derived(i)%r)THEN
total_error = total_error + 1
END IF
IF(rbuf_derived(i)%i.NE.wbuf_derived(i)%i)THEN
total_error = total_error + 1
END IF
IF(rbuf_derived(i)%c.NE.wbuf_derived(i)%c)THEN
total_error = total_error + 1
END IF
END DO
DO i = 1, idim
DO j = 1, idim2
DO k = 1, idim3
IF(rbuf_intmd(i,j,k).NE.wbuf_intmd(i,j,k))THEN
total_error = total_error + 1
END IF
END DO
ENDDO
ENDDO
DO i = 1, ndset
CALL H5Dclose_f(dset_id(i), error)
CALL check("H5Dclose_f", error, total_error)
CALL H5Sclose_f(file_space_id(i), error)
CALL check("H5Sclose_f", error, total_error)
ENDDO
CALL H5Tclose_f(mem_type_id(4), error)
CALL check("H5Tclose_f", error, total_error)
CALL h5fget_obj_count_f(file_id, H5F_OBJ_ALL_F, obj_count, error)
IF(obj_count.NE.1)THEN
total_error = total_error + 1
END IF
CALL H5Fclose_f(file_id, error)
END SUBROUTINE multiple_dset_rw
END MODULE TH5T_F03
+1 -1
View File
@@ -88,7 +88,7 @@ CONTAINS
error_string = skip
ENDIF
WRITE(*, fmt = '(A, T80, A)') test_title, error_string
WRITE(*, fmt = '(A, T88, A)') test_title, error_string
IF(test_result.GT.0) total_error = total_error + test_result
+1
View File
@@ -20,6 +20,7 @@ add_executable (parallel_test
ptest.F90
hyper.F90
mdset.F90
multidsetrw.F90
)
target_include_directories (parallel_test
PRIVATE ${TESTPAR_INCLUDES}
+1 -1
View File
@@ -40,7 +40,7 @@ check_PROGRAMS=$(TEST_PROG_PARA)
CHECK_CLEANFILES+=parf[12].h5 subf.h5*
# Test source files
parallel_test_SOURCES=ptest.F90 hyper.F90 mdset.F90
parallel_test_SOURCES=ptest.F90 hyper.F90 mdset.F90 multidsetrw.F90
subfiling_test_SOURCES=subfiling.F90
# The tests depend on several libraries.
+17 -14
View File
@@ -237,19 +237,23 @@ SUBROUTINE hyper(length,do_collective,do_chunk, mpi_size, mpi_rank, nerrors)
CALL h5pget_mpio_actual_io_mode_f(dxpl_id, actual_io_mode, hdferror)
CALL check("h5pget_mpio_actual_io_mode_f", hdferror, nerrors)
IF(do_collective.AND.do_chunk)THEN
IF(actual_io_mode.NE.H5D_MPIO_CHUNK_COLLECTIVE_F)THEN
CALL check("h5pget_mpio_actual_io_mode_f", -1, nerrors)
ENDIF
ELSEIF(.NOT.do_collective)THEN
IF(actual_io_mode.NE.H5D_MPIO_NO_COLLECTIVE_F)THEN
CALL check("h5pget_mpio_actual_io_mode_f", -1, nerrors)
ENDIF
ELSEIF( do_collective.AND.(.NOT.do_chunk))THEN
IF(actual_io_mode.NE.H5D_MPIO_CONTIG_COLLECTIVE_F)THEN
CALL check("h5pget_mpio_actual_io_mode_f", -1, nerrors)
ENDIF
ENDIF
! MSB -- TODO FIX: skipping for now since multi-dataset
! has no specific path for contiguous collective
!
! IF(do_collective.AND.do_chunk)THEN
! IF(actual_io_mode.NE.H5D_MPIO_CHUNK_COLLECTIVE_F)THEN
! CALL check("h5pget_mpio_actual_io_mode_f", -1, nerrors)
! ENDIF
! ELSEIF(.NOT.do_collective)THEN
! IF(actual_io_mode.NE.H5D_MPIO_NO_COLLECTIVE_F)THEN
! CALL check("h5pget_mpio_actual_io_mode_f", -1, nerrors)
! ENDIF
! ELSEIF( do_collective.AND.(.NOT.do_chunk))THEN
! IF(actual_io_mode.NE.H5D_MPIO_CONTIG_COLLECTIVE_F)THEN
! CALL check("h5pget_mpio_actual_io_mode_f", -1, nerrors)
! ENDIF
! ENDIF
! MSB
!
! close HDF5 I/O
@@ -318,7 +322,6 @@ SUBROUTINE hyper(length,do_collective,do_chunk, mpi_size, mpi_rank, nerrors)
CALL h5pcreate_f(H5P_DATASET_XFER_F, dxpl_id, hdferror)
CALL check("h5pcreate_f", hdferror, nerrors)
IF (do_collective) THEN
CALL h5pset_dxpl_mpio_f(dxpl_id, H5FD_MPIO_COLLECTIVE_F, hdferror)
CALL check("h5pset_dxpl_mpio_f", hdferror, nerrors)
+235
View File
@@ -0,0 +1,235 @@
! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
! Copyright by The HDF Group. *
! All rights reserved. *
! *
! This file is part of HDF5. The full HDF5 copyright notice, including *
! terms governing use, modification, and redistribution, is contained in *
! the files COPYING and Copyright.html. COPYING can be found at the root *
! of the source code distribution tree; Copyright.html can be found at the *
! root level of an installed copy of the electronic HDF5 document set and *
! is linked from the top-level documents page. It can also be found at *
! http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
! access to either file, you may request a copy from help@hdfgroup.org. *
! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
!
! writes/reads dataset by hyperslabs using multi-dataset routines, h5dread_multi and
! h5dwrite_multi
!
SUBROUTINE pmultiple_dset_hyper_rw(do_collective, do_chunk, mpi_size, mpi_rank, nerrors)
USE iso_c_binding
USE TH5_MISC
USE hdf5
USE mpi
IMPLICIT NONE
LOGICAL, INTENT(in) :: do_collective ! use collective IO
LOGICAL, INTENT(in) :: do_chunk ! use chunking
INTEGER, INTENT(in) :: mpi_size ! number of processes in the group of communicator
INTEGER, INTENT(in) :: mpi_rank ! rank of the calling process in the communicator
INTEGER, INTENT(inout) :: nerrors ! number of errors
CHARACTER(LEN=80):: dsetname ! Dataset name
INTEGER(hsize_t), DIMENSION(1:2) :: cdims ! chunk dimensions
INTEGER(HID_T) :: file_id ! File identifier
INTEGER(HID_T) :: filespace ! Dataspace identifier in file
INTEGER(HID_T) :: memspace ! Dataspace identifier in memory
INTEGER(HID_T) :: plist_id ! Property list identifier
INTEGER(HID_T) :: dcpl_id ! Dataset creation property list
INTEGER(HSIZE_T), DIMENSION(1:2) :: dimsf ! Dataset dimensions.
INTEGER(HSIZE_T), DIMENSION(1:2) :: count
INTEGER(HSSIZE_T), DIMENSION(1:2) :: offset
INTEGER, ALLOCATABLE, DIMENSION(:,:,:), TARGET :: DATA ! Data to write
INTEGER, ALLOCATABLE, DIMENSION(:,:,:), TARGET :: rDATA ! Data to write
INTEGER, PARAMETER :: rank = 2 ! Dataset rank
INTEGER :: i
INTEGER(HSIZE_T) :: ii, jj, kk, istart
INTEGER :: error ! Error flags
INTEGER(SIZE_T), PARAMETER :: ndsets = 5
INTEGER(HID_T), DIMENSION(1:ndsets) :: dset_id
INTEGER(HID_T), DIMENSION(1:ndsets) :: mem_type_id
INTEGER(HID_T), DIMENSION(1:ndsets) :: mem_space_id
INTEGER(HID_T), DIMENSION(1:ndsets) :: file_space_id
TYPE(C_PTR), DIMENSION(1:ndsets) :: buf_md
INTEGER(SIZE_T) :: obj_count
INTEGER :: data_xfer_mode
dimsf(1) = 5_hsize_t
dimsf(2) = INT(mpi_size, hsize_t)*8_hsize_t
!
! Setup file access property list with parallel I/O access.
!
CALL h5pcreate_f(H5P_FILE_ACCESS_F, plist_id, error)
CALL check("h5pcreate_f", error, nerrors)
CALL h5pset_fapl_mpio_f(plist_id, MPI_COMM_WORLD, MPI_INFO_NULL, error)
CALL check("h5pset_fapl_mpio_f", error, nerrors)
!
! Create the file collectively.
!
CALL h5fcreate_f("parf2.h5", H5F_ACC_TRUNC_F, file_id, error, access_prp = plist_id)
CALL check("h5fcreate_f", error, nerrors)
CALL h5pclose_f(plist_id, error)
CALL check("h5pclose_f", error, nerrors)
!
! Create the data space for the dataset.
!
CALL h5screate_simple_f(rank, dimsf, filespace, error)
CALL check("h5screate_simple_f", error, nerrors)
!
! Each process defines dataset in memory and writes it to the hyperslab
! in the file.
!
count(1) = dimsf(1)
count(2) = dimsf(2)/mpi_size
offset(1) = 0
offset(2) = mpi_rank * count(2)
CALL h5screate_simple_f(rank, count, memspace, error)
CALL check("h5screate_simple_f", error, nerrors)
!
! Modify dataset creation properties to enable chunking
!
CALL h5pcreate_f(H5P_DATASET_CREATE_F, dcpl_id, error)
CALL check("h5pcreate_f", error, nerrors)
IF (do_chunk) THEN
cdims(1) = dimsf(1)
cdims(2) = dimsf(2)/mpi_size/2
CALL h5pset_chunk_f(dcpl_id, 2, cdims, error)
CALL check("h5pset_chunk_f", error, nerrors)
ENDIF
!
! Select hyperslab in the file.
!
CALL h5sselect_hyperslab_f(filespace, H5S_SELECT_SET_F, offset, count, error)
CALL check("h5sselect_hyperslab_f", error, nerrors)
!
! Initialize data buffer
!
ALLOCATE ( DATA(COUNT(1),COUNT(2), ndsets))
ALLOCATE ( rdata(COUNT(1),COUNT(2), ndsets))
! Create property list for collective dataset write
!
CALL h5pcreate_f(H5P_DATASET_XFER_F, plist_id, error)
CALL check("h5pcreate_f", error, nerrors)
IF(do_collective)THEN
CALL h5pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, error)
CALL check("h5pset_dxpl_mpio_f", error, nerrors)
ELSE
CALL h5pset_dxpl_mpio_f(plist_id, H5FD_MPIO_INDEPENDENT_F, error)
CALL check("h5pset_dxpl_mpio_f", error, nerrors)
ENDIF
!
! Create the dataset with default properties.
!
mem_type_id(1:ndsets) = H5T_NATIVE_INTEGER
mem_space_id(1:ndsets) = memspace
file_space_id(1:ndsets)= filespace
DO ii = 1, ndsets
! Create the data
DO kk = 1, COUNT(1)
DO jj = 1, COUNT(2)
istart = (kk-1)*dimsf(2) + mpi_rank*COUNT(2)
DATA(kk,jj,ii) = INT((istart + jj)*10**(ii-1))
ENDDO
ENDDO
! Point to te data
buf_md(ii) = C_LOC(DATA(1,1,ii))
! direct the output of the write statement to unit "dsetname"
WRITE(dsetname,'("dataset ",I0)') ii
! create the dataset
CALL h5dcreate_f(file_id, dsetname, H5T_NATIVE_INTEGER, filespace, dset_id(ii), error, dcpl_id)
CALL check("h5dcreate_f", error, nerrors)
ENDDO
!
! Write the dataset collectively.
!
CALL h5dwrite_multi_f(ndsets, dset_id, mem_type_id, mem_space_id, file_space_id, buf_md, error, plist_id)
CALL check("h5dwrite_multi_f", error, nerrors)
CALL h5pget_dxpl_mpio_f(plist_id, data_xfer_mode, error)
CALL check("h5pget_dxpl_mpio_f", error, nerrors)
IF(do_collective)THEN
IF(data_xfer_mode.NE.H5FD_MPIO_COLLECTIVE_F)THEN
nerrors = nerrors + 1
ENDIF
ENDIF
DO i = 1, ndsets
! Point to the read buffer
buf_md(i) = C_LOC(rdata(1,1,i))
ENDDO
CALL H5Dread_multi_f(ndsets, dset_id, mem_type_id, mem_space_id, file_space_id, buf_md, error, plist_id)
CALL check("h5dread_multi_f", error, nerrors)
CALL h5pget_dxpl_mpio_f(plist_id, data_xfer_mode, error)
CALL check("h5pget_dxpl_mpio_f", error, nerrors)
IF(do_collective)THEN
IF(data_xfer_mode.NE.H5FD_MPIO_COLLECTIVE_F)THEN
nerrors = nerrors + 1
ENDIF
ENDIF
DO i = 1, ndsets
! Close all the datasets
CALL h5dclose_f(dset_id(i), error)
CALL check("h5dclose_f", error, nerrors)
ENDDO
! check the data read and write buffers
DO ii = 1, ndsets
! Create the data
DO kk = 1, COUNT(1)
DO jj = 1, COUNT(2)
IF(rDATA(kk,jj,ii).NE.DATA(kk,jj,ii))THEN
nerrors = nerrors + 1
ENDIF
ENDDO
ENDDO
ENDDO
!
! Deallocate data buffer.
!
DEALLOCATE(data, rdata)
!
! Close dataspaces.
!
CALL h5sclose_f(filespace, error)
CALL check("h5sclose_f", error, nerrors)
CALL h5sclose_f(memspace, error)
CALL check("h5sclose_f", error, nerrors)
!
! Close the dataset and property list.
!
CALL h5pclose_f(dcpl_id, error)
CALL check("h5pclose_f", error, nerrors)
CALL h5pclose_f(plist_id, error)
CALL check("h5pclose_f", error, nerrors)
CALL h5fget_obj_count_f(file_id, H5F_OBJ_ALL_F, obj_count, error)
IF(obj_count.NE.1)THEN
nerrors = nerrors + 1
END IF
!
! Close the file.
!
CALL h5fclose_f(file_id, error)
CALL check("h5fclose_f", error, nerrors)
END SUBROUTINE pmultiple_dset_hyper_rw
+12 -1
View File
@@ -76,7 +76,18 @@ PROGRAM parallel_test
CALL multiple_dset_write(length, do_collective(1), do_chunk(1), mpi_size, mpi_rank, ret_total_error)
IF(mpi_rank==0) CALL write_test_status(ret_total_error, &
'Writing/reading several datasets (contiguous layout, independent MPI I/O)', total_error)
!
! test write/read multiple hyperslab datasets
!
DO i = 1, 2
DO j = 1, 2
ret_total_error = 0
CALL pmultiple_dset_hyper_rw(do_collective(j), do_chunk(i), mpi_size, mpi_rank, ret_total_error)
IF(mpi_rank==0) CALL write_test_status(ret_total_error, &
"Writing/reading multiple datasets by hyperslab ("//TRIM(chr_chunk(i))//" layout, "&
//TRIM(chr_collective(j))//" MPI I/O)", total_error)
ENDDO
ENDDO
!
! close HDF5 interface
!
+275 -33
View File
@@ -50,10 +50,11 @@ static hid_t H5D__create_api_common(hid_t loc_id, const char *name, hid_t type_
static hid_t H5D__open_api_common(hid_t loc_id, const char *name, hid_t dapl_id, void **token_ptr,
H5VL_object_t **_vol_obj_ptr);
static hid_t H5D__get_space_api_common(hid_t dset_id, void **token_ptr, H5VL_object_t **_vol_obj_ptr);
static herr_t H5D__read_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, void *buf, void **token_ptr, H5VL_object_t **_vol_obj_ptr);
static herr_t H5D__write_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, const void *buf, void **token_ptr,
static herr_t H5D__read_api_common(size_t count, hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, void *buf[], void **token_ptr,
H5VL_object_t **_vol_obj_ptr);
static herr_t H5D__write_api_common(size_t count, hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[], void **token_ptr,
H5VL_object_t **_vol_obj_ptr);
static herr_t H5D__set_extent_api_common(hid_t dset_id, const hsize_t size[], void **token_ptr,
H5VL_object_t **_vol_obj_ptr);
@@ -943,26 +944,64 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__read_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id,
void *buf, void **token_ptr, H5VL_object_t **_vol_obj_ptr)
H5D__read_api_common(size_t count, hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, void *buf[], void **token_ptr,
H5VL_object_t **_vol_obj_ptr)
{
H5VL_object_t *tmp_vol_obj = NULL; /* Object for loc_id */
H5VL_object_t **vol_obj_ptr =
(_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */
herr_t ret_value = SUCCEED; /* Return value */
void *obj_local; /* Local buffer for obj */
void **obj = &obj_local; /* Array of object pointers */
H5VL_t *connector; /* VOL connector pointer */
size_t i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Check arguments */
if (mem_space_id < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid memory dataspace ID")
if (file_space_id < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file dataspace ID")
if (count == 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "count must be greater than 0")
if (!dset_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dset_id array not provided")
if (!mem_type_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_type_id array not provided")
if (!mem_space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_space_id array not provided")
if (!file_space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_space_id array not provided")
if (!buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf array not provided")
/* Get dataset pointer */
if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
/* Allocate obj array if necessary */
if (count > 1)
if (NULL == (obj = (void **)H5MM_malloc(count * sizeof(void *))))
HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate space for object array")
/* Get vol_obj_ptr (return just the first dataset to caller if requested) */
if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(dset_id[0], H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID")
/* Save the connector of the first dataset. Unpack the connector and call
* the "direct" read function here to avoid allocating an array of count
* H5VL_object_ts. */
connector = (*vol_obj_ptr)->connector;
/* Build obj array */
obj[0] = (*vol_obj_ptr)->data;
for (i = 1; i < count; i++) {
/* Get the object */
if (NULL == (tmp_vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id[i], H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID")
obj[i] = tmp_vol_obj->data;
/* Make sure the class matches */
if (tmp_vol_obj->connector->cls->value != connector->cls->value)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
"datasets are accessed through different VOL connectors and can't be used in the "
"same I/O call")
}
/* 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;
@@ -970,11 +1009,15 @@ H5D__read_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
/* Read the data */
if (H5VL_dataset_read(*vol_obj_ptr, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, token_ptr) <
0)
if (H5VL_dataset_read_direct(count, obj, connector, mem_type_id, mem_space_id, file_space_id, dxpl_id,
buf, token_ptr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
done:
/* Free memory */
if (obj != &obj_local)
H5MM_free(obj);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__read_api_common() */
@@ -1022,7 +1065,8 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_i
H5TRACE6("e", "iiiiix", dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf);
/* Read the data */
if (H5D__read_api_common(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, NULL, NULL) < 0)
if (H5D__read_api_common(1, &dset_id, &mem_type_id, &mem_space_id, &file_space_id, dxpl_id, &buf, NULL,
NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't synchronously read data")
done:
@@ -1059,8 +1103,8 @@ H5Dread_async(const char *app_file, const char *app_func, unsigned app_line, hid
token_ptr = &token; /* Point at token for VOL connector to set up */
/* Read the data */
if (H5D__read_api_common(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, token_ptr,
&vol_obj) < 0)
if (H5D__read_api_common(1, &dset_id, &mem_type_id, &mem_space_id, &file_space_id, dxpl_id, &buf,
token_ptr, &vol_obj) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't asynchronously read data")
/* If a token was created, add the token to the event set */
@@ -1075,6 +1119,84 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Dread_async() */
/*-------------------------------------------------------------------------
* Function: H5Dread_multi
*
* Purpose: Multi-version of H5Dread(), which reads selections from
* multiple datasets from a file into application memory BUFS.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Jonathan Kim Nov, 2013
*
*-------------------------------------------------------------------------
*/
herr_t
H5Dread_multi(size_t count, hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[], hid_t file_space_id[],
hid_t dxpl_id, void *buf[] /*out*/)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE7("e", "z*i*i*i*iix", count, dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf);
if (count == 0)
HGOTO_DONE(SUCCEED)
/* Read the data */
if (H5D__read_api_common(count, dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, NULL,
NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't synchronously read data")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Dread_multi() */
/*-------------------------------------------------------------------------
* Function: H5Dread_multi_async
*
* Purpose: Asynchronously read dataset elements from multiple
* datasets.
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
herr_t
H5Dread_multi_async(const char *app_file, const char *app_func, unsigned app_line, size_t count,
hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[], hid_t file_space_id[],
hid_t dxpl_id, void *buf[] /*out*/, hid_t es_id)
{
H5VL_object_t *vol_obj = NULL; /* Dataset VOL object */
void *token = NULL; /* Request token for async operation */
void **token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE11("e", "*s*sIuz*i*i*i*iixi", app_file, app_func, app_line, count, dset_id, mem_type_id,
mem_space_id, file_space_id, dxpl_id, buf, es_id);
/* Set up request token pointer for asynchronous operation */
if (H5ES_NONE != es_id)
token_ptr = &token; /* Point at token for VOL connector to set up */
/* Read the data */
if (H5D__read_api_common(count, dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf,
token_ptr, &vol_obj) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't asynchronously read data")
/* If a token was created, add the token to the event set */
if (NULL != token)
/* clang-format off */
if (H5ES_insert(es_id, vol_obj->connector, token,
H5ARG_TRACE11(__func__, "*s*sIuz*i*i*i*iixi", app_file, app_func, app_line, count, dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, es_id)) < 0)
/* clang-format on */
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert token into event set")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Dread_multi_async() */
/*-------------------------------------------------------------------------
* Function: H5Dread_chunk
*
@@ -1142,26 +1264,64 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__write_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, const void *buf, void **token_ptr, H5VL_object_t **_vol_obj_ptr)
H5D__write_api_common(size_t count, hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[], void **token_ptr,
H5VL_object_t **_vol_obj_ptr)
{
H5VL_object_t *tmp_vol_obj = NULL; /* Object for loc_id */
H5VL_object_t **vol_obj_ptr =
(_vol_obj_ptr ? _vol_obj_ptr : &tmp_vol_obj); /* Ptr to object ptr for loc_id */
herr_t ret_value = SUCCEED; /* Return value */
void *obj_local; /* Local buffer for obj */
void **obj = &obj_local; /* Array of object pointers */
H5VL_t *connector; /* VOL connector pointer */
size_t i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Check arguments */
if (mem_space_id < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid memory dataspace ID")
if (file_space_id < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file dataspace ID")
if (count == 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "count must be greater than 0")
if (!dset_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dset_id array not provided")
if (!mem_type_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_type_id array not provided")
if (!mem_space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_space_id array not provided")
if (!file_space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_space_id array not provided")
if (!buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf array not provided")
/* Get dataset pointer */
if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(dset_id, H5I_DATASET)))
/* Allocate obj array if necessary */
if (count > 1)
if (NULL == (obj = (void **)H5MM_malloc(count * sizeof(void *))))
HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate space for object array")
/* Get vol_obj_ptr (return just the first dataset to caller if requested) */
if (NULL == (*vol_obj_ptr = (H5VL_object_t *)H5I_object_verify(dset_id[0], H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID")
/* Save the connector of the first dataset. Unpack the connector and call
* the "direct" write function here to avoid allocating an array of count
* H5VL_object_ts. */
connector = (*vol_obj_ptr)->connector;
/* Build obj array */
obj[0] = (*vol_obj_ptr)->data;
for (i = 1; i < count; i++) {
/* Get the object */
if (NULL == (tmp_vol_obj = (H5VL_object_t *)H5I_object_verify(dset_id[i], H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dset_id is not a dataset ID")
obj[i] = tmp_vol_obj->data;
/* Make sure the class matches */
if (tmp_vol_obj->connector->cls->value != connector->cls->value)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
"datasets are accessed through different VOL connectors and can't be used in the "
"same I/O call")
}
/* 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;
@@ -1169,11 +1329,15 @@ H5D__write_api_common(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
/* Write the data */
if (H5VL_dataset_write(*vol_obj_ptr, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, token_ptr) <
0)
if (H5VL_dataset_write_direct(count, obj, connector, mem_type_id, mem_space_id, file_space_id, dxpl_id,
buf, token_ptr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
done:
/* Free memory */
if (obj != &obj_local)
H5MM_free(obj);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__write_api_common() */
@@ -1222,8 +1386,8 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_
H5TRACE6("e", "iiiii*x", dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf);
/* Write the data */
if (H5D__write_api_common(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, NULL, NULL) <
0)
if (H5D__write_api_common(1, &dset_id, &mem_type_id, &mem_space_id, &file_space_id, dxpl_id, &buf, NULL,
NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't synchronously write data")
done:
@@ -1261,8 +1425,8 @@ H5Dwrite_async(const char *app_file, const char *app_func, unsigned app_line, hi
token_ptr = &token; /* Point at token for VOL connector to set up */
/* Write the data */
if (H5D__write_api_common(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, token_ptr,
&vol_obj) < 0)
if (H5D__write_api_common(1, &dset_id, &mem_type_id, &mem_space_id, &file_space_id, dxpl_id, &buf,
token_ptr, &vol_obj) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't asynchronously write data")
/* If a token was created, add the token to the event set */
@@ -1277,6 +1441,84 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Dwrite_async() */
/*-------------------------------------------------------------------------
* Function: H5Dwrite_multi
*
* Purpose: Multi-version of H5Dwrite(), which writes selections from
* application memory BUFs into multiple datasets in a file.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Jonathan Kim Nov, 2013
*
*-------------------------------------------------------------------------
*/
herr_t
H5Dwrite_multi(size_t count, hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[])
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE7("e", "z*i*i*i*ii**x", count, dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf);
if (count == 0)
HGOTO_DONE(SUCCEED)
/* Write the data */
if (H5D__write_api_common(count, dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, NULL,
NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't synchronously write data")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Dwrite_multi() */
/*-------------------------------------------------------------------------
* Function: H5Dwrite_multi_async
*
* Purpose: Asynchronously write dataset elements to multiple
* datasets.
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
herr_t
H5Dwrite_multi_async(const char *app_file, const char *app_func, unsigned app_line, size_t count,
hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[], hid_t file_space_id[],
hid_t dxpl_id, const void *buf[], hid_t es_id)
{
H5VL_object_t *vol_obj = NULL; /* Dataset VOL object */
void *token = NULL; /* Request token for async operation */
void **token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE11("e", "*s*sIuz*i*i*i*ii**xi", app_file, app_func, app_line, count, dset_id, mem_type_id,
mem_space_id, file_space_id, dxpl_id, buf, es_id);
/* Set up request token pointer for asynchronous operation */
if (H5ES_NONE != es_id)
token_ptr = &token; /* Point at token for VOL connector to set up */
/* Write the data */
if (H5D__write_api_common(count, dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf,
token_ptr, &vol_obj) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't asynchronously write data")
/* If a token was created, add the token to the event set */
if (NULL != token)
/* clang-format off */
if (H5ES_insert(es_id, vol_obj->connector, token,
H5ARG_TRACE11(__func__, "*s*sIuz*i*i*i*ii**xi", app_file, app_func, app_line, count, dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, es_id)) < 0)
/* clang-format on */
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "can't insert token into event set")
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Dwrite_multi_async() */
/*-------------------------------------------------------------------------
* Function: H5Dwrite_chunk
*
+947 -746
View File
@@ -67,11 +67,19 @@
/****************/
/* Macros for iterating over chunks to operate on */
#define H5D_CHUNK_GET_FIRST_NODE(map) (map->use_single ? (H5SL_node_t *)(1) : H5SL_first(map->sel_chunks))
#define H5D_CHUNK_GET_NODE_INFO(map, node) \
(map->use_single ? map->single_chunk_info : (H5D_chunk_info_t *)H5SL_item(node))
#define H5D_CHUNK_GET_NEXT_NODE(map, node) (map->use_single ? (H5SL_node_t *)NULL : H5SL_next(node))
#define H5D_CHUNK_GET_NODE_COUNT(map) (map->use_single ? (size_t)1 : H5SL_count(map->sel_chunks))
#define H5D_CHUNK_GET_FIRST_NODE(dinfo) \
(dinfo->layout_io_info.chunk_map->use_single \
? (H5SL_node_t *)(1) \
: H5SL_first(dinfo->layout_io_info.chunk_map->dset_sel_pieces))
#define H5D_CHUNK_GET_NODE_INFO(dinfo, node) \
(dinfo->layout_io_info.chunk_map->use_single ? dinfo->layout_io_info.chunk_map->single_piece_info \
: (H5D_piece_info_t *)H5SL_item(node))
#define H5D_CHUNK_GET_NEXT_NODE(dinfo, node) \
(dinfo->layout_io_info.chunk_map->use_single ? (H5SL_node_t *)NULL : H5SL_next(node))
#define H5D_CHUNK_GET_NODE_COUNT(dinfo) \
(dinfo->layout_io_info.chunk_map->use_single \
? (size_t)1 \
: H5SL_count(dinfo->layout_io_info.chunk_map->dset_sel_pieces))
/* Sanity check on chunk index types: commonly used by a lot of routines in this file */
#define H5D_CHUNK_STORAGE_INDEX_CHK(storage) \
@@ -143,6 +151,7 @@ typedef struct H5D_chunk_it_ud1_t {
H5D_chunk_common_ud_t common; /* Common info for B-tree user data (must be first) */
const H5D_chk_idx_info_t *idx_info; /* Chunked index info */
const H5D_io_info_t *io_info; /* I/O info for dataset operation */
const H5D_dset_io_info_t *dset_info; /* Dataset specific I/O info */
const hsize_t *space_dim; /* New dataset dimensions */
const hbool_t *shrunk_dim; /* Dimensions which have been shrunk */
H5S_t *chunk_space; /* Dataspace for a chunk */
@@ -231,14 +240,6 @@ typedef struct H5D_chunk_info_iter_ud_t {
hbool_t found; /* Whether the chunk was found */
} H5D_chunk_info_iter_ud_t;
/* Callback info for file selection iteration */
typedef struct H5D_chunk_file_iter_ud_t {
H5D_chunk_map_t *fm; /* File->memory chunk mapping info */
#ifdef H5_HAVE_PARALLEL
const H5D_io_info_t *io_info; /* I/O info for operation */
#endif /* H5_HAVE_PARALLEL */
} H5D_chunk_file_iter_ud_t;
#ifdef H5_HAVE_PARALLEL
/* information to construct a collective I/O operation for filling chunks */
typedef struct H5D_chunk_coll_fill_info_t {
@@ -264,16 +265,13 @@ typedef struct H5D_chunk_iter_ud_t {
/* Chunked layout operation callbacks */
static herr_t H5D__chunk_construct(H5F_t *f, H5D_t *dset);
static herr_t H5D__chunk_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id);
static herr_t H5D__chunk_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm);
static herr_t H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_map_t *fm);
static herr_t H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm);
static herr_t H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm);
static herr_t H5D__chunk_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__chunk_io_init_selections(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__chunk_mdio_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__chunk_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__chunk_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__chunk_flush(H5D_t *dset);
static herr_t H5D__chunk_io_term(const H5D_chunk_map_t *fm);
static herr_t H5D__chunk_io_term(H5D_io_info_t *io_info, H5D_dset_io_info_t *di);
static herr_t H5D__chunk_dest(H5D_t *dset);
/* Chunk query operation callbacks */
@@ -283,8 +281,8 @@ static int H5D__get_chunk_info_by_coord_cb(const H5D_chunk_rec_t *chunk_rec, voi
static int H5D__chunk_iter_cb(const H5D_chunk_rec_t *chunk_rec, void *udata);
/* "Nonexistent" layout operation callback */
static ssize_t H5D__nonexistent_readvv(const H5D_io_info_t *io_info, size_t chunk_max_nseq,
size_t *chunk_curr_seq, size_t chunk_len_arr[],
static ssize_t H5D__nonexistent_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[],
hsize_t chunk_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_offset_arr[]);
@@ -292,29 +290,28 @@ static ssize_t H5D__nonexistent_readvv(const H5D_io_info_t *io_info, size_t chun
static int H5D__chunk_format_convert_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata);
/* Helper routines */
static herr_t H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims, const hsize_t *curr_dims,
const hsize_t *max_dims);
static herr_t H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
static herr_t H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *udata);
static hbool_t H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last, H5D_chunk_ud_t *udata);
static herr_t H5D__free_chunk_info(void *item, void *key, void *opdata);
static herr_t H5D__create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info);
static herr_t H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info);
static herr_t H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t *io_info);
static herr_t H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm);
static herr_t H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm);
static herr_t H5D__chunk_file_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords,
void *fm);
static herr_t H5D__chunk_mem_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords,
void *fm);
static htri_t H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info);
static herr_t H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims, const hsize_t *curr_dims,
const hsize_t *max_dims);
static herr_t H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
static herr_t H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *udata);
static hbool_t H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last, H5D_chunk_ud_t *udata);
static herr_t H5D__create_piece_map_single(H5D_dset_io_info_t *di, H5D_io_info_t *io_info);
static herr_t H5D__create_piece_file_map_all(H5D_dset_io_info_t *di, H5D_io_info_t *io_info);
static herr_t H5D__create_piece_file_map_hyper(H5D_dset_io_info_t *di, H5D_io_info_t *io_info);
static herr_t H5D__create_piece_mem_map_1d(const H5D_dset_io_info_t *di);
static herr_t H5D__create_piece_mem_map_hyper(const H5D_dset_io_info_t *di);
static herr_t H5D__piece_file_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords,
void *_opdata);
static herr_t H5D__piece_mem_cb(void *elem, const H5T_t *type, unsigned ndims, const hsize_t *coords,
void *_opdata);
static htri_t H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
static unsigned H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled);
static herr_t H5D__chunk_flush_entry(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t reset);
static herr_t H5D__chunk_cache_evict(const H5D_t *dset, H5D_rdcc_ent_t *ent, hbool_t flush);
static void *H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t relax,
hbool_t prev_unfilt_chunk);
static herr_t H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, hbool_t dirty,
void *chunk, uint32_t naccessed);
static void *H5D__chunk_lock(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
H5D_chunk_ud_t *udata, hbool_t relax, hbool_t prev_unfilt_chunk);
static herr_t H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
const H5D_chunk_ud_t *udata, hbool_t dirty, void *chunk, uint32_t naccessed);
static herr_t H5D__chunk_cache_prune(const H5D_t *dset, size_t size);
static herr_t H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk);
#ifdef H5_HAVE_PARALLEL
@@ -337,17 +334,14 @@ const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{
H5D__chunk_is_space_alloc, /* is_space_alloc */
H5D__chunk_is_data_cached, /* is_data_cached */
H5D__chunk_io_init, /* io_init */
H5D__chunk_mdio_init, /* mdio_init */
H5D__chunk_read, /* ser_read */
H5D__chunk_write, /* ser_write */
#ifdef H5_HAVE_PARALLEL
H5D__chunk_collective_read, /* par_read */
H5D__chunk_collective_write, /* par_write */
#endif
NULL, /* readvv */
NULL, /* writevv */
H5D__chunk_flush, /* flush */
H5D__chunk_io_term, /* io_term */
H5D__chunk_dest /* dest */
NULL, /* readvv */
NULL, /* writevv */
H5D__chunk_flush, /* flush */
H5D__chunk_io_term, /* io_term */
H5D__chunk_dest /* dest */
}};
/*******************/
@@ -355,11 +349,8 @@ const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{
/*******************/
/* "nonexistent" storage layout I/O ops */
const H5D_layout_ops_t H5D_LOPS_NONEXISTENT[1] = {{NULL, NULL, NULL, NULL, NULL, NULL, NULL,
#ifdef H5_HAVE_PARALLEL
NULL, NULL,
#endif /* H5_HAVE_PARALLEL */
H5D__nonexistent_readvv, NULL, NULL, NULL, NULL}};
const H5D_layout_ops_t H5D_LOPS_NONEXISTENT[1] = {
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, H5D__nonexistent_readvv, NULL, NULL, NULL, NULL}};
/* Declare a free list to manage the H5F_rdcc_ent_ptr_t sequence information */
H5FL_SEQ_DEFINE_STATIC(H5D_rdcc_ent_ptr_t);
@@ -368,7 +359,10 @@ H5FL_SEQ_DEFINE_STATIC(H5D_rdcc_ent_ptr_t);
H5FL_DEFINE_STATIC(H5D_rdcc_ent_t);
/* Declare a free list to manage the H5D_chunk_info_t struct */
H5FL_DEFINE(H5D_chunk_info_t);
H5FL_DEFINE(H5D_chunk_map_t);
/* Declare a free list to manage the H5D_piece_info_t struct */
H5FL_DEFINE(H5D_piece_info_t);
/* Declare a free list to manage the chunk sequence information */
H5FL_BLK_DEFINE_STATIC(chunk);
@@ -389,8 +383,7 @@ H5FL_EXTERN(H5S_sel_iter_t);
*-------------------------------------------------------------------------
*/
herr_t
H5D__chunk_direct_write(const H5D_t *dset, uint32_t filters, hsize_t *offset, uint32_t data_size,
const void *buf)
H5D__chunk_direct_write(H5D_t *dset, uint32_t filters, hsize_t *offset, uint32_t data_size, const void *buf)
{
const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */
H5D_chunk_ud_t udata; /* User data for querying chunk info */
@@ -406,16 +399,9 @@ H5D__chunk_direct_write(const H5D_t *dset, uint32_t filters, hsize_t *offset, ui
HDassert(layout->type == H5D_CHUNKED);
/* Allocate dataspace and initialize it if it hasn't been. */
if (!H5D__chunk_is_space_alloc(&layout->storage)) {
H5D_io_info_t io_info; /* to hold the dset info */
io_info.dset = dset;
io_info.f_sh = H5F_SHARED(dset->oloc.file);
/* Allocate storage */
if (H5D__alloc_storage(&io_info, H5D_ALLOC_WRITE, FALSE, NULL) < 0)
if (!H5D__chunk_is_space_alloc(&layout->storage))
if (H5D__alloc_storage(dset, H5D_ALLOC_WRITE, FALSE, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
}
/* Calculate the index of this chunk */
H5VM_chunk_scaled(dset->shared->ndims, offset, layout->u.chunk.dim, scaled);
@@ -1069,26 +1055,40 @@ H5D__chunk_is_data_cached(const H5D_shared_t *shared_dset)
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm)
H5D__chunk_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
{
const H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */
hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */
htri_t file_space_normalized = FALSE; /* File dataspace was normalized */
unsigned f_ndims; /* The number of dimensions of the file's dataspace */
int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */
htri_t use_selection_io = FALSE; /* Whether to use selection I/O */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
const H5D_t *dataset = dinfo->dset; /* Local pointer to dataset info */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */
htri_t file_space_normalized = FALSE; /* File dataspace was normalized */
unsigned f_ndims; /* The number of dimensions of the file's dataspace */
int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */
htri_t use_selection_io = FALSE; /* Whether to use selection I/O */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Allocate chunk map */
if (NULL == (dinfo->layout_io_info.chunk_map = H5FL_MALLOC(H5D_chunk_map_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate chunk map")
fm = dinfo->layout_io_info.chunk_map;
/* Get layout for dataset */
fm->layout = &(dataset->shared->layout);
fm->nelmts = nelmts;
dinfo->layout = &(dataset->shared->layout);
/* Initialize "last chunk" information */
fm->last_index = (hsize_t)-1;
fm->last_piece_info = NULL;
/* Clear other fields */
fm->mchunk_tmpl = NULL;
fm->dset_sel_pieces = NULL;
fm->single_space = NULL;
fm->single_piece_info = NULL;
/* Check if the memory space is scalar & make equivalent memory space */
if ((sm_ndims = H5S_GET_EXTENT_NDIMS(mem_space)) < 0)
if ((sm_ndims = H5S_GET_EXTENT_NDIMS(dinfo->mem_space)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number")
/* Set the number of dimensions for the memory dataspace */
H5_CHECKED_ASSIGN(fm->m_ndims, unsigned, sm_ndims, int);
@@ -1102,49 +1102,28 @@ H5D__chunk_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsi
* speed up hyperslab calculations by removing the extra checks and/or
* additions involving the offset and the hyperslab selection -QAK)
*/
if ((file_space_normalized = H5S_hyper_normalize_offset(file_space, old_offset)) < 0)
if ((file_space_normalized = H5S_hyper_normalize_offset(dinfo->file_space, old_offset)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to normalize selection")
/* Decide the number of chunks in each dimension */
for (u = 0; u < f_ndims; u++)
/* Keep the size of the chunk dimensions as hsize_t for various routines */
fm->chunk_dim[u] = fm->layout->u.chunk.dim[u];
fm->chunk_dim[u] = dinfo->layout->u.chunk.dim[u];
#ifdef H5_HAVE_PARALLEL
/* Calculate total chunk in file map*/
fm->select_chunk = NULL;
if (io_info->using_mpi_vfd) {
H5_CHECK_OVERFLOW(fm->layout->u.chunk.nchunks, hsize_t, size_t);
if (fm->layout->u.chunk.nchunks)
if (NULL == (fm->select_chunk = (H5D_chunk_info_t **)H5MM_calloc(
(size_t)fm->layout->u.chunk.nchunks * sizeof(H5D_chunk_info_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
} /* end if */
#endif /* H5_HAVE_PARALLEL */
/* Initialize "last chunk" information */
fm->last_index = (hsize_t)-1;
fm->last_chunk_info = NULL;
/* Point at the dataspaces */
fm->file_space = file_space;
fm->mem_space = mem_space;
if (H5D__chunk_io_init_selections(io_info, type_info, fm) < 0)
if (H5D__chunk_io_init_selections(io_info, dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file and memory chunk selections")
/* Check if we're performing selection I/O and save the result */
if ((use_selection_io = H5D__chunk_may_use_select_io(io_info)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible")
io_info->use_select_io = (hbool_t)use_selection_io;
/* Check if we're performing selection I/O and save the result if it hasn't
* been disabled already */
if (io_info->use_select_io) {
if ((use_selection_io = H5D__chunk_may_use_select_io(io_info, dinfo)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible")
io_info->use_select_io = (hbool_t)use_selection_io;
}
done:
/* Reset the global dataspace info */
fm->file_space = NULL;
fm->mem_space = NULL;
if (file_space_normalized == TRUE)
if (H5S_hyper_denormalize_offset(file_space, old_offset) < 0)
if (H5S_hyper_denormalize_offset(dinfo->file_space, old_offset) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't denormalize selection")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1163,34 +1142,44 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_map_t *fm)
H5D__chunk_io_init_selections(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
{
const H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */
const H5T_t *mem_type = type_info->mem_type; /* Local pointer to memory datatype */
H5S_t *tmp_mspace = NULL; /* Temporary memory dataspace */
H5T_t *file_type = NULL; /* Temporary copy of file datatype for iteration */
hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
char bogus; /* "bogus" buffer to pass to selection iterator */
herr_t ret_value = SUCCEED; /* Return value */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
const H5D_t *dataset; /* Local pointer to dataset info */
const H5T_t *mem_type; /* Local pointer to memory datatype */
H5S_t *tmp_mspace = NULL; /* Temporary memory dataspace */
H5T_t *file_type = NULL; /* Temporary copy of file datatype for iteration */
hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
char bogus; /* "bogus" buffer to pass to selection iterator */
H5D_io_info_wrap_t io_info_wrap;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
HDassert(io_info);
HDassert(dinfo);
/* Set convenience pointers */
fm = dinfo->layout_io_info.chunk_map;
HDassert(fm);
dataset = dinfo->dset;
mem_type = dinfo->type_info.mem_type;
/* Special case for only one element in selection */
/* (usually appending a record) */
if (fm->nelmts == 1
if (dinfo->nelmts == 1
#ifdef H5_HAVE_PARALLEL
&& !(io_info->using_mpi_vfd)
#endif /* H5_HAVE_PARALLEL */
&& H5S_SEL_ALL != H5S_GET_SELECT_TYPE(fm->file_space)) {
&& H5S_SEL_ALL != H5S_GET_SELECT_TYPE(dinfo->file_space)) {
/* Initialize skip list for chunk selections */
fm->sel_chunks = NULL;
fm->use_single = TRUE;
/* Initialize single chunk dataspace */
if (NULL == dataset->shared->cache.chunk.single_space) {
/* Make a copy of the dataspace for the dataset */
if ((dataset->shared->cache.chunk.single_space = H5S_copy(fm->file_space, TRUE, FALSE)) == NULL)
if ((dataset->shared->cache.chunk.single_space = H5S_copy(dinfo->file_space, TRUE, FALSE)) ==
NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
/* Resize chunk's dataspace dimensions to size of chunk */
@@ -1205,17 +1194,17 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_
HDassert(fm->single_space);
/* Allocate the single chunk information */
if (NULL == dataset->shared->cache.chunk.single_chunk_info)
if (NULL == (dataset->shared->cache.chunk.single_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
if (NULL == dataset->shared->cache.chunk.single_piece_info)
if (NULL == (dataset->shared->cache.chunk.single_piece_info = H5FL_MALLOC(H5D_piece_info_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
fm->single_chunk_info = dataset->shared->cache.chunk.single_chunk_info;
HDassert(fm->single_chunk_info);
fm->single_piece_info = dataset->shared->cache.chunk.single_piece_info;
HDassert(fm->single_piece_info);
/* Reset chunk template information */
fm->mchunk_tmpl = NULL;
/* Set up chunk mapping for single element */
if (H5D__create_chunk_map_single(fm, io_info) < 0)
if (H5D__create_piece_map_single(dinfo, io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"unable to create chunk selections for single element")
} /* end if */
@@ -1226,16 +1215,16 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_
if (NULL == dataset->shared->cache.chunk.sel_chunks)
if (NULL == (dataset->shared->cache.chunk.sel_chunks = H5SL_create(H5SL_TYPE_HSIZE, NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create skip list for chunk selections")
fm->sel_chunks = dataset->shared->cache.chunk.sel_chunks;
HDassert(fm->sel_chunks);
fm->dset_sel_pieces = dataset->shared->cache.chunk.sel_chunks;
HDassert(fm->dset_sel_pieces);
/* We are not using single element mode */
fm->use_single = FALSE;
/* Get type of selection on disk & in memory */
if ((fm->fsel_type = H5S_GET_SELECT_TYPE(fm->file_space)) < H5S_SEL_NONE)
if ((fm->fsel_type = H5S_GET_SELECT_TYPE(dinfo->file_space)) < H5S_SEL_NONE)
HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
if ((fm->msel_type = H5S_GET_SELECT_TYPE(fm->mem_space)) < H5S_SEL_NONE)
if ((fm->msel_type = H5S_GET_SELECT_TYPE(dinfo->mem_space)) < H5S_SEL_NONE)
HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
/* If the selection is NONE or POINTS, set the flag to FALSE */
@@ -1248,57 +1237,53 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_
if (sel_hyper_flag) {
/* Build the file selection for each chunk */
if (H5S_SEL_ALL == fm->fsel_type) {
if (H5D__create_chunk_file_map_all(fm, io_info) < 0)
if (H5D__create_piece_file_map_all(dinfo, io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
} /* end if */
else {
/* Sanity check */
HDassert(fm->fsel_type == H5S_SEL_HYPERSLABS);
if (H5D__create_chunk_file_map_hyper(fm, io_info) < 0)
if (H5D__create_piece_file_map_hyper(dinfo, io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
} /* end else */
} /* end if */
else {
H5S_sel_iter_op_t iter_op; /* Operator for iteration */
H5D_chunk_file_iter_ud_t udata; /* User data for iteration */
H5S_sel_iter_op_t iter_op; /* Operator for iteration */
/* Create temporary datatypes for selection iteration */
if (NULL == (file_type = H5T_copy(dataset->shared->type, H5T_COPY_ALL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy file datatype")
/* Initialize the user data */
udata.fm = fm;
#ifdef H5_HAVE_PARALLEL
udata.io_info = io_info;
#endif /* H5_HAVE_PARALLEL */
iter_op.op_type = H5S_SEL_ITER_OP_LIB;
iter_op.u.lib_op = H5D__chunk_file_cb;
/* set opdata for H5D__piece_mem_cb */
io_info_wrap.io_info = io_info;
io_info_wrap.dinfo = dinfo;
iter_op.op_type = H5S_SEL_ITER_OP_LIB;
iter_op.u.lib_op = H5D__piece_file_cb;
/* Spaces might not be the same shape, iterate over the file selection directly */
if (H5S_select_iterate(&bogus, file_type, fm->file_space, &iter_op, &udata) < 0)
if (H5S_select_iterate(&bogus, file_type, dinfo->file_space, &iter_op, &io_info_wrap) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
/* Reset "last chunk" info */
/* Reset "last piece" info */
fm->last_index = (hsize_t)-1;
fm->last_chunk_info = NULL;
fm->last_piece_info = NULL;
} /* end else */
/* Build the memory selection for each chunk */
if (sel_hyper_flag && H5S_SELECT_SHAPE_SAME(fm->file_space, fm->mem_space) == TRUE) {
if (sel_hyper_flag && H5S_SELECT_SHAPE_SAME(dinfo->file_space, dinfo->mem_space) == TRUE) {
/* Reset chunk template information */
fm->mchunk_tmpl = NULL;
/* If the selections are the same shape, use the file chunk information
* to generate the memory chunk information quickly.
/* If the selections are the same shape, use the file chunk
* information to generate the memory chunk information quickly.
*/
if (H5D__create_chunk_mem_map_hyper(fm) < 0)
if (H5D__create_piece_mem_map_hyper(dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
} /* end if */
else if (sel_hyper_flag && fm->f_ndims == 1 && fm->m_ndims == 1 &&
H5S_SELECT_IS_REGULAR(fm->mem_space) && H5S_SELECT_IS_SINGLE(fm->mem_space)) {
if (H5D__create_chunk_mem_map_1d(fm) < 0)
H5S_SELECT_IS_REGULAR(dinfo->mem_space) && H5S_SELECT_IS_SINGLE(dinfo->mem_space)) {
if (H5D__create_piece_mem_map_1d(dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
} /* end else-if */
else {
@@ -1306,7 +1291,7 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_
size_t elmt_size; /* Memory datatype size */
/* Make a copy of equivalent memory space */
if ((tmp_mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
if ((tmp_mspace = H5S_copy(dinfo->mem_space, TRUE, FALSE)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
/* De-select the mem space copy */
@@ -1324,15 +1309,18 @@ H5D__chunk_io_init_selections(const H5D_io_info_t *io_info, const H5D_type_info_
/* Create selection iterator for memory selection */
if (0 == (elmt_size = H5T_get_size(mem_type)))
HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid")
if (H5S_select_iter_init(&(fm->mem_iter), fm->mem_space, elmt_size, 0) < 0)
if (H5S_select_iter_init(&(fm->mem_iter), dinfo->mem_space, elmt_size, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
iter_init = TRUE; /* Selection iteration info has been initialized */
iter_op.op_type = H5S_SEL_ITER_OP_LIB;
iter_op.u.lib_op = H5D__chunk_mem_cb;
/* set opdata for H5D__piece_mem_cb */
io_info_wrap.io_info = io_info;
io_info_wrap.dinfo = dinfo;
iter_op.op_type = H5S_SEL_ITER_OP_LIB;
iter_op.u.lib_op = H5D__piece_mem_cb;
/* Spaces aren't the same shape, iterate over the memory selection directly */
if (H5S_select_iterate(&bogus, file_type, fm->file_space, &iter_op, fm) < 0)
if (H5S_select_iterate(&bogus, file_type, dinfo->file_space, &iter_op, &io_info_wrap) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
} /* end else */
} /* end else */
@@ -1344,7 +1332,7 @@ done:
if (H5S_close(tmp_mspace) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL,
"can't release memory chunk dataspace template")
if (H5D__chunk_io_term(fm) < 0)
if (H5D__chunk_io_term(io_info, dinfo) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release chunk mapping")
} /* end if */
@@ -1466,14 +1454,17 @@ H5D__chunk_mem_realloc(void *chk, size_t size, const H5O_pline_t *pline)
/*--------------------------------------------------------------------------
NAME
H5D__free_chunk_info
H5D__free_piece_info
PURPOSE
Internal routine to destroy a chunk info node
Performs initialization before any sort of I/O on the raw data
This was derived from H5D__free_chunk_info for multi-dset work.
USAGE
void H5D__free_chunk_info(chunk_info)
herr_t H5D__free_piece_info(chunk_info, key, opdata)
void *chunk_info; IN: Pointer to chunk info to destroy
void *key; Unused
void *opdata; Unused
RETURNS
No return value
Non-negative on success, negative on failure
DESCRIPTION
Releases all the memory for a chunk info node. Called by H5SL_free
GLOBAL VARIABLES
@@ -1481,51 +1472,48 @@ H5D__chunk_mem_realloc(void *chk, size_t size, const H5O_pline_t *pline)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
H5D__free_chunk_info(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *opdata)
herr_t
H5D__free_piece_info(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *opdata)
{
H5D_chunk_info_t *chunk_info = (H5D_chunk_info_t *)item;
H5D_piece_info_t *piece_info = (H5D_piece_info_t *)item;
FUNC_ENTER_PACKAGE_NOERR
HDassert(chunk_info);
HDassert(piece_info);
/* Close the chunk's file dataspace, if it's not shared */
if (!chunk_info->fspace_shared)
(void)H5S_close(chunk_info->fspace);
/* Close the piece's file dataspace, if it's not shared */
if (!piece_info->fspace_shared)
(void)H5S_close(piece_info->fspace);
else
H5S_select_all(chunk_info->fspace, TRUE);
H5S_select_all(piece_info->fspace, TRUE);
/* Close the chunk's memory dataspace, if it's not shared */
if (!chunk_info->mspace_shared && chunk_info->mspace)
(void)H5S_close(chunk_info->mspace);
/* Close the piece's memory dataspace, if it's not shared */
if (!piece_info->mspace_shared && piece_info->mspace)
(void)H5S_close((H5S_t *)piece_info->mspace);
/* Free the actual chunk info */
chunk_info = H5FL_FREE(H5D_chunk_info_t, chunk_info);
/* Free the actual piece info */
piece_info = H5FL_FREE(H5D_piece_info_t, piece_info);
FUNC_LEAVE_NOAPI(0)
} /* H5D__free_chunk_info() */
} /* H5D__free_piece_info() */
/*-------------------------------------------------------------------------
* Function: H5D__create_chunk_map_single
* Function: H5D__create_piece_map_single
*
* Purpose: Create chunk selections when appending a single record
* Purpose: Create piece selections when appending a single record
* This was derived from H5D__create_chunk_map_single for
* multi-dset work.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Tuesday, November 20, 2007
*
* Programmer: Jonathan Kim Nov, 2013
*-------------------------------------------------------------------------
*/
static herr_t
H5D__create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t
#ifndef H5_HAVE_PARALLEL
H5_ATTR_UNUSED
#endif /* H5_HAVE_PARALLEL */
*io_info)
H5D__create_piece_map_single(H5D_dset_io_info_t *di, H5D_io_info_t *io_info)
{
H5D_chunk_info_t *chunk_info; /* Chunk information to insert into skip list */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
H5D_piece_info_t *piece_info; /* Piece information to insert into skip list */
hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk */
hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
@@ -1534,64 +1522,68 @@ H5D__create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t
FUNC_ENTER_PACKAGE
/* Sanity check */
/* Set convenience pointer */
fm = di->layout_io_info.chunk_map;
/* Sanity checks */
HDassert(fm);
HDassert(fm->f_ndims > 0);
/* Get coordinate for selection */
if (H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
if (H5S_SELECT_BOUNDS(di->file_space, sel_start, sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
/* Initialize the 'single chunk' file & memory chunk information */
chunk_info = fm->single_chunk_info;
chunk_info->chunk_points = 1;
/* Initialize the 'single piece' file & memory piece information */
piece_info = fm->single_piece_info;
piece_info->piece_points = 1;
/* Set chunk location & hyperslab size */
for (u = 0; u < fm->f_ndims; u++) {
/* Validate this chunk dimension */
if (fm->layout->u.chunk.dim[u] == 0)
if (di->layout->u.chunk.dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
HDassert(sel_start[u] == sel_end[u]);
chunk_info->scaled[u] = sel_start[u] / fm->layout->u.chunk.dim[u];
coords[u] = chunk_info->scaled[u] * fm->layout->u.chunk.dim[u];
piece_info->scaled[u] = sel_start[u] / di->layout->u.chunk.dim[u];
coords[u] = piece_info->scaled[u] * di->layout->u.chunk.dim[u];
} /* end for */
chunk_info->scaled[fm->f_ndims] = 0;
piece_info->scaled[fm->f_ndims] = 0;
/* Calculate the index of this chunk */
chunk_info->index =
H5VM_array_offset_pre(fm->f_ndims, fm->layout->u.chunk.down_chunks, chunk_info->scaled);
piece_info->index =
H5VM_array_offset_pre(fm->f_ndims, di->layout->u.chunk.down_chunks, piece_info->scaled);
/* Copy selection for file's dataspace into chunk dataspace */
if (H5S_select_copy(fm->single_space, fm->file_space, FALSE) < 0)
if (H5S_select_copy(fm->single_space, di->file_space, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file selection")
/* Move selection back to have correct offset in chunk */
if (H5S_SELECT_ADJUST_U(fm->single_space, coords) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
#ifdef H5_HAVE_PARALLEL
/* store chunk selection information */
if (io_info->using_mpi_vfd)
fm->select_chunk[chunk_info->index] = chunk_info;
#endif /* H5_HAVE_PARALLEL */
/* Set the file dataspace for the chunk to the shared 'single' dataspace */
chunk_info->fspace = fm->single_space;
piece_info->fspace = fm->single_space;
/* Indicate that the chunk's file dataspace is shared */
chunk_info->fspace_shared = TRUE;
piece_info->fspace_shared = TRUE;
/* Just point at the memory dataspace & selection */
chunk_info->mspace = fm->mem_space;
piece_info->mspace = di->mem_space;
/* Indicate that the chunk's memory dataspace is shared */
chunk_info->mspace_shared = TRUE;
piece_info->mspace_shared = TRUE;
/* make connection to related dset info from this piece_info */
piece_info->dset_info = di;
/* Add piece to global piece_count */
io_info->piece_count++;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__create_chunk_map_single() */
} /* end H5D__create_piece_map_single() */
/*-------------------------------------------------------------------------
* Function: H5D__create_chunk_file_map_all
* Function: H5D__create_piece_file_map_all
*
* Purpose: Create all chunk selections in file, for an "all" selection.
*
@@ -1603,21 +1595,18 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm, const H5D_io_info_t
#ifndef H5_HAVE_PARALLEL
H5_ATTR_UNUSED
#endif /* H5_HAVE_PARALLEL */
*io_info)
H5D__create_piece_file_map_all(H5D_dset_io_info_t *di, H5D_io_info_t *io_info)
{
H5S_t *tmp_fchunk = NULL; /* Temporary file dataspace */
hsize_t file_dims[H5S_MAX_RANK]; /* File dataspace dims */
hsize_t sel_points; /* Number of elements in file selection */
hsize_t zeros[H5S_MAX_RANK]; /* All zero vector (for start parameter to setting hyperslab on partial
chunks) */
hsize_t coords[H5S_MAX_RANK]; /* Current coordinates of chunk */
hsize_t end[H5S_MAX_RANK]; /* Final coordinates of chunk */
hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */
hsize_t chunk_index; /* "Index" of chunk */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
H5S_t *tmp_fchunk = NULL; /* Temporary file dataspace */
hsize_t file_dims[H5S_MAX_RANK]; /* File dataspace dims */
hsize_t sel_points; /* Number of elements in file selection */
hsize_t zeros[H5S_MAX_RANK]; /* All zero vector (for start parameter to setting hyperslab on partial
chunks) */
hsize_t coords[H5S_MAX_RANK]; /* Current coordinates of chunk */
hsize_t end[H5S_MAX_RANK]; /* Final coordinates of chunk */
hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */
hsize_t chunk_index; /* "Index" of chunk */
hsize_t curr_partial_clip[H5S_MAX_RANK]; /* Current partial dimension sizes to clip against */
hsize_t partial_dim_size[H5S_MAX_RANK]; /* Size of a partial dimension */
hbool_t is_partial_dim[H5S_MAX_RANK]; /* Whether a dimension is currently a partial chunk */
@@ -1627,14 +1616,18 @@ H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm, const H5D_io_info_t
FUNC_ENTER_PACKAGE
/* Sanity check */
/* Set convenience pointer */
fm = di->layout_io_info.chunk_map;
/* Sanity checks */
HDassert(fm);
HDassert(fm->f_ndims > 0);
/* Get number of elements selected in file */
sel_points = fm->nelmts;
sel_points = di->nelmts;
/* Get dataspace dimensions */
if (H5S_get_simple_extent_dims(fm->file_space, file_dims, NULL) < 0)
if (H5S_get_simple_extent_dims(di->file_space, file_dims, NULL) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
/* Set initial chunk location, partial dimensions, etc */
@@ -1642,7 +1635,7 @@ H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm, const H5D_io_info_t
HDmemset(zeros, 0, sizeof(zeros));
for (u = 0; u < fm->f_ndims; u++) {
/* Validate this chunk dimension */
if (fm->layout->u.chunk.dim[u] == 0)
if (di->layout->u.chunk.dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
/* Set up start / end coordinates for first chunk */
@@ -1672,54 +1665,54 @@ H5D__create_chunk_file_map_all(H5D_chunk_map_t *fm, const H5D_io_info_t
/* Iterate through each chunk in the dataset */
while (sel_points) {
H5D_chunk_info_t *new_chunk_info; /* chunk information to insert into skip list */
H5D_piece_info_t *new_piece_info; /* Piece information to insert into skip list */
hsize_t chunk_points; /* Number of elements in chunk selection */
/* Add temporary chunk to the list of chunks */
/* Add temporary chunk to the list of pieces */
/* Allocate the file & memory chunk information */
if (NULL == (new_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk info")
if (NULL == (new_piece_info = H5FL_MALLOC(H5D_piece_info_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate piece info")
/* Initialize the chunk information */
/* Set the chunk index */
new_chunk_info->index = chunk_index;
#ifdef H5_HAVE_PARALLEL
/* Store chunk selection information, for multi-chunk I/O */
if (io_info->using_mpi_vfd)
fm->select_chunk[chunk_index] = new_chunk_info;
#endif /* H5_HAVE_PARALLEL */
new_piece_info->index = chunk_index;
/* Set the file chunk dataspace */
if (NULL == (new_chunk_info->fspace = H5S_copy(tmp_fchunk, TRUE, FALSE)))
if (NULL == (new_piece_info->fspace = H5S_copy(tmp_fchunk, TRUE, FALSE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy chunk dataspace")
new_chunk_info->fspace_shared = FALSE;
new_piece_info->fspace_shared = FALSE;
/* If there are partial dimensions for this chunk, set the hyperslab for them */
if (num_partial_dims > 0)
if (H5S_select_hyperslab(new_chunk_info->fspace, H5S_SELECT_SET, zeros, NULL, curr_partial_clip,
if (H5S_select_hyperslab(new_piece_info->fspace, H5S_SELECT_SET, zeros, NULL, curr_partial_clip,
NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't create chunk selection")
/* Set the memory chunk dataspace */
new_chunk_info->mspace = NULL;
new_chunk_info->mspace_shared = FALSE;
new_piece_info->mspace = NULL;
new_piece_info->mspace_shared = FALSE;
/* Copy the chunk's scaled coordinates */
H5MM_memcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
new_chunk_info->scaled[fm->f_ndims] = 0;
H5MM_memcpy(new_piece_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
new_piece_info->scaled[fm->f_ndims] = 0;
/* make connection to related dset info from this piece_info */
new_piece_info->dset_info = di;
/* Insert the new chunk into the skip list */
if (H5SL_insert(fm->sel_chunks, new_chunk_info, &new_chunk_info->index) < 0) {
H5D__free_chunk_info(new_chunk_info, NULL, NULL);
if (H5SL_insert(fm->dset_sel_pieces, new_piece_info, &new_piece_info->index) < 0) {
H5D__free_piece_info(new_piece_info, NULL, NULL);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into skip list")
} /* end if */
/* Add piece to global piece_count*/
io_info->piece_count++;
/* Get number of elements selected in chunk */
chunk_points = H5S_GET_SELECT_NPOINTS(new_chunk_info->fspace);
H5_CHECKED_ASSIGN(new_chunk_info->chunk_points, uint32_t, chunk_points, hsize_t);
chunk_points = H5S_GET_SELECT_NPOINTS(new_piece_info->fspace);
new_piece_info->piece_points = chunk_points;
/* Decrement # of points left in file selection */
sel_points -= chunk_points;
@@ -1796,74 +1789,75 @@ done:
} /* end H5D__create_chunk_file_map_all() */
/*-------------------------------------------------------------------------
* Function: H5D__create_chunk_file_map_hyper
* Function: H5D__create_piece_file_map_hyper
*
* Purpose: Create all chunk selections in file, for a hyperslab selection.
* Purpose: Create all chunk selections in file.
* This was derived from H5D__create_chunk_file_map_hyper for
* multi-dset work.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Thursday, May 29, 2003
*
* Programmer: Jonathan Kim Nov, 2013
*-------------------------------------------------------------------------
*/
static herr_t
H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
#ifndef H5_HAVE_PARALLEL
H5_ATTR_UNUSED
#endif /* H5_HAVE_PARALLEL */
*io_info)
H5D__create_piece_file_map_hyper(H5D_dset_io_info_t *dinfo, H5D_io_info_t *io_info)
{
H5S_t *tmp_fchunk = NULL; /* Temporary file dataspace */
hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
hsize_t sel_points; /* Number of elements in file selection */
hsize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */
hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
hsize_t end[H5O_LAYOUT_NDIMS]; /* Final coordinates of chunk */
hsize_t chunk_index; /* Index of chunk */
hsize_t start_scaled[H5S_MAX_RANK]; /* Starting scaled coordinates of selection */
hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */
int curr_dim; /* Current dimension to increment */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
H5S_t *tmp_fchunk = NULL; /* Temporary file dataspace */
hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
hsize_t sel_points; /* Number of elements in file selection */
hsize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */
hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
hsize_t end[H5O_LAYOUT_NDIMS]; /* Final coordinates of chunk */
hsize_t chunk_index; /* Index of chunk */
hsize_t start_scaled[H5S_MAX_RANK]; /* Starting scaled coordinates of selection */
hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */
int curr_dim; /* Current dimension to increment */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
/* Set convenience pointer */
fm = dinfo->layout_io_info.chunk_map;
/* Sanity checks */
HDassert(fm);
HDassert(fm->f_ndims > 0);
/* Get number of elements selected in file */
sel_points = fm->nelmts;
sel_points = dinfo->nelmts;
/* Get bounding box for selection (to reduce the number of chunks to iterate over) */
if (H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
if (H5S_SELECT_BOUNDS(dinfo->file_space, sel_start, sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
/* Set initial chunk location & hyperslab size */
for (u = 0; u < fm->f_ndims; u++) {
/* Validate this chunk dimension */
if (fm->layout->u.chunk.dim[u] == 0)
if (dinfo->layout->u.chunk.dim[u] == 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u)
scaled[u] = start_scaled[u] = sel_start[u] / fm->layout->u.chunk.dim[u];
coords[u] = start_coords[u] = scaled[u] * fm->layout->u.chunk.dim[u];
scaled[u] = start_scaled[u] = sel_start[u] / dinfo->layout->u.chunk.dim[u];
coords[u] = start_coords[u] = scaled[u] * dinfo->layout->u.chunk.dim[u];
end[u] = (coords[u] + fm->chunk_dim[u]) - 1;
} /* end for */
/* Calculate the index of this chunk */
chunk_index = H5VM_array_offset_pre(fm->f_ndims, fm->layout->u.chunk.down_chunks, scaled);
chunk_index = H5VM_array_offset_pre(fm->f_ndims, dinfo->layout->u.chunk.down_chunks, scaled);
/* Iterate through each chunk in the dataset */
while (sel_points) {
/* Check for intersection of current chunk and file selection */
if (TRUE == H5S_SELECT_INTERSECT_BLOCK(fm->file_space, coords, end)) {
H5D_chunk_info_t *new_chunk_info; /* chunk information to insert into skip list */
if (TRUE == H5S_SELECT_INTERSECT_BLOCK(dinfo->file_space, coords, end)) {
H5D_piece_info_t *new_piece_info; /* chunk information to insert into skip list */
hsize_t chunk_points; /* Number of elements in chunk selection */
/* Create dataspace for chunk, 'AND'ing the overall selection with
* the current chunk.
*/
if (H5S_combine_hyperslab(fm->file_space, H5S_SELECT_AND, coords, NULL, fm->chunk_dim, NULL,
if (H5S_combine_hyperslab(dinfo->file_space, H5S_SELECT_AND, coords, NULL, fm->chunk_dim, NULL,
&tmp_fchunk) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL,
"unable to combine file space selection with chunk block")
@@ -1879,42 +1873,42 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
/* Add temporary chunk to the list of chunks */
/* Allocate the file & memory chunk information */
if (NULL == (new_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
if (NULL == (new_piece_info = H5FL_MALLOC(H5D_piece_info_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk info")
/* Initialize the chunk information */
/* Set the chunk index */
new_chunk_info->index = chunk_index;
#ifdef H5_HAVE_PARALLEL
/* Store chunk selection information, for multi-chunk I/O */
if (io_info->using_mpi_vfd)
fm->select_chunk[chunk_index] = new_chunk_info;
#endif /* H5_HAVE_PARALLEL */
new_piece_info->index = chunk_index;
/* Set the file chunk dataspace */
new_chunk_info->fspace = tmp_fchunk;
new_chunk_info->fspace_shared = FALSE;
new_piece_info->fspace = tmp_fchunk;
new_piece_info->fspace_shared = FALSE;
tmp_fchunk = NULL;
/* Set the memory chunk dataspace */
new_chunk_info->mspace = NULL;
new_chunk_info->mspace_shared = FALSE;
new_piece_info->mspace = NULL;
new_piece_info->mspace_shared = FALSE;
/* Copy the chunk's scaled coordinates */
H5MM_memcpy(new_chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
new_chunk_info->scaled[fm->f_ndims] = 0;
H5MM_memcpy(new_piece_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
new_piece_info->scaled[fm->f_ndims] = 0;
/* Insert the new chunk into the skip list */
if (H5SL_insert(fm->sel_chunks, new_chunk_info, &new_chunk_info->index) < 0) {
H5D__free_chunk_info(new_chunk_info, NULL, NULL);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into skip list")
/* make connection to related dset info from this piece_info */
new_piece_info->dset_info = dinfo;
/* Add piece to global piece_count */
io_info->piece_count++;
/* Insert the new piece into the skip list */
if (H5SL_insert(fm->dset_sel_pieces, new_piece_info, &new_piece_info->index) < 0) {
H5D__free_piece_info(new_piece_info, NULL, NULL);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert piece into skip list")
} /* end if */
/* Get number of elements selected in chunk */
chunk_points = H5S_GET_SELECT_NPOINTS(new_chunk_info->fspace);
H5_CHECKED_ASSIGN(new_chunk_info->chunk_points, uint32_t, chunk_points, hsize_t);
chunk_points = H5S_GET_SELECT_NPOINTS(new_piece_info->fspace);
new_piece_info->piece_points = chunk_points;
/* Decrement # of points left in file selection */
sel_points -= chunk_points;
@@ -1957,7 +1951,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
} while (curr_dim >= 0 && (coords[curr_dim] > sel_end[curr_dim]));
/* Re-calculate the index of this chunk */
chunk_index = H5VM_array_offset_pre(fm->f_ndims, fm->layout->u.chunk.down_chunks, scaled);
chunk_index = H5VM_array_offset_pre(fm->f_ndims, dinfo->layout->u.chunk.down_chunks, scaled);
} /* end if */
} /* end while */
@@ -1968,28 +1962,29 @@ done:
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release temporary dataspace")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__create_chunk_file_map_hyper() */
} /* end H5D__create_piece_file_map_hyper() */
/*-------------------------------------------------------------------------
* Function: H5D__create_chunk_mem_map_hyper
* Function: H5D__create_piece_mem_map_hyper
*
* Purpose: Create all chunk selections in memory by copying the file
* Purpose: Create all chunk selections in memory by copying the file
* chunk selections and adjusting their offsets to be correct
* for the memory.
* or the memory.
* This was derived from H5D__create_chunk_mem_map_hyper for
* multi-dset work.
*
* Return: Non-negative on success/Negative on failure
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Thursday, May 29, 2003
* Programmer: Jonathan Kim Nov, 2013
*
* Assumptions: That the file and memory selections are the same shape.
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
H5D__create_piece_mem_map_hyper(const H5D_dset_io_info_t *dinfo)
{
H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
H5D_piece_info_t *piece_info; /* Pointer to piece information */
H5SL_node_t *curr_node; /* Current node in skip list */
hsize_t file_sel_start[H5S_MAX_RANK]; /* Offset of low bound of file selection */
hsize_t file_sel_end[H5S_MAX_RANK]; /* Offset of high bound of file selection */
@@ -2002,30 +1997,33 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(fm->f_ndims > 0);
HDassert(dinfo->layout_io_info.chunk_map->f_ndims > 0);
/* Set convenience pointer */
fm = dinfo->layout_io_info.chunk_map;
/* Check for all I/O going to a single chunk */
if (H5SL_count(fm->sel_chunks) == 1) {
if (H5SL_count(fm->dset_sel_pieces) == 1) {
/* Get the node */
curr_node = H5SL_first(fm->sel_chunks);
curr_node = H5SL_first(fm->dset_sel_pieces);
/* Get pointer to chunk's information */
chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
HDassert(chunk_info);
/* Get pointer to piece's information */
piece_info = (H5D_piece_info_t *)H5SL_item(curr_node);
HDassert(piece_info);
/* Just point at the memory dataspace & selection */
chunk_info->mspace = fm->mem_space;
piece_info->mspace = dinfo->mem_space;
/* Indicate that the chunk's memory space is shared */
chunk_info->mspace_shared = TRUE;
/* Indicate that the piece's memory space is shared */
piece_info->mspace_shared = TRUE;
} /* end if */
else {
/* Get bounding box for file selection */
if (H5S_SELECT_BOUNDS(fm->file_space, file_sel_start, file_sel_end) < 0)
if (H5S_SELECT_BOUNDS(dinfo->file_space, file_sel_start, file_sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
/* Get bounding box for memory selection */
if (H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0)
if (H5S_SELECT_BOUNDS(dinfo->mem_space, mem_sel_start, mem_sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
/* Calculate the adjustment for memory selection from file selection */
@@ -2037,28 +2035,29 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
} /* end for */
/* Iterate over each chunk in the chunk list */
curr_node = H5SL_first(fm->sel_chunks);
HDassert(fm->dset_sel_pieces);
curr_node = H5SL_first(fm->dset_sel_pieces);
while (curr_node) {
hsize_t coords[H5S_MAX_RANK]; /* Current coordinates of chunk */
hssize_t chunk_adjust[H5S_MAX_RANK]; /* Adjustment to make to a particular chunk */
hssize_t piece_adjust[H5S_MAX_RANK]; /* Adjustment to make to a particular chunk */
H5S_sel_type chunk_sel_type; /* Chunk's selection type */
/* Get pointer to chunk's information */
chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
HDassert(chunk_info);
/* Get pointer to piece's information */
piece_info = (H5D_piece_info_t *)H5SL_item(curr_node);
HDassert(piece_info);
/* Compute the chunk coordinates from the scaled coordinates */
for (u = 0; u < fm->f_ndims; u++)
coords[u] = chunk_info->scaled[u] * fm->layout->u.chunk.dim[u];
coords[u] = piece_info->scaled[u] * dinfo->layout->u.chunk.dim[u];
/* Copy the information */
/* Copy the memory dataspace */
if ((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
if ((piece_info->mspace = H5S_copy(dinfo->mem_space, TRUE, FALSE)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
/* Get the chunk's selection type */
if ((chunk_sel_type = H5S_GET_SELECT_TYPE(chunk_info->fspace)) < H5S_SEL_NONE)
if ((chunk_sel_type = H5S_GET_SELECT_TYPE(piece_info->fspace)) < H5S_SEL_NONE)
HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
/* Set memory selection for "all" chunk selections */
@@ -2068,7 +2067,7 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
coords[u] = (hsize_t)((hssize_t)coords[u] - adjust[u]);
/* Set to same shape as chunk */
if (H5S_select_hyperslab(chunk_info->mspace, H5S_SELECT_SET, coords, NULL, fm->chunk_dim,
if (H5S_select_hyperslab(piece_info->mspace, H5S_SELECT_SET, coords, NULL, fm->chunk_dim,
NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't create chunk memory selection")
} /* end if */
@@ -2077,32 +2076,32 @@ H5D__create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
HDassert(H5S_SEL_HYPERSLABS == chunk_sel_type);
/* Copy the file chunk's selection */
if (H5S_SELECT_COPY(chunk_info->mspace, chunk_info->fspace, FALSE) < 0)
if (H5S_SELECT_COPY(piece_info->mspace, piece_info->fspace, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection")
/* Compute the adjustment for this chunk */
for (u = 0; u < fm->f_ndims; u++) {
/* Compensate for the chunk offset */
H5_CHECK_OVERFLOW(coords[u], hsize_t, hssize_t);
chunk_adjust[u] = adjust[u] - (hssize_t)coords[u];
piece_adjust[u] = adjust[u] - (hssize_t)coords[u];
} /* end for */
/* Adjust the selection */
if (H5S_SELECT_ADJUST_S(chunk_info->mspace, chunk_adjust) < 0)
if (H5S_SELECT_ADJUST_S(piece_info->mspace, piece_adjust) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to adjust selection")
} /* end else */
/* Get the next chunk node in the skip list */
/* Get the next piece node in the skip list */
curr_node = H5SL_next(curr_node);
} /* end while */
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__create_chunk_mem_map_hyper() */
} /* end H5D__create_piece_mem_map_hyper() */
/*-------------------------------------------------------------------------
* Function: H5D__create_mem_map_1d
* Function: H5D__create_piece_mem_map_1d
*
* Purpose: Create all chunk selections for 1-dimensional regular memory space
* that has only one single block in the selection
@@ -2115,31 +2114,36 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm)
H5D__create_piece_mem_map_1d(const H5D_dset_io_info_t *dinfo)
{
H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
H5D_piece_info_t *piece_info; /* Pointer to chunk information */
H5SL_node_t *curr_node; /* Current node in skip list */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(fm->f_ndims > 0);
HDassert(dinfo->layout_io_info.chunk_map->f_ndims > 0);
/* Set convenience pointer */
fm = dinfo->layout_io_info.chunk_map;
HDassert(fm);
/* Check for all I/O going to a single chunk */
if (H5SL_count(fm->sel_chunks) == 1) {
if (H5SL_count(fm->dset_sel_pieces) == 1) {
/* Get the node */
curr_node = H5SL_first(fm->sel_chunks);
curr_node = H5SL_first(fm->dset_sel_pieces);
/* Get pointer to chunk's information */
chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
HDassert(chunk_info);
piece_info = (H5D_piece_info_t *)H5SL_item(curr_node);
HDassert(piece_info);
/* Just point at the memory dataspace & selection */
chunk_info->mspace = fm->mem_space;
piece_info->mspace = dinfo->mem_space;
/* Indicate that the chunk's memory space is shared */
chunk_info->mspace_shared = TRUE;
piece_info->mspace_shared = TRUE;
} /* end if */
else {
hsize_t mem_sel_start[H5S_MAX_RANK]; /* Offset of low bound of file selection */
@@ -2147,26 +2151,26 @@ H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm)
HDassert(fm->m_ndims == 1);
if (H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0)
if (H5S_SELECT_BOUNDS(dinfo->mem_space, mem_sel_start, mem_sel_end) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
/* Iterate over each chunk in the chunk list */
curr_node = H5SL_first(fm->sel_chunks);
curr_node = H5SL_first(fm->dset_sel_pieces);
while (curr_node) {
hsize_t chunk_points; /* Number of elements in chunk selection */
hsize_t tmp_count = 1;
/* Get pointer to chunk's information */
chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
HDassert(chunk_info);
piece_info = (H5D_piece_info_t *)H5SL_item(curr_node);
HDassert(piece_info);
/* Copy the memory dataspace */
if ((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
if ((piece_info->mspace = H5S_copy(dinfo->mem_space, TRUE, FALSE)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
chunk_points = H5S_GET_SELECT_NPOINTS(chunk_info->fspace);
chunk_points = H5S_GET_SELECT_NPOINTS(piece_info->fspace);
if (H5S_select_hyperslab(chunk_info->mspace, H5S_SELECT_SET, mem_sel_start, NULL, &tmp_count,
if (H5S_select_hyperslab(piece_info->mspace, H5S_SELECT_SET, mem_sel_start, NULL, &tmp_count,
&chunk_points) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "can't create chunk memory selection")
@@ -2179,177 +2183,187 @@ H5D__create_chunk_mem_map_1d(const H5D_chunk_map_t *fm)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__create_chunk_mem_map_1d() */
} /* end H5D__create_piece_mem_map_1d() */
/*-------------------------------------------------------------------------
* Function: H5D__chunk_file_cb
* Function: H5D__piece_file_cb
*
* Purpose: Callback routine for file selection iterator. Used when
* Purpose: Callback routine for file selection iterator. Used when
* creating selections in file for each point selected.
*
* Return: Non-negative on success/Negative on failure
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Wednesday, July 23, 2003
* Programmer: Jonathan Kim Nov, 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_file_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, unsigned ndims,
const hsize_t *coords, void *_udata)
H5D__piece_file_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, unsigned ndims,
const hsize_t *coords, void *_opdata)
{
H5D_chunk_file_iter_ud_t *udata = (H5D_chunk_file_iter_ud_t *)_udata; /* User data for operation */
H5D_chunk_map_t *fm = udata->fm; /* File<->memory chunk mapping info */
H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */
hsize_t chunk_index; /* Chunk index */
hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
H5D_io_info_wrap_t *opdata = (H5D_io_info_wrap_t *)_opdata;
H5D_io_info_t *io_info = (H5D_io_info_t *)opdata->io_info; /* io info for multi dset */
H5D_dset_io_info_t *dinfo = (H5D_dset_io_info_t *)opdata->dinfo; /* File<->memory piece mapping info */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
H5D_piece_info_t *piece_info; /* Chunk information for current piece */
hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */
hsize_t chunk_index; /* Chunk index */
hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Set convenience pointer */
fm = dinfo->layout_io_info.chunk_map;
/* Calculate the index of this chunk */
chunk_index = H5VM_chunk_index_scaled(ndims, coords, fm->layout->u.chunk.dim,
fm->layout->u.chunk.down_chunks, scaled);
chunk_index = H5VM_chunk_index_scaled(ndims, coords, dinfo->layout->u.chunk.dim,
dinfo->layout->u.chunk.down_chunks, scaled);
/* Find correct chunk in file & memory skip list */
if (chunk_index == fm->last_index) {
/* If the chunk index is the same as the last chunk index we used,
* get the cached info to operate on.
*/
chunk_info = fm->last_chunk_info;
piece_info = fm->last_piece_info;
} /* end if */
else {
/* If the chunk index is not the same as the last chunk index we used,
* find the chunk in the skip list.
*/
/* Get the chunk node from the skip list */
if (NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index))) {
* find the chunk in the skip list. If we do not find it, create
* a new node. */
if (NULL == (piece_info = (H5D_piece_info_t *)H5SL_search(fm->dset_sel_pieces, &chunk_index))) {
H5S_t *fspace; /* Memory chunk's dataspace */
/* Allocate the file & memory chunk information */
if (NULL == (chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
if (NULL == (piece_info = H5FL_MALLOC(H5D_piece_info_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
/* Initialize the chunk information */
/* Set the chunk index */
chunk_info->index = chunk_index;
piece_info->index = chunk_index;
/* Create a dataspace for the chunk */
if ((fspace = H5S_create_simple(fm->f_ndims, fm->chunk_dim, NULL)) == NULL) {
chunk_info = H5FL_FREE(H5D_chunk_info_t, chunk_info);
piece_info = H5FL_FREE(H5D_piece_info_t, piece_info);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace for chunk")
} /* end if */
/* De-select the chunk space */
if (H5S_select_none(fspace) < 0) {
(void)H5S_close(fspace);
chunk_info = H5FL_FREE(H5D_chunk_info_t, chunk_info);
piece_info = H5FL_FREE(H5D_piece_info_t, piece_info);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select dataspace")
} /* end if */
/* Set the file chunk dataspace */
chunk_info->fspace = fspace;
chunk_info->fspace_shared = FALSE;
piece_info->fspace = fspace;
piece_info->fspace_shared = FALSE;
/* Set the memory chunk dataspace */
chunk_info->mspace = NULL;
chunk_info->mspace_shared = FALSE;
piece_info->mspace = NULL;
piece_info->mspace_shared = FALSE;
/* Set the number of selected elements in chunk to zero */
chunk_info->chunk_points = 0;
piece_info->piece_points = 0;
/* Set the chunk's scaled coordinates */
H5MM_memcpy(chunk_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
chunk_info->scaled[fm->f_ndims] = 0;
H5MM_memcpy(piece_info->scaled, scaled, sizeof(hsize_t) * fm->f_ndims);
piece_info->scaled[fm->f_ndims] = 0;
/* Make connection to related dset info from this piece_info */
piece_info->dset_info = dinfo;
/* Insert the new chunk into the skip list */
if (H5SL_insert(fm->sel_chunks, chunk_info, &chunk_info->index) < 0) {
H5D__free_chunk_info(chunk_info, NULL, NULL);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into skip list")
if (H5SL_insert(fm->dset_sel_pieces, piece_info, &piece_info->index) < 0) {
H5D__free_piece_info(piece_info, NULL, NULL);
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into dataset skip list")
} /* end if */
} /* end if */
#ifdef H5_HAVE_PARALLEL
/* Store chunk selection information, for collective multi-chunk I/O */
if (udata->io_info->using_mpi_vfd)
fm->select_chunk[chunk_index] = chunk_info;
#endif /* H5_HAVE_PARALLEL */
/* Add piece to global piece_count */
io_info->piece_count++;
} /* end if */
/* Update the "last chunk seen" information */
fm->last_index = chunk_index;
fm->last_chunk_info = chunk_info;
fm->last_piece_info = piece_info;
} /* end else */
/* Get the offset of the element within the chunk */
for (u = 0; u < fm->f_ndims; u++)
coords_in_chunk[u] = coords[u] - (scaled[u] * fm->layout->u.chunk.dim[u]);
coords_in_chunk[u] = coords[u] - (scaled[u] * dinfo->layout->u.chunk.dim[u]);
/* Add point to file selection for chunk */
if (H5S_select_elements(chunk_info->fspace, H5S_SELECT_APPEND, (size_t)1, coords_in_chunk) < 0)
if (H5S_select_elements(piece_info->fspace, H5S_SELECT_APPEND, (size_t)1, coords_in_chunk) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
/* Increment the number of elemented selected in chunk */
chunk_info->chunk_points++;
piece_info->piece_points++;
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_file_cb() */
} /* end H5D__piece_file_cb */
/*-------------------------------------------------------------------------
* Function: H5D__chunk_mem_cb
* Function: H5D__piece_mem_cb
*
* Purpose: Callback routine for file selection iterator. Used when
* creating selections in memory for each chunk.
* Purpose: Callback routine for file selection iterator. Used when
* creating selections in memory for each piece.
* This was derived from H5D__chunk_mem_cb for multi-dset
* work.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Raymond Lu
* Thursday, April 10, 2003
* Programmer: Jonathan Kim Nov, 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, unsigned ndims,
const hsize_t *coords, void *_fm)
H5D__piece_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, unsigned ndims,
const hsize_t *coords, void *_opdata)
{
H5D_chunk_map_t *fm = (H5D_chunk_map_t *)_fm; /* File<->memory chunk mapping info */
H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
hsize_t coords_in_mem[H5S_MAX_RANK]; /* Coordinates of element in memory */
hsize_t chunk_index; /* Chunk index */
herr_t ret_value = SUCCEED; /* Return value */
H5D_io_info_wrap_t *opdata = (H5D_io_info_wrap_t *)_opdata;
H5D_dset_io_info_t *dinfo = (H5D_dset_io_info_t *)opdata->dinfo; /* File<->memory chunk mapping info */
H5D_piece_info_t *piece_info; /* Chunk information for current chunk */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
hsize_t coords_in_mem[H5S_MAX_RANK]; /* Coordinates of element in memory */
hsize_t chunk_index; /* Chunk index */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Set convenience pointer */
fm = dinfo->layout_io_info.chunk_map;
/* Calculate the index of this chunk */
chunk_index = H5VM_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks);
chunk_index =
H5VM_chunk_index(ndims, coords, dinfo->layout->u.chunk.dim, dinfo->layout->u.chunk.down_chunks);
/* Find correct chunk in file & memory skip list */
if (chunk_index == fm->last_index) {
/* If the chunk index is the same as the last chunk index we used,
* get the cached spaces to operate on.
*/
chunk_info = fm->last_chunk_info;
piece_info = fm->last_piece_info;
} /* end if */
else {
/* If the chunk index is not the same as the last chunk index we used,
* find the chunk in the skip list.
* find the chunk in the dataset skip list.
*/
/* Get the chunk node from the skip list */
if (NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index)))
HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, H5_ITER_ERROR, "can't locate chunk in skip list")
if (NULL == (piece_info = (H5D_piece_info_t *)H5SL_search(fm->dset_sel_pieces, &chunk_index)))
HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, H5_ITER_ERROR, "can't locate piece in dataset skip list")
/* Check if the chunk already has a memory space */
if (NULL == chunk_info->mspace)
if (NULL == piece_info->mspace)
/* Copy the template memory chunk dataspace */
if (NULL == (chunk_info->mspace = H5S_copy(fm->mchunk_tmpl, FALSE, FALSE)))
if (NULL == (piece_info->mspace = H5S_copy(fm->mchunk_tmpl, FALSE, FALSE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy file space")
/* Update the "last chunk seen" information */
fm->last_index = chunk_index;
fm->last_chunk_info = chunk_info;
fm->last_piece_info = piece_info;
} /* end else */
/* Get coordinates of selection iterator for memory */
@@ -2358,11 +2372,11 @@ H5D__chunk_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, u
/* Add point to memory selection for chunk */
if (fm->msel_type == H5S_SEL_POINTS) {
if (H5S_select_elements(chunk_info->mspace, H5S_SELECT_APPEND, (size_t)1, coords_in_mem) < 0)
if (H5S_select_elements(piece_info->mspace, H5S_SELECT_APPEND, (size_t)1, coords_in_mem) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, H5_ITER_ERROR, "unable to select element")
} /* end if */
else {
if (H5S_hyper_add_span_element(chunk_info->mspace, fm->m_ndims, coords_in_mem) < 0)
if (H5S_hyper_add_span_element(piece_info->mspace, fm->m_ndims, coords_in_mem) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, H5_ITER_ERROR, "unable to select element")
} /* end else */
@@ -2372,7 +2386,62 @@ H5D__chunk_mem_cb(void H5_ATTR_UNUSED *elem, const H5T_t H5_ATTR_UNUSED *type, u
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_mem_cb() */
} /* end H5D__piece_mem_cb() */
/*-------------------------------------------------------------------------
* Function: H5D__chunk_mdio_init
*
* Purpose: Performs second phase of initialization for multi-dataset
* I/O. Currently looks up chunk addresses and adds chunks to
* sel_pieces.
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_mdio_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
{
H5SL_node_t *piece_node; /* Current node in chunk skip list */
H5D_piece_info_t *piece_info; /* Piece information for current piece */
H5D_chunk_ud_t udata; /* Chunk data from index */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Get first node in skip list. Note we don't check for failure since NULL
* simply indicates an empty skip list. */
piece_node = H5D_CHUNK_GET_FIRST_NODE(dinfo);
/* Iterate over skip list */
while (piece_node) {
/* Get piece info */
if (NULL == (piece_info = (H5D_piece_info_t *)H5D_CHUNK_GET_NODE_INFO(dinfo, piece_node)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't get piece info from list")
/* Get the info for the chunk in the file */
if (H5D__chunk_lookup(dinfo->dset, piece_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
/* Save chunk file address */
piece_info->faddr = udata.chunk_block.offset;
/* Add piece to MDIO operation if it has a file address */
if (H5F_addr_defined(piece_info->faddr)) {
HDassert(io_info->sel_pieces);
HDassert(io_info->pieces_added < io_info->piece_count);
/* Add to sel_pieces and update pieces_added */
io_info->sel_pieces[io_info->pieces_added++] = piece_info;
}
/* Advance to next skip list node */
piece_node = H5D_CHUNK_GET_NEXT_NODE(dinfo, piece_node);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_mdio_init() */
/*-------------------------------------------------------------------------
* Function: H5D__chunk_cacheable
@@ -2388,16 +2457,19 @@ done:
*-------------------------------------------------------------------------
*/
htri_t
H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr, hbool_t write_op)
H5D__chunk_cacheable(const H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, haddr_t caddr,
hbool_t write_op)
{
const H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */
hbool_t has_filters = FALSE; /* Whether there are filters on the chunk or not */
htri_t ret_value = FAIL; /* Return value */
const H5D_t *dataset = NULL; /* Local pointer to dataset info */
hbool_t has_filters = FALSE; /* Whether there are filters on the chunk or not */
htri_t ret_value = FAIL; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(io_info);
HDassert(dset_info);
dataset = dset_info->dset;
HDassert(dataset);
/* Must bring the whole chunk in if there are any filters on the chunk.
@@ -2405,9 +2477,9 @@ H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr, hbool_t write_
* chunk because it is a partial edge chunk. */
if (dataset->shared->dcpl_cache.pline.nused > 0) {
if (dataset->shared->layout.u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) {
has_filters = !H5D__chunk_is_partial_edge_chunk(
io_info->dset->shared->ndims, io_info->dset->shared->layout.u.chunk.dim,
io_info->store->chunk.scaled, io_info->dset->shared->curr_dims);
has_filters =
!H5D__chunk_is_partial_edge_chunk(dataset->shared->ndims, dataset->shared->layout.u.chunk.dim,
dset_info->store->chunk.scaled, dataset->shared->curr_dims);
} /* end if */
else
has_filters = TRUE;
@@ -2478,7 +2550,7 @@ done:
*-------------------------------------------------------------------------
*/
static htri_t
H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info)
H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info)
{
const H5D_t *dataset = NULL; /* Local pointer to dataset info */
htri_t ret_value = FAIL; /* Return value */
@@ -2487,19 +2559,19 @@ H5D__chunk_may_use_select_io(const H5D_io_info_t *io_info)
/* Sanity check */
HDassert(io_info);
HDassert(dset_info);
dataset = io_info->dset;
dataset = dset_info->dset;
HDassert(dataset);
/* Don't use selection I/O if it's globally disabled, there is a type
* conversion, or if there are filters on the dataset (for now) */
if (!H5_use_selection_io_g || io_info->io_ops.single_read != H5D__select_read ||
dataset->shared->dcpl_cache.pline.nused > 0)
if (dset_info->io_ops.single_read != H5D__select_read || dataset->shared->dcpl_cache.pline.nused > 0)
ret_value = FALSE;
else {
hbool_t page_buf_enabled;
HDassert(io_info->io_ops.single_write == H5D__select_write);
HDassert(dset_info->io_ops.single_write == H5D__select_write);
/* Check if the page buffer is enabled */
if (H5PB_enabled(io_info->f_sh, H5FD_MEM_DRAW, &page_buf_enabled) < 0)
@@ -2549,36 +2621,40 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t H5_ATTR_UNUSED nelmts,
H5S_t H5_ATTR_UNUSED *file_space, H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm)
H5D__chunk_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
{
H5SL_node_t *chunk_node; /* Current node in chunk skip list */
H5D_io_info_t nonexistent_io_info; /* "nonexistent" I/O info object */
uint32_t src_accessed_bytes = 0; /* Total accessed size in a chunk */
hbool_t skip_missing_chunks = FALSE; /* Whether to skip missing chunks */
H5S_t **chunk_mem_spaces = NULL; /* Array of chunk memory spaces */
H5S_t *chunk_mem_spaces_static[8]; /* Static buffer for chunk_mem_spaces */
H5S_t **chunk_file_spaces = NULL; /* Array of chunk file spaces */
H5S_t *chunk_file_spaces_static[8]; /* Static buffer for chunk_file_spaces */
haddr_t *chunk_addrs = NULL; /* Array of chunk addresses */
haddr_t chunk_addrs_static[8]; /* Static buffer for chunk_addrs */
herr_t ret_value = SUCCEED; /*return value */
H5SL_node_t *chunk_node; /* Current node in chunk skip list */
H5D_io_info_t nonexistent_io_info; /* "nonexistent" I/O info object */
H5D_dset_io_info_t nonexistent_dset_info; /* "nonexistent" I/O dset info object */
H5D_dset_io_info_t ctg_dset_info; /* Contiguous I/O dset info object */
H5D_dset_io_info_t cpt_dset_info; /* Compact I/O dset info object */
uint32_t src_accessed_bytes = 0; /* Total accessed size in a chunk */
hbool_t skip_missing_chunks = FALSE; /* Whether to skip missing chunks */
H5S_t **chunk_mem_spaces = NULL; /* Array of chunk memory spaces */
H5S_t *chunk_mem_spaces_local[8]; /* Local buffer for chunk_mem_spaces */
H5S_t **chunk_file_spaces = NULL; /* Array of chunk file spaces */
H5S_t *chunk_file_spaces_local[8]; /* Local buffer for chunk_file_spaces */
haddr_t *chunk_addrs = NULL; /* Array of chunk addresses */
haddr_t chunk_addrs_local[8]; /* Local buffer for chunk_addrs */
herr_t ret_value = SUCCEED; /*return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(io_info);
HDassert(io_info->u.rbuf);
HDassert(type_info);
HDassert(fm);
HDassert(dset_info);
HDassert(dset_info->buf.vp);
/* Set up "nonexistent" I/O info object */
H5MM_memcpy(&nonexistent_io_info, io_info, sizeof(nonexistent_io_info));
nonexistent_io_info.layout_ops = *H5D_LOPS_NONEXISTENT;
H5MM_memcpy(&nonexistent_dset_info, dset_info, sizeof(nonexistent_dset_info));
nonexistent_dset_info.layout_ops = *H5D_LOPS_NONEXISTENT;
nonexistent_io_info.dsets_info = &nonexistent_dset_info;
nonexistent_io_info.count = 1;
{
const H5O_fill_t *fill = &(io_info->dset->shared->dcpl_cache.fill); /* Fill value info */
H5D_fill_value_t fill_status; /* Fill value status */
const H5O_fill_t *fill = &(dset_info->dset->shared->dcpl_cache.fill); /* Fill value info */
H5D_fill_value_t fill_status; /* Fill value status */
/* Check the fill value status */
if (H5P_is_fill_value_defined(fill, &fill_status) < 0)
@@ -2596,48 +2672,53 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_
/* Different blocks depending on whether we're using selection I/O */
if (io_info->use_select_io) {
size_t num_chunks;
size_t element_sizes[2] = {type_info->dst_type_size, 0};
void *bufs[2] = {io_info->u.rbuf, NULL};
size_t element_sizes[2] = {dset_info->type_info.src_type_size, 0};
void *bufs[2] = {dset_info->buf.vp, NULL};
/* Cache number of chunks */
num_chunks = H5D_CHUNK_GET_NODE_COUNT(fm);
/* Only create selection I/O arrays if not performing multi dataset I/O,
* otherwise the higher level will handle it */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
/* Cache number of chunks */
num_chunks = H5D_CHUNK_GET_NODE_COUNT(dset_info);
/* Allocate arrays of dataspaces and offsets for use with selection I/O,
* or point to static buffers */
HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) ==
sizeof(chunk_file_spaces_static) / sizeof(chunk_file_spaces_static[0]));
HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) ==
sizeof(chunk_addrs_static) / sizeof(chunk_addrs_static[0]));
if (num_chunks > (sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]))) {
if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for memory space list")
if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for file space list")
if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for chunk address list")
/* Allocate arrays of dataspaces and offsets for use with selection I/O,
* or point to local buffers */
HDassert(sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]) ==
sizeof(chunk_file_spaces_local) / sizeof(chunk_file_spaces_local[0]));
HDassert(sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]) ==
sizeof(chunk_addrs_local) / sizeof(chunk_addrs_local[0]));
if (num_chunks > (sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]))) {
if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for memory space list")
if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for file space list")
if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for chunk address list")
} /* end if */
else {
chunk_mem_spaces = chunk_mem_spaces_local;
chunk_file_spaces = chunk_file_spaces_local;
chunk_addrs = chunk_addrs_local;
} /* end else */
/* Reset num_chunks */
num_chunks = 0;
} /* end if */
else {
chunk_mem_spaces = chunk_mem_spaces_static;
chunk_file_spaces = chunk_file_spaces_static;
chunk_addrs = chunk_addrs_static;
} /* end else */
/* Reset num_chunks */
num_chunks = 0;
/* Iterate through nodes in chunk skip list */
chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
chunk_node = H5D_CHUNK_GET_FIRST_NODE(dset_info);
while (chunk_node) {
H5D_chunk_info_t *chunk_info; /* Chunk information */
H5D_piece_info_t *chunk_info; /* Chunk information */
H5D_chunk_ud_t udata; /* Chunk index pass-through */
/* Get the actual chunk information from the skip list node */
chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
chunk_info = H5D_CHUNK_GET_NODE_INFO(dset_info, chunk_node);
/* Get the info for the chunk in the file */
if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0)
if (H5D__chunk_lookup(dset_info->dset, chunk_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
/* There should be no chunks cached */
@@ -2649,45 +2730,66 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_
/* Check for non-existent chunk & skip it if appropriate */
if (H5F_addr_defined(udata.chunk_block.offset)) {
/* Add chunk to list for selection I/O */
chunk_mem_spaces[num_chunks] = chunk_info->mspace;
chunk_file_spaces[num_chunks] = chunk_info->fspace;
chunk_addrs[num_chunks] = udata.chunk_block.offset;
num_chunks++;
/* Add chunk to list for selection I/O, if not performing multi dataset I/O */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
chunk_mem_spaces[num_chunks] = chunk_info->mspace;
chunk_file_spaces[num_chunks] = chunk_info->fspace;
chunk_addrs[num_chunks] = udata.chunk_block.offset;
num_chunks++;
} /* end if */
else {
/* Add to mdset selection I/O arrays */
HDassert(io_info->mem_spaces);
HDassert(io_info->file_spaces);
HDassert(io_info->addrs);
HDassert(io_info->element_sizes);
HDassert(io_info->rbufs);
HDassert(io_info->pieces_added < io_info->piece_count);
io_info->mem_spaces[io_info->pieces_added] = chunk_info->mspace;
io_info->file_spaces[io_info->pieces_added] = chunk_info->fspace;
io_info->addrs[io_info->pieces_added] = udata.chunk_block.offset;
io_info->element_sizes[io_info->pieces_added] = element_sizes[0];
io_info->rbufs[io_info->pieces_added] = bufs[0];
io_info->pieces_added++;
}
} /* end if */
else if (!skip_missing_chunks) {
/* Perform the actual read operation from the nonexistent chunk
*/
if ((io_info->io_ops.single_read)(&nonexistent_io_info, type_info,
(hsize_t)chunk_info->chunk_points, chunk_info->fspace,
chunk_info->mspace) < 0)
nonexistent_dset_info.file_space = chunk_info->fspace;
nonexistent_dset_info.mem_space = chunk_info->mspace;
nonexistent_dset_info.nelmts = chunk_info->piece_points;
if ((dset_info->io_ops.single_read)(&nonexistent_io_info, &nonexistent_dset_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed")
} /* end if */
/* Advance to next chunk in list */
chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node);
} /* end while */
/* Issue selection I/O call (we can skip the page buffer because we've
* already verified it won't be used, and the metadata accumulator
* because this is raw data) */
if (H5F_shared_select_read(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, (uint32_t)num_chunks,
chunk_mem_spaces, chunk_file_spaces, chunk_addrs, element_sizes, bufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunk selection read failed")
/* Only perform I/O if not performing multi dataset I/O, otherwise the
* higher level will handle it after all datasets have been processed */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
/* Issue selection I/O call (we can skip the page buffer because we've
* already verified it won't be used, and the metadata accumulator
* because this is raw data) */
H5_CHECK_OVERFLOW(num_chunks, size_t, uint32_t)
if (H5F_shared_select_read(H5F_SHARED(dset_info->dset->oloc.file), H5FD_MEM_DRAW,
(uint32_t)num_chunks, chunk_mem_spaces, chunk_file_spaces, chunk_addrs,
element_sizes, bufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunk selection read failed")
/* Clean up memory */
if (chunk_mem_spaces != chunk_mem_spaces_static) {
HDassert(chunk_mem_spaces);
HDassert(chunk_file_spaces != chunk_file_spaces_static);
HDassert(chunk_addrs != chunk_addrs_static);
H5MM_free(chunk_mem_spaces);
chunk_mem_spaces = NULL;
H5MM_free(chunk_file_spaces);
chunk_file_spaces = NULL;
H5MM_free(chunk_addrs);
chunk_addrs = NULL;
} /* end if */
} /* end if */
/* Clean up memory */
if (chunk_mem_spaces != chunk_mem_spaces_local) {
HDassert(chunk_file_spaces != chunk_file_spaces_local);
HDassert(chunk_addrs != chunk_addrs_local);
chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces);
chunk_file_spaces = H5MM_xfree(chunk_file_spaces);
chunk_addrs = H5MM_xfree(chunk_addrs);
} /* end if */
} /* end if */
} /* end if */
else {
H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
@@ -2697,33 +2799,39 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_
/* Set up contiguous I/O info object */
H5MM_memcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
ctg_io_info.store = &ctg_store;
ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
HDmemcpy(&ctg_dset_info, dset_info, sizeof(ctg_dset_info));
ctg_dset_info.store = &ctg_store;
ctg_dset_info.layout_ops = *H5D_LOPS_CONTIG;
ctg_io_info.dsets_info = &ctg_dset_info;
ctg_io_info.count = 1;
/* Initialize temporary contiguous storage info */
H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size,
H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, dset_info->dset->shared->layout.u.chunk.size,
uint32_t);
/* Set up compact I/O info object */
H5MM_memcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
cpt_io_info.store = &cpt_store;
cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
HDmemcpy(&cpt_dset_info, dset_info, sizeof(cpt_dset_info));
cpt_dset_info.store = &cpt_store;
cpt_dset_info.layout_ops = *H5D_LOPS_COMPACT;
cpt_io_info.dsets_info = &cpt_dset_info;
cpt_io_info.count = 1;
/* Initialize temporary compact storage info */
cpt_store.compact.dirty = &cpt_dirty;
/* Iterate through nodes in chunk skip list */
chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
chunk_node = H5D_CHUNK_GET_FIRST_NODE(dset_info);
while (chunk_node) {
H5D_chunk_info_t *chunk_info; /* Chunk information */
H5D_piece_info_t *chunk_info; /* Chunk information */
H5D_chunk_ud_t udata; /* Chunk index pass-through */
htri_t cacheable; /* Whether the chunk is cacheable */
/* Get the actual chunk information from the skip list node */
chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
chunk_info = H5D_CHUNK_GET_NODE_INFO(dset_info, chunk_node);
/* Get the info for the chunk in the file */
if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0)
if (H5D__chunk_lookup(dset_info->dset, chunk_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
/* Sanity check */
@@ -2737,20 +2845,23 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_
void *chunk = NULL; /* Pointer to locked chunk buffer */
/* Set chunk's [scaled] coordinates */
io_info->store->chunk.scaled = chunk_info->scaled;
dset_info->store->chunk.scaled = chunk_info->scaled;
/* Determine if we should use the chunk cache */
if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, FALSE)) < 0)
if ((cacheable = H5D__chunk_cacheable(io_info, dset_info, udata.chunk_block.offset, FALSE)) <
0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable")
if (cacheable) {
/* Load the chunk into cache and lock it. */
/* Compute # of bytes accessed in chunk */
H5_CHECK_OVERFLOW(type_info->src_type_size, /*From:*/ size_t, /*To:*/ uint32_t);
src_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->src_type_size;
H5_CHECK_OVERFLOW(dset_info->type_info.src_type_size, /*From:*/ size_t, /*To:*/ uint32_t);
H5_CHECK_OVERFLOW(chunk_info->piece_points, /*From:*/ size_t, /*To:*/ uint32_t);
src_accessed_bytes =
(uint32_t)chunk_info->piece_points * (uint32_t)dset_info->type_info.src_type_size;
/* Lock the chunk into the cache */
if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, FALSE, FALSE)))
if (NULL == (chunk = H5D__chunk_lock(io_info, dset_info, &udata, FALSE, FALSE)))
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
/* Set up the storage buffer information for this chunk */
@@ -2772,35 +2883,39 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_
} /* end else */
/* Perform the actual read operation */
if ((io_info->io_ops.single_read)(chk_io_info, type_info, (hsize_t)chunk_info->chunk_points,
chunk_info->fspace, chunk_info->mspace) < 0)
HDassert(chk_io_info->count == 1);
chk_io_info->dsets_info[0].file_space = chunk_info->fspace;
chk_io_info->dsets_info[0].mem_space = chunk_info->mspace;
chk_io_info->dsets_info[0].nelmts = chunk_info->piece_points;
if ((dset_info->io_ops.single_read)(chk_io_info, &chk_io_info->dsets_info[0]) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed")
/* Release the cache lock on the chunk. */
if (chunk && H5D__chunk_unlock(io_info, &udata, FALSE, chunk, src_accessed_bytes) < 0)
if (chunk &&
H5D__chunk_unlock(io_info, dset_info, &udata, FALSE, chunk, src_accessed_bytes) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
} /* end if */
/* Advance to next chunk in list */
chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node);
} /* end while */
} /* end else */
done:
/* Cleanup on failure */
if (ret_value < 0) {
if (chunk_mem_spaces != chunk_mem_spaces_static)
if (chunk_mem_spaces != chunk_mem_spaces_local)
chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces);
if (chunk_file_spaces != chunk_file_spaces_static)
if (chunk_file_spaces != chunk_file_spaces_local)
chunk_file_spaces = H5MM_xfree(chunk_file_spaces);
if (chunk_addrs != chunk_addrs_static)
if (chunk_addrs != chunk_addrs_local)
chunk_addrs = H5MM_xfree(chunk_addrs);
} /* end if */
/* Make sure we cleaned up */
HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_static);
HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_static);
HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_static);
HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_local);
HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_local);
HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_local);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5D__chunk_read() */
@@ -2818,45 +2933,51 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t H5_ATTR_UNUSED nelmts,
H5S_t H5_ATTR_UNUSED *file_space, H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm)
H5D__chunk_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
{
H5SL_node_t *chunk_node; /* Current node in chunk skip list */
H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
H5D_io_info_t cpt_io_info; /* Compact I/O info object */
H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
uint32_t dst_accessed_bytes = 0; /* Total accessed size in a chunk */
H5S_t **chunk_mem_spaces = NULL; /* Array of chunk memory spaces */
H5S_t *chunk_mem_spaces_static[8]; /* Static buffer for chunk_mem_spaces */
H5S_t **chunk_file_spaces = NULL; /* Array of chunk file spaces */
H5S_t *chunk_file_spaces_static[8]; /* Static buffer for chunk_file_spaces */
haddr_t *chunk_addrs = NULL; /* Array of chunk addresses */
haddr_t chunk_addrs_static[8]; /* Static buffer for chunk_addrs */
herr_t ret_value = SUCCEED; /* Return value */
H5SL_node_t *chunk_node; /* Current node in chunk skip list */
H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
H5D_dset_io_info_t ctg_dset_info; /* Contiguous I/O dset info object */
H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
H5D_io_info_t cpt_io_info; /* Compact I/O info object */
H5D_dset_io_info_t cpt_dset_info; /* Compact I/O dset info object */
H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
uint32_t dst_accessed_bytes = 0; /* Total accessed size in a chunk */
H5S_t **chunk_mem_spaces = NULL; /* Array of chunk memory spaces */
H5S_t *chunk_mem_spaces_local[8]; /* Local buffer for chunk_mem_spaces */
H5S_t **chunk_file_spaces = NULL; /* Array of chunk file spaces */
H5S_t *chunk_file_spaces_local[8]; /* Local buffer for chunk_file_spaces */
haddr_t *chunk_addrs = NULL; /* Array of chunk addresses */
haddr_t chunk_addrs_local[8]; /* Local buffer for chunk_addrs */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(io_info);
HDassert(io_info->u.wbuf);
HDassert(type_info);
HDassert(fm);
HDassert(dset_info);
HDassert(dset_info->buf.cvp);
/* Set up contiguous I/O info object */
H5MM_memcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
ctg_io_info.store = &ctg_store;
ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
HDmemcpy(&ctg_dset_info, dset_info, sizeof(ctg_dset_info));
ctg_dset_info.store = &ctg_store;
ctg_dset_info.layout_ops = *H5D_LOPS_CONTIG;
ctg_io_info.dsets_info = &ctg_dset_info;
ctg_io_info.count = 1;
/* Initialize temporary contiguous storage info */
H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, io_info->dset->shared->layout.u.chunk.size,
H5_CHECKED_ASSIGN(ctg_store.contig.dset_size, hsize_t, dset_info->dset->shared->layout.u.chunk.size,
uint32_t);
/* Set up compact I/O info object */
H5MM_memcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
cpt_io_info.store = &cpt_store;
cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
HDmemcpy(&cpt_dset_info, dset_info, sizeof(cpt_dset_info));
cpt_dset_info.store = &cpt_store;
cpt_dset_info.layout_ops = *H5D_LOPS_COMPACT;
cpt_io_info.dsets_info = &cpt_dset_info;
cpt_io_info.count = 1;
/* Initialize temporary compact storage info */
cpt_store.compact.dirty = &cpt_dirty;
@@ -2864,51 +2985,56 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
/* Different blocks depending on whether we're using selection I/O */
if (io_info->use_select_io) {
size_t num_chunks;
size_t element_sizes[2] = {type_info->dst_type_size, 0};
const void *bufs[2] = {io_info->u.wbuf, NULL};
size_t element_sizes[2] = {dset_info->type_info.dst_type_size, 0};
const void *bufs[2] = {dset_info->buf.cvp, NULL};
/* Cache number of chunks */
num_chunks = H5D_CHUNK_GET_NODE_COUNT(fm);
/* Only create selection I/O arrays if not performing multi dataset I/O,
* otherwise the higher level will handle it */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
/* Cache number of chunks */
num_chunks = H5D_CHUNK_GET_NODE_COUNT(dset_info);
/* Allocate arrays of dataspaces and offsets for use with selection I/O,
* or point to static buffers */
HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) ==
sizeof(chunk_file_spaces_static) / sizeof(chunk_file_spaces_static[0]));
HDassert(sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]) ==
sizeof(chunk_addrs_static) / sizeof(chunk_addrs_static[0]));
if (num_chunks > (sizeof(chunk_mem_spaces_static) / sizeof(chunk_mem_spaces_static[0]))) {
if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for memory space list")
if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for file space list")
if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for chunk address list")
/* Allocate arrays of dataspaces and offsets for use with selection I/O,
* or point to local buffers */
HDassert(sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]) ==
sizeof(chunk_file_spaces_local) / sizeof(chunk_file_spaces_local[0]));
HDassert(sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]) ==
sizeof(chunk_addrs_local) / sizeof(chunk_addrs_local[0]));
if (num_chunks > (sizeof(chunk_mem_spaces_local) / sizeof(chunk_mem_spaces_local[0]))) {
if (NULL == (chunk_mem_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for memory space list")
if (NULL == (chunk_file_spaces = H5MM_malloc(num_chunks * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for file space list")
if (NULL == (chunk_addrs = H5MM_malloc(num_chunks * sizeof(haddr_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for chunk address list")
} /* end if */
else {
chunk_mem_spaces = chunk_mem_spaces_local;
chunk_file_spaces = chunk_file_spaces_local;
chunk_addrs = chunk_addrs_local;
} /* end else */
/* Reset num_chunks */
num_chunks = 0;
} /* end if */
else {
chunk_mem_spaces = chunk_mem_spaces_static;
chunk_file_spaces = chunk_file_spaces_static;
chunk_addrs = chunk_addrs_static;
} /* end else */
/* Reset num_chunks */
num_chunks = 0;
/* Iterate through nodes in chunk skip list */
chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
chunk_node = H5D_CHUNK_GET_FIRST_NODE(dset_info);
while (chunk_node) {
H5D_chunk_info_t *chunk_info; /* Chunk information */
H5D_piece_info_t *chunk_info; /* Chunk information */
H5D_chk_idx_info_t idx_info; /* Chunked index info */
H5D_chunk_ud_t udata; /* Index pass-through */
htri_t cacheable; /* Whether the chunk is cacheable */
hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */
/* Get the actual chunk information from the skip list node */
chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
chunk_info = H5D_CHUNK_GET_NODE_INFO(dset_info, chunk_node);
/* Get the info for the chunk in the file */
if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0)
if (H5D__chunk_lookup(dset_info->dset, chunk_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
/* There should be no chunks cached */
@@ -2919,10 +3045,10 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
(!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
/* Set chunk's [scaled] coordinates */
io_info->store->chunk.scaled = chunk_info->scaled;
dset_info->store->chunk.scaled = chunk_info->scaled;
/* Determine if we should use the chunk cache */
if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, TRUE)) < 0)
if ((cacheable = H5D__chunk_cacheable(io_info, dset_info, udata.chunk_block.offset, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable")
if (cacheable) {
/* Load the chunk into cache. But if the whole chunk is written,
@@ -2931,42 +3057,47 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
/* Compute # of bytes accessed in chunk */
H5_CHECK_OVERFLOW(type_info->dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t);
dst_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->dst_type_size;
H5_CHECK_OVERFLOW(dset_info->type_info.dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t);
H5_CHECK_OVERFLOW(chunk_info->piece_points, /*From:*/ size_t, /*To:*/ uint32_t);
dst_accessed_bytes =
(uint32_t)chunk_info->piece_points * (uint32_t)dset_info->type_info.dst_type_size;
/* Determine if we will access all the data in the chunk */
if (dst_accessed_bytes != ctg_store.contig.dset_size ||
(chunk_info->chunk_points * type_info->src_type_size) != ctg_store.contig.dset_size ||
fm->fsel_type == H5S_SEL_POINTS)
(chunk_info->piece_points * dset_info->type_info.src_type_size) !=
ctg_store.contig.dset_size ||
dset_info->layout_io_info.chunk_map->fsel_type == H5S_SEL_POINTS)
entire_chunk = FALSE;
/* Lock the chunk into the cache */
if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, entire_chunk, FALSE)))
if (NULL == (chunk = H5D__chunk_lock(io_info, dset_info, &udata, entire_chunk, FALSE)))
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
/* Set up the storage buffer information for this chunk */
cpt_store.compact.buf = chunk;
/* Perform the actual write operation */
if ((io_info->io_ops.single_write)(&cpt_io_info, type_info, (hsize_t)chunk_info->chunk_points,
chunk_info->fspace, chunk_info->mspace) < 0)
cpt_dset_info.file_space = chunk_info->fspace;
cpt_dset_info.mem_space = chunk_info->mspace;
cpt_dset_info.nelmts = chunk_info->piece_points;
if ((dset_info->io_ops.single_write)(&cpt_io_info, &cpt_dset_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed")
/* Release the cache lock on the chunk */
if (H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0)
if (H5D__chunk_unlock(io_info, dset_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
} /* end if */
else {
/* If the chunk hasn't been allocated on disk, do so now. */
if (!H5F_addr_defined(udata.chunk_block.offset)) {
/* Compose chunked index info struct */
idx_info.f = io_info->dset->oloc.file;
idx_info.pline = &(io_info->dset->shared->dcpl_cache.pline);
idx_info.layout = &(io_info->dset->shared->layout.u.chunk);
idx_info.storage = &(io_info->dset->shared->layout.storage.u.chunk);
idx_info.f = dset_info->dset->oloc.file;
idx_info.pline = &(dset_info->dset->shared->dcpl_cache.pline);
idx_info.layout = &(dset_info->dset->shared->layout.u.chunk);
idx_info.storage = &(dset_info->dset->shared->layout.storage.u.chunk);
/* Set up the size of chunk for user data */
udata.chunk_block.length = io_info->dset->shared->layout.u.chunk.size;
udata.chunk_block.length = dset_info->dset->shared->layout.u.chunk.size;
/* Allocate the chunk */
if (H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert,
@@ -2979,53 +3110,72 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined")
/* Cache the new chunk information */
H5D__chunk_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, &udata);
H5D__chunk_cinfo_cache_update(&dset_info->dset->shared->cache.chunk.last, &udata);
/* Insert chunk into index */
if (need_insert && io_info->dset->shared->layout.storage.u.chunk.ops->insert)
if ((io_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata,
NULL) < 0)
if (need_insert && dset_info->dset->shared->layout.storage.u.chunk.ops->insert)
if ((dset_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata,
NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL,
"unable to insert chunk addr into index")
} /* end if */
/* Add chunk to list for selection I/O */
chunk_mem_spaces[num_chunks] = chunk_info->mspace;
chunk_file_spaces[num_chunks] = chunk_info->fspace;
chunk_addrs[num_chunks] = udata.chunk_block.offset;
num_chunks++;
/* Add chunk to list for selection I/O, if not performing multi dataset I/O */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
chunk_mem_spaces[num_chunks] = chunk_info->mspace;
chunk_file_spaces[num_chunks] = chunk_info->fspace;
chunk_addrs[num_chunks] = udata.chunk_block.offset;
num_chunks++;
} /* end if */
else {
/* Add to mdset selection I/O arrays */
HDassert(io_info->mem_spaces);
HDassert(io_info->file_spaces);
HDassert(io_info->addrs);
HDassert(io_info->element_sizes);
HDassert(io_info->wbufs);
HDassert(io_info->pieces_added < io_info->piece_count);
io_info->mem_spaces[io_info->pieces_added] = chunk_info->mspace;
io_info->file_spaces[io_info->pieces_added] = chunk_info->fspace;
io_info->addrs[io_info->pieces_added] = udata.chunk_block.offset;
io_info->element_sizes[io_info->pieces_added] = element_sizes[0];
io_info->wbufs[io_info->pieces_added] = bufs[0];
io_info->pieces_added++;
}
} /* end else */
/* Advance to next chunk in list */
chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node);
} /* end while */
/* Issue selection I/O call (we can skip the page buffer because we've
* already verified it won't be used, and the metadata accumulator
* because this is raw data) */
if (H5F_shared_select_write(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, (uint32_t)num_chunks,
chunk_mem_spaces, chunk_file_spaces, chunk_addrs, element_sizes,
bufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunk selection read failed")
/* Only perform I/O if not performing multi dataset I/O, otherwise the
* higher level will handle it after all datasets have been processed */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
/* Issue selection I/O call (we can skip the page buffer because we've
* already verified it won't be used, and the metadata accumulator
* because this is raw data) */
H5_CHECK_OVERFLOW(num_chunks, size_t, uint32_t)
if (H5F_shared_select_write(H5F_SHARED(dset_info->dset->oloc.file), H5FD_MEM_DRAW,
(uint32_t)num_chunks, chunk_mem_spaces, chunk_file_spaces,
chunk_addrs, element_sizes, bufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "chunk selection write failed")
/* Clean up memory */
if (chunk_mem_spaces != chunk_mem_spaces_static) {
HDassert(chunk_mem_spaces);
HDassert(chunk_file_spaces != chunk_file_spaces_static);
HDassert(chunk_addrs != chunk_addrs_static);
H5MM_free(chunk_mem_spaces);
chunk_mem_spaces = NULL;
H5MM_free(chunk_file_spaces);
chunk_file_spaces = NULL;
H5MM_free(chunk_addrs);
chunk_addrs = NULL;
} /* end if */
} /* end if */
/* Clean up memory */
if (chunk_mem_spaces != chunk_mem_spaces_local) {
HDassert(chunk_file_spaces != chunk_file_spaces_local);
HDassert(chunk_addrs != chunk_addrs_local);
chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces);
chunk_file_spaces = H5MM_xfree(chunk_file_spaces);
chunk_addrs = H5MM_xfree(chunk_addrs);
} /* end if */
} /* end if */
} /* end if */
else {
/* Iterate through nodes in chunk skip list */
chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
chunk_node = H5D_CHUNK_GET_FIRST_NODE(dset_info);
while (chunk_node) {
H5D_chunk_info_t *chunk_info; /* Chunk information */
H5D_piece_info_t *chunk_info; /* Chunk information */
H5D_chk_idx_info_t idx_info; /* Chunked index info */
H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
void *chunk; /* Pointer to locked chunk buffer */
@@ -3034,10 +3184,10 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */
/* Get the actual chunk information from the skip list node */
chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
chunk_info = H5D_CHUNK_GET_NODE_INFO(dset_info, chunk_node);
/* Look up the chunk */
if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0)
if (H5D__chunk_lookup(dset_info->dset, chunk_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
/* Sanity check */
@@ -3045,10 +3195,10 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
(!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
/* Set chunk's [scaled] coordinates */
io_info->store->chunk.scaled = chunk_info->scaled;
dset_info->store->chunk.scaled = chunk_info->scaled;
/* Determine if we should use the chunk cache */
if ((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, TRUE)) < 0)
if ((cacheable = H5D__chunk_cacheable(io_info, dset_info, udata.chunk_block.offset, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable")
if (cacheable) {
/* Load the chunk into cache. But if the whole chunk is written,
@@ -3056,17 +3206,20 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
/* Compute # of bytes accessed in chunk */
H5_CHECK_OVERFLOW(type_info->dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t);
dst_accessed_bytes = chunk_info->chunk_points * (uint32_t)type_info->dst_type_size;
H5_CHECK_OVERFLOW(dset_info->type_info.dst_type_size, /*From:*/ size_t, /*To:*/ uint32_t);
H5_CHECK_OVERFLOW(chunk_info->piece_points, /*From:*/ size_t, /*To:*/ uint32_t);
dst_accessed_bytes =
(uint32_t)chunk_info->piece_points * (uint32_t)dset_info->type_info.dst_type_size;
/* Determine if we will access all the data in the chunk */
if (dst_accessed_bytes != ctg_store.contig.dset_size ||
(chunk_info->chunk_points * type_info->src_type_size) != ctg_store.contig.dset_size ||
fm->fsel_type == H5S_SEL_POINTS)
(chunk_info->piece_points * dset_info->type_info.src_type_size) !=
ctg_store.contig.dset_size ||
dset_info->layout_io_info.chunk_map->fsel_type == H5S_SEL_POINTS)
entire_chunk = FALSE;
/* Lock the chunk into the cache */
if (NULL == (chunk = H5D__chunk_lock(io_info, &udata, entire_chunk, FALSE)))
if (NULL == (chunk = H5D__chunk_lock(io_info, dset_info, &udata, entire_chunk, FALSE)))
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
/* Set up the storage buffer information for this chunk */
@@ -3079,13 +3232,13 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
/* If the chunk hasn't been allocated on disk, do so now. */
if (!H5F_addr_defined(udata.chunk_block.offset)) {
/* Compose chunked index info struct */
idx_info.f = io_info->dset->oloc.file;
idx_info.pline = &(io_info->dset->shared->dcpl_cache.pline);
idx_info.layout = &(io_info->dset->shared->layout.u.chunk);
idx_info.storage = &(io_info->dset->shared->layout.storage.u.chunk);
idx_info.f = dset_info->dset->oloc.file;
idx_info.pline = &(dset_info->dset->shared->dcpl_cache.pline);
idx_info.layout = &(dset_info->dset->shared->layout.u.chunk);
idx_info.storage = &(dset_info->dset->shared->layout.storage.u.chunk);
/* Set up the size of chunk for user data */
udata.chunk_block.length = io_info->dset->shared->layout.u.chunk.size;
udata.chunk_block.length = dset_info->dset->shared->layout.u.chunk.size;
/* Allocate the chunk */
if (H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert,
@@ -3098,7 +3251,7 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined")
/* Cache the new chunk information */
H5D__chunk_cinfo_cache_update(&io_info->dset->shared->cache.chunk.last, &udata);
H5D__chunk_cinfo_cache_update(&dset_info->dset->shared->cache.chunk.last, &udata);
} /* end if */
/* Set up the storage address information for this chunk */
@@ -3112,43 +3265,46 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
} /* end else */
/* Perform the actual write operation */
if ((io_info->io_ops.single_write)(chk_io_info, type_info, (hsize_t)chunk_info->chunk_points,
chunk_info->fspace, chunk_info->mspace) < 0)
HDassert(chk_io_info->count == 1);
chk_io_info->dsets_info[0].file_space = chunk_info->fspace;
chk_io_info->dsets_info[0].mem_space = chunk_info->mspace;
chk_io_info->dsets_info[0].nelmts = chunk_info->piece_points;
if ((dset_info->io_ops.single_write)(chk_io_info, &chk_io_info->dsets_info[0]) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed")
/* Release the cache lock on the chunk, or insert chunk into index. */
if (chunk) {
if (H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0)
if (H5D__chunk_unlock(io_info, dset_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
} /* end if */
else {
if (need_insert && io_info->dset->shared->layout.storage.u.chunk.ops->insert)
if ((io_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata, NULL) <
0)
if (need_insert && dset_info->dset->shared->layout.storage.u.chunk.ops->insert)
if ((dset_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata,
NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL,
"unable to insert chunk addr into index")
} /* end else */
/* Advance to next chunk in list */
chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
chunk_node = H5D_CHUNK_GET_NEXT_NODE(dset_info, chunk_node);
} /* end while */
} /* end else */
done:
/* Cleanup on failure */
if (ret_value < 0) {
if (chunk_mem_spaces != chunk_mem_spaces_static)
if (chunk_mem_spaces != chunk_mem_spaces_local)
chunk_mem_spaces = H5MM_xfree(chunk_mem_spaces);
if (chunk_file_spaces != chunk_file_spaces_static)
if (chunk_file_spaces != chunk_file_spaces_local)
chunk_file_spaces = H5MM_xfree(chunk_file_spaces);
if (chunk_addrs != chunk_addrs_static)
if (chunk_addrs != chunk_addrs_local)
chunk_addrs = H5MM_xfree(chunk_addrs);
} /* end if */
/* Make sure we cleaned up */
HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_static);
HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_static);
HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_static);
HDassert(!chunk_mem_spaces || chunk_mem_spaces == chunk_mem_spaces_local);
HDassert(!chunk_file_spaces || chunk_file_spaces == chunk_file_spaces_local);
HDassert(!chunk_addrs || chunk_addrs == chunk_addrs_local);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5D__chunk_write() */
@@ -3199,44 +3355,56 @@ done:
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Saturday, May 17, 2003
* Programmer: Jonathan Kim Nov, 2013
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_io_term(const H5D_chunk_map_t *fm)
H5D__chunk_io_term(H5D_io_info_t H5_ATTR_UNUSED *io_info, H5D_dset_io_info_t *di)
{
herr_t ret_value = SUCCEED; /*return value */
H5D_chunk_map_t *fm; /* Convenience pointer to chunk map */
herr_t ret_value = SUCCEED; /*return value */
FUNC_ENTER_PACKAGE
HDassert(di);
/* Set convenience pointer */
fm = di->layout_io_info.chunk_map;
/* Single element I/O vs. multiple element I/O cleanup */
if (fm->use_single) {
/* Sanity checks */
HDassert(fm->sel_chunks == NULL);
HDassert(fm->single_chunk_info);
HDassert(fm->single_chunk_info->fspace_shared);
HDassert(fm->single_chunk_info->mspace_shared);
HDassert(fm->dset_sel_pieces == NULL);
HDassert(fm->last_piece_info == NULL);
HDassert(fm->single_piece_info);
HDassert(fm->single_piece_info->fspace_shared);
HDassert(fm->single_piece_info->mspace_shared);
/* Reset the selection for the single element I/O */
H5S_select_all(fm->single_space, TRUE);
} /* end if */
else {
/* Release the nodes on the list of selected chunks */
if (fm->sel_chunks)
if (H5SL_free(fm->sel_chunks, H5D__free_chunk_info, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTNEXT, FAIL, "can't iterate over chunks")
} /* end else */
/* Release the nodes on the list of selected pieces, or the last (only)
* piece if the skiplist is not available */
if (fm->dset_sel_pieces) {
if (H5SL_free(fm->dset_sel_pieces, H5D__free_piece_info, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTNEXT, FAIL, "can't free dataset skip list")
} /* end if */
else if (fm->last_piece_info) {
if (H5D__free_piece_info(fm->last_piece_info, NULL, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't free piece info")
fm->last_piece_info = NULL;
} /* end if */
} /* end else */
/* Free the memory chunk dataspace template */
/* Free the memory piece dataspace template */
if (fm->mchunk_tmpl)
if (H5S_close(fm->mchunk_tmpl) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
#ifdef H5_HAVE_PARALLEL
if (fm->select_chunk)
H5MM_xfree(fm->select_chunk);
#endif /* H5_HAVE_PARALLEL */
/* Free chunk map */
di->layout_io_info.chunk_map = H5FL_FREE(H5D_chunk_map_t, di->layout_io_info.chunk_map);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -4099,20 +4267,19 @@ done:
*-------------------------------------------------------------------------
*/
static void *
H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t relax, hbool_t prev_unfilt_chunk)
H5D__chunk_lock(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, H5D_chunk_ud_t *udata,
hbool_t relax, hbool_t prev_unfilt_chunk)
{
const H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
H5O_pline_t *pline =
&(dset->shared->dcpl_cache
.pline); /* I/O pipeline info - always equal to the pline passed to H5D__chunk_mem_alloc */
H5O_pline_t *old_pline = pline; /* Old pipeline, i.e. pipeline used to read the chunk */
const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */
const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill); /* Fill value info */
H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache*/
H5D_rdcc_ent_t *ent; /*cache entry */
size_t chunk_size; /*size of a chunk */
const H5D_t *dset; /* Convenience pointer to the dataset */
H5O_pline_t *pline; /* I/O pipeline info - always equal to the pline passed to H5D__chunk_mem_alloc */
H5O_pline_t *old_pline; /* Old pipeline, i.e. pipeline used to read the chunk */
const H5O_layout_t *layout; /* Dataset layout */
const H5O_fill_t *fill; /* Fill value info */
H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
H5D_rdcc_t *rdcc; /*raw data chunk cache*/
H5D_rdcc_ent_t *ent; /*cache entry */
size_t chunk_size; /*size of a chunk */
hbool_t disable_filters = FALSE; /* Whether to disable filters (when adding to cache) */
void *chunk = NULL; /*the file chunk */
void *ret_value = NULL; /* Return value */
@@ -4121,10 +4288,20 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t rel
/* Sanity checks */
HDassert(io_info);
HDassert(io_info->store);
HDassert(udata);
HDassert(dset_info);
HDassert(dset_info->store);
dset = dset_info->dset;
HDassert(dset);
HDassert(udata);
HDassert(!(udata->new_unfilt_chunk && prev_unfilt_chunk));
/* Set convenience pointers */
pline = &(dset->shared->dcpl_cache.pline);
old_pline = pline;
layout = &(dset->shared->layout);
fill = &(dset->shared->dcpl_cache.fill);
rdcc = &(dset->shared->cache.chunk);
HDassert(!rdcc->tmp_head);
/* Get the chunk's size */
@@ -4146,7 +4323,7 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t rel
/* Make sure this is the right chunk */
for (u = 0; u < layout->u.chunk.ndims - 1; u++)
HDassert(io_info->store->chunk.scaled[u] == ent->scaled[u]);
HDassert(dset_info->store->chunk.scaled[u] == ent->scaled[u]);
}
#endif /* NDEBUG */
@@ -4261,9 +4438,9 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t rel
} /* end if */
else if (layout->u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) {
/* Check if this is an edge chunk */
if (H5D__chunk_is_partial_edge_chunk(io_info->dset->shared->ndims, layout->u.chunk.dim,
io_info->store->chunk.scaled,
io_info->dset->shared->curr_dims)) {
if (H5D__chunk_is_partial_edge_chunk(dset->shared->ndims, layout->u.chunk.dim,
dset_info->store->chunk.scaled,
dset->shared->curr_dims)) {
/* Disable the filters for both writing and reading */
disable_filters = TRUE;
old_pline = NULL;
@@ -4388,17 +4565,17 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata, hbool_t rel
/* See if the chunk can be cached */
if (rdcc->nslots > 0 && chunk_size <= rdcc->nbytes_max) {
/* Calculate the index */
udata->idx_hint = H5D__chunk_hash_val(io_info->dset->shared, udata->common.scaled);
udata->idx_hint = H5D__chunk_hash_val(dset->shared, udata->common.scaled);
/* Add the chunk to the cache only if the slot is not already locked */
ent = rdcc->slot[udata->idx_hint];
if (!ent || !ent->locked) {
/* Preempt enough things from the cache to make room */
if (ent) {
if (H5D__chunk_cache_evict(io_info->dset, ent, TRUE) < 0)
if (H5D__chunk_cache_evict(dset, ent, TRUE) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk from cache")
} /* end if */
if (H5D__chunk_cache_prune(io_info->dset, chunk_size) < 0)
if (H5D__chunk_cache_prune(dset, chunk_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk(s) from cache")
/* Create a new entry */
@@ -4498,19 +4675,26 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, hbool_t dirty, void *chunk,
uint32_t naccessed)
H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
const H5D_chunk_ud_t *udata, hbool_t dirty, void *chunk, uint32_t naccessed)
{
const H5O_layout_t *layout = &(io_info->dset->shared->layout); /* Dataset layout */
const H5D_rdcc_t *rdcc = &(io_info->dset->shared->cache.chunk);
const H5O_layout_t *layout; /* Dataset layout */
const H5D_rdcc_t *rdcc;
const H5D_t *dset; /* Local pointer to the dataset info */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(io_info);
HDassert(dset_info);
HDassert(udata);
/* Set convenience pointers */
layout = &(dset_info->dset->shared->layout);
rdcc = &(dset_info->dset->shared->cache.chunk);
dset = dset_info->dset;
if (UINT_MAX == udata->idx_hint) {
/*
* It's not in the cache, probably because it's too big. If it's
@@ -4526,9 +4710,9 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, hbo
} /* end if */
else if (layout->u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) {
/* Check if the chunk is an edge chunk, and disable filters if so */
is_unfiltered_edge_chunk = H5D__chunk_is_partial_edge_chunk(
io_info->dset->shared->ndims, layout->u.chunk.dim, io_info->store->chunk.scaled,
io_info->dset->shared->curr_dims);
is_unfiltered_edge_chunk =
H5D__chunk_is_partial_edge_chunk(dset->shared->ndims, layout->u.chunk.dim,
dset_info->store->chunk.scaled, dset->shared->curr_dims);
} /* end if */
if (dirty) {
@@ -4547,13 +4731,13 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata, hbo
fake_ent.chunk_block.length = udata->chunk_block.length;
fake_ent.chunk = (uint8_t *)chunk;
if (H5D__chunk_flush_entry(io_info->dset, &fake_ent, TRUE) < 0)
if (H5D__chunk_flush_entry(dset, &fake_ent, TRUE) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
} /* end if */
else {
if (chunk)
chunk = H5D__chunk_mem_xfree(
chunk, (is_unfiltered_edge_chunk ? NULL : &(io_info->dset->shared->dcpl_cache.pline)));
chunk, (is_unfiltered_edge_chunk ? NULL : &(dset->shared->dcpl_cache.pline)));
} /* end else */
} /* end if */
else {
@@ -4676,9 +4860,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite, const hsize_t old_dim[])
H5D__chunk_allocate(const H5D_t *dset, hbool_t full_overwrite, const hsize_t old_dim[])
{
const H5D_t *dset = io_info->dset; /* the dataset pointer */
H5D_chk_idx_info_t idx_info; /* Chunked index info */
const H5D_chunk_ops_t *ops = dset->shared->layout.storage.u.chunk.ops; /* Chunk operations */
hsize_t min_unalloc[H5O_LAYOUT_NDIMS]; /* First chunk in each dimension that is unallocated (in scaled
@@ -5170,6 +5353,7 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[])
H5D_io_info_t chk_io_info; /* Chunked I/O info object */
H5D_chunk_ud_t chk_udata; /* User data for locking chunk */
H5D_storage_t chk_store; /* Chunk storage information */
H5D_dset_io_info_t chk_dset_info; /* Chunked I/O dset info object */
void *chunk; /* The file chunk */
hbool_t carry; /* Flag to indicate that chunk increment carrys to higher dimension (sorta) */
herr_t ret_value = SUCCEED; /* Return value */
@@ -5203,7 +5387,13 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[])
* Note that we only need to set chunk_offset once, as the array's address
* will never change. */
chk_store.chunk.scaled = chunk_sc;
H5D_BUILD_IO_INFO_RD(&chk_io_info, dset, &chk_store, NULL);
chk_io_info.op_type = H5D_IO_OP_READ;
chk_dset_info.dset = dset;
chk_dset_info.store = &chk_store;
chk_dset_info.buf.vp = NULL;
chk_io_info.dsets_info = &chk_dset_info;
/*
* Determine the edges of the dataset which need to be modified
@@ -5268,11 +5458,12 @@ H5D__chunk_update_old_edge_chunks(H5D_t *dset, hsize_t old_dim[])
if (H5F_addr_defined(chk_udata.chunk_block.offset) || (UINT_MAX != chk_udata.idx_hint)) {
/* Lock the chunk into cache. H5D__chunk_lock will take care of
* updating the chunk to no longer be an edge chunk. */
if (NULL == (chunk = (void *)H5D__chunk_lock(&chk_io_info, &chk_udata, FALSE, TRUE)))
if (NULL ==
(chunk = (void *)H5D__chunk_lock(&chk_io_info, &chk_dset_info, &chk_udata, FALSE, TRUE)))
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to lock raw data chunk")
/* Unlock the chunk */
if (H5D__chunk_unlock(&chk_io_info, &chk_udata, TRUE, chunk, (uint32_t)0) < 0)
if (H5D__chunk_unlock(&chk_io_info, &chk_dset_info, &chk_udata, TRUE, chunk, (uint32_t)0) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to unlock raw data chunk")
} /* end if */
@@ -5603,7 +5794,7 @@ static herr_t
H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk)
{
const H5D_io_info_t *io_info = udata->io_info; /* Local pointer to I/O info */
const H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
const H5D_t *dset = udata->dset_info->dset; /* Local pointer to the dataset info */
const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset's layout */
unsigned rank = udata->common.layout->ndims - 1; /* Dataset rank */
const hsize_t *scaled = udata->common.scaled; /* Scaled chunk offset */
@@ -5658,7 +5849,7 @@ H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "unable to select hyperslab")
/* Lock the chunk into the cache, to get a pointer to the chunk buffer */
if (NULL == (chunk = (void *)H5D__chunk_lock(io_info, &chk_udata, FALSE, FALSE)))
if (NULL == (chunk = (void *)H5D__chunk_lock(io_info, udata->dset_info, &chk_udata, FALSE, FALSE)))
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to lock raw data chunk")
/* Fill the selection in the memory buffer */
@@ -5695,7 +5886,7 @@ H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata, hbool_t new_unfilt_chunk)
bytes_accessed = (uint32_t)sel_nelmts * layout->u.chunk.dim[rank];
/* Release lock on chunk */
if (H5D__chunk_unlock(io_info, &chk_udata, TRUE, chunk, bytes_accessed) < 0)
if (H5D__chunk_unlock(io_info, udata->dset_info, &chk_udata, TRUE, chunk, bytes_accessed) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to unlock raw data chunk")
done:
@@ -5822,6 +6013,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim)
unfiltered */
H5D_chk_idx_info_t idx_info; /* Chunked index info */
H5D_io_info_t chk_io_info; /* Chunked I/O info object */
H5D_dset_io_info_t chk_dset_info; /* Chunked I/O dset info object */
H5D_storage_t chk_store; /* Chunk storage information */
const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset's layout */
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
@@ -5889,7 +6081,14 @@ H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim)
* Note that we only need to set scaled once, as the array's address
* will never change. */
chk_store.chunk.scaled = scaled;
H5D_BUILD_IO_INFO_RD(&chk_io_info, dset, &chk_store, NULL);
chk_io_info.op_type = H5D_IO_OP_READ;
chk_dset_info.dset = dset;
chk_dset_info.store = &chk_store;
chk_dset_info.buf.vp = NULL;
chk_io_info.dsets_info = &chk_dset_info;
chk_io_info.count = 1;
/* Compose chunked index info struct */
idx_info.f = dset->oloc.file;
@@ -5903,6 +6102,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim)
udata.common.storage = sc;
udata.common.scaled = scaled;
udata.io_info = &chk_io_info;
udata.dset_info = &chk_dset_info;
udata.idx_info = &idx_info;
udata.space_dim = space_dim;
udata.shrunk_dim = shrunk_dim;
@@ -6183,18 +6383,18 @@ H5D__chunk_addrmap_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
*-------------------------------------------------------------------------
*/
herr_t
H5D__chunk_addrmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[])
H5D__chunk_addrmap(const H5D_t *dset, haddr_t chunk_addr[])
{
H5D_chk_idx_info_t idx_info; /* Chunked index info */
const H5D_t *dset = io_info->dset; /* Local pointer to dataset info */
H5D_chunk_it_ud2_t udata; /* User data for iteration callback */
H5O_storage_chunk_t *sc = &(dset->shared->layout.storage.u.chunk);
H5D_chk_idx_info_t idx_info; /* Chunked index info */
H5D_chunk_it_ud2_t udata; /* User data for iteration callback */
H5O_storage_chunk_t *sc;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
HDassert(dset);
HDassert(dset->shared);
sc = &(dset->shared->layout.storage.u.chunk);
H5D_CHUNK_STORAGE_INDEX_CHK(sc);
HDassert(chunk_addr);
@@ -7254,9 +7454,10 @@ done:
*-------------------------------------------------------------------------
*/
static ssize_t
H5D__nonexistent_readvv(const H5D_io_info_t *io_info, size_t chunk_max_nseq, size_t *chunk_curr_seq,
size_t chunk_len_arr[], hsize_t chunk_off_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
H5D__nonexistent_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[],
hsize_t chunk_off_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_off_arr[])
{
H5D_chunk_readvv_ud_t udata; /* User data for H5VM_opvv() operator */
ssize_t ret_value = -1; /* Return value */
@@ -7273,8 +7474,8 @@ H5D__nonexistent_readvv(const H5D_io_info_t *io_info, size_t chunk_max_nseq, siz
HDassert(mem_off_arr);
/* Set up user data for H5VM_opvv() */
udata.rbuf = (unsigned char *)io_info->u.rbuf;
udata.dset = io_info->dset;
udata.rbuf = (unsigned char *)dset_info->buf.vp;
udata.dset = dset_info->dset;
/* Call generic sequence operation routine */
if ((ret_value = H5VM_opvv(chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_off_arr, mem_max_nseq,
+40 -37
View File
@@ -63,15 +63,16 @@ typedef struct H5D_compact_iovv_memmanage_ud_t {
/* Layout operation callbacks */
static herr_t H5D__compact_construct(H5F_t *f, H5D_t *dset);
static hbool_t H5D__compact_is_space_alloc(const H5O_storage_t *storage);
static herr_t H5D__compact_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *cm);
static herr_t H5D__compact_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__compact_iovv_memmanage_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata);
static ssize_t H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_size_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]);
static ssize_t H5D__compact_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_size_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]);
static ssize_t H5D__compact_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[],
hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_size_arr[], hsize_t mem_offset_arr[]);
static ssize_t H5D__compact_writevv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[],
hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_size_arr[], hsize_t mem_offset_arr[]);
static herr_t H5D__compact_flush(H5D_t *dset);
static herr_t H5D__compact_dest(H5D_t *dset);
@@ -86,17 +87,14 @@ const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = {{
H5D__compact_is_space_alloc, /* is_space_alloc */
NULL, /* is_data_cached */
H5D__compact_io_init, /* io_init */
NULL, /* mdio_init */
H5D__contig_read, /* ser_read */
H5D__contig_write, /* ser_write */
#ifdef H5_HAVE_PARALLEL
NULL, /* par_read */
NULL, /* par_write */
#endif
H5D__compact_readvv, /* readvv */
H5D__compact_writevv, /* writevv */
H5D__compact_flush, /* flush */
NULL, /* io_term */
H5D__compact_dest /* dest */
H5D__compact_readvv, /* readvv */
H5D__compact_writevv, /* writevv */
H5D__compact_flush, /* flush */
NULL, /* io_term */
H5D__compact_dest /* dest */
}};
/*******************/
@@ -247,14 +245,15 @@ H5D__compact_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED *storage)
*-------------------------------------------------------------------------
*/
static herr_t
H5D__compact_io_init(H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info,
hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space,
H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm)
H5D__compact_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
{
FUNC_ENTER_PACKAGE_NOERR
io_info->store->compact.buf = io_info->dset->shared->layout.storage.u.compact.buf;
io_info->store->compact.dirty = &io_info->dset->shared->layout.storage.u.compact.dirty;
dinfo->store->compact.buf = dinfo->dset->shared->layout.storage.u.compact.buf;
dinfo->store->compact.dirty = &dinfo->dset->shared->layout.storage.u.compact.dirty;
/* Disable selection I/O */
io_info->use_select_io = FALSE;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__compact_io_init() */
@@ -320,15 +319,17 @@ done:
*-------------------------------------------------------------------------
*/
static ssize_t
H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_size_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[])
H5D__compact_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, size_t dset_max_nseq,
size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[],
hsize_t mem_offset_arr[])
{
ssize_t ret_value = -1; /* Return value */
FUNC_ENTER_PACKAGE
HDassert(io_info);
HDassert(dset_info);
/* Check if file driver wishes to do its own memory management */
if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_MEMMANAGE)) {
@@ -336,8 +337,8 @@ H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *
/* Set up udata for memory copy operation */
udata.f_sh = io_info->f_sh;
udata.dstbuf = io_info->u.rbuf;
udata.srcbuf = io_info->store->compact.buf;
udata.dstbuf = dset_info->buf.vp;
udata.srcbuf = dset_info->store->compact.buf;
/* Request that file driver does the memory copy */
if ((ret_value = H5VM_opvv(mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, dset_max_nseq,
@@ -347,8 +348,8 @@ H5D__compact_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *
}
else {
/* Use the vectorized memory copy routine to do actual work */
if ((ret_value = H5VM_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr,
mem_offset_arr, io_info->store->compact.buf, dset_max_nseq,
if ((ret_value = H5VM_memcpyvv(dset_info->buf.vp, mem_max_nseq, mem_curr_seq, mem_size_arr,
mem_offset_arr, dset_info->store->compact.buf, dset_max_nseq,
dset_curr_seq, dset_size_arr, dset_offset_arr)) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
}
@@ -379,15 +380,17 @@ done:
*-------------------------------------------------------------------------
*/
static ssize_t
H5D__compact_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_size_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[])
H5D__compact_writevv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, size_t dset_max_nseq,
size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[],
hsize_t mem_offset_arr[])
{
ssize_t ret_value = -1; /* Return value */
FUNC_ENTER_PACKAGE
HDassert(io_info);
HDassert(dset_info);
/* Check if file driver wishes to do its own memory management */
if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_MEMMANAGE)) {
@@ -395,8 +398,8 @@ H5D__compact_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t
/* Set up udata for memory copy operation */
udata.f_sh = io_info->f_sh;
udata.dstbuf = io_info->store->compact.buf;
udata.srcbuf = io_info->u.wbuf;
udata.dstbuf = dset_info->store->compact.buf;
udata.srcbuf = dset_info->buf.cvp;
/* Request that file driver does the memory copy */
if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, mem_max_nseq,
@@ -406,14 +409,14 @@ H5D__compact_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t
}
else {
/* Use the vectorized memory copy routine to do actual work */
if ((ret_value = H5VM_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq,
dset_size_arr, dset_offset_arr, io_info->u.wbuf, mem_max_nseq,
if ((ret_value = H5VM_memcpyvv(dset_info->store->compact.buf, dset_max_nseq, dset_curr_seq,
dset_size_arr, dset_offset_arr, dset_info->buf.cvp, mem_max_nseq,
mem_curr_seq, mem_size_arr, mem_offset_arr)) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
}
/* Mark the compact dataset's buffer as dirty */
*io_info->store->compact.dirty = TRUE;
*dset_info->store->compact.dirty = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
+320 -102
View File
@@ -91,19 +91,24 @@ typedef struct H5D_contig_writevv_ud_t {
/* Layout operation callbacks */
static herr_t H5D__contig_construct(H5F_t *f, H5D_t *dset);
static herr_t H5D__contig_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id);
static herr_t H5D__contig_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *cm);
static ssize_t H5D__contig_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_len_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
static ssize_t H5D__contig_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_len_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
static herr_t H5D__contig_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__contig_mdio_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static ssize_t H5D__contig_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dinfo,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[],
hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_offset_arr[]);
static ssize_t H5D__contig_writevv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dinfo,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[],
hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_offset_arr[]);
static herr_t H5D__contig_flush(H5D_t *dset);
static herr_t H5D__contig_io_term(H5D_io_info_t *io_info, H5D_dset_io_info_t *di);
/* Helper routines */
static herr_t H5D__contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size_t size);
static htri_t H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, H5D_io_op_type_t op_type);
static herr_t H5D__contig_write_one(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, hsize_t offset,
size_t size);
static htri_t H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
H5D_io_op_type_t op_type);
/*********************/
/* Package Variables */
@@ -116,17 +121,14 @@ const H5D_layout_ops_t H5D_LOPS_CONTIG[1] = {{
H5D__contig_is_space_alloc, /* is_space_alloc */
H5D__contig_is_data_cached, /* is_data_cached */
H5D__contig_io_init, /* io_init */
H5D__contig_mdio_init, /* mdio_init */
H5D__contig_read, /* ser_read */
H5D__contig_write, /* ser_write */
#ifdef H5_HAVE_PARALLEL
H5D__contig_collective_read, /* par_read */
H5D__contig_collective_write, /* par_write */
#endif
H5D__contig_readvv, /* readvv */
H5D__contig_writevv, /* writevv */
H5D__contig_flush, /* flush */
NULL, /* io_term */
NULL /* dest */
H5D__contig_readvv, /* readvv */
H5D__contig_writevv, /* writevv */
H5D__contig_flush, /* flush */
H5D__contig_io_term, /* io_term */
NULL /* dest */
}};
/*******************/
@@ -139,6 +141,9 @@ H5FL_BLK_DEFINE(sieve_buf);
/* Declare extern the free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(type_conv);
/* Declare extern the free list to manage the H5D_piece_info_t struct */
H5FL_EXTERN(H5D_piece_info_t);
/*-------------------------------------------------------------------------
* Function: H5D__contig_alloc
*
@@ -183,15 +188,15 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__contig_fill(const H5D_io_info_t *io_info)
H5D__contig_fill(H5D_t *dset)
{
const H5D_t *dset = io_info->dset; /* the dataset pointer */
H5D_io_info_t ioinfo; /* Dataset I/O info */
H5D_storage_t store; /* Union of storage info for dataset */
hssize_t snpoints; /* Number of points in space (for error checking) */
size_t npoints; /* Number of points in space */
hsize_t offset; /* Offset of dataset */
size_t max_temp_buf; /* Maximum size of temporary buffer */
H5D_io_info_t ioinfo; /* Dataset I/O info */
H5D_dset_io_info_t dset_info; /* Dset info */
H5D_storage_t store; /* Union of storage info for dataset */
hssize_t snpoints; /* Number of points in space (for error checking) */
size_t npoints; /* Number of points in space */
hsize_t offset; /* Offset of dataset */
size_t max_temp_buf; /* Maximum size of temporary buffer */
#ifdef H5_HAVE_PARALLEL
MPI_Comm mpi_comm = MPI_COMM_NULL; /* MPI communicator for file */
int mpi_rank = (-1); /* This process's rank */
@@ -252,7 +257,14 @@ H5D__contig_fill(const H5D_io_info_t *io_info)
offset = 0;
/* Simple setup for dataset I/O info struct */
H5D_BUILD_IO_INFO_WRT(&ioinfo, dset, &store, fb_info.fill_buf);
ioinfo.op_type = H5D_IO_OP_WRITE;
dset_info.dset = (H5D_t *)dset;
dset_info.store = &store;
dset_info.buf.cvp = fb_info.fill_buf;
dset_info.mem_space = NULL;
ioinfo.dsets_info = &dset_info;
ioinfo.f_sh = H5F_SHARED(dset->oloc.file);
/*
* Fill the entire current extent with the fill value. We can do
@@ -281,7 +293,7 @@ H5D__contig_fill(const H5D_io_info_t *io_info)
/* Write the chunks out from only one process */
/* !! Use the internal "independent" DXPL!! -QAK */
if (H5_PAR_META_WRITE == mpi_rank) {
if (H5D__contig_write_one(&ioinfo, offset, size) < 0) {
if (H5D__contig_write_one(&ioinfo, &dset_info, offset, size) < 0) {
/* If writing fails, push an error and stop writing, but
* still participate in following MPI_Barrier.
*/
@@ -297,7 +309,7 @@ H5D__contig_fill(const H5D_io_info_t *io_info)
else {
#endif /* H5_HAVE_PARALLEL */
H5_CHECK_OVERFLOW(size, size_t, hsize_t);
if (H5D__contig_write_one(&ioinfo, offset, size) < 0)
if (H5D__contig_write_one(&ioinfo, &dset_info, offset, size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset")
#ifdef H5_HAVE_PARALLEL
} /* end else */
@@ -562,32 +574,159 @@ H5D__contig_is_data_cached(const H5D_shared_t *shared_dset)
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Thursday, March 20, 2008
* Programmer: Jonathan Kim
*-------------------------------------------------------------------------
*/
static herr_t
H5D__contig_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
{
H5D_t *dataset = dinfo->dset; /* Local pointer to dataset info */
hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */
htri_t file_space_normalized = FALSE; /* File dataspace was normalized */
int sf_ndims; /* The number of dimensions of the file dataspace (signed) */
htri_t use_selection_io = FALSE; /* Whether to use selection I/O */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
dinfo->store->contig.dset_addr = dataset->shared->layout.storage.u.contig.addr;
dinfo->store->contig.dset_size = dataset->shared->layout.storage.u.contig.size;
/* Initialize piece info */
dinfo->layout_io_info.contig_piece_info = NULL;
/* Get layout for dataset */
dinfo->layout = &(dataset->shared->layout);
/* Get dim number and dimensionality for each dataspace */
if ((sf_ndims = H5S_GET_EXTENT_NDIMS(dinfo->file_space)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number")
/* Normalize hyperslab selections by adjusting them by the offset */
/* (It might be worthwhile to normalize both the file and memory dataspaces
* before any (contiguous, chunked, etc) file I/O operation, in order to
* speed up hyperslab calculations by removing the extra checks and/or
* additions involving the offset and the hyperslab selection -QAK)
*/
if ((file_space_normalized = H5S_hyper_normalize_offset(dinfo->file_space, old_offset)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
/* if selected elements exist */
if (dinfo->nelmts) {
int u;
H5D_piece_info_t *new_piece_info; /* piece information to insert into skip list */
/* Get copy of dset file_space, so it can be changed temporarily
* purpose
* This tmp_fspace allows multiple write before close dset */
H5S_t *tmp_fspace; /* Temporary file dataspace */
/* Create "temporary" chunk for selection operations (copy file space) */
if (NULL == (tmp_fspace = H5S_copy(dinfo->file_space, TRUE, FALSE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
/* Add temporary chunk to the list of pieces */
/* collect piece_info into Skip List */
/* Allocate the file & memory chunk information */
if (NULL == (new_piece_info = H5FL_MALLOC(H5D_piece_info_t))) {
(void)H5S_close(tmp_fspace);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
} /* end if */
/* Set the piece index */
new_piece_info->index = 0;
/* Set the file chunk dataspace */
new_piece_info->fspace = tmp_fspace;
new_piece_info->fspace_shared = FALSE;
/* Set the memory chunk dataspace */
/* same as one chunk, just use dset mem space */
new_piece_info->mspace = dinfo->mem_space;
/* set true for sharing mem space with dset, which means
* fspace gets free by application H5Sclose(), and
* doesn't require providing layout_ops.io_term() for H5D_LOPS_CONTIG.
*/
new_piece_info->mspace_shared = TRUE;
/* Set the number of points */
new_piece_info->piece_points = dinfo->nelmts;
/* Copy the piece's coordinates */
for (u = 0; u < sf_ndims; u++)
new_piece_info->scaled[u] = 0;
new_piece_info->scaled[sf_ndims] = 0;
/* make connection to related dset info from this piece_info */
new_piece_info->dset_info = dinfo;
/* get dset file address for piece */
new_piece_info->faddr = dinfo->dset->shared->layout.storage.u.contig.addr;
/* Save piece to dataset info struct so it is freed at the end of the
* operation */
dinfo->layout_io_info.contig_piece_info = new_piece_info;
/* Add piece to piece_count */
io_info->piece_count++;
} /* end if */
/* Check if we're performing selection I/O if it hasn't been disabled
* already */
if (io_info->use_select_io) {
if ((use_selection_io = H5D__contig_may_use_select_io(io_info, dinfo, H5D_IO_OP_READ)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible")
io_info->use_select_io = (hbool_t)use_selection_io;
}
done:
if (ret_value < 0) {
if (H5D__contig_io_term(io_info, dinfo) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataset I/O info")
} /* end if */
if (file_space_normalized) {
/* (Casting away const OK -QAK) */
if (H5S_hyper_denormalize_offset(dinfo->file_space, old_offset) < 0)
HDONE_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__contig_io_init() */
/*-------------------------------------------------------------------------
* Function: H5D__contig_mdio_init
*
* Purpose: Performs second phase of initialization for multi-dataset
* I/O. Currently just adds data block to sel_pieces.
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__contig_io_init(H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info,
hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space,
H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm)
H5D__contig_mdio_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
{
htri_t use_selection_io = FALSE; /* Whether to use selection I/O */
htri_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE_NOERR
FUNC_ENTER_PACKAGE
/* Add piece if it exists */
if (dinfo->layout_io_info.contig_piece_info) {
HDassert(io_info->sel_pieces);
HDassert(io_info->pieces_added < io_info->piece_count);
io_info->store->contig.dset_addr = io_info->dset->shared->layout.storage.u.contig.addr;
io_info->store->contig.dset_size = io_info->dset->shared->layout.storage.u.contig.size;
/* Add contiguous data block to sel_pieces */
io_info->sel_pieces[io_info->pieces_added] = dinfo->layout_io_info.contig_piece_info;
/* Check if we're performing selection I/O */
if ((use_selection_io = H5D__contig_may_use_select_io(io_info, H5D_IO_OP_READ)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if selection I/O is possible")
io_info->use_select_io = (hbool_t)use_selection_io;
/* Update pieces_added */
io_info->pieces_added++;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__contig_io_init() */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__contig_mdio_init() */
/*-------------------------------------------------------------------------
* Function: H5D__contig_may_use_select_io
@@ -603,7 +742,8 @@ done:
*-------------------------------------------------------------------------
*/
static htri_t
H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, H5D_io_op_type_t op_type)
H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
H5D_io_op_type_t op_type)
{
const H5D_t *dataset = NULL; /* Local pointer to dataset info */
htri_t ret_value = FAIL; /* Return value */
@@ -612,24 +752,25 @@ H5D__contig_may_use_select_io(const H5D_io_info_t *io_info, H5D_io_op_type_t op_
/* Sanity check */
HDassert(io_info);
HDassert(io_info->dset);
HDassert(dset_info);
HDassert(dset_info->dset);
HDassert(op_type == H5D_IO_OP_READ || op_type == H5D_IO_OP_WRITE);
dataset = io_info->dset;
dataset = dset_info->dset;
/* Don't use selection I/O if it's globally disabled, if there is a type
* conversion, or if it's not a contiguous dataset, or if the sieve buffer
* exists (write) or is dirty (read) */
if (!H5_use_selection_io_g || io_info->io_ops.single_read != H5D__select_read ||
io_info->layout_ops.readvv != H5D__contig_readvv ||
if (dset_info->io_ops.single_read != H5D__select_read ||
dset_info->layout_ops.readvv != H5D__contig_readvv ||
(op_type == H5D_IO_OP_READ && dataset->shared->cache.contig.sieve_dirty) ||
(op_type == H5D_IO_OP_WRITE && dataset->shared->cache.contig.sieve_buf))
ret_value = FALSE;
else {
hbool_t page_buf_enabled;
HDassert(io_info->io_ops.single_write == H5D__select_write);
HDassert(io_info->layout_ops.writevv == H5D__contig_writevv);
HDassert(dset_info->io_ops.single_write == H5D__select_write);
HDassert(dset_info->layout_ops.writevv == H5D__contig_writevv);
/* Check if the page buffer is enabled */
if (H5PB_enabled(io_info->f_sh, H5FD_MEM_DRAW, &page_buf_enabled) < 0)
@@ -657,8 +798,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, H5S_t *file_space,
H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm)
H5D__contig_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -666,25 +806,49 @@ H5D__contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize
/* Sanity check */
HDassert(io_info);
HDassert(io_info->u.rbuf);
HDassert(type_info);
HDassert(mem_space);
HDassert(file_space);
HDassert(dinfo);
HDassert(dinfo->buf.vp);
HDassert(dinfo->mem_space);
HDassert(dinfo->file_space);
if (io_info->use_select_io) {
size_t dst_type_size = type_info->dst_type_size;
/* Only perform I/O if not performing multi dataset I/O with selection
* I/O, otherwise the higher level will handle it after all datasets
* have been processed */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
size_t dst_type_size = dinfo->type_info.dst_type_size;
/* Issue selection I/O call (we can skip the page buffer because we've
* already verified it won't be used, and the metadata accumulator
* because this is raw data) */
if (H5F_shared_select_read(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, nelmts > 0 ? 1 : 0,
&mem_space, &file_space, &(io_info->store->contig.dset_addr),
&dst_type_size, &(io_info->u.rbuf)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "contiguous selection read failed")
/* Issue selection I/O call (we can skip the page buffer because we've
* already verified it won't be used, and the metadata accumulator
* because this is raw data) */
if (H5F_shared_select_read(H5F_SHARED(dinfo->dset->oloc.file), H5FD_MEM_DRAW,
dinfo->nelmts > 0 ? 1 : 0, &dinfo->mem_space, &dinfo->file_space,
&(dinfo->store->contig.dset_addr), &dst_type_size,
&(dinfo->buf.vp)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "contiguous selection read failed")
}
else {
if (dinfo->layout_io_info.contig_piece_info) {
/* Add to mdset selection I/O arrays */
HDassert(io_info->mem_spaces);
HDassert(io_info->file_spaces);
HDassert(io_info->addrs);
HDassert(io_info->element_sizes);
HDassert(io_info->rbufs);
HDassert(io_info->pieces_added < io_info->piece_count);
io_info->mem_spaces[io_info->pieces_added] = dinfo->mem_space;
io_info->file_spaces[io_info->pieces_added] = dinfo->file_space;
io_info->addrs[io_info->pieces_added] = dinfo->store->contig.dset_addr;
io_info->element_sizes[io_info->pieces_added] = dinfo->type_info.src_type_size;
io_info->rbufs[io_info->pieces_added] = dinfo->buf.vp;
io_info->pieces_added++;
}
}
} /* end if */
else
/* Read data through legacy (non-selection I/O) pathway */
if ((io_info->io_ops.single_read)(io_info, type_info, nelmts, file_space, mem_space) < 0)
if ((dinfo->io_ops.single_read)(io_info, dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "contiguous read failed")
done:
@@ -704,8 +868,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, H5S_t *file_space,
H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm)
H5D__contig_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -713,25 +876,49 @@ H5D__contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsiz
/* Sanity check */
HDassert(io_info);
HDassert(io_info->u.wbuf);
HDassert(type_info);
HDassert(mem_space);
HDassert(file_space);
HDassert(dinfo);
HDassert(dinfo->buf.cvp);
HDassert(dinfo->mem_space);
HDassert(dinfo->file_space);
if (io_info->use_select_io) {
size_t dst_type_size = type_info->dst_type_size;
/* Only perform I/O if not performing multi dataset I/O with selection
* I/O, otherwise the higher level will handle it after all datasets
* have been processed */
if (H5D_LAYOUT_CB_PERFORM_IO(io_info)) {
size_t dst_type_size = dinfo->type_info.dst_type_size;
/* Issue selection I/O call (we can skip the page buffer because we've
* already verified it won't be used, and the metadata accumulator
* because this is raw data) */
if (H5F_shared_select_write(H5F_SHARED(io_info->dset->oloc.file), H5FD_MEM_DRAW, nelmts > 0 ? 1 : 0,
&mem_space, &file_space, &(io_info->store->contig.dset_addr),
&dst_type_size, &(io_info->u.wbuf)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "contiguous selection write failed")
/* Issue selection I/O call (we can skip the page buffer because we've
* already verified it won't be used, and the metadata accumulator
* because this is raw data) */
if (H5F_shared_select_write(H5F_SHARED(dinfo->dset->oloc.file), H5FD_MEM_DRAW,
dinfo->nelmts > 0 ? 1 : 0, &dinfo->mem_space, &dinfo->file_space,
&(dinfo->store->contig.dset_addr), &dst_type_size,
&(dinfo->buf.cvp)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "contiguous selection write failed")
}
else {
if (dinfo->layout_io_info.contig_piece_info) {
/* Add to mdset selection I/O arrays */
HDassert(io_info->mem_spaces);
HDassert(io_info->file_spaces);
HDassert(io_info->addrs);
HDassert(io_info->element_sizes);
HDassert(io_info->wbufs);
HDassert(io_info->pieces_added < io_info->piece_count);
io_info->mem_spaces[io_info->pieces_added] = dinfo->mem_space;
io_info->file_spaces[io_info->pieces_added] = dinfo->file_space;
io_info->addrs[io_info->pieces_added] = dinfo->store->contig.dset_addr;
io_info->element_sizes[io_info->pieces_added] = dinfo->type_info.dst_type_size;
io_info->wbufs[io_info->pieces_added] = dinfo->buf.cvp;
io_info->pieces_added++;
}
}
} /* end if */
else
/* Write data through legacy (non-selection I/O) pathway */
if ((io_info->io_ops.single_write)(io_info, type_info, nelmts, file_space, mem_space) < 0)
if ((dinfo->io_ops.single_write)(io_info, dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "contiguous write failed")
done:
@@ -753,7 +940,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size_t size)
H5D__contig_write_one(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, hsize_t offset, size_t size)
{
hsize_t dset_off = offset; /* Offset in dataset */
size_t dset_len = size; /* Length in dataset */
@@ -767,7 +954,7 @@ H5D__contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size_t size)
HDassert(io_info);
if (H5D__contig_writevv(io_info, (size_t)1, &dset_curr_seq, &dset_len, &dset_off, (size_t)1,
if (H5D__contig_writevv(io_info, dset_info, (size_t)1, &dset_curr_seq, &dset_len, &dset_off, (size_t)1,
&mem_curr_seq, &mem_len, &mem_off) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed")
@@ -990,9 +1177,9 @@ done:
*-------------------------------------------------------------------------
*/
static ssize_t
H5D__contig_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_off_arr[])
H5D__contig_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, size_t dset_max_nseq,
size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
{
ssize_t ret_value = -1; /* Return value */
@@ -1000,6 +1187,7 @@ H5D__contig_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *d
/* Check args */
HDassert(io_info);
HDassert(dset_info);
HDassert(dset_curr_seq);
HDassert(dset_len_arr);
HDassert(dset_off_arr);
@@ -1013,9 +1201,9 @@ H5D__contig_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *d
/* Set up user data for H5VM_opvv() */
udata.f_sh = io_info->f_sh;
udata.dset_contig = &(io_info->dset->shared->cache.contig);
udata.store_contig = &(io_info->store->contig);
udata.rbuf = (unsigned char *)io_info->u.rbuf;
udata.dset_contig = &(dset_info->dset->shared->cache.contig);
udata.store_contig = &(dset_info->store->contig);
udata.rbuf = (unsigned char *)dset_info->buf.vp;
/* Call generic sequence operation routine */
if ((ret_value =
@@ -1028,8 +1216,8 @@ H5D__contig_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *d
/* Set up user data for H5VM_opvv() */
udata.f_sh = io_info->f_sh;
udata.dset_addr = io_info->store->contig.dset_addr;
udata.rbuf = (unsigned char *)io_info->u.rbuf;
udata.dset_addr = dset_info->store->contig.dset_addr;
udata.rbuf = (unsigned char *)dset_info->buf.vp;
/* Call generic sequence operation routine */
if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
@@ -1308,9 +1496,9 @@ done:
*-------------------------------------------------------------------------
*/
static ssize_t
H5D__contig_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_off_arr[])
H5D__contig_writevv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, size_t dset_max_nseq,
size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
{
ssize_t ret_value = -1; /* Return value (Size of sequence in bytes) */
@@ -1318,6 +1506,7 @@ H5D__contig_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *
/* Check args */
HDassert(io_info);
HDassert(dset_info);
HDassert(dset_curr_seq);
HDassert(dset_len_arr);
HDassert(dset_off_arr);
@@ -1331,9 +1520,9 @@ H5D__contig_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *
/* Set up user data for H5VM_opvv() */
udata.f_sh = io_info->f_sh;
udata.dset_contig = &(io_info->dset->shared->cache.contig);
udata.store_contig = &(io_info->store->contig);
udata.wbuf = (const unsigned char *)io_info->u.wbuf;
udata.dset_contig = &(dset_info->dset->shared->cache.contig);
udata.store_contig = &(dset_info->store->contig);
udata.wbuf = (const unsigned char *)dset_info->buf.cvp;
/* Call generic sequence operation routine */
if ((ret_value =
@@ -1346,8 +1535,8 @@ H5D__contig_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *
/* Set up user data for H5VM_opvv() */
udata.f_sh = io_info->f_sh;
udata.dset_addr = io_info->store->contig.dset_addr;
udata.wbuf = (const unsigned char *)io_info->u.wbuf;
udata.dset_addr = dset_info->store->contig.dset_addr;
udata.wbuf = (const unsigned char *)dset_info->buf.cvp;
/* Call generic sequence operation routine */
if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
@@ -1390,6 +1579,35 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__contig_flush() */
/*-------------------------------------------------------------------------
* Function: H5D__contig_io_term
*
* Purpose: Destroy I/O operation information.
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__contig_io_term(H5D_io_info_t H5_ATTR_UNUSED *io_info, H5D_dset_io_info_t *di)
{
herr_t ret_value = SUCCEED; /*return value */
FUNC_ENTER_PACKAGE
HDassert(di);
/* Free piece info */
if (di->layout_io_info.contig_piece_info) {
if (H5D__free_piece_info(di->layout_io_info.contig_piece_info, NULL, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't free piece info")
di->layout_io_info.contig_piece_info = NULL;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__contig_io_term() */
/*-------------------------------------------------------------------------
* Function: H5D__contig_copy
*
+42 -41
View File
@@ -61,14 +61,15 @@ typedef struct H5D_efl_writevv_ud_t {
/* Layout operation callbacks */
static herr_t H5D__efl_construct(H5F_t *f, H5D_t *dset);
static herr_t H5D__efl_io_init(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *cm);
static ssize_t H5D__efl_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_len_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
static ssize_t H5D__efl_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_len_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
static herr_t H5D__efl_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static ssize_t H5D__efl_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[],
hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_offset_arr[]);
static ssize_t H5D__efl_writevv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[],
hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_offset_arr[]);
/* Helper routines */
static herr_t H5D__efl_read(const H5O_efl_t *efl, const H5D_t *dset, haddr_t addr, size_t size, uint8_t *buf);
@@ -86,17 +87,14 @@ const H5D_layout_ops_t H5D_LOPS_EFL[1] = {{
H5D__efl_is_space_alloc, /* is_space_alloc */
NULL, /* is_data_cached */
H5D__efl_io_init, /* io_init */
NULL, /* mdio_init */
H5D__contig_read, /* ser_read */
H5D__contig_write, /* ser_write */
#ifdef H5_HAVE_PARALLEL
NULL, /* par_read */
NULL, /* par_write */
#endif
H5D__efl_readvv, /* readvv */
H5D__efl_writevv, /* writevv */
NULL, /* flush */
NULL, /* io_term */
NULL /* dest */
H5D__efl_readvv, /* readvv */
H5D__efl_writevv, /* writevv */
NULL, /* flush */
NULL, /* io_term */
NULL /* dest */
}};
/*******************/
@@ -209,13 +207,14 @@ H5D__efl_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED *storage)
*-------------------------------------------------------------------------
*/
static herr_t
H5D__efl_io_init(H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info,
hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space,
H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm)
H5D__efl_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
{
FUNC_ENTER_PACKAGE_NOERR
H5MM_memcpy(&io_info->store->efl, &(io_info->dset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
H5MM_memcpy(&dinfo->store->efl, &(dinfo->dset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
/* Disable selection I/O */
io_info->use_select_io = FALSE;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__efl_io_init() */
@@ -443,9 +442,9 @@ done:
*-------------------------------------------------------------------------
*/
static ssize_t
H5D__efl_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_off_arr[])
H5D__efl_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, size_t dset_max_nseq,
size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
{
H5D_efl_readvv_ud_t udata; /* User data for H5VM_opvv() operator */
ssize_t ret_value = -1; /* Return value (Total size of sequence in bytes) */
@@ -454,10 +453,11 @@ H5D__efl_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset
/* Check args */
HDassert(io_info);
HDassert(io_info->store->efl.nused > 0);
HDassert(io_info->u.rbuf);
HDassert(io_info->dset);
HDassert(io_info->dset->shared);
HDassert(dset_info);
HDassert(dset_info->store->efl.nused > 0);
HDassert(dset_info->buf.vp);
HDassert(dset_info->dset);
HDassert(dset_info->dset->shared);
HDassert(dset_curr_seq);
HDassert(dset_len_arr);
HDassert(dset_off_arr);
@@ -466,9 +466,9 @@ H5D__efl_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset
HDassert(mem_off_arr);
/* Set up user data for H5VM_opvv() */
udata.efl = &(io_info->store->efl);
udata.dset = io_info->dset;
udata.rbuf = (unsigned char *)io_info->u.rbuf;
udata.efl = &(dset_info->store->efl);
udata.dset = dset_info->dset;
udata.rbuf = (unsigned char *)dset_info->buf.vp;
/* Call generic sequence operation routine */
if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
@@ -523,9 +523,9 @@ done:
*-------------------------------------------------------------------------
*/
static ssize_t
H5D__efl_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
size_t mem_len_arr[], hsize_t mem_off_arr[])
H5D__efl_writevv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, size_t dset_max_nseq,
size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
{
H5D_efl_writevv_ud_t udata; /* User data for H5VM_opvv() operator */
ssize_t ret_value = -1; /* Return value (Total size of sequence in bytes) */
@@ -534,10 +534,11 @@ H5D__efl_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dse
/* Check args */
HDassert(io_info);
HDassert(io_info->store->efl.nused > 0);
HDassert(io_info->u.wbuf);
HDassert(io_info->dset);
HDassert(io_info->dset->shared);
HDassert(dset_info);
HDassert(dset_info->store->efl.nused > 0);
HDassert(dset_info->buf.cvp);
HDassert(dset_info->dset);
HDassert(dset_info->dset->shared);
HDassert(dset_curr_seq);
HDassert(dset_len_arr);
HDassert(dset_off_arr);
@@ -546,9 +547,9 @@ H5D__efl_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dse
HDassert(mem_off_arr);
/* Set up user data for H5VM_opvv() */
udata.efl = &(io_info->store->efl);
udata.dset = io_info->dset;
udata.wbuf = (const unsigned char *)io_info->u.wbuf;
udata.efl = &(dset_info->store->efl);
udata.dset = dset_info->dset;
udata.wbuf = (const unsigned char *)dset_info->buf.cvp;
/* Call generic sequence operation routine */
if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
+42 -45
View File
@@ -61,7 +61,7 @@ typedef struct {
/* Internal data structure for computing variable-length dataset's total size */
/* (Used for generic 'get vlen buf size' operation) */
typedef struct {
H5VL_object_t *dset_vol_obj; /* VOL object for the dataset */
const H5VL_object_t *dset_vol_obj; /* VOL object for the dataset */
hid_t fspace_id; /* Dataset dataspace ID of the dataset we are working on */
H5S_t *fspace; /* Dataset's dataspace for operation */
hid_t mspace_id; /* Memory dataspace ID of the dataset we are working on */
@@ -81,7 +81,7 @@ static herr_t H5D__init_space(H5F_t *file, const H5D_t *dset, const H5S_t
static herr_t H5D__update_oh_info(H5F_t *file, H5D_t *dset, hid_t dapl_id);
static herr_t H5D__build_file_prefix(const H5D_t *dset, H5F_prefix_open_t prefix_type, char **file_prefix);
static herr_t H5D__open_oid(H5D_t *dataset, hid_t dapl_id);
static herr_t H5D__init_storage(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_t old_dim[]);
static herr_t H5D__init_storage(H5D_t *dset, hbool_t full_overwrite, hsize_t old_dim[]);
static herr_t H5D__append_flush_setup(H5D_t *dset, hid_t dapl_id);
static herr_t H5D__close_cb(H5VL_object_t *dset_vol_obj, void **request);
static herr_t H5D__use_minimized_dset_headers(H5F_t *file, hbool_t *minimize);
@@ -119,8 +119,8 @@ H5FL_DEFINE_STATIC(H5D_shared_t);
/* Declare the external PQ free list for the sieve buffer information */
H5FL_BLK_EXTERN(sieve_buf);
/* Declare the external free list to manage the H5D_chunk_info_t struct */
H5FL_EXTERN(H5D_chunk_info_t);
/* Declare the external free list to manage the H5D_piece_info_t struct */
H5FL_EXTERN(H5D_piece_info_t);
/* Declare extern the free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(type_conv);
@@ -1793,14 +1793,9 @@ H5D__open_oid(H5D_t *dataset, hid_t dapl_id)
*/
if ((H5F_INTENT(dataset->oloc.file) & H5F_ACC_RDWR) &&
!(*dataset->shared->layout.ops->is_space_alloc)(&dataset->shared->layout.storage) &&
H5F_HAS_FEATURE(dataset->oloc.file, H5FD_FEAT_ALLOCATE_EARLY)) {
H5D_io_info_t io_info;
io_info.dset = dataset;
if (H5D__alloc_storage(&io_info, H5D_ALLOC_OPEN, FALSE, NULL) < 0)
H5F_HAS_FEATURE(dataset->oloc.file, H5FD_FEAT_ALLOCATE_EARLY))
if (H5D__alloc_storage(dataset, H5D_ALLOC_OPEN, FALSE, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file storage")
} /* end if */
done:
if (ret_value < 0) {
@@ -1894,10 +1889,10 @@ H5D_close(H5D_t *dataset)
} /* end if */
/* Check for cached single element chunk info */
if (dataset->shared->cache.chunk.single_chunk_info) {
dataset->shared->cache.chunk.single_chunk_info =
H5FL_FREE(H5D_chunk_info_t, dataset->shared->cache.chunk.single_chunk_info);
dataset->shared->cache.chunk.single_chunk_info = NULL;
if (dataset->shared->cache.chunk.single_piece_info) {
dataset->shared->cache.chunk.single_piece_info =
H5FL_FREE(H5D_piece_info_t, dataset->shared->cache.chunk.single_piece_info);
dataset->shared->cache.chunk.single_piece_info = NULL;
} /* end if */
break;
@@ -2088,10 +2083,10 @@ H5D_mult_refresh_close(hid_t dset_id)
} /* end if */
/* Check for cached single element chunk info */
if (dataset->shared->cache.chunk.single_chunk_info) {
dataset->shared->cache.chunk.single_chunk_info =
H5FL_FREE(H5D_chunk_info_t, dataset->shared->cache.chunk.single_chunk_info);
dataset->shared->cache.chunk.single_chunk_info = NULL;
if (dataset->shared->cache.chunk.single_piece_info) {
dataset->shared->cache.chunk.single_piece_info =
H5FL_FREE(H5D_piece_info_t, dataset->shared->cache.chunk.single_piece_info);
dataset->shared->cache.chunk.single_piece_info = NULL;
} /* end if */
break;
@@ -2209,11 +2204,9 @@ H5D_nameof(H5D_t *dataset)
*-------------------------------------------------------------------------
*/
herr_t
H5D__alloc_storage(const H5D_io_info_t *io_info, H5D_time_alloc_t time_alloc, hbool_t full_overwrite,
hsize_t old_dim[])
H5D__alloc_storage(H5D_t *dset, H5D_time_alloc_t time_alloc, hbool_t full_overwrite, hsize_t old_dim[])
{
const H5D_t *dset = io_info->dset; /* The dataset object */
H5F_t *f = dset->oloc.file; /* The dataset's file pointer */
H5F_t *f; /* The dataset's file pointer */
H5O_layout_t *layout; /* The dataset's layout information */
hbool_t must_init_space = FALSE; /* Flag to indicate that space should be initialized */
hbool_t addr_set = FALSE; /* Flag to indicate that the dataset's storage address was set */
@@ -2223,6 +2216,7 @@ H5D__alloc_storage(const H5D_io_info_t *io_info, H5D_time_alloc_t time_alloc, hb
/* check args */
HDassert(dset);
f = dset->oloc.file;
HDassert(f);
/* If the data is stored in external files, don't set an address for the layout
@@ -2333,7 +2327,7 @@ H5D__alloc_storage(const H5D_io_info_t *io_info, H5D_time_alloc_t time_alloc, hb
*/
if (!(dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_INCR &&
time_alloc == H5D_ALLOC_WRITE))
if (H5D__init_storage(io_info, full_overwrite, old_dim) < 0)
if (H5D__init_storage(dset, full_overwrite, old_dim) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"unable to initialize dataset with fill value")
} /* end if */
@@ -2349,7 +2343,7 @@ H5D__alloc_storage(const H5D_io_info_t *io_info, H5D_time_alloc_t time_alloc, hb
if (dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC ||
(dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET &&
fill_status == H5D_FILL_VALUE_USER_DEFINED))
if (H5D__init_storage(io_info, full_overwrite, old_dim) < 0)
if (H5D__init_storage(dset, full_overwrite, old_dim) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"unable to initialize dataset with fill value")
} /* end else */
@@ -2383,10 +2377,9 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__init_storage(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_t old_dim[])
H5D__init_storage(H5D_t *dset, hbool_t full_overwrite, hsize_t old_dim[])
{
const H5D_t *dset = io_info->dset; /* dataset pointer */
herr_t ret_value = SUCCEED; /* Return value */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2408,7 +2401,7 @@ H5D__init_storage(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_t
/* If we will be immediately overwriting the values, don't bother to clear them */
if ((dset->shared->dcpl_cache.efl.nused == 0 || dset->shared->dcpl_cache.fill.buf) &&
!full_overwrite)
if (H5D__contig_fill(io_info) < 0)
if (H5D__contig_fill(dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset")
break;
@@ -2424,7 +2417,7 @@ H5D__init_storage(const H5D_io_info_t *io_info, hbool_t full_overwrite, hsize_t
if (old_dim == NULL)
old_dim = zero_dim;
if (H5D__chunk_allocate(io_info, full_overwrite, old_dim) < 0)
if (H5D__chunk_allocate(dset, full_overwrite, old_dim) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset")
break;
} /* end block */
@@ -2599,7 +2592,8 @@ H5D__vlen_get_buf_size_cb(void H5_ATTR_UNUSED *elem, hid_t type_id, unsigned H5_
const hsize_t *point, void *op_data)
{
H5D_vlen_bufsize_native_t *vlen_bufsize = (H5D_vlen_bufsize_native_t *)op_data;
herr_t ret_value = H5_ITER_CONT; /* Return value */
H5D_dset_io_info_t dset_info; /* Internal multi-dataset info placeholder */
herr_t ret_value = H5_ITER_CONT; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2612,10 +2606,17 @@ H5D__vlen_get_buf_size_cb(void H5_ATTR_UNUSED *elem, hid_t type_id, unsigned H5_
if (H5S_select_elements(vlen_bufsize->fspace, H5S_SELECT_SET, (size_t)1, point) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, H5_ITER_ERROR, "can't select point")
/* Read in the point (with the custom VL memory allocator) */
if (H5D__read(vlen_bufsize->dset, type_id, vlen_bufsize->mspace, vlen_bufsize->fspace,
vlen_bufsize->common.fl_tbuf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, H5_ITER_ERROR, "can't read point")
{
dset_info.dset = vlen_bufsize->dset;
dset_info.mem_space = vlen_bufsize->mspace;
dset_info.file_space = vlen_bufsize->fspace;
dset_info.buf.vp = vlen_bufsize->common.fl_tbuf;
dset_info.mem_type_id = type_id;
/* Read in the point (with the custom VL memory allocator) */
if (H5D__read(1, &dset_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2767,8 +2768,8 @@ H5D__vlen_get_buf_size_gen_cb(void H5_ATTR_UNUSED *elem, hid_t type_id, unsigned
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't select point")
/* Read in the point (with the custom VL memory allocator) */
if (H5VL_dataset_read(vlen_bufsize->dset_vol_obj, type_id, vlen_bufsize->mspace_id,
vlen_bufsize->fspace_id, vlen_bufsize->dxpl_id, vlen_bufsize->common.fl_tbuf,
if (H5VL_dataset_read(1, &vlen_bufsize->dset_vol_obj, &type_id, &vlen_bufsize->mspace_id,
&vlen_bufsize->fspace_id, vlen_bufsize->dxpl_id, &vlen_bufsize->common.fl_tbuf,
H5_REQUEST_NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read point")
@@ -2814,7 +2815,7 @@ H5D__vlen_get_buf_size_gen(H5VL_object_t *vol_obj, hid_t type_id, hid_t space_id
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "dataspace does not have extent set")
/* Save the dataset */
vlen_bufsize.dset_vol_obj = vol_obj;
vlen_bufsize.dset_vol_obj = (const H5VL_object_t *)vol_obj;
/* Set up VOL callback arguments */
vol_cb_args.op_type = H5VL_DATASET_GET_SPACE;
@@ -3095,14 +3096,10 @@ H5D__set_extent(H5D_t *dset, const hsize_t *size)
} /* end if */
/* Allocate space for the new parts of the dataset, if appropriate */
if (expand && dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY) {
H5D_io_info_t io_info;
io_info.dset = dset;
if (H5D__alloc_storage(&io_info, H5D_ALLOC_EXTEND, FALSE, curr_dims) < 0)
if (expand && dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY)
if (H5D__alloc_storage(dset, H5D_ALLOC_EXTEND, FALSE, curr_dims) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to extend dataset storage")
}
/*-------------------------------------------------------------------------
* Remove chunk information in the case of chunked datasets
* This removal takes place only in case we are shrinking the dataset
+869 -494
View File
@@ -44,15 +44,14 @@
/********************/
/* Setup/teardown routines */
static herr_t H5D__ioinfo_init(H5D_t *dset, const H5D_type_info_t *type_info, H5D_storage_t *store,
H5D_io_info_t *io_info);
static herr_t H5D__typeinfo_init(const H5D_t *dset, hid_t mem_type_id, hbool_t do_write,
H5D_type_info_t *type_info);
static herr_t H5D__ioinfo_init(size_t count, H5D_dset_io_info_t *dset_info, H5D_io_info_t *io_info);
static herr_t H5D__dset_ioinfo_init(H5D_t *dset, H5D_dset_io_info_t *dset_info, H5D_storage_t *store);
static herr_t H5D__typeinfo_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, hid_t mem_type_id);
static herr_t H5D__typeinfo_init_phase2(H5D_io_info_t *io_info);
#ifdef H5_HAVE_PARALLEL
static herr_t H5D__ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, const H5S_t *file_space,
const H5S_t *mem_space, const H5D_type_info_t *type_info);
static herr_t H5D__ioinfo_adjust(H5D_io_info_t *io_info);
#endif /* H5_HAVE_PARALLEL */
static herr_t H5D__typeinfo_term(const H5D_type_info_t *type_info);
static herr_t H5D__typeinfo_term(H5D_io_info_t *io_info, size_t type_info_init);
/*********************/
/* Package Variables */
@@ -65,66 +64,63 @@ static herr_t H5D__typeinfo_term(const H5D_type_info_t *type_info);
/* Declare a free list to manage blocks of type conversion data */
H5FL_BLK_DEFINE(type_conv);
/* Declare a free list to manage the H5D_chunk_map_t struct */
H5FL_DEFINE(H5D_chunk_map_t);
/*-------------------------------------------------------------------------
* Function: H5D__read
*
* Purpose: Reads (part of) a DATASET into application memory BUF. See
* H5Dread() for complete details.
* Purpose: Reads multiple (parts of) DATASETs into application memory BUFs.
* See H5Dread_multi() for complete details.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Thursday, December 4, 1997
*
*-------------------------------------------------------------------------
*/
herr_t
H5D__read(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_space, void *buf /*out*/)
H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
{
H5D_chunk_map_t *fm = NULL; /* Chunk file<->memory mapping */
H5D_io_info_t io_info; /* Dataset I/O info */
H5D_type_info_t type_info; /* Datatype info for operation */
H5D_layout_t layout_type; /* Dataset's layout type (contig, chunked, compact, etc.) */
hbool_t type_info_init = FALSE; /* Whether the datatype info has been initialized */
H5S_t *projected_mem_space = NULL; /* If not NULL, ptr to dataspace containing a */
/* projection of the supplied mem_space to a new */
/* dataspace with rank equal to that of */
/* file_space. */
/* */
/* This field is only used if */
/* H5S_select_shape_same() returns TRUE when */
/* comparing the mem_space and the data_space, */
/* and the mem_space have different rank. */
/* */
/* Note that if this variable is used, the */
/* projected mem space must be discarded at the */
/* end of the function to avoid a memory leak. */
H5D_storage_t store; /* union of EFL and chunk pointer in file space */
hsize_t nelmts; /* total number of elmts */
hbool_t io_op_init = FALSE; /* Whether the I/O op has been initialized */
char fake_char; /* Temporary variable for NULL buffer pointers */
herr_t ret_value = SUCCEED; /* Return value */
H5D_io_info_t io_info; /* Dataset I/O info for multi dsets */
size_t type_info_init = 0; /* Number of datatype info structs that have been initialized */
H5S_t *orig_mem_space_local; /* Local buffer for orig_mem_space */
H5S_t **orig_mem_space = NULL; /* If not NULL, ptr to an array of dataspaces */
/* containing the original memory spaces contained */
/* in dset_info. This is needed in order to */
/* restore the original state of dset_info if we */
/* replaced any mem spaces with equivalents */
/* projected to a rank equal to that of file_space. */
/* */
/* This field is only used if */
/* H5S_select_shape_same() returns TRUE when */
/* comparing at least one mem_space and data_space, */
/* and the mem_space has a different rank. */
/* */
/* Note that this is a temporary variable - the */
/* projected memory space is stored in dset_info, */
/* and will be freed when that structure is */
/* freed. */
H5D_storage_t store_local; /* Local buffer for store */
H5D_storage_t *store = &store_local; /* Union of EFL and chunk pointer in file space */
size_t io_op_init = 0; /* Number I/O ops that have been initialized */
size_t io_skipped =
0; /* Number I/O ops that have been skipped (due to the dataset not being allocated) */
size_t i; /* Local index variable */
char fake_char; /* Temporary variable for NULL buffer pointers */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE_TAG(dataset->oloc.addr)
FUNC_ENTER_NOAPI(FAIL)
/* check args */
HDassert(dataset && dataset->oloc.file);
HDassert(file_space);
HDassert(mem_space);
/* Init io_info */
if (H5D__ioinfo_init(count, dset_info, &io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info")
io_info.op_type = H5D_IO_OP_READ;
layout_type = dataset->shared->layout.type;
/* Set up datatype info for operation */
if (H5D__typeinfo_init(dataset, mem_type_id, FALSE, &type_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
type_info_init = TRUE;
/* Allocate store buffer if necessary */
if (count > 1)
if (NULL == (store = (H5D_storage_t *)H5MM_malloc(count * sizeof(H5D_storage_t))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate dset storage info array buffer")
#ifdef H5_HAVE_PARALLEL
/* Check for non-MPI-based VFD */
if (!(H5F_HAS_FEATURE(dataset->oloc.file, H5FD_FEAT_HAS_MPI))) {
/* Check for non-MPI-based VFD. Only need to check first dataset since all
* share the same file. */
if (!(H5F_HAS_FEATURE(dset_info[0].dset->oloc.file, H5FD_FEAT_HAS_MPI))) {
H5FD_mpio_xfer_t io_xfer_mode; /* MPI I/O transfer mode */
/* Get I/O transfer mode */
@@ -137,363 +133,626 @@ H5D__read(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_space
} /* end if */
#endif /*H5_HAVE_PARALLEL*/
/* Make certain that the number of elements in each selection is the same */
nelmts = H5S_GET_SELECT_NPOINTS(mem_space);
if (nelmts != H5S_GET_SELECT_NPOINTS(file_space))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
"src and dest dataspaces have different number of elements selected")
/* iterate over all dsets and construct I/O information necessary to do I/O */
for (i = 0; i < count; i++) {
haddr_t prev_tag = HADDR_UNDEF;
/* Check for a NULL buffer */
if (NULL == buf) {
/* Check for any elements selected (which is invalid) */
if (nelmts > 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer")
/* check args */
if (NULL == dset_info[i].dset)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if (NULL == dset_info[i].dset->oloc.file)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* If the buffer is nil, and 0 element is selected, make a fake buffer.
* This is for some MPI package like ChaMPIon on NCSA's tungsten which
* doesn't support this feature.
/* set metadata tagging with dset oheader addr */
H5AC_tag(dset_info[i].dset->oloc.addr, &prev_tag);
/* Set up datatype info for operation */
if (H5D__typeinfo_init(&io_info, &(dset_info[i]), dset_info[i].mem_type_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
type_info_init++;
/* Make certain that the number of elements in each selection is the same, and cache nelmts in
* dset_info */
dset_info[i].nelmts = H5S_GET_SELECT_NPOINTS(dset_info[i].mem_space);
if (dset_info[i].nelmts != H5S_GET_SELECT_NPOINTS(dset_info[i].file_space))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
"src and dest dataspaces have different number of elements selected")
/* Check for a NULL buffer */
if (NULL == dset_info[i].buf.vp) {
/* Check for any elements selected (which is invalid) */
if (dset_info[i].nelmts > 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer")
/* If the buffer is nil, and 0 element is selected, make a fake buffer.
* This is for some MPI package like ChaMPIon on NCSA's tungsten which
* doesn't support this feature.
*/
dset_info[i].buf.vp = &fake_char;
} /* end if */
/* Make sure that both selections have their extents set */
if (!(H5S_has_extent(dset_info[i].file_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set")
if (!(H5S_has_extent(dset_info[i].mem_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set")
/* H5S_select_shape_same() has been modified to accept topologically identical
* selections with different rank as having the same shape (if the most
* rapidly changing coordinates match up), but the I/O code still has
* difficulties with the notion.
*
* To solve this, we check to see if H5S_select_shape_same() returns true,
* and if the ranks of the mem and file spaces are different. If they are,
* construct a new mem space that is equivalent to the old mem space, and
* use that instead.
*
* Note that in general, this requires us to touch up the memory buffer as
* well.
*/
buf = &fake_char;
} /* end if */
if (dset_info[i].nelmts > 0 &&
TRUE == H5S_SELECT_SHAPE_SAME(dset_info[i].mem_space, dset_info[i].file_space) &&
H5S_GET_EXTENT_NDIMS(dset_info[i].mem_space) != H5S_GET_EXTENT_NDIMS(dset_info[i].file_space)) {
ptrdiff_t buf_adj = 0;
/* Make sure that both selections have their extents set */
if (!(H5S_has_extent(file_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set")
if (!(H5S_has_extent(mem_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set")
/* Allocate original memory space buffer if necessary */
if (!orig_mem_space) {
if (count > 1) {
/* Allocate buffer */
if (NULL == (orig_mem_space = (H5S_t **)H5MM_calloc(count * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL,
"couldn't allocate original memory space array buffer")
}
else
/* Use local buffer */
orig_mem_space = &orig_mem_space_local;
}
/* H5S_select_shape_same() has been modified to accept topologically identical
* selections with different rank as having the same shape (if the most
* rapidly changing coordinates match up), but the I/O code still has
* difficulties with the notion.
*
* To solve this, we check to see if H5S_select_shape_same() returns true,
* and if the ranks of the mem and file spaces are different. If they are,
* construct a new mem space that is equivalent to the old mem space, and
* use that instead.
*
* Note that in general, this requires us to touch up the memory buffer as
* well.
*/
if (nelmts > 0 && TRUE == H5S_SELECT_SHAPE_SAME(mem_space, file_space) &&
H5S_GET_EXTENT_NDIMS(mem_space) != H5S_GET_EXTENT_NDIMS(file_space)) {
ptrdiff_t buf_adj = 0;
/* Save original memory space */
orig_mem_space[i] = dset_info[i].mem_space;
dset_info[i].mem_space = NULL;
/* Attempt to construct projected dataspace for memory dataspace */
if (H5S_select_construct_projection(mem_space, &projected_mem_space,
(unsigned)H5S_GET_EXTENT_NDIMS(file_space),
type_info.dst_type_size, &buf_adj) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace")
HDassert(projected_mem_space);
/* Attempt to construct projected dataspace for memory dataspace */
if (H5S_select_construct_projection(orig_mem_space[i], &dset_info[i].mem_space,
(unsigned)H5S_GET_EXTENT_NDIMS(dset_info[i].file_space),
(hsize_t)dset_info[i].type_info.dst_type_size, &buf_adj) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace")
HDassert(dset_info[i].mem_space);
/* Adjust the buffer by the given amount */
buf = (void *)(((uint8_t *)buf) + buf_adj);
/* Adjust the buffer by the given amount */
dset_info[i].buf.vp = (void *)(((uint8_t *)dset_info[i].buf.vp) + buf_adj);
} /* end if */
/* Switch to using projected memory dataspace & adjusted buffer */
mem_space = projected_mem_space;
} /* end if */
/* If space hasn't been allocated and not using external storage,
* return fill value to buffer if fill time is upon allocation, or
* do nothing if fill time is never. If the dataset is compact and
* fill time is NEVER, there is no way to tell whether part of data
* has been overwritten. So just proceed in reading.
*/
if (dset_info[i].nelmts > 0 && dset_info[i].dset->shared->dcpl_cache.efl.nused == 0 &&
!(*dset_info[i].dset->shared->layout.ops->is_space_alloc)(
&dset_info[i].dset->shared->layout.storage) &&
!(dset_info[i].dset->shared->layout.ops->is_data_cached &&
(*dset_info[i].dset->shared->layout.ops->is_data_cached)(dset_info[i].dset->shared))) {
H5D_fill_value_t fill_status; /* Whether/How the fill value is defined */
/* Retrieve dataset properties */
/* <none needed in the general case> */
/* Retrieve dataset's fill-value properties */
if (H5P_is_fill_value_defined(&dset_info[i].dset->shared->dcpl_cache.fill, &fill_status) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
/* If space hasn't been allocated and not using external storage,
* return fill value to buffer if fill time is upon allocation, or
* do nothing if fill time is never. If the dataset is compact and
* fill time is NEVER, there is no way to tell whether part of data
* has been overwritten. So just proceed in reading.
*/
if (nelmts > 0 && dataset->shared->dcpl_cache.efl.nused == 0 &&
!(*dataset->shared->layout.ops->is_space_alloc)(&dataset->shared->layout.storage) &&
!(dataset->shared->layout.ops->is_data_cached &&
(*dataset->shared->layout.ops->is_data_cached)(dataset->shared))) {
H5D_fill_value_t fill_status; /* Whether/How the fill value is defined */
/* Should be impossible, but check anyway... */
if (fill_status == H5D_FILL_VALUE_UNDEFINED &&
(dset_info[i].dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC ||
dset_info[i].dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET))
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL,
"read failed: dataset doesn't exist, no data can be read")
/* Retrieve dataset's fill-value properties */
if (H5P_is_fill_value_defined(&dataset->shared->dcpl_cache.fill, &fill_status) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
/* If we're never going to fill this dataset, just leave the junk in the user's buffer */
if (dset_info[i].dset->shared->dcpl_cache.fill.fill_time != H5D_FILL_TIME_NEVER)
/* Go fill the user's selection with the dataset's fill value */
if (H5D__fill(dset_info[i].dset->shared->dcpl_cache.fill.buf, dset_info[i].dset->shared->type,
dset_info[i].buf.vp, dset_info[i].type_info.mem_type,
dset_info[i].mem_space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "filling buf failed")
/* Should be impossible, but check anyway... */
if (fill_status == H5D_FILL_VALUE_UNDEFINED &&
(dataset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC ||
dataset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET))
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL,
"read failed: dataset doesn't exist, no data can be read")
/* No need to perform any more I/O for this dataset */
dset_info[i].skip_io = TRUE;
io_skipped++;
} /* end if */
else {
/* Set up I/O operation */
if (H5D__dset_ioinfo_init(dset_info[i].dset, &(dset_info[i]), &(store[i])) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to set up I/O operation")
/* If we're never going to fill this dataset, just leave the junk in the user's buffer */
if (dataset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_NEVER)
HGOTO_DONE(SUCCEED)
/* Sanity check that space is allocated, if there are elements */
if (dset_info[i].nelmts > 0)
HDassert(
(*dset_info[i].dset->shared->layout.ops->is_space_alloc)(
&dset_info[i].dset->shared->layout.storage) ||
(dset_info[i].dset->shared->layout.ops->is_data_cached &&
(*dset_info[i].dset->shared->layout.ops->is_data_cached)(dset_info[i].dset->shared)) ||
dset_info[i].dset->shared->dcpl_cache.efl.nused > 0 ||
dset_info[i].dset->shared->layout.type == H5D_COMPACT);
/* Go fill the user's selection with the dataset's fill value */
if (H5D__fill(dataset->shared->dcpl_cache.fill.buf, dataset->shared->type, buf, type_info.mem_type,
mem_space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "filling buf failed")
else
HGOTO_DONE(SUCCEED)
} /* end if */
/* Call storage method's I/O initialization routine */
if (dset_info[i].layout_ops.io_init &&
(dset_info[i].layout_ops.io_init)(&io_info, &(dset_info[i])) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info")
dset_info[i].skip_io = FALSE;
io_op_init++;
/* Set up I/O operation */
io_info.op_type = H5D_IO_OP_READ;
io_info.u.rbuf = buf;
if (H5D__ioinfo_init(dataset, &type_info, &store, &io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to set up I/O operation")
/* Reset metadata tagging */
H5AC_tag(prev_tag, NULL);
}
} /* end of for loop */
/* Sanity check that space is allocated, if there are elements */
if (nelmts > 0)
HDassert((*dataset->shared->layout.ops->is_space_alloc)(&dataset->shared->layout.storage) ||
(dataset->shared->layout.ops->is_data_cached &&
(*dataset->shared->layout.ops->is_data_cached)(dataset->shared)) ||
dataset->shared->dcpl_cache.efl.nused > 0 || layout_type == H5D_COMPACT);
HDassert(type_info_init == count);
HDassert(io_op_init + io_skipped == count);
/* Allocate the chunk map */
if (H5D_CONTIGUOUS != layout_type && H5D_COMPACT != layout_type) {
if (NULL == (fm = H5FL_CALLOC(H5D_chunk_map_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk map")
}
/* If no datasets have I/O, we're done */
if (io_op_init == 0)
HGOTO_DONE(SUCCEED)
/* Call storage method's I/O initialization routine */
if (io_info.layout_ops.io_init &&
(*io_info.layout_ops.io_init)(&io_info, &type_info, nelmts, file_space, mem_space, fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info")
io_op_init = TRUE;
/* Perform second phase of type info initialization */
if (H5D__typeinfo_init_phase2(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (second phase)")
#ifdef H5_HAVE_PARALLEL
/* Adjust I/O info for any parallel I/O */
if (H5D__ioinfo_adjust(&io_info, dataset, file_space, mem_space, &type_info) < 0)
if (H5D__ioinfo_adjust(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
#endif /*H5_HAVE_PARALLEL*/
/* Invoke correct "high level" I/O routine */
if ((*io_info.io_ops.multi_read)(&io_info, &type_info, nelmts, file_space, mem_space, fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
/* If multi dataset I/O callback is not provided, perform read IO via
* single-dset path with looping */
if (io_info.md_io_ops.multi_read_md) {
/* Create sel_pieces array if any pieces are selected */
if (io_info.piece_count > 0) {
HDassert(!io_info.sel_pieces);
HDassert(io_info.pieces_added == 0);
/* Allocate sel_pieces array */
if (NULL ==
(io_info.sel_pieces = H5MM_malloc(io_info.piece_count * sizeof(io_info.sel_pieces[0]))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate array of selected pieces")
}
/* MDIO-specific second phase initialization */
for (i = 0; i < count; i++)
if (dset_info[i].layout_ops.mdio_init) {
haddr_t prev_tag = HADDR_UNDEF;
/* set metadata tagging with dset oheader addr */
H5AC_tag(dset_info[i].dset->oloc.addr, &prev_tag);
/* Make second phase IO init call */
if ((dset_info[i].layout_ops.mdio_init)(&io_info, &(dset_info[i])) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't populate array of selected pieces")
/* Reset metadata tagging */
H5AC_tag(prev_tag, NULL);
}
/* Invoke correct "high level" I/O routine */
if ((*io_info.md_io_ops.multi_read_md)(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
} /* end if */
else {
haddr_t prev_tag = HADDR_UNDEF;
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info) && io_info.piece_count > 0) {
if (NULL == (io_info.mem_spaces = H5MM_malloc(io_info.piece_count * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for memory space list")
if (NULL == (io_info.file_spaces = H5MM_malloc(io_info.piece_count * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for file space list")
if (NULL == (io_info.addrs = H5MM_malloc(io_info.piece_count * sizeof(haddr_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for piece address list")
if (NULL == (io_info.element_sizes = H5MM_malloc(io_info.piece_count * sizeof(size_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for element size list")
if (NULL == (io_info.rbufs = H5MM_malloc(io_info.piece_count * sizeof(void *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for read buffer list")
}
/* Loop with serial & single-dset read IO path */
for (i = 0; i < count; i++) {
/* Check for skipped I/O */
if (dset_info[i].skip_io)
continue;
/* set metadata tagging with dset oheader addr */
H5AC_tag(dset_info[i].dset->oloc.addr, &prev_tag);
/* Invoke correct "high level" I/O routine */
if ((*dset_info[i].io_ops.multi_read)(&io_info, &dset_info[i]) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
/* Reset metadata tagging */
H5AC_tag(prev_tag, NULL);
}
/* Make final multi dataset selection I/O call if we are using both
* features - in this case the multi_read callbacks did not perform the
* actual I/O */
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info))
if (H5F_shared_select_read(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
io_info.element_sizes, io_info.rbufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "selection read failed")
}
done:
/* Shut down the I/O op information */
if (io_op_init && io_info.layout_ops.io_term && (*io_info.layout_ops.io_term)(fm) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down I/O op info")
if (fm)
fm = H5FL_FREE(H5D_chunk_map_t, fm);
for (i = 0; i < io_op_init; i++)
if (!dset_info[i].skip_io && dset_info[i].layout_ops.io_term &&
(*dset_info[i].layout_ops.io_term)(&io_info, &(dset_info[i])) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down I/O op info")
/* Shut down datatype info for operation */
if (type_info_init && H5D__typeinfo_term(&type_info) < 0)
if (H5D__typeinfo_term(&io_info, type_info_init) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info")
/* discard projected mem space if it was created */
if (NULL != projected_mem_space)
if (H5S_close(projected_mem_space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down projected memory dataspace")
/* Discard projected mem spaces and restore originals */
if (orig_mem_space) {
for (i = 0; i < count; i++)
if (orig_mem_space[i]) {
if (H5S_close(dset_info[i].mem_space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL,
"unable to shut down projected memory dataspace")
dset_info[i].mem_space = orig_mem_space[i];
}
FUNC_LEAVE_NOAPI_TAG(ret_value)
/* Free orig_mem_space array if it was allocated */
if (orig_mem_space != &orig_mem_space_local)
H5MM_free(orig_mem_space);
}
/* Free global piece array */
H5MM_xfree(io_info.sel_pieces);
/* Free selection I/O arrays */
H5MM_xfree(io_info.mem_spaces);
H5MM_xfree(io_info.file_spaces);
H5MM_xfree(io_info.addrs);
H5MM_xfree(io_info.element_sizes);
H5MM_xfree(io_info.rbufs);
/* Free store array if it was allocated */
if (store != &store_local)
H5MM_free(store);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__read() */
/*-------------------------------------------------------------------------
* Function: H5D__write
*
* Purpose: Writes (part of) a DATASET to a file from application memory
* BUF. See H5Dwrite() for complete details.
* Purpose: Writes multiple (part of) DATASETs to a file from application
* memory BUFs. See H5Dwrite_multi() for complete details.
*
* This was referred from H5D__write for multi-dset work.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Thursday, December 4, 1997
*
*-------------------------------------------------------------------------
*/
herr_t
H5D__write(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_space, const void *buf)
H5D__write(size_t count, H5D_dset_io_info_t *dset_info)
{
H5D_chunk_map_t *fm = NULL; /* Chunk file<->memory mapping */
H5D_io_info_t io_info; /* Dataset I/O info */
H5D_type_info_t type_info; /* Datatype info for operation */
H5D_layout_t layout_type; /* Dataset's layout type (contig, chunked, compact, etc.) */
hbool_t type_info_init = FALSE; /* Whether the datatype info has been initialized */
hbool_t should_alloc_space = FALSE; /* Whether or not to initialize dataset's storage */
H5S_t *projected_mem_space = NULL; /* If not NULL, ptr to dataspace containing a */
/* projection of the supplied mem_space to a new */
/* dataspace with rank equal to that of */
/* file_space. */
/* */
/* This field is only used if */
/* H5S_select_shape_same() returns TRUE when */
/* comparing the mem_space and the data_space, */
/* and the mem_space have different rank. */
/* */
/* Note that if this variable is used, the */
/* projected mem space must be discarded at the */
/* end of the function to avoid a memory leak. */
H5D_storage_t store; /* union of EFL and chunk pointer in file space */
hsize_t nelmts; /* total number of elmts */
hbool_t io_op_init = FALSE; /* Whether the I/O op has been initialized */
char fake_char; /* Temporary variable for NULL buffer pointers */
herr_t ret_value = SUCCEED; /* Return value */
H5D_io_info_t io_info; /* Dataset I/O info for multi dsets */
size_t type_info_init = 0; /* Number of datatype info structs that have been initialized */
H5S_t *orig_mem_space_local; /* Local buffer for orig_mem_space */
H5S_t **orig_mem_space = NULL; /* If not NULL, ptr to an array of dataspaces */
/* containing the original memory spaces contained */
/* in dset_info. This is needed in order to */
/* restore the original state of dset_info if we */
/* replaced any mem spaces with equivalents */
/* projected to a rank equal to that of file_space. */
/* */
/* This field is only used if */
/* H5S_select_shape_same() returns TRUE when */
/* comparing at least one mem_space and data_space, */
/* and the mem_space has a different rank. */
/* */
/* Note that this is a temporary variable - the */
/* projected memory space is stored in dset_info, */
/* and will be freed when that structure is */
/* freed. */
H5D_storage_t store_local; /* Local buffer for store */
H5D_storage_t *store = &store_local; /* Union of EFL and chunk pointer in file space */
size_t io_op_init = 0; /* Number I/O ops that have been initialized */
size_t i; /* Local index variable */
char fake_char; /* Temporary variable for NULL buffer pointers */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE_TAG(dataset->oloc.addr)
FUNC_ENTER_NOAPI(FAIL)
/* check args */
HDassert(dataset && dataset->oloc.file);
HDassert(file_space);
HDassert(mem_space);
layout_type = dataset->shared->layout.type;
/* All filters in the DCPL must have encoding enabled. */
if (!dataset->shared->checked_filters) {
if (H5Z_can_apply(dataset->shared->dcpl_id, dataset->shared->type_id) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "can't apply filters")
dataset->shared->checked_filters = TRUE;
} /* end if */
/* Check if we are allowed to write to this file */
if (0 == (H5F_INTENT(dataset->oloc.file) & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Set up datatype info for operation */
if (H5D__typeinfo_init(dataset, mem_type_id, TRUE, &type_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
type_info_init = TRUE;
/* Various MPI based checks */
#ifdef H5_HAVE_PARALLEL
if (H5F_HAS_FEATURE(dataset->oloc.file, H5FD_FEAT_HAS_MPI)) {
/* If MPI based VFD is used, no VL or region reference datatype support yet. */
/* This is because they use the global heap in the file and we don't */
/* support parallel access of that yet */
if (H5T_is_vl_storage(type_info.mem_type) > 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL,
"Parallel IO does not support writing VL or region reference datatypes yet")
} /* end if */
else {
H5FD_mpio_xfer_t io_xfer_mode; /* MPI I/O transfer mode */
/* Get I/O transfer mode */
if (H5CX_get_io_xfer_mode(&io_xfer_mode) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode")
/* Collective access is not permissible without a MPI based VFD */
if (io_xfer_mode == H5FD_MPIO_COLLECTIVE)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPI-based driver only")
} /* end else */
#endif /*H5_HAVE_PARALLEL*/
/* Make certain that the number of elements in each selection is the same */
nelmts = H5S_GET_SELECT_NPOINTS(mem_space);
if (nelmts != H5S_GET_SELECT_NPOINTS(file_space))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
"src and dest dataspaces have different number of elements selected")
/* Check for a NULL buffer */
if (NULL == buf) {
/* Check for any elements selected (which is invalid) */
if (nelmts > 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer")
/* If the buffer is nil, and 0 element is selected, make a fake buffer.
* This is for some MPI package like ChaMPIon on NCSA's tungsten which
* doesn't support this feature.
*/
buf = &fake_char;
} /* end if */
/* Make sure that both selections have their extents set */
if (!(H5S_has_extent(file_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set")
if (!(H5S_has_extent(mem_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set")
/* H5S_select_shape_same() has been modified to accept topologically
* identical selections with different rank as having the same shape
* (if the most rapidly changing coordinates match up), but the I/O
* code still has difficulties with the notion.
*
* To solve this, we check to see if H5S_select_shape_same() returns
* true, and if the ranks of the mem and file spaces are different.
* If the are, construct a new mem space that is equivalent to the
* old mem space, and use that instead.
*
* Note that in general, this requires us to touch up the memory buffer
* as well.
*/
if (nelmts > 0 && TRUE == H5S_SELECT_SHAPE_SAME(mem_space, file_space) &&
H5S_GET_EXTENT_NDIMS(mem_space) != H5S_GET_EXTENT_NDIMS(file_space)) {
ptrdiff_t buf_adj = 0;
/* Attempt to construct projected dataspace for memory dataspace */
if (H5S_select_construct_projection(mem_space, &projected_mem_space,
(unsigned)H5S_GET_EXTENT_NDIMS(file_space),
type_info.src_type_size, &buf_adj) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace")
HDassert(projected_mem_space);
/* Adjust the buffer by the given amount */
buf = (const void *)(((const uint8_t *)buf) + buf_adj);
/* Switch to using projected memory dataspace & adjusted buffer */
mem_space = projected_mem_space;
} /* end if */
/* Retrieve dataset properties */
/* <none needed currently> */
/* Set up I/O operation */
io_info.op_type = H5D_IO_OP_WRITE;
io_info.u.wbuf = buf;
if (H5D__ioinfo_init(dataset, &type_info, &store, &io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up I/O operation")
/* Allocate dataspace and initialize it if it hasn't been. */
should_alloc_space = dataset->shared->dcpl_cache.efl.nused == 0 &&
!(*dataset->shared->layout.ops->is_space_alloc)(&dataset->shared->layout.storage);
/*
* If not using an MPI-based VFD, we only need to allocate
* and initialize storage if there's a selection in the
* dataset's dataspace. Otherwise, we always need to participate
* in the storage allocation since this may use collective
* operations and we will hang if we don't participate.
*/
if (!H5F_HAS_FEATURE(dataset->oloc.file, H5FD_FEAT_HAS_MPI))
should_alloc_space = should_alloc_space && (nelmts > 0);
if (should_alloc_space) {
hssize_t file_nelmts; /* Number of elements in file dataset's dataspace */
hbool_t full_overwrite; /* Whether we are over-writing all the elements */
/* Get the number of elements in file dataset's dataspace */
if ((file_nelmts = H5S_GET_EXTENT_NPOINTS(file_space)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "can't retrieve number of elements in file dataset")
/* Always allow fill values to be written if the dataset has a VL datatype */
if (H5T_detect_class(dataset->shared->type, H5T_VLEN, FALSE))
full_overwrite = FALSE;
else
full_overwrite = (hbool_t)((hsize_t)file_nelmts == nelmts ? TRUE : FALSE);
/* Allocate storage */
if (H5D__alloc_storage(&io_info, H5D_ALLOC_WRITE, full_overwrite, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
} /* end if */
/* Allocate the chunk map */
if (H5D_CONTIGUOUS != layout_type && H5D_COMPACT != layout_type) {
if (NULL == (fm = H5FL_CALLOC(H5D_chunk_map_t)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate chunk map")
}
/* Call storage method's I/O initialization routine */
if (io_info.layout_ops.io_init &&
(*io_info.layout_ops.io_init)(&io_info, &type_info, nelmts, file_space, mem_space, fm) < 0)
/* Init io_info */
if (H5D__ioinfo_init(count, dset_info, &io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info")
io_op_init = TRUE;
io_info.op_type = H5D_IO_OP_WRITE;
/* Allocate store buffer if necessary */
if (count > 1)
if (NULL == (store = (H5D_storage_t *)H5MM_malloc(count * sizeof(H5D_storage_t))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate dset storage info array buffer")
/* iterate over all dsets and construct I/O information */
for (i = 0; i < count; i++) {
hbool_t should_alloc_space = FALSE; /* Whether or not to initialize dataset's storage */
haddr_t prev_tag = HADDR_UNDEF;
/* check args */
if (NULL == dset_info[i].dset)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if (NULL == dset_info[i].dset->oloc.file)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* set metadata tagging with dset oheader addr */
H5AC_tag(dset_info[i].dset->oloc.addr, &prev_tag);
/* All filters in the DCPL must have encoding enabled. */
if (!dset_info[i].dset->shared->checked_filters) {
if (H5Z_can_apply(dset_info[i].dset->shared->dcpl_id, dset_info[i].dset->shared->type_id) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "can't apply filters")
dset_info[i].dset->shared->checked_filters = TRUE;
} /* end if */
/* Check if we are allowed to write to this file */
if (0 == (H5F_INTENT(dset_info[i].dset->oloc.file) & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Set up datatype info for operation */
if (H5D__typeinfo_init(&io_info, &(dset_info[i]), dset_info[i].mem_type_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
type_info_init++;
/* Various MPI based checks */
#ifdef H5_HAVE_PARALLEL
if (H5F_HAS_FEATURE(dset_info[i].dset->oloc.file, H5FD_FEAT_HAS_MPI)) {
/* If MPI based VFD is used, no VL or region reference datatype support yet. */
/* This is because they use the global heap in the file and we don't */
/* support parallel access of that yet */
if (H5T_is_vl_storage(dset_info[i].type_info.mem_type) > 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL,
"Parallel IO does not support writing VL or region reference datatypes yet")
} /* end if */
else {
H5FD_mpio_xfer_t io_xfer_mode; /* MPI I/O transfer mode */
/* Get I/O transfer mode */
if (H5CX_get_io_xfer_mode(&io_xfer_mode) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode")
/* Collective access is not permissible without a MPI based VFD */
if (io_xfer_mode == H5FD_MPIO_COLLECTIVE)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPI-based driver only")
} /* end else */
#endif /*H5_HAVE_PARALLEL*/
/* Make certain that the number of elements in each selection is the same, and cache nelmts in
* dset_info */
dset_info[i].nelmts = H5S_GET_SELECT_NPOINTS(dset_info[i].mem_space);
if (dset_info[i].nelmts != H5S_GET_SELECT_NPOINTS(dset_info[i].file_space))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
"src and dest dataspaces have different number of elements selected")
/* Check for a NULL buffer */
if (NULL == dset_info[i].buf.cvp) {
/* Check for any elements selected (which is invalid) */
if (dset_info[i].nelmts > 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer")
/* If the buffer is nil, and 0 element is selected, make a fake buffer.
* This is for some MPI package like ChaMPIon on NCSA's tungsten which
* doesn't support this feature.
*/
dset_info[i].buf.cvp = &fake_char;
} /* end if */
/* Make sure that both selections have their extents set */
if (!(H5S_has_extent(dset_info[i].file_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set")
if (!(H5S_has_extent(dset_info[i].mem_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set")
/* H5S_select_shape_same() has been modified to accept topologically
* identical selections with different rank as having the same shape
* (if the most rapidly changing coordinates match up), but the I/O
* code still has difficulties with the notion.
*
* To solve this, we check to see if H5S_select_shape_same() returns
* true, and if the ranks of the mem and file spaces are different.
* If they are, construct a new mem space that is equivalent to the
* old mem space, and use that instead.
*
* Note that in general, this requires us to touch up the memory buffer
* as well.
*/
if (dset_info[i].nelmts > 0 &&
TRUE == H5S_SELECT_SHAPE_SAME(dset_info[i].mem_space, dset_info[i].file_space) &&
H5S_GET_EXTENT_NDIMS(dset_info[i].mem_space) != H5S_GET_EXTENT_NDIMS(dset_info[i].file_space)) {
ptrdiff_t buf_adj = 0;
/* Allocate original memory space buffer if necessary */
if (!orig_mem_space) {
if (count > 1) {
/* Allocate buffer */
if (NULL == (orig_mem_space = (H5S_t **)H5MM_calloc(count * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL,
"couldn't allocate original memory space array buffer")
}
else
/* Use local buffer */
orig_mem_space = &orig_mem_space_local;
}
/* Save original memory space */
orig_mem_space[i] = dset_info[i].mem_space;
dset_info[i].mem_space = NULL;
/* Attempt to construct projected dataspace for memory dataspace */
if (H5S_select_construct_projection(orig_mem_space[i], &dset_info[i].mem_space,
(unsigned)H5S_GET_EXTENT_NDIMS(dset_info[i].file_space),
dset_info[i].type_info.src_type_size, &buf_adj) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to construct projected memory dataspace")
HDassert(dset_info[i].mem_space);
/* Adjust the buffer by the given amount */
dset_info[i].buf.cvp = (const void *)(((const uint8_t *)dset_info[i].buf.cvp) + buf_adj);
} /* end if */
/* Retrieve dataset properties */
/* <none needed currently> */
/* Set up I/O operation */
if (H5D__dset_ioinfo_init(dset_info[i].dset, &(dset_info[i]), &(store[i])) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up I/O operation")
/* Allocate dataspace and initialize it if it hasn't been. */
should_alloc_space = dset_info[i].dset->shared->dcpl_cache.efl.nused == 0 &&
!(*dset_info[i].dset->shared->layout.ops->is_space_alloc)(
&dset_info[i].dset->shared->layout.storage);
/*
* If not using an MPI-based VFD, we only need to allocate
* and initialize storage if there's a selection in the
* dataset's dataspace. Otherwise, we always need to participate
* in the storage allocation since this may use collective
* operations and we will hang if we don't participate.
*/
if (!H5F_HAS_FEATURE(dset_info[i].dset->oloc.file, H5FD_FEAT_HAS_MPI))
should_alloc_space = should_alloc_space && (dset_info[i].nelmts > 0);
if (should_alloc_space) {
hssize_t file_nelmts; /* Number of elements in file dataset's dataspace */
hbool_t full_overwrite; /* Whether we are over-writing all the elements */
/* Get the number of elements in file dataset's dataspace */
if ((file_nelmts = H5S_GET_EXTENT_NPOINTS(dset_info[i].file_space)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL,
"can't retrieve number of elements in file dataset")
/* Always allow fill values to be written if the dataset has a VL datatype */
if (H5T_detect_class(dset_info[i].dset->shared->type, H5T_VLEN, FALSE))
full_overwrite = FALSE;
else
full_overwrite = (hbool_t)((hsize_t)file_nelmts == dset_info[i].nelmts ? TRUE : FALSE);
/* Allocate storage */
if (H5D__alloc_storage(dset_info[i].dset, H5D_ALLOC_WRITE, full_overwrite, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
} /* end if */
/* Call storage method's I/O initialization routine */
/* Init io_info.dset_info[] and generate piece_info in skip list */
if (dset_info[i].layout_ops.io_init &&
(*dset_info[i].layout_ops.io_init)(&io_info, &(dset_info[i])) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info")
dset_info[i].skip_io = FALSE;
io_op_init++;
/* Reset metadata tagging */
H5AC_tag(prev_tag, NULL);
} /* end of for loop */
HDassert(type_info_init == count);
HDassert(io_op_init == count);
/* Perform second phase of type info initialization */
if (H5D__typeinfo_init_phase2(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info (second phase)")
#ifdef H5_HAVE_PARALLEL
/* Adjust I/O info for any parallel I/O */
if (H5D__ioinfo_adjust(&io_info, dataset, file_space, mem_space, &type_info) < 0)
if (H5D__ioinfo_adjust(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
#endif /*H5_HAVE_PARALLEL*/
/* Invoke correct "high level" I/O routine */
if ((*io_info.io_ops.multi_write)(&io_info, &type_info, nelmts, file_space, mem_space, fm) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
/* If multi dataset I/O callback is not provided, perform write IO via
* single-dset path with looping */
if (io_info.md_io_ops.multi_write_md) {
/* Create sel_pieces array if any pieces are selected */
if (io_info.piece_count > 0) {
HDassert(!io_info.sel_pieces);
HDassert(io_info.pieces_added == 0);
/* Allocate sel_pieces array */
if (NULL ==
(io_info.sel_pieces = H5MM_malloc(io_info.piece_count * sizeof(io_info.sel_pieces[0]))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate array of selected pieces")
}
/* MDIO-specific second phase initialization */
for (i = 0; i < count; i++)
if (dset_info[i].layout_ops.mdio_init) {
haddr_t prev_tag = HADDR_UNDEF;
/* set metadata tagging with dset oheader addr */
H5AC_tag(dset_info[i].dset->oloc.addr, &prev_tag);
/* Make second phase IO init call */
if ((dset_info[i].layout_ops.mdio_init)(&io_info, &(dset_info[i])) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't populate array of selected pieces")
/* Reset metadata tagging */
H5AC_tag(prev_tag, NULL);
}
/* Invoke correct "high level" I/O routine */
if ((*io_info.md_io_ops.multi_write_md)(&io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
} /* end if */
else {
haddr_t prev_tag = HADDR_UNDEF;
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info) && io_info.piece_count > 0) {
if (NULL == (io_info.mem_spaces = H5MM_malloc(io_info.piece_count * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for memory space list")
if (NULL == (io_info.file_spaces = H5MM_malloc(io_info.piece_count * sizeof(H5S_t *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed for file space list")
if (NULL == (io_info.addrs = H5MM_malloc(io_info.piece_count * sizeof(haddr_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for piece address list")
if (NULL == (io_info.element_sizes = H5MM_malloc(io_info.piece_count * sizeof(size_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for element size list")
if (NULL == (io_info.wbufs = H5MM_malloc(io_info.piece_count * sizeof(const void *))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
"memory allocation failed for read buffer list")
}
/* loop with serial & single-dset write IO path */
for (i = 0; i < count; i++) {
HDassert(!dset_info[i].skip_io);
/* set metadata tagging with dset oheader addr */
H5AC_tag(dset_info->dset->oloc.addr, &prev_tag);
/* Invoke correct "high level" I/O routine */
if ((*dset_info[i].io_ops.multi_write)(&io_info, &dset_info[i]) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
/* Reset metadata tagging */
H5AC_tag(prev_tag, NULL);
}
/* Make final multi dataset selection I/O call if we are using both
* features - in this case the multi_write callbacks did not perform the
* actual I/O */
H5_CHECK_OVERFLOW(io_info.pieces_added, size_t, uint32_t)
if (!H5D_LAYOUT_CB_PERFORM_IO(&io_info))
if (H5F_shared_select_write(io_info.f_sh, H5FD_MEM_DRAW, (uint32_t)io_info.pieces_added,
io_info.mem_spaces, io_info.file_spaces, io_info.addrs,
io_info.element_sizes, io_info.wbufs) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "selection write failed")
}
#ifdef OLD_WAY
/*
@@ -515,88 +774,138 @@ H5D__write(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_spac
done:
/* Shut down the I/O op information */
if (io_op_init && io_info.layout_ops.io_term && (*io_info.layout_ops.io_term)(fm) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down I/O op info")
if (fm)
fm = H5FL_FREE(H5D_chunk_map_t, fm);
for (i = 0; i < io_op_init; i++) {
HDassert(!dset_info[i].skip_io);
if (dset_info[i].layout_ops.io_term &&
(*dset_info[i].layout_ops.io_term)(&io_info, &(dset_info[i])) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down I/O op info")
}
/* Shut down datatype info for operation */
if (type_info_init && H5D__typeinfo_term(&type_info) < 0)
if (H5D__typeinfo_term(&io_info, type_info_init) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info")
/* discard projected mem space if it was created */
if (NULL != projected_mem_space)
if (H5S_close(projected_mem_space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down projected memory dataspace")
/* Discard projected mem spaces and restore originals */
if (orig_mem_space) {
for (i = 0; i < count; i++)
if (orig_mem_space[i]) {
if (H5S_close(dset_info[i].mem_space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL,
"unable to shut down projected memory dataspace")
dset_info[i].mem_space = orig_mem_space[i];
}
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5D__write() */
/* Free orig_mem_space array if it was allocated */
if (orig_mem_space != &orig_mem_space_local)
H5MM_free(orig_mem_space);
}
/* Free global piece array */
H5MM_xfree(io_info.sel_pieces);
/* Free store array if it was allocated */
if (store != &store_local)
H5MM_free(store);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__write */
/*-------------------------------------------------------------------------
* Function: H5D__ioinfo_init
*
* Purpose: Routine for determining correct I/O operations for
* each I/O action.
* Purpose: General setup for H5D_io_info_t struct
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Thursday, September 30, 2004
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__ioinfo_init(H5D_t *dset, const H5D_type_info_t *type_info, H5D_storage_t *store, H5D_io_info_t *io_info)
H5D__ioinfo_init(size_t count, H5D_dset_io_info_t *dset_info, H5D_io_info_t *io_info)
{
FUNC_ENTER_PACKAGE_NOERR
/* check args */
HDassert(count > 0);
HDassert(dset_info);
HDassert(dset_info[0].dset->oloc.file);
HDassert(io_info);
/* Zero out struct */
HDmemset(io_info, 0, sizeof(*io_info));
/* Set up simple fields */
io_info->f_sh = count > 0 ? H5F_SHARED(dset_info[0].dset->oloc.file) : NULL;
io_info->count = count;
/* Start without multi-dataset I/O ops. If we're not using the collective
* I/O path then we will call the single dataset callbacks in a loop. */
/* Use provided dset_info */
io_info->dsets_info = dset_info;
/* Start with selection I/O on if the global is on, layout callback will
* turn it off if appropriate */
io_info->use_select_io = H5_use_selection_io_g;
#ifdef H5_HAVE_PARALLEL
/* Determine if the file was opened with an MPI VFD */
if (count > 0)
io_info->using_mpi_vfd = H5F_HAS_FEATURE(dset_info[0].dset->oloc.file, H5FD_FEAT_HAS_MPI);
#endif /* H5_HAVE_PARALLEL */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__ioinfo_init() */
/*-------------------------------------------------------------------------
* Function: H5D__dset_ioinfo_init
*
* Purpose: Routine for determining correct I/O operations for each I/O action.
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__dset_ioinfo_init(H5D_t *dset, H5D_dset_io_info_t *dset_info, H5D_storage_t *store)
{
FUNC_ENTER_PACKAGE_NOERR
/* check args */
HDassert(dset);
HDassert(dset->oloc.file);
HDassert(type_info);
HDassert(type_info->tpath);
HDassert(io_info);
HDassert(dset_info->type_info.tpath);
/* Set up "normal" I/O fields */
io_info->dset = dset;
io_info->f_sh = H5F_SHARED(dset->oloc.file);
io_info->store = store;
dset_info->dset = dset;
dset_info->store = store;
/* Set I/O operations to initial values */
io_info->layout_ops = *dset->shared->layout.ops;
dset_info->layout_ops = *dset->shared->layout.ops;
/* Set the "high-level" I/O operations for the dataset */
io_info->io_ops.multi_read = dset->shared->layout.ops->ser_read;
io_info->io_ops.multi_write = dset->shared->layout.ops->ser_write;
dset_info->io_ops.multi_read = dset->shared->layout.ops->ser_read;
dset_info->io_ops.multi_write = dset->shared->layout.ops->ser_write;
/* Set the I/O operations for reading/writing single blocks on disk */
if (type_info->is_xform_noop && type_info->is_conv_noop) {
if (dset_info->type_info.is_xform_noop && dset_info->type_info.is_conv_noop) {
/*
* If there is no data transform or type conversion then read directly into
* the application's buffer. This saves at least one mem-to-mem copy.
* If there is no data transform or type conversion then read directly
* into the application's buffer.
* This saves at least one mem-to-mem copy.
*/
io_info->io_ops.single_read = H5D__select_read;
io_info->io_ops.single_write = H5D__select_write;
dset_info->io_ops.single_read = H5D__select_read;
dset_info->io_ops.single_write = H5D__select_write;
} /* end if */
else {
/*
* This is the general case (type conversion, usually).
*/
io_info->io_ops.single_read = H5D__scatgath_read;
io_info->io_ops.single_write = H5D__scatgath_write;
dset_info->io_ops.single_read = H5D__scatgath_read;
dset_info->io_ops.single_write = H5D__scatgath_write;
} /* end else */
/* Start with selection I/O off, layout callback will turn it on if
* appropriate */
io_info->use_select_io = FALSE;
#ifdef H5_HAVE_PARALLEL
/* Determine if the file was opened with an MPI VFD */
io_info->using_mpi_vfd = H5F_HAS_FEATURE(dset->oloc.file, H5FD_FEAT_HAS_MPI);
#endif /* H5_HAVE_PARALLEL */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__ioinfo_init() */
} /* end H5D__dset_ioinfo_init() */
/*-------------------------------------------------------------------------
* Function: H5D__typeinfo_init
@@ -612,8 +921,10 @@ H5D__ioinfo_init(H5D_t *dset, const H5D_type_info_t *type_info, H5D_storage_t *s
*-------------------------------------------------------------------------
*/
static herr_t
H5D__typeinfo_init(const H5D_t *dset, hid_t mem_type_id, hbool_t do_write, H5D_type_info_t *type_info)
H5D__typeinfo_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, hid_t mem_type_id)
{
H5D_type_info_t *type_info;
const H5D_t *dset;
const H5T_t *src_type; /* Source datatype */
const H5T_t *dst_type; /* Destination datatype */
H5Z_data_xform_t *data_transform; /* Data transform info */
@@ -622,7 +933,12 @@ H5D__typeinfo_init(const H5D_t *dset, hid_t mem_type_id, hbool_t do_write, H5D_t
FUNC_ENTER_PACKAGE
/* check args */
HDassert(type_info);
HDassert(io_info);
HDassert(dset_info);
/* Set convenience pointers */
type_info = &dset_info->type_info;
dset = dset_info->dset;
HDassert(dset);
/* Patch the top level file pointer for dt->shared->u.vlen.f if needed */
@@ -637,7 +953,7 @@ H5D__typeinfo_init(const H5D_t *dset, hid_t mem_type_id, hbool_t do_write, H5D_t
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
type_info->dset_type = dset->shared->type;
if (do_write) {
if (io_info->op_type == H5D_IO_OP_WRITE) {
src_type = type_info->mem_type;
dst_type = dset->shared->type;
type_info->src_type_id = mem_type_id;
@@ -667,7 +983,6 @@ H5D__typeinfo_init(const H5D_t *dset, hid_t mem_type_id, hbool_t do_write, H5D_t
/* Precompute some useful information */
type_info->src_type_size = H5T_get_size(src_type);
type_info->dst_type_size = H5T_get_size(dst_type);
type_info->max_type_size = MAX(type_info->src_type_size, type_info->dst_type_size);
type_info->is_conv_noop = H5T_path_noop(type_info->tpath);
type_info->is_xform_noop = H5Z_xform_noop(data_transform);
if (type_info->is_xform_noop && type_info->is_conv_noop) {
@@ -675,27 +990,21 @@ H5D__typeinfo_init(const H5D_t *dset, hid_t mem_type_id, hbool_t do_write, H5D_t
type_info->need_bkg = H5T_BKG_NO;
} /* end if */
else {
void *tconv_buf; /* Temporary conversion buffer pointer */
void *bkgr_buf; /* Background conversion buffer pointer */
size_t max_temp_buf; /* Maximum temporary buffer size */
H5T_bkg_t bkgr_buf_type; /* Background buffer type */
size_t target_size; /* Desired buffer size */
/* Get info from API context */
if (H5CX_get_max_temp_buf(&max_temp_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve max. temp. buf size")
if (H5CX_get_tconv_buf(&tconv_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve temp. conversion buffer pointer")
if (H5CX_get_bkgr_buf(&bkgr_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve background conversion buffer pointer")
if (H5CX_get_bkgr_buf_type(&bkgr_buf_type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve background buffer type")
/* Check if the datatypes are compound subsets of one another */
type_info->cmpd_subset = H5T_path_compound_subset(type_info->tpath);
/* Update io_info->max_type_size */
io_info->max_type_size =
MAX3(io_info->max_type_size, type_info->src_type_size, type_info->dst_type_size);
/* Check if we need a background buffer */
if (do_write && H5T_detect_class(dset->shared->type, H5T_VLEN, FALSE))
if ((io_info->op_type == H5D_IO_OP_WRITE) && H5T_detect_class(dset->shared->type, H5T_VLEN, FALSE))
type_info->need_bkg = H5T_BKG_YES;
else {
H5T_bkg_t path_bkg; /* Type conversion's background info */
@@ -708,13 +1017,54 @@ H5D__typeinfo_init(const H5D_t *dset, hid_t mem_type_id, hbool_t do_write, H5D_t
else
type_info->need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
} /* end else */
} /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__typeinfo_init() */
/*-------------------------------------------------------------------------
* Function: H5D__typeinfo_init_phase2
*
* Purpose: Finish initializing type info for all datasets after
* calculating the max type size across all datasets.
*
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__typeinfo_init_phase2(H5D_io_info_t *io_info)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* check args */
HDassert(io_info);
/* Check if we need to allocate a shared type conversion buffer */
if (io_info->max_type_size) {
void *tconv_buf; /* Temporary conversion buffer pointer */
void *bkgr_buf; /* Background conversion buffer pointer */
size_t max_temp_buf; /* Maximum temporary buffer size */
size_t target_size; /* Desired buffer size */
size_t i; /* Local index variable */
/* Get info from API context */
if (H5CX_get_max_temp_buf(&max_temp_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve max. temp. buf size")
if (H5CX_get_tconv_buf(&tconv_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve temp. conversion buffer pointer")
if (H5CX_get_bkgr_buf(&bkgr_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve background conversion buffer pointer")
/* Set up datatype conversion/background buffers */
target_size = max_temp_buf;
/* If the buffer is too small to hold even one element, try to make it bigger */
if (target_size < type_info->max_type_size) {
/* If the buffer is too small to hold even one element (in the dataset with the largest , try to make
* it bigger */
if (target_size < io_info->max_type_size) {
hbool_t default_buffer_info; /* Whether the buffer information are the defaults */
/* Detect if we have all default settings for buffers */
@@ -724,50 +1074,64 @@ H5D__typeinfo_init(const H5D_t *dset, hid_t mem_type_id, hbool_t do_write, H5D_t
/* Check if we are using the default buffer info */
if (default_buffer_info)
/* OK to get bigger for library default settings */
target_size = type_info->max_type_size;
target_size = io_info->max_type_size;
else
/* Don't get bigger than the application has requested */
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
} /* end if */
/* Compute the number of elements that will fit into buffer */
type_info->request_nelmts = target_size / type_info->max_type_size;
/* Sanity check elements in temporary buffer */
if (type_info->request_nelmts == 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
/* Get a temporary buffer for type conversion unless the app has already
* supplied one through the xfer properties. Instead of allocating a
* buffer which is the exact size, we allocate the target size.
*/
if (NULL == (type_info->tconv_buf = (uint8_t *)tconv_buf)) {
* buffer which is the exact size, we allocate the target size. This
* buffer is shared among all datasets in the operation, unlike for the
* background buffer, where each dataset gets its own. */
if (NULL == (io_info->tconv_buf = (uint8_t *)tconv_buf)) {
/* Allocate temporary buffer */
if (NULL == (type_info->tconv_buf = H5FL_BLK_CALLOC(type_conv, target_size)))
if (NULL == (io_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
type_info->tconv_buf_allocated = TRUE;
io_info->tconv_buf_allocated = TRUE;
} /* end if */
if (type_info->need_bkg && NULL == (type_info->bkg_buf = (uint8_t *)bkgr_buf)) {
size_t bkg_size; /* Desired background buffer size */
/* Compute the background buffer size */
/* (don't try to use buffers smaller than the default size) */
bkg_size = type_info->request_nelmts * type_info->dst_type_size;
if (bkg_size < max_temp_buf)
bkg_size = max_temp_buf;
/* Don't use API provided background buffer if there's more than one dataset, since each
* dataset needs its own */
if (io_info->count > 1)
bkgr_buf = NULL;
/* Allocate background buffer */
/* (Need calloc()-like call since memory needs to be initialized) */
if (NULL == (type_info->bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"memory allocation failed for background conversion")
type_info->bkg_buf_allocated = TRUE;
} /* end if */
} /* end else */
/* Iterate over datasets */
for (i = 0; i < io_info->count; i++) {
H5D_type_info_t *type_info = &io_info->dsets_info[i].type_info;
/* Compute the number of elements that will fit into buffer */
type_info->request_nelmts = target_size / MAX(type_info->src_type_size, type_info->dst_type_size);
;
/* Sanity check elements in temporary buffer */
if (type_info->request_nelmts == 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
/* Allocate background buffer if necessary */
if (type_info->need_bkg && NULL == (type_info->bkg_buf = (uint8_t *)bkgr_buf)) {
size_t bkg_size; /* Desired background buffer size */
/* Compute the background buffer size */
/* (don't try to use buffers smaller than the default size) */
bkg_size = type_info->request_nelmts * type_info->dst_type_size;
if (bkg_size < max_temp_buf)
bkg_size = max_temp_buf;
/* Allocate background buffer */
/* (Need calloc()-like call since memory needs to be initialized) */
if (NULL == (type_info->bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"memory allocation failed for background conversion")
type_info->bkg_buf_allocated = TRUE;
} /* end if */
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__typeinfo_init() */
} /* end H5D__typeinfo_init_phase2() */
#ifdef H5_HAVE_PARALLEL
@@ -776,30 +1140,28 @@ done:
*
* Purpose: Adjust operation's I/O info for any parallel I/O
*
* Return: Non-negative on success/Negative on failure
* This was derived from H5D__ioinfo_adjust for multi-dset work.
*
* Programmer: Quincey Koziol
* Thursday, March 27, 2008
* Return: Non-negative on success/Negative on failure
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, const H5S_t *file_space, const H5S_t *mem_space,
const H5D_type_info_t *type_info)
H5D__ioinfo_adjust(H5D_io_info_t *io_info)
{
H5D_t *dset0; /* only the first dset , also for single dsets case */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* check args */
HDassert(dset);
HDassert(dset->oloc.file);
HDassert(mem_space);
HDassert(file_space);
HDassert(type_info);
HDassert(type_info->tpath);
HDassert(io_info);
/* check the first dset, should exist either single or multi dset cases */
HDassert(io_info->dsets_info[0].dset);
dset0 = io_info->dsets_info[0].dset;
HDassert(dset0->oloc.file);
/* Reset the actual io mode properties to the default values in case
* the DXPL (if it's non-default) was previously used in a collective
* I/O operation.
@@ -819,11 +1181,11 @@ H5D__ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, const H5S_t *file_
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O transfer mode")
/* Get MPI communicator */
if (MPI_COMM_NULL == (io_info->comm = H5F_mpi_get_comm(dset->oloc.file)))
if (MPI_COMM_NULL == (io_info->comm = H5F_mpi_get_comm(dset0->oloc.file)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve MPI communicator")
/* Check if we can set direct MPI-IO read/write functions */
if ((opt = H5D__mpio_opt_possible(io_info, file_space, mem_space, type_info)) < 0)
if ((opt = H5D__mpio_opt_possible(io_info)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for direct IO dataspace ")
/* Check if we can use the optimized parallel I/O routines */
@@ -833,10 +1195,10 @@ H5D__ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, const H5S_t *file_
* handle collective I/O */
/* Check for selection/vector support in file driver? -NAF */
if (!io_info->use_select_io) {
io_info->io_ops.multi_read = dset->shared->layout.ops->par_read;
io_info->io_ops.multi_write = dset->shared->layout.ops->par_write;
io_info->io_ops.single_read = H5D__mpio_select_read;
io_info->io_ops.single_write = H5D__mpio_select_write;
io_info->md_io_ops.multi_read_md = H5D__collective_read;
io_info->md_io_ops.multi_write_md = H5D__collective_write;
io_info->md_io_ops.single_read_md = H5D__mpio_select_read;
io_info->md_io_ops.single_write_md = H5D__mpio_select_write;
} /* end if */
} /* end if */
else {
@@ -857,28 +1219,38 @@ H5D__ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset, const H5S_t *file_
* with multiple ranks involved; otherwise, there will be metadata
* inconsistencies in the file.
*/
if (io_info->op_type == H5D_IO_OP_WRITE && io_info->dset->shared->dcpl_cache.pline.nused > 0) {
int comm_size = 0;
if (io_info->op_type == H5D_IO_OP_WRITE) {
size_t i;
/* Retrieve size of MPI communicator used for file */
if ((comm_size = H5F_shared_mpi_get_size(io_info->f_sh)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get MPI communicator size")
/* Check all datasets for filters */
for (i = 0; i < io_info->count; i++)
if (io_info->dsets_info[i].dset->shared->dcpl_cache.pline.nused > 0)
break;
if (comm_size > 1) {
char local_no_coll_cause_string[512];
char global_no_coll_cause_string[512];
/* If the above loop didn't complete at least one dataset has a filter */
if (i < io_info->count) {
int comm_size = 0;
if (H5D__mpio_get_no_coll_cause_strings(local_no_coll_cause_string, 512,
global_no_coll_cause_string, 512) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,
"can't get reasons for breaking collective I/O")
/* Retrieve size of MPI communicator used for file */
if ((comm_size = H5F_shared_mpi_get_size(io_info->f_sh)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get MPI communicator size")
HGOTO_ERROR(H5E_IO, H5E_NO_INDEPENDENT, FAIL,
"Can't perform independent write with filters in pipeline.\n"
" The following caused a break from collective I/O:\n"
" Local causes: %s\n"
" Global causes: %s",
local_no_coll_cause_string, global_no_coll_cause_string);
if (comm_size > 1) {
char local_no_coll_cause_string[512];
char global_no_coll_cause_string[512];
if (H5D__mpio_get_no_coll_cause_strings(local_no_coll_cause_string, 512,
global_no_coll_cause_string, 512) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,
"can't get reasons for breaking collective I/O")
HGOTO_ERROR(H5E_IO, H5E_NO_INDEPENDENT, FAIL,
"Can't perform independent write with filters in pipeline.\n"
" The following caused a break from collective I/O:\n"
" Local causes: %s\n"
" Global causes: %s",
local_no_coll_cause_string, global_no_coll_cause_string);
}
}
}
@@ -899,31 +1271,34 @@ done:
#endif /* H5_HAVE_PARALLEL */
/*-------------------------------------------------------------------------
* Function: H5D__typeinfo_term
* Function: H5D__typeinfo_term
*
* Purpose: Common logic for terminating a type info object
* Purpose: Common logic for terminating a type info object
*
* Return: Non-negative on success/Negative on failure
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Thursday, March 6, 2008
* Programmer: Quincey Koziol
* Thursday, March 6, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__typeinfo_term(const H5D_type_info_t *type_info)
H5D__typeinfo_term(H5D_io_info_t *io_info, size_t type_info_init)
{
size_t i;
FUNC_ENTER_PACKAGE_NOERR
/* Check for releasing datatype conversion & background buffers */
if (type_info->tconv_buf_allocated) {
HDassert(type_info->tconv_buf);
(void)H5FL_BLK_FREE(type_conv, type_info->tconv_buf);
} /* end if */
if (type_info->bkg_buf_allocated) {
HDassert(type_info->bkg_buf);
(void)H5FL_BLK_FREE(type_conv, type_info->bkg_buf);
if (io_info->tconv_buf_allocated) {
HDassert(io_info->tconv_buf);
(void)H5FL_BLK_FREE(type_conv, io_info->tconv_buf);
} /* end if */
for (i = 0; i < type_info_init; i++)
if (io_info->dsets_info[i].type_info.bkg_buf_allocated) {
HDassert(io_info->dsets_info[i].type_info.bkg_buf);
(void)H5FL_BLK_FREE(type_conv, io_info->dsets_info[i].type_info.bkg_buf);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__typeinfo_term() */
+2 -7
View File
@@ -489,14 +489,9 @@ H5D__layout_oh_create(H5F_t *file, H5O_t *oh, H5D_t *dset, hid_t dapl_id)
* Allocate storage if space allocate time is early; otherwise delay
* allocation until later.
*/
if (fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY) {
H5D_io_info_t io_info;
io_info.dset = dset;
if (H5D__alloc_storage(&io_info, H5D_ALLOC_CREATE, FALSE, NULL) < 0)
if (fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY)
if (H5D__alloc_storage(dset, H5D_ALLOC_CREATE, FALSE, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
}
/* Update external storage message, if it's used */
if (dset->shared->dcpl_cache.efl.nused > 0) {
+799 -888
View File
@@ -55,12 +55,15 @@
#define H5D_MULTI_CHUNK_IO 1
#define H5D_ONE_LINK_CHUNK_IO_MORE_OPT 2
#define H5D_MULTI_CHUNK_IO_MORE_OPT 3
#define H5D_NO_IO 4
/***** Macros for One linked collective IO case. *****/
/* The default value to do one linked collective IO for all chunks.
If the average number of chunks per process is greater than this value,
the library will create an MPI derived datatype to link all chunks to do collective IO.
The user can set this value through an API. */
* If the average number of chunks per process is greater than this
* value, the library will create an MPI derived datatype to link all
* chunks to do collective IO. The user can set this value through an
* API.
*/
/* Macros to represent options on how to obtain chunk address for one linked-chunk IO case */
#define H5D_OBTAIN_ONE_CHUNK_ADDR_IND 0
@@ -71,10 +74,10 @@
#define H5D_ALL_CHUNK_ADDR_THRES_COL_NUM 10000
/***** Macros for multi-chunk collective IO case. *****/
/* The default value of the threshold to do collective IO for this chunk.
If the average number of processes per chunk is greater than the default value,
collective IO is done for this chunk.
*/
/* The default value of the threshold to do collective IO for this
* chunk. If the average number of processes per chunk is greater
* than the default value, collective IO is done for this chunk.
*/
/* Macros to represent different IO modes(NONE, Independent or collective)for multiple chunk IO case */
#define H5D_CHUNK_IO_MODE_COL 1
@@ -107,12 +110,12 @@
* structure, given a pointer to a H5D_io_info_t
* structure
*/
#define H5D_MPIO_INIT_CHUNK_IDX_INFO(index_info, io_info_ptr) \
#define H5D_MPIO_INIT_CHUNK_IDX_INFO(index_info, dset) \
do { \
index_info.f = (io_info_ptr)->dset->oloc.file; \
index_info.pline = &((io_info_ptr)->dset->shared->dcpl_cache.pline); \
index_info.layout = &((io_info_ptr)->dset->shared->layout.u.chunk); \
index_info.storage = &((io_info_ptr)->dset->shared->layout.storage.u.chunk); \
index_info.f = (dset)->oloc.file; \
index_info.pline = &((dset)->shared->dcpl_cache.pline); \
index_info.layout = &((dset)->shared->layout.u.chunk); \
index_info.storage = &((dset)->shared->layout.storage.u.chunk); \
} while (0)
/*
@@ -130,10 +133,12 @@
/* Local Typedefs */
/******************/
/* Combine chunk address and chunk info into a struct for better performance. */
/* Combine chunk/piece address and chunk/piece info into a struct for
* better performance. */
typedef struct H5D_chunk_addr_info_t {
haddr_t chunk_addr;
H5D_chunk_info_t chunk_info;
/* piece for multi-dset */
haddr_t piece_addr;
H5D_piece_info_t piece_info;
} H5D_chunk_addr_info_t;
/* Rank 0 Bcast values */
@@ -187,7 +192,7 @@ typedef struct H5D_chunk_index_info_t {
* need_insert - A flag which determines whether or not a chunk needs to be re-inserted into
* the chunk index after the write operation.
*
* chunk_info - A pointer to the chunk's H5D_chunk_info_t structure, which contains useful
* chunk_info - A pointer to the chunk's H5D_piece_info_t structure, which contains useful
* information like the dataspaces containing the selection in the chunk.
*
* chunk_current - The address in the file and size of this chunk before the filtering
@@ -241,7 +246,7 @@ typedef struct H5D_chunk_index_info_t {
typedef struct H5D_filtered_collective_io_info_t {
H5D_chunk_index_info_t index_info;
H5D_chunk_info_t *chunk_info;
H5D_piece_info_t *chunk_info;
H5F_block_t chunk_current;
H5F_block_t chunk_new;
hbool_t need_read;
@@ -281,65 +286,57 @@ typedef struct H5D_chunk_insert_info_t {
/********************/
/* Local Prototypes */
/********************/
static herr_t H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_map_t *fm);
static herr_t H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_map_t *fm, int mpi_rank, int mpi_size);
static herr_t H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, H5D_chunk_map_t *fm,
static herr_t H5D__piece_io(H5D_io_info_t *io_info);
static herr_t H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info,
int mpi_rank, int mpi_size);
static herr_t H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info,
int mpi_rank, int mpi_size);
static herr_t H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_map_t *fm, int sum_chunk, int mpi_rank, int mpi_size);
static herr_t H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_map_t *fm, int mpi_rank, int mpi_size);
static herr_t H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
static herr_t H5D__link_piece_collective_io(H5D_io_info_t *io_info, int mpi_rank);
static herr_t H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info,
int mpi_rank, int mpi_size);
static herr_t H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t *di,
H5S_t *file_space, H5S_t *mem_space);
static herr_t H5D__final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, MPI_Datatype mpi_file_type, MPI_Datatype mpi_buf_type);
static herr_t H5D__sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
H5D_chunk_addr_info_t chunk_addr_info_array[], int many_chunk_opt, int mpi_rank,
int mpi_size);
static herr_t H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assign_io_mode[],
static herr_t H5D__final_collective_io(H5D_io_info_t *io_info, hsize_t mpi_buf_count,
MPI_Datatype mpi_file_type, MPI_Datatype mpi_buf_type);
static herr_t H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_dset_io_info_t *di, uint8_t assign_io_mode[],
haddr_t chunk_addr[], int mpi_rank, int mpi_size);
static herr_t H5D__mpio_get_sum_chunk(const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
int *sum_chunkf);
static herr_t H5D__mpio_get_sum_chunk(const H5D_io_info_t *io_info, int *sum_chunkf);
static herr_t H5D__mpio_get_sum_chunk_dset(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
int *sum_chunkf);
static herr_t H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info,
const H5D_type_info_t *type_info,
const H5D_chunk_map_t *fm,
const H5D_dset_io_info_t *di,
H5D_filtered_collective_io_info_t **chunk_list,
size_t *num_entries, int mpi_rank);
static herr_t H5D__mpio_redistribute_shared_chunks(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries,
const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
int mpi_rank, int mpi_size,
const H5D_io_info_t *io_info, int mpi_rank, int mpi_size,
size_t **rank_chunks_assigned_map);
static herr_t H5D__mpio_redistribute_shared_chunks_int(H5D_filtered_collective_io_info_t *chunk_list,
size_t *num_chunks_assigned_map,
hbool_t all_ranks_involved,
const H5D_io_info_t *io_info,
const H5D_chunk_map_t *fm, int mpi_rank, int mpi_size);
size_t *num_chunks_assigned_map,
hbool_t all_ranks_involved,
const H5D_io_info_t *io_info, int mpi_rank,
int mpi_size);
static herr_t H5D__mpio_share_chunk_modification_data(H5D_filtered_collective_io_info_t *chunk_list,
size_t *chunk_list_num_entries, H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, int mpi_rank,
H5D_dset_io_info_t *dset_info, int mpi_rank,
int mpi_size,
H5D_filtered_collective_io_info_t **chunk_hash_table,
unsigned char ***chunk_msg_bufs,
int *chunk_msg_bufs_len);
static herr_t H5D__mpio_collective_filtered_chunk_common_io(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries,
const H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, int mpi_size);
size_t chunk_list_num_entries,
const H5D_io_info_t *io_info, int mpi_size);
static herr_t H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries,
const H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, int mpi_rank,
size_t chunk_list_num_entries,
const H5D_io_info_t *io_info,
const H5D_dset_io_info_t *di, int mpi_rank,
int mpi_size);
static herr_t H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries,
H5D_filtered_collective_io_info_t *chunk_hash_table,
unsigned char **chunk_msg_bufs,
int chunk_msg_bufs_len, const H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, int mpi_rank,
const H5D_dset_io_info_t *di, int mpi_rank,
int mpi_size);
static herr_t H5D__mpio_collective_filtered_chunk_reallocate(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries,
@@ -348,9 +345,9 @@ static herr_t H5D__mpio_collective_filtered_chunk_reallocate(H5D_filtered_collec
H5D_chk_idx_info_t *idx_info, int mpi_rank,
int mpi_size);
static herr_t H5D__mpio_collective_filtered_chunk_reinsert(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries,
size_t *num_chunks_assigned_map,
H5D_io_info_t *io_info,
size_t chunk_list_num_entries,
size_t *num_chunks_assigned_map,
H5D_io_info_t *io_info, H5D_dset_io_info_t *di,
H5D_chk_idx_info_t *idx_info, int mpi_rank,
int mpi_size);
static herr_t H5D__mpio_get_chunk_redistribute_info_types(MPI_Datatype *contig_type,
@@ -366,7 +363,7 @@ static herr_t H5D__mpio_collective_filtered_io_type(H5D_filtered_collective_io_i
size_t num_entries, H5D_io_op_type_t op_type,
MPI_Datatype *new_mem_type, hbool_t *mem_type_derived,
MPI_Datatype *new_file_type, hbool_t *file_type_derived);
static int H5D__cmp_chunk_addr(const void *chunk_addr_info1, const void *chunk_addr_info2);
static int H5D__cmp_piece_addr(const void *chunk_addr_info1, const void *chunk_addr_info2);
static int H5D__cmp_filtered_collective_io_info_entry(const void *filtered_collective_io_info_entry1,
const void *filtered_collective_io_info_entry2);
static int H5D__cmp_chunk_redistribute_info(const void *entry1, const void *entry2);
@@ -572,34 +569,40 @@ H5D__mpio_debug_init(void)
* Function: H5D__mpio_opt_possible
*
* Purpose: Checks if an direct I/O transfer is possible between memory and
* the file.
* the file.
*
* This was derived from H5D__mpio_opt_possible for
* multi-dset work.
*
* Return: Success: Non-negative: TRUE or FALSE
* Failure: Negative
*
* Programmer: Quincey Koziol
* Wednesday, April 3, 2002
*
*-------------------------------------------------------------------------
*/
htri_t
H5D__mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space, const H5S_t *mem_space,
const H5D_type_info_t *type_info)
H5D__mpio_opt_possible(H5D_io_info_t *io_info)
{
H5FD_mpio_xfer_t io_xfer_mode; /* MPI I/O transfer mode */
H5FD_mpio_xfer_t io_xfer_mode; /* MPI I/O transfer mode */
size_t i;
H5D_t *dset;
const H5S_t *file_space;
const H5S_t *mem_space;
H5D_type_info_t *type_info;
unsigned local_cause[2] = {0, 0}; /* [0] Local reason(s) for breaking collective mode */
/* [1] Flag if dataset is both: H5S_ALL and small */
unsigned global_cause[2] = {0, 0}; /* Global reason(s) for breaking collective mode */
htri_t is_vl_storage; /* Whether the dataset's datatype is stored in a variable-length form */
htri_t ret_value = SUCCEED; /* Return value */
htri_t is_vl_storage; /* Whether the dataset's datatype is stored in a variable-length form */
htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_PACKAGE
/* Check args */
HDassert(io_info);
HDassert(mem_space);
HDassert(file_space);
HDassert(type_info);
for (i = 0; i < io_info->count; i++) {
HDassert(io_info->dsets_info[i].file_space);
HDassert(io_info->dsets_info[i].mem_space);
}
/* For independent I/O, get out quickly and don't try to form consensus */
if (H5CX_get_io_xfer_mode(&io_xfer_mode) < 0)
@@ -608,90 +611,103 @@ H5D__mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space, co
if (io_xfer_mode == H5FD_MPIO_INDEPENDENT)
local_cause[0] |= H5D_MPIO_SET_INDEPENDENT;
/* Optimized MPI types flag must be set */
/* (based on 'HDF5_MPI_OPT_TYPES' environment variable) */
if (!H5FD_mpi_opt_types_g)
local_cause[0] |= H5D_MPIO_MPI_OPT_TYPES_ENV_VAR_DISABLED;
for (i = 0; i < io_info->count; i++) {
/* Check for skipped I/O */
if (io_info->dsets_info[i].skip_io)
continue;
/* Don't allow collective operations if datatype conversions need to happen */
if (!type_info->is_conv_noop)
local_cause[0] |= H5D_MPIO_DATATYPE_CONVERSION;
/* Set convenience pointers */
dset = io_info->dsets_info[i].dset;
file_space = io_info->dsets_info[i].file_space;
mem_space = io_info->dsets_info[i].mem_space;
type_info = &io_info->dsets_info[i].type_info;
/* Don't allow collective operations if data transform operations should occur */
if (!type_info->is_xform_noop)
local_cause[0] |= H5D_MPIO_DATA_TRANSFORMS;
/* Optimized MPI types flag must be set */
/* (based on 'HDF5_MPI_OPT_TYPES' environment variable) */
if (!H5FD_mpi_opt_types_g)
local_cause[0] |= H5D_MPIO_MPI_OPT_TYPES_ENV_VAR_DISABLED;
/* Check whether these are both simple or scalar dataspaces */
if (!((H5S_SIMPLE == H5S_GET_EXTENT_TYPE(mem_space) || H5S_SCALAR == H5S_GET_EXTENT_TYPE(mem_space)) &&
(H5S_SIMPLE == H5S_GET_EXTENT_TYPE(file_space) || H5S_SCALAR == H5S_GET_EXTENT_TYPE(file_space))))
local_cause[0] |= H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES;
/* Don't allow collective operations if datatype conversions need to happen */
if (!type_info->is_conv_noop)
local_cause[0] |= H5D_MPIO_DATATYPE_CONVERSION;
/* Dataset storage must be contiguous or chunked */
if (!(io_info->dset->shared->layout.type == H5D_CONTIGUOUS ||
io_info->dset->shared->layout.type == H5D_CHUNKED))
local_cause[0] |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
/* Don't allow collective operations if data transform operations should occur */
if (!type_info->is_xform_noop)
local_cause[0] |= H5D_MPIO_DATA_TRANSFORMS;
/* check if external-file storage is used */
if (io_info->dset->shared->dcpl_cache.efl.nused > 0)
local_cause[0] |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
/* Check whether these are both simple or scalar dataspaces */
if (!((H5S_SIMPLE == H5S_GET_EXTENT_TYPE(mem_space) ||
H5S_SCALAR == H5S_GET_EXTENT_TYPE(mem_space)) &&
(H5S_SIMPLE == H5S_GET_EXTENT_TYPE(file_space) ||
H5S_SCALAR == H5S_GET_EXTENT_TYPE(file_space))))
local_cause[0] |= H5D_MPIO_NOT_SIMPLE_OR_SCALAR_DATASPACES;
/* The handling of memory space is different for chunking and contiguous
* storage. For contiguous storage, mem_space and file_space won't change
* when it it is doing disk IO. For chunking storage, mem_space will
* change for different chunks. So for chunking storage, whether we can
* use collective IO will defer until each chunk IO is reached.
*/
/* Dataset storage must be contiguous or chunked */
if (!(dset->shared->layout.type == H5D_CONTIGUOUS || dset->shared->layout.type == H5D_CHUNKED))
local_cause[0] |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
/* check if external-file storage is used */
if (dset->shared->dcpl_cache.efl.nused > 0)
local_cause[0] |= H5D_MPIO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
/* The handling of memory space is different for chunking and contiguous
* storage. For contiguous storage, mem_space and file_space won't change
* when it it is doing disk IO. For chunking storage, mem_space will
* change for different chunks. So for chunking storage, whether we can
* use collective IO will defer until each chunk IO is reached.
*/
#ifndef H5_HAVE_PARALLEL_FILTERED_WRITES
/* Don't allow writes to filtered datasets if the functionality is disabled */
if (io_info->op_type == H5D_IO_OP_WRITE && io_info->dset->shared->dcpl_cache.pline.nused > 0)
local_cause[0] |= H5D_MPIO_PARALLEL_FILTERED_WRITES_DISABLED;
/* Don't allow writes to filtered datasets if the functionality is disabled */
if (io_info->op_type == H5D_IO_OP_WRITE && dset->shared->dcpl_cache.pline.nused > 0)
local_cause[0] |= H5D_MPIO_PARALLEL_FILTERED_WRITES_DISABLED;
#endif
/* Check if we are able to do a MPI_Bcast of the data from one rank
* instead of having all the processes involved in the collective I/O call.
*/
/* Check to see if the process is reading the entire dataset */
if (H5S_GET_SELECT_TYPE(file_space) != H5S_SEL_ALL)
local_cause[1] |= H5D_MPIO_RANK0_NOT_H5S_ALL;
/* Only perform this optimization for contiguous datasets, currently */
else if (H5D_CONTIGUOUS != io_info->dset->shared->layout.type)
/* Flag to do a MPI_Bcast of the data from one proc instead of
* having all the processes involved in the collective I/O.
/* Check if we are able to do a MPI_Bcast of the data from one rank
* instead of having all the processes involved in the collective I/O call.
*/
local_cause[1] |= H5D_MPIO_RANK0_NOT_CONTIGUOUS;
else if ((is_vl_storage = H5T_is_vl_storage(type_info->dset_type)) < 0)
local_cause[0] |= H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE;
else if (is_vl_storage)
local_cause[1] |= H5D_MPIO_RANK0_NOT_FIXED_SIZE;
else {
size_t type_size; /* Size of dataset's datatype */
/* Retrieve the size of the dataset's datatype */
if (0 == (type_size = H5T_GET_SIZE(type_info->dset_type)))
/* Check to see if the process is reading the entire dataset */
if (H5S_GET_SELECT_TYPE(file_space) != H5S_SEL_ALL)
local_cause[1] |= H5D_MPIO_RANK0_NOT_H5S_ALL;
/* Only perform this optimization for contiguous datasets, currently */
else if (H5D_CONTIGUOUS != dset->shared->layout.type)
/* Flag to do a MPI_Bcast of the data from one proc instead of
* having all the processes involved in the collective I/O.
*/
local_cause[1] |= H5D_MPIO_RANK0_NOT_CONTIGUOUS;
else if ((is_vl_storage = H5T_is_vl_storage(type_info->dset_type)) < 0)
local_cause[0] |= H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE;
else if (is_vl_storage)
local_cause[1] |= H5D_MPIO_RANK0_NOT_FIXED_SIZE;
else {
hssize_t snelmts; /* [Signed] # of elements in dataset's dataspace */
size_t type_size; /* Size of dataset's datatype */
/* Retrieve the size of the dataset's datatype */
if ((snelmts = H5S_GET_EXTENT_NPOINTS(file_space)) < 0)
if (0 == (type_size = H5T_GET_SIZE(type_info->dset_type)))
local_cause[0] |= H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE;
else {
hsize_t dset_size;
hssize_t snelmts; /* [Signed] # of elements in dataset's dataspace */
/* Determine dataset size */
dset_size = ((hsize_t)snelmts) * type_size;
/* Retrieve the size of the dataset's datatype */
if ((snelmts = H5S_GET_EXTENT_NPOINTS(file_space)) < 0)
local_cause[0] |= H5D_MPIO_ERROR_WHILE_CHECKING_COLLECTIVE_POSSIBLE;
else {
hsize_t dset_size;
/* If the size of the dataset is less than 2GB then do an MPI_Bcast
* of the data from one process instead of having all the processes
* involved in the collective I/O.
*/
if (dset_size > ((hsize_t)(2.0F * H5_GB) - 1))
local_cause[1] |= H5D_MPIO_RANK0_GREATER_THAN_2GB;
} /* end else */
} /* end else */
} /* end else */
/* Determine dataset size */
dset_size = ((hsize_t)snelmts) * type_size;
/* If the size of the dataset is less than 2GB then do an MPI_Bcast
* of the data from one process instead of having all the processes
* involved in the collective I/O.
*/
if (dset_size > ((hsize_t)(2.0F * H5_GB) - 1))
local_cause[1] |= H5D_MPIO_RANK0_GREATER_THAN_2GB;
} /* end else */
} /* end else */
} /* end else */
} /* end for loop */
/* Check for independent I/O */
if (local_cause[0] & H5D_MPIO_SET_INDEPENDENT)
@@ -875,26 +891,29 @@ done:
*
* Purpose: MPI-IO function to read directly from app buffer to file.
*
* Return: non-negative on success, negative on failure.
* This was referred from H5D__mpio_select_read for
* multi-dset work.
*
* Programmer:
* Return: non-negative on success, negative on failure.
*
*-------------------------------------------------------------------------
*/
herr_t
H5D__mpio_select_read(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info,
hsize_t mpi_buf_count, H5S_t H5_ATTR_UNUSED *file_space,
H5D__mpio_select_read(const H5D_io_info_t *io_info, hsize_t mpi_buf_count, H5S_t H5_ATTR_UNUSED *file_space,
H5S_t H5_ATTR_UNUSED *mem_space)
{
const H5D_contig_storage_t *store_contig =
&(io_info->store->contig); /* Contiguous storage info for this I/O operation */
void *rbuf = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
/* memory addr from a piece with lowest file addr */
rbuf = io_info->base_maddr.vp;
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
H5_CHECK_OVERFLOW(mpi_buf_count, hsize_t, size_t);
if (H5F_shared_block_read(io_info->f_sh, H5FD_MEM_DRAW, store_contig->dset_addr, (size_t)mpi_buf_count,
io_info->u.rbuf) < 0)
if (H5F_shared_block_read(io_info->f_sh, H5FD_MEM_DRAW, io_info->store_faddr, (size_t)mpi_buf_count,
rbuf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "can't finish collective parallel read")
done:
@@ -906,27 +925,29 @@ done:
*
* Purpose: MPI-IO function to write directly from app buffer to file.
*
* Return: non-negative on success, negative on failure.
* This was referred from H5D__mpio_select_write for
* multi-dset work.
*
* Programmer:
* Return: non-negative on success, negative on failure.
*
*-------------------------------------------------------------------------
*/
herr_t
H5D__mpio_select_write(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info,
hsize_t mpi_buf_count, H5S_t H5_ATTR_UNUSED *file_space,
H5D__mpio_select_write(const H5D_io_info_t *io_info, hsize_t mpi_buf_count, H5S_t H5_ATTR_UNUSED *file_space,
H5S_t H5_ATTR_UNUSED *mem_space)
{
const H5D_contig_storage_t *store_contig =
&(io_info->store->contig); /* Contiguous storage info for this I/O operation */
herr_t ret_value = SUCCEED;
const void *wbuf = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
/* memory addr from a piece with lowest file addr */
wbuf = io_info->base_maddr.cvp;
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
H5_CHECK_OVERFLOW(mpi_buf_count, hsize_t, size_t);
if (H5F_shared_block_write(io_info->f_sh, H5FD_MEM_DRAW, store_contig->dset_addr, (size_t)mpi_buf_count,
io_info->u.wbuf) < 0)
if (H5F_shared_block_write(io_info->f_sh, H5FD_MEM_DRAW, io_info->store_faddr, (size_t)mpi_buf_count,
wbuf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "can't finish collective parallel write")
done:
@@ -937,17 +958,15 @@ done:
* Function: H5D__mpio_get_sum_chunk
*
* Purpose: Routine for obtaining total number of chunks to cover
* hyperslab selection selected by all processors.
* hyperslab selection selected by all processors. Operates
* on all datasets in the operation.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Muqun Yang
* Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__mpio_get_sum_chunk(const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm, int *sum_chunkf)
H5D__mpio_get_sum_chunk(const H5D_io_info_t *io_info, int *sum_chunkf)
{
int num_chunkf; /* Number of chunks to iterate over */
size_t ori_num_chunkf;
@@ -958,7 +977,7 @@ H5D__mpio_get_sum_chunk(const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
/* Get the number of chunks to perform I/O on */
num_chunkf = 0;
ori_num_chunkf = H5SL_count(fm->sel_chunks);
ori_num_chunkf = io_info->pieces_added;
H5_CHECKED_ASSIGN(num_chunkf, int, ori_num_chunkf, size_t);
/* Determine the summation of number of chunks for all processes */
@@ -971,85 +990,47 @@ done:
} /* end H5D__mpio_get_sum_chunk() */
/*-------------------------------------------------------------------------
* Function: H5D__contig_collective_read
* Function: H5D__mpio_get_sum_chunk_dset
*
* Purpose: Reads directly from contiguous data in file into application
* memory using collective I/O.
* Purpose: Routine for obtaining total number of chunks to cover
* hyperslab selection selected by all processors. Operates
* on a single dataset.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Tuesday, March 4, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
H5D__contig_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t H5_ATTR_UNUSED nelmts, H5S_t *file_space, H5S_t *mem_space,
H5D_chunk_map_t H5_ATTR_UNUSED *fm)
static herr_t
H5D__mpio_get_sum_chunk_dset(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
int *sum_chunkf)
{
H5D_mpio_actual_io_mode_t actual_io_mode = H5D_MPIO_CONTIGUOUS_COLLECTIVE;
herr_t ret_value = SUCCEED; /* Return value */
int num_chunkf; /* Number of chunks to iterate over */
size_t ori_num_chunkf;
int mpi_code; /* MPI return code */
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_HAS_MPI));
/* Check for non-chunked dataset, in this case we know the number of "chunks"
* is simply the mpi size */
HDassert(dset_info->layout->type == H5D_CHUNKED);
/* Call generic internal collective I/O routine */
if (H5D__inter_collective_io(io_info, type_info, file_space, mem_space) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't finish shared collective MPI-IO")
/* Get the number of chunks to perform I/O on */
num_chunkf = 0;
ori_num_chunkf = H5SL_count(dset_info->layout_io_info.chunk_map->dset_sel_pieces);
H5_CHECKED_ASSIGN(num_chunkf, int, ori_num_chunkf, size_t);
/* Set the actual I/O mode property. internal_collective_io will not break to
* independent I/O, so we set it here.
*/
H5CX_set_mpio_actual_io_mode(actual_io_mode);
/* Determine the summation of number of chunks for all processes */
if (MPI_SUCCESS !=
(mpi_code = MPI_Allreduce(&num_chunkf, sum_chunkf, 1, MPI_INT, MPI_SUM, io_info->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__contig_collective_read() */
} /* end H5D__mpio_get_sum_chunk_dset() */
/*-------------------------------------------------------------------------
* Function: H5D__contig_collective_write
*
* Purpose: Write directly to contiguous data in file from application
* memory using collective I/O.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Tuesday, March 4, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
H5D__contig_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t H5_ATTR_UNUSED nelmts, H5S_t *file_space, H5S_t *mem_space,
H5D_chunk_map_t H5_ATTR_UNUSED *fm)
{
H5D_mpio_actual_io_mode_t actual_io_mode = H5D_MPIO_CONTIGUOUS_COLLECTIVE;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity check */
HDassert(H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_HAS_MPI));
/* Call generic internal collective I/O routine */
if (H5D__inter_collective_io(io_info, type_info, file_space, mem_space) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "couldn't finish shared collective MPI-IO")
/* Set the actual I/O mode property. internal_collective_io will not break to
* independent I/O, so we set it here.
*/
H5CX_set_mpio_actual_io_mode(actual_io_mode);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__contig_collective_write() */
/*-------------------------------------------------------------------------
* Function: H5D__chunk_collective_io
* Function: H5D__piece_io
*
* Purpose: Routine for
* 1) choose an IO option:
@@ -1085,34 +1066,34 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm)
H5D__piece_io(H5D_io_info_t *io_info)
{
H5FD_mpio_chunk_opt_t chunk_opt_mode;
#ifdef H5Dmpio_DEBUG
hbool_t log_file_flag = FALSE;
FILE *debug_log_file = NULL;
#endif
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
htri_t temp_not_link_io = FALSE;
#endif
int io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
int sum_chunk = -1;
int mpi_rank;
int mpi_size;
herr_t ret_value = SUCCEED;
int io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
hbool_t recalc_io_option = FALSE;
hbool_t use_multi_dset = FALSE;
unsigned one_link_chunk_io_threshold; /* Threshold to use single collective I/O for all chunks */
int sum_chunk = -1;
int mpi_rank;
int mpi_size;
size_t i;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
/* Sanity checks */
HDassert(io_info);
HDassert(io_info->using_mpi_vfd);
HDassert(type_info);
HDassert(fm);
HDassert(io_info->count > 0);
/* Obtain the current rank of the process and the number of ranks */
if ((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0)
if ((mpi_rank = H5F_mpi_get_rank(io_info->dsets_info[0].dset->oloc.file)) < 0)
HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain MPI rank")
if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0)
if ((mpi_size = H5F_mpi_get_size(io_info->dsets_info[0].dset->oloc.file)) < 0)
HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain MPI size")
#ifdef H5Dmpio_DEBUG
@@ -1139,7 +1120,9 @@ H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
}
#endif
/* Check the optional property list for the collective chunk IO optimization option */
/* Check the optional property list for the collective chunk IO optimization option.
* Only set here if it's a static option, if it needs to be calculated using the
* number of chunks per process delay that calculation until later. */
if (H5CX_get_mpio_chunk_opt_mode(&chunk_opt_mode) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't get chunk optimization option")
@@ -1148,81 +1131,190 @@ H5D__chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
/* direct request to multi-chunk-io */
else if (H5FD_MPIO_CHUNK_MULTI_IO == chunk_opt_mode)
io_option = H5D_MULTI_CHUNK_IO;
/* via default path. branch by num threshold */
else {
unsigned one_link_chunk_io_threshold; /* Threshold to use single collective I/O for all chunks */
else
recalc_io_option = TRUE;
if (H5D__mpio_get_sum_chunk(io_info, fm, &sum_chunk) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL,
"unable to obtain the total chunk number of all processes");
/* Check if we can and should use multi dataset path */
if (io_info->count > 1 && (io_option == H5D_ONE_LINK_CHUNK_IO || recalc_io_option)) {
/* Use multi dataset path for now */
use_multi_dset = TRUE;
/* Get the chunk optimization option threshold */
if (H5CX_get_mpio_chunk_opt_num(&one_link_chunk_io_threshold) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,
"couldn't get chunk optimization option threshold value")
/* Check for filtered datasets */
for (i = 0; i < io_info->count; i++)
if (io_info->dsets_info[i].dset->shared->dcpl_cache.pline.nused > 0) {
use_multi_dset = FALSE;
break;
}
/* step 1: choose an IO option */
/* If the average number of chunk per process is greater than a threshold, we will do one link chunked
* IO. */
if ((unsigned)sum_chunk / (unsigned)mpi_size >= one_link_chunk_io_threshold)
io_option = H5D_ONE_LINK_CHUNK_IO_MORE_OPT;
/* Check if this I/O exceeds one linked chunk threshold */
if (recalc_io_option && use_multi_dset) {
/* Get the chunk optimization option threshold */
if (H5CX_get_mpio_chunk_opt_num(&one_link_chunk_io_threshold) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,
"couldn't get chunk optimization option threshold value")
/* If the threshold is 0, no need to check number of chunks */
if (one_link_chunk_io_threshold > 0) {
/* Get number of chunks for all processes */
if (H5D__mpio_get_sum_chunk(io_info, &sum_chunk) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL,
"unable to obtain the total chunk number of all processes");
/* If the average number of chunk per process is less than the threshold, we will do multi
* chunk IO. If this threshold is not exceeded for all datasets, no need to check it again
* for each individual dataset. */
if ((unsigned)sum_chunk / (unsigned)mpi_size < one_link_chunk_io_threshold) {
recalc_io_option = FALSE;
use_multi_dset = FALSE;
}
}
}
/* Perform multi dataset I/O if appropriate */
if (use_multi_dset) {
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
else
temp_not_link_io = TRUE;
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
} /* end else */
/*** Set collective chunk user-input optimization API. ***/
if (H5D_ONE_LINK_CHUNK_IO == io_option) {
if (H5CX_test_set_mpio_coll_chunk_link_hard(0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property value")
} /* end if */
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
{
/*** Set collective chunk user-input optimization APIs. ***/
if (H5D_ONE_LINK_CHUNK_IO == io_option) {
if (H5CX_test_set_mpio_coll_chunk_link_hard(0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property value")
} /* end if */
else if (H5D_MULTI_CHUNK_IO == io_option) {
if (H5CX_test_set_mpio_coll_chunk_multi_hard(0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property value")
} /* end else-if */
else if (H5D_ONE_LINK_CHUNK_IO_MORE_OPT == io_option) {
if (H5CX_test_set_mpio_coll_chunk_link_num_true(0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property value")
} /* end if */
else if (temp_not_link_io) {
if (H5CX_test_set_mpio_coll_chunk_link_num_false(0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property value")
} /* end if */
/* Perform unfiltered link chunk collective IO */
if (H5D__link_piece_collective_io(io_info, mpi_rank) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish linked chunk MPI-IO")
}
}
if (!use_multi_dset) {
/* Loop over datasets */
for (i = 0; i < io_info->count; i++) {
if (io_info->dsets_info[i].layout->type == H5D_CONTIGUOUS) {
/* Contiguous: call H5D__inter_collective_io() directly */
H5D_mpio_actual_io_mode_t actual_io_mode = H5D_MPIO_CONTIGUOUS_COLLECTIVE;
io_info->store_faddr = io_info->dsets_info[i].store->contig.dset_addr;
io_info->base_maddr = io_info->dsets_info[i].buf;
if (H5D__inter_collective_io(io_info, &io_info->dsets_info[i],
io_info->dsets_info[i].file_space,
io_info->dsets_info[i].mem_space) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
/* Set the actual I/O mode property. internal_collective_io will not break to
* independent I/O, so we set it here.
*/
H5CX_set_mpio_actual_io_mode(actual_io_mode);
}
else {
/* Chunked I/O path */
HDassert(io_info->dsets_info[i].layout->type == H5D_CHUNKED);
/* Recalculate io_option if necessary */
if (recalc_io_option) {
/* Get the chunk optimization option threshold */
if (H5CX_get_mpio_chunk_opt_num(&one_link_chunk_io_threshold) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,
"couldn't get chunk optimization option threshold value")
/* If the threshold is 0, no need to check number of chunks */
if (one_link_chunk_io_threshold == 0) {
io_option = H5D_ONE_LINK_CHUNK_IO_MORE_OPT;
recalc_io_option = FALSE;
}
else {
/* Get number of chunks for all processes */
if (H5D__mpio_get_sum_chunk_dset(io_info, &io_info->dsets_info[i], &sum_chunk) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL,
"unable to obtain the total chunk number of all processes");
/* step 1: choose an IO option */
/* If the average number of chunk per process is greater than a threshold, we will do
* one link chunked IO. */
if ((unsigned)sum_chunk / (unsigned)mpi_size >= one_link_chunk_io_threshold)
io_option = H5D_ONE_LINK_CHUNK_IO_MORE_OPT;
else
io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
}
}
/* step 2: Go ahead to do IO.*/
switch (io_option) {
case H5D_ONE_LINK_CHUNK_IO:
case H5D_ONE_LINK_CHUNK_IO_MORE_OPT:
/* Check if there are any filters in the pipeline */
if (io_info->dsets_info[i].dset->shared->dcpl_cache.pline.nused > 0) {
if (H5D__link_chunk_filtered_collective_io(io_info, &io_info->dsets_info[i],
mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,
"couldn't finish filtered linked chunk MPI-IO")
} /* end if */
else {
/* If there is more than one dataset we cannot make the multi dataset call here,
* fall back to multi chunk */
if (io_info->count > 1) {
io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
recalc_io_option = TRUE;
if (H5D__multi_chunk_collective_io(io_info, &io_info->dsets_info[i], mpi_rank,
mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,
"couldn't finish optimized multiple chunk MPI-IO")
}
else {
/* Perform unfiltered link chunk collective IO */
if (H5D__link_piece_collective_io(io_info, mpi_rank) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,
"couldn't finish linked chunk MPI-IO")
}
}
break;
case H5D_MULTI_CHUNK_IO: /* direct request to do multi-chunk IO */
default: /* multiple chunk IO via threshold */
/* Check if there are any filters in the pipeline */
if (io_info->dsets_info[i].dset->shared->dcpl_cache.pline.nused > 0) {
if (H5D__multi_chunk_filtered_collective_io(io_info, &io_info->dsets_info[i],
mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,
"couldn't finish optimized multiple filtered chunk MPI-IO")
} /* end if */
else {
/* Perform unfiltered multi chunk collective IO */
if (H5D__multi_chunk_collective_io(io_info, &io_info->dsets_info[i], mpi_rank,
mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,
"couldn't finish optimized multiple chunk MPI-IO")
}
break;
} /* end switch */
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
{
/*** Set collective chunk user-input optimization APIs. ***/
if (H5D_ONE_LINK_CHUNK_IO == io_option) {
if (H5CX_test_set_mpio_coll_chunk_link_hard(0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property value")
} /* end if */
else if (H5D_MULTI_CHUNK_IO == io_option) {
if (H5CX_test_set_mpio_coll_chunk_multi_hard(0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property value")
} /* end else-if */
else if (H5D_ONE_LINK_CHUNK_IO_MORE_OPT == io_option) {
if (H5CX_test_set_mpio_coll_chunk_link_num_true(0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property value")
} /* end if */
else if (H5D_MULTI_CHUNK_IO_MORE_OPT == io_option) {
if (H5CX_test_set_mpio_coll_chunk_link_num_false(0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property value")
} /* end if */
}
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
/* step 2: Go ahead to do IO.*/
switch (io_option) {
case H5D_ONE_LINK_CHUNK_IO:
case H5D_ONE_LINK_CHUNK_IO_MORE_OPT:
/* Check if there are any filters in the pipeline */
if (io_info->dset->shared->dcpl_cache.pline.nused > 0) {
if (H5D__link_chunk_filtered_collective_io(io_info, type_info, fm, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish filtered linked chunk MPI-IO")
} /* end if */
else
/* Perform unfiltered link chunk collective IO */
if (H5D__link_chunk_collective_io(io_info, type_info, fm, sum_chunk, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish linked chunk MPI-IO")
break;
case H5D_MULTI_CHUNK_IO: /* direct request to do multi-chunk IO */
default: /* multiple chunk IO via threshold */
/* Check if there are any filters in the pipeline */
if (io_info->dset->shared->dcpl_cache.pline.nused > 0) {
if (H5D__multi_chunk_filtered_collective_io(io_info, type_info, fm, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,
"couldn't finish optimized multiple filtered chunk MPI-IO")
} /* end if */
else
/* Perform unfiltered multi chunk collective IO */
if (H5D__multi_chunk_collective_io(io_info, type_info, fm, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish optimized multiple chunk MPI-IO")
break;
} /* end switch */
}
}
}
done:
#ifdef H5Dmpio_DEBUG
@@ -1236,13 +1328,13 @@ done:
#endif
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_collective_io */
} /* end H5D__piece_io */
/*-------------------------------------------------------------------------
* Function: H5D__chunk_collective_read
* Function: H5D__collective_read
*
* Purpose: Reads directly from chunks in file into application memory
* using collective I/O.
* Purpose: Read directly from pieces (chunks/contig) in file into
* application memory using collective I/O.
*
* Return: Non-negative on success/Negative on failure
*
@@ -1252,27 +1344,25 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__chunk_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space,
H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm)
H5D__collective_read(H5D_io_info_t *io_info)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Call generic selection operation */
if (H5D__chunk_collective_io(io_info, type_info, fm) < 0)
if (H5D__piece_io(io_info) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_collective_read() */
} /* end H5D__collective_read() */
/*-------------------------------------------------------------------------
* Function: H5D__chunk_collective_write
* Function: H5D__collective_write
*
* Purpose: Write directly to chunks in file from application memory
* using collective I/O.
* Purpose: Write directly to pieces (chunks/contig) in file into
* application memory using collective I/O.
*
* Return: Non-negative on success/Negative on failure
*
@@ -1282,31 +1372,30 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__chunk_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t H5_ATTR_UNUSED nelmts, H5S_t H5_ATTR_UNUSED *file_space,
H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t *fm)
H5D__collective_write(H5D_io_info_t *io_info)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Call generic selection operation */
if (H5D__chunk_collective_io(io_info, type_info, fm) < 0)
if (H5D__piece_io(io_info) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_collective_write() */
} /* end H5D__collective_write() */
/*-------------------------------------------------------------------------
* Function: H5D__link_chunk_collective_io
* Function: H5D__link_piece_collective_io
*
* Purpose: Routine for one collective IO with one MPI derived datatype to link with all chunks
* Purpose: Routine for single collective IO with one MPI derived datatype
* to link with all pieces (chunks + contig)
*
* 1. Sort the chunk address and chunk info
* 2. Build up MPI derived datatype for each chunk
* 3. Build up the final MPI derived datatype
* 4. Use common collective IO routine to do MPI-IO
* 1. Use the piece addresses and piece info sorted in skiplist
* 2. Build up MPI derived datatype for each chunk
* 3. Build up the final MPI derived datatype
* 4. Use common collective IO routine to do MPI-IO
*
* Return: Non-negative on success/Negative on failure
*
@@ -1316,121 +1405,100 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm,
int sum_chunk, int mpi_rank, int mpi_size)
H5D__link_piece_collective_io(H5D_io_info_t *io_info, int mpi_rank)
{
H5D_chunk_addr_info_t *chunk_addr_info_array = NULL;
MPI_Datatype chunk_final_mtype; /* Final memory MPI datatype for all chunks with selection */
hbool_t chunk_final_mtype_is_derived = FALSE;
MPI_Datatype chunk_final_ftype; /* Final file MPI datatype for all chunks with selection */
hbool_t chunk_final_ftype_is_derived = FALSE;
H5D_storage_t ctg_store; /* Storage info for "fake" contiguous dataset */
size_t total_chunks;
MPI_Datatype *chunk_mtype = NULL;
MPI_Datatype *chunk_ftype = NULL;
MPI_Aint *chunk_disp_array = NULL;
MPI_Aint *chunk_mem_disp_array = NULL;
hbool_t *chunk_mft_is_derived_array =
MPI_Datatype chunk_final_mtype; /* Final memory MPI datatype for all chunks with selection */
hbool_t chunk_final_mtype_is_derived = FALSE;
MPI_Datatype chunk_final_ftype; /* Final file MPI datatype for all chunks with selection */
hbool_t chunk_final_ftype_is_derived = FALSE;
H5D_storage_t ctg_store; /* Storage info for "fake" contiguous dataset */
MPI_Datatype *chunk_mtype = NULL;
MPI_Datatype *chunk_ftype = NULL;
MPI_Aint *chunk_file_disp_array = NULL;
MPI_Aint *chunk_mem_disp_array = NULL;
hbool_t *chunk_mft_is_derived_array =
NULL; /* Flags to indicate each chunk's MPI file datatype is derived */
hbool_t *chunk_mbt_is_derived_array =
NULL; /* Flags to indicate each chunk's MPI memory datatype is derived */
int *chunk_mpi_file_counts = NULL; /* Count of MPI file datatype for each chunk */
int *chunk_mpi_mem_counts = NULL; /* Count of MPI memory datatype for each chunk */
int mpi_code; /* MPI return code */
herr_t ret_value = SUCCEED;
NULL; /* Flags to indicate each chunk's MPI memory datatype is derived */
int *chunk_mpi_file_counts = NULL; /* Count of MPI file datatype for each chunk */
int *chunk_mpi_mem_counts = NULL; /* Count of MPI memory datatype for each chunk */
int mpi_code; /* MPI return code */
H5D_mpio_actual_chunk_opt_mode_t actual_chunk_opt_mode = H5D_MPIO_LINK_CHUNK;
H5D_mpio_actual_io_mode_t actual_io_mode = 0;
size_t i; /* Local index variable */
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
/* set actual_io_mode */
for (i = 0; i < io_info->count; i++) {
HDassert(io_info->dsets_info[i].dset->shared->dcpl_cache.pline.nused == 0);
if (io_info->dsets_info[i].layout->type == H5D_CHUNKED)
actual_io_mode |= H5D_MPIO_CHUNK_COLLECTIVE;
else if (io_info->dsets_info[i].layout->type == H5D_CONTIGUOUS) {
actual_io_mode |= H5D_MPIO_CONTIGUOUS_COLLECTIVE;
/* if only single-dset */
if (1 == io_info->count)
actual_chunk_opt_mode = H5D_MPIO_NO_CHUNK_OPTIMIZATION;
}
else
HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout")
}
/* Set the actual-chunk-opt-mode property. */
H5CX_set_mpio_actual_chunk_opt(H5D_MPIO_LINK_CHUNK);
H5CX_set_mpio_actual_chunk_opt(actual_chunk_opt_mode);
/* Set the actual-io-mode property.
* Link chunk I/O does not break to independent, so can set right away */
H5CX_set_mpio_actual_io_mode(H5D_MPIO_CHUNK_COLLECTIVE);
H5CX_set_mpio_actual_io_mode(actual_io_mode);
/* Get the sum # of chunks, if not already available */
if (sum_chunk < 0) {
if (H5D__mpio_get_sum_chunk(io_info, fm, &sum_chunk) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL,
"unable to obtain the total chunk number of all processes");
} /* end if */
/* Retrieve total # of chunks in dataset */
H5_CHECKED_ASSIGN(total_chunks, size_t, fm->layout->u.chunk.nchunks, hsize_t);
/* Handle special case when dataspace dimensions only allow one chunk in
* the dataset. [This sometimes is used by developers who want the
* equivalent of compressed contiguous datasets - QAK]
*/
if (total_chunks == 1) {
H5SL_node_t *chunk_node; /* Pointer to chunk node for selection */
H5S_t *fspace; /* Dataspace describing chunk & selection in it */
H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
/* Check for this process having selection in this chunk */
chunk_node = H5SL_first(fm->sel_chunks);
if (chunk_node == NULL) {
/* Set the dataspace info for I/O to NULL, this process doesn't have any I/O to perform */
fspace = mspace = NULL;
/* Initialize chunk address */
ctg_store.contig.dset_addr = 0;
} /* end if */
else {
H5D_chunk_ud_t udata; /* User data for querying chunk info */
H5D_chunk_info_t *chunk_info; /* Info for chunk in skiplist */
/* Get the chunk info, for the selection in the chunk */
if (NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_item(chunk_node)))
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skip list")
/* Set the dataspace info for I/O */
fspace = chunk_info->fspace;
mspace = chunk_info->mspace;
/* Look up address of chunk */
if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk address")
ctg_store.contig.dset_addr = udata.chunk_block.offset;
} /* end else */
/* Set up the base storage address for this chunk */
io_info->store = &ctg_store;
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG(mpi_rank, "before inter_collective_io for total chunk = 1");
#endif
/* Perform I/O */
if (H5D__inter_collective_io(io_info, type_info, fspace, mspace) < 0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
} /* end if */
else {
/* Code block for actual actions (Build a MPI Type, IO) */
{
hsize_t mpi_buf_count; /* Number of MPI types */
size_t num_chunk; /* Number of chunks for this process */
size_t u; /* Local index variable */
H5D_piece_info_t *piece_info;
/* local variable for base address for buffer */
H5_flexible_const_ptr_t base_buf_addr;
base_buf_addr.cvp = NULL;
/* Get the number of chunks with a selection */
num_chunk = H5SL_count(fm->sel_chunks);
num_chunk = io_info->pieces_added;
H5_CHECK_OVERFLOW(num_chunk, size_t, int);
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG_VA(mpi_rank, "total_chunks = %zu, num_chunk = %zu", total_chunks, num_chunk);
H5D_MPIO_DEBUG_VA(mpi_rank, "num_chunk = %zu\n", num_chunk);
#endif
/* Set up MPI datatype for chunks selected */
if (num_chunk) {
hbool_t need_sort = FALSE;
/* Check if sel_pieces array is sorted */
HDassert(io_info->sel_pieces[0]->faddr != HADDR_UNDEF);
for (i = 1; i < num_chunk; i++) {
HDassert(io_info->sel_pieces[i]->faddr != HADDR_UNDEF);
if (io_info->sel_pieces[i]->faddr < io_info->sel_pieces[i - 1]->faddr) {
need_sort = TRUE;
break;
}
}
/* Sort sel_pieces if necessary */
if (need_sort)
HDqsort(io_info->sel_pieces, io_info->pieces_added, sizeof(io_info->sel_pieces[0]),
H5D__cmp_piece_addr);
/* Allocate chunking information */
if (NULL == (chunk_addr_info_array =
(H5D_chunk_addr_info_t *)H5MM_malloc(num_chunk * sizeof(H5D_chunk_addr_info_t))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk array buffer")
if (NULL == (chunk_mtype = (MPI_Datatype *)H5MM_malloc(num_chunk * sizeof(MPI_Datatype))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL,
"couldn't allocate chunk memory datatype buffer")
if (NULL == (chunk_ftype = (MPI_Datatype *)H5MM_malloc(num_chunk * sizeof(MPI_Datatype))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate chunk file datatype buffer")
if (NULL == (chunk_disp_array = (MPI_Aint *)H5MM_malloc(num_chunk * sizeof(MPI_Aint))))
if (NULL == (chunk_file_disp_array = (MPI_Aint *)H5MM_malloc(num_chunk * sizeof(MPI_Aint))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL,
"couldn't allocate chunk file displacement buffer")
if (NULL == (chunk_mem_disp_array = (MPI_Aint *)H5MM_calloc(num_chunk * sizeof(MPI_Aint))))
@@ -1447,36 +1515,37 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL,
"couldn't allocate chunk file is derived datatype flags buffer")
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG(mpi_rank, "before sorting chunk addresses");
#endif
/* save lowest file address */
ctg_store.contig.dset_addr = io_info->sel_pieces[0]->faddr;
/* Sort the chunk address */
if (H5D__sort_chunk(io_info, fm, chunk_addr_info_array, sum_chunk, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to sort chunk address")
ctg_store.contig.dset_addr = chunk_addr_info_array[0].chunk_addr;
/* save base mem addr of piece for read/write */
base_buf_addr = io_info->sel_pieces[0]->dset_info->buf;
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG(mpi_rank, "after sorting chunk addresses");
H5D_MPIO_DEBUG(mpi_rank, "before iterate over selected pieces\n");
#endif
/* Obtain MPI derived datatype from all individual chunks */
for (u = 0; u < num_chunk; u++) {
/* Obtain MPI derived datatype from all individual pieces */
/* Iterate over selected pieces for this process */
for (i = 0; i < num_chunk; i++) {
hsize_t *permute_map = NULL; /* array that holds the mapping from the old,
out-of-order displacements to the in-order
displacements of the MPI datatypes of the
point selection of the file space */
hbool_t is_permuted = FALSE;
/* Assign convenience pointer to piece info */
piece_info = io_info->sel_pieces[i];
/* Obtain disk and memory MPI derived datatype */
/* NOTE: The permute_map array can be allocated within H5S_mpio_space_type
* and will be fed into the next call to H5S_mpio_space_type
* where it will be freed.
*/
if (H5S_mpio_space_type(chunk_addr_info_array[u].chunk_info.fspace, type_info->src_type_size,
&chunk_ftype[u], /* OUT: datatype created */
&chunk_mpi_file_counts[u], /* OUT */
&(chunk_mft_is_derived_array[u]), /* OUT */
if (H5S_mpio_space_type(piece_info->fspace, piece_info->dset_info->type_info.src_type_size,
&chunk_ftype[i], /* OUT: datatype created */
&chunk_mpi_file_counts[i], /* OUT */
&(chunk_mft_is_derived_array[i]), /* OUT */
TRUE, /* this is a file space,
so permute the
datatype if the point
@@ -1488,12 +1557,13 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ
are out of order */
&is_permuted /* OUT */) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI file type")
/* Sanity check */
if (is_permuted)
HDassert(permute_map);
if (H5S_mpio_space_type(chunk_addr_info_array[u].chunk_info.mspace, type_info->dst_type_size,
&chunk_mtype[u], &chunk_mpi_mem_counts[u],
&(chunk_mbt_is_derived_array[u]), FALSE, /* this is a memory
if (H5S_mpio_space_type(piece_info->mspace, piece_info->dset_info->type_info.dst_type_size,
&chunk_mtype[i], &chunk_mpi_mem_counts[i],
&(chunk_mbt_is_derived_array[i]), FALSE, /* this is a memory
space, so if the file
space is not
permuted, there is no
@@ -1512,19 +1582,27 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ
if (is_permuted)
HDassert(!permute_map);
/* Chunk address relative to the first chunk */
chunk_addr_info_array[u].chunk_addr -= ctg_store.contig.dset_addr;
/* Piece address relative to the first piece addr
* Assign piece address to MPI displacement
* (assume MPI_Aint big enough to hold it) */
chunk_file_disp_array[i] = (MPI_Aint)piece_info->faddr - (MPI_Aint)ctg_store.contig.dset_addr;
/* Assign chunk address to MPI displacement */
/* (assume MPI_Aint big enough to hold it) */
chunk_disp_array[u] = (MPI_Aint)chunk_addr_info_array[u].chunk_addr;
if (io_info->op_type == H5D_IO_OP_WRITE) {
chunk_mem_disp_array[i] =
(MPI_Aint)piece_info->dset_info->buf.cvp - (MPI_Aint)base_buf_addr.cvp;
}
else if (io_info->op_type == H5D_IO_OP_READ) {
chunk_mem_disp_array[i] =
(MPI_Aint)piece_info->dset_info->buf.vp - (MPI_Aint)base_buf_addr.vp;
}
} /* end for */
/* Create final MPI derived datatype for the file */
if (MPI_SUCCESS !=
(mpi_code = MPI_Type_create_struct((int)num_chunk, chunk_mpi_file_counts, chunk_disp_array,
chunk_ftype, &chunk_final_ftype)))
(mpi_code = MPI_Type_create_struct((int)num_chunk, chunk_mpi_file_counts,
chunk_file_disp_array, chunk_ftype, &chunk_final_ftype)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_struct failed", mpi_code)
if (MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_ftype)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
chunk_final_ftype_is_derived = TRUE;
@@ -1539,13 +1617,13 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ
chunk_final_mtype_is_derived = TRUE;
/* Free the file & memory MPI datatypes for each chunk */
for (u = 0; u < num_chunk; u++) {
if (chunk_mbt_is_derived_array[u])
if (MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_mtype + u)))
for (i = 0; i < num_chunk; i++) {
if (chunk_mbt_is_derived_array[i])
if (MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_mtype + i)))
HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
if (chunk_mft_is_derived_array[u])
if (MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_ftype + u)))
if (chunk_mft_is_derived_array[i])
if (MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_ftype + i)))
HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
} /* end for */
@@ -1555,6 +1633,9 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ
else { /* no selection at all for this process */
ctg_store.contig.dset_addr = 0;
/* just provide a valid mem address. no actual IO occur */
base_buf_addr = io_info->dsets_info[0].buf;
/* Set the MPI datatype */
chunk_final_ftype = MPI_BYTE;
chunk_final_mtype = MPI_BYTE;
@@ -1566,15 +1647,14 @@ H5D__link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *typ
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG(mpi_rank, "before coming to final collective I/O");
#endif
/* Set up the base storage address for this chunk */
io_info->store = &ctg_store;
/* Set up the base storage address for this piece */
io_info->store_faddr = ctg_store.contig.dset_addr;
io_info->base_maddr = base_buf_addr;
/* Perform final collective I/O operation */
if (H5D__final_collective_io(io_info, type_info, mpi_buf_count, chunk_final_ftype,
chunk_final_mtype) < 0)
if (H5D__final_collective_io(io_info, mpi_buf_count, chunk_final_ftype, chunk_final_mtype) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish MPI-IO")
} /* end else */
}
done:
#ifdef H5Dmpio_DEBUG
@@ -1583,14 +1663,12 @@ done:
#endif
/* Release resources */
if (chunk_addr_info_array)
H5MM_xfree(chunk_addr_info_array);
if (chunk_mtype)
H5MM_xfree(chunk_mtype);
if (chunk_ftype)
H5MM_xfree(chunk_ftype);
if (chunk_disp_array)
H5MM_xfree(chunk_disp_array);
if (chunk_file_disp_array)
H5MM_xfree(chunk_file_disp_array);
if (chunk_mem_disp_array)
H5MM_xfree(chunk_mem_disp_array);
if (chunk_mpi_mem_counts)
@@ -1609,7 +1687,7 @@ done:
HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__link_chunk_collective_io */
} /* end H5D__link_piece_collective_io */
/*-------------------------------------------------------------------------
* Function: H5D__link_chunk_filtered_collective_io
@@ -1680,29 +1758,27 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_map_t *fm, int mpi_rank, int mpi_size)
H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, int mpi_rank,
int mpi_size)
{
H5D_filtered_collective_io_info_t *chunk_list = NULL; /* The list of chunks being read/written */
H5D_filtered_collective_io_info_t *chunk_hash_table = NULL;
unsigned char **chunk_msg_bufs = NULL;
H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
MPI_Datatype mem_type = MPI_BYTE;
MPI_Datatype file_type = MPI_BYTE;
hbool_t mem_type_is_derived = FALSE;
H5D_filtered_collective_io_info_t *chunk_list = NULL; /* The list of chunks being read/written */
H5D_filtered_collective_io_info_t *chunk_hash_table = NULL;
unsigned char **chunk_msg_bufs = NULL;
MPI_Datatype mem_type = MPI_BYTE;
MPI_Datatype file_type = MPI_BYTE;
hbool_t mem_type_is_derived = FALSE;
hbool_t file_type_is_derived = FALSE;
size_t *rank_chunks_assigned_map = NULL;
size_t chunk_list_num_entries;
size_t i;
int chunk_msg_bufs_len = 0;
int mpi_code;
herr_t ret_value = SUCCEED;
char fake_buf; /* Used as a fake buffer for ranks with no chunks, thus a NULL buf pointer */
int mpi_code;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
FUNC_ENTER_PACKAGE_TAG(dset_info->dset->oloc.addr)
HDassert(io_info);
HDassert(type_info);
HDassert(fm);
#ifdef H5Dmpio_DEBUG
H5D_MPIO_TRACE_ENTER(mpi_rank);
@@ -1720,12 +1796,12 @@ H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_in
H5CX_set_mpio_actual_io_mode(H5D_MPIO_CHUNK_COLLECTIVE);
/* Build a list of selected chunks in the collective io operation */
if (H5D__mpio_collective_filtered_chunk_io_setup(io_info, type_info, fm, &chunk_list,
&chunk_list_num_entries, mpi_rank) < 0)
if (H5D__mpio_collective_filtered_chunk_io_setup(io_info, dset_info, &chunk_list, &chunk_list_num_entries,
mpi_rank) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't construct filtered I/O info list")
if (io_info->op_type == H5D_IO_OP_READ) { /* Filtered collective read */
if (H5D__mpio_collective_filtered_chunk_read(chunk_list, chunk_list_num_entries, io_info, type_info,
if (H5D__mpio_collective_filtered_chunk_read(chunk_list, chunk_list_num_entries, io_info, dset_info,
mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't read filtered chunks")
}
@@ -1733,17 +1809,17 @@ H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_in
H5D_chk_idx_info_t index_info;
hsize_t mpi_buf_count;
H5D_MPIO_INIT_CHUNK_IDX_INFO(index_info, io_info);
H5D_MPIO_INIT_CHUNK_IDX_INFO(index_info, dset_info->dset);
if (mpi_size > 1) {
/* Redistribute shared chunks being written to */
if (H5D__mpio_redistribute_shared_chunks(chunk_list, chunk_list_num_entries, io_info, fm,
mpi_rank, mpi_size, &rank_chunks_assigned_map) < 0)
if (H5D__mpio_redistribute_shared_chunks(chunk_list, chunk_list_num_entries, io_info, mpi_rank,
mpi_size, &rank_chunks_assigned_map) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to redistribute shared chunks")
/* Send any chunk modification messages for chunks this rank no longer owns */
if (H5D__mpio_share_chunk_modification_data(chunk_list, &chunk_list_num_entries, io_info,
type_info, mpi_rank, mpi_size, &chunk_hash_table,
dset_info, mpi_rank, mpi_size, &chunk_hash_table,
&chunk_msg_bufs, &chunk_msg_bufs_len) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL,
"unable to send chunk modification data between MPI ranks")
@@ -1758,7 +1834,7 @@ H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_in
* must participate.
*/
if (H5D__mpio_collective_filtered_chunk_update(chunk_list, chunk_list_num_entries, chunk_hash_table,
chunk_msg_bufs, chunk_msg_bufs_len, io_info, type_info,
chunk_msg_bufs, chunk_msg_bufs_len, io_info, dset_info,
mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't update modified chunks")
@@ -1790,20 +1866,21 @@ H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_in
* Override the write buffer to point to the first
* chunk's data buffer
*/
io_info->u.wbuf = chunk_list[0].buf;
io_info->base_maddr.cvp = chunk_list[0].buf;
/*
* Setup the base storage address for this operation
* to be the first chunk's file address
*/
ctg_store.contig.dset_addr = chunk_list[0].chunk_new.offset;
io_info->store_faddr = chunk_list[0].chunk_new.offset;
}
else {
io_info->base_maddr.cvp = &fake_buf;
io_info->store_faddr = 0;
}
else
ctg_store.contig.dset_addr = 0;
/* Perform I/O */
io_info->store = &ctg_store;
if (H5D__final_collective_io(io_info, type_info, mpi_buf_count, file_type, mem_type) < 0)
if (H5D__final_collective_io(io_info, mpi_buf_count, file_type, mem_type) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish MPI-IO")
/* Free up resources in anticipation of following collective operation */
@@ -1818,8 +1895,8 @@ H5D__link_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_in
* into the chunk index
*/
if (H5D__mpio_collective_filtered_chunk_reinsert(chunk_list, chunk_list_num_entries,
rank_chunks_assigned_map, io_info, &index_info,
mpi_rank, mpi_size) < 0)
rank_chunks_assigned_map, io_info, dset_info,
&index_info, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL,
"couldn't collectively re-insert modified chunks into chunk index")
}
@@ -1857,7 +1934,7 @@ done:
H5D_MPIO_TRACE_EXIT(mpi_rank);
#endif
FUNC_LEAVE_NOAPI(ret_value)
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5D__link_chunk_filtered_collective_io() */
/*-------------------------------------------------------------------------
@@ -1878,33 +1955,39 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5D_chunk_map_t *fm,
int mpi_rank, int mpi_size)
H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, int mpi_rank,
int mpi_size)
{
H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
H5D_io_info_t cpt_io_info; /* Compact I/O info object */
H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
uint8_t *chunk_io_option = NULL;
haddr_t *chunk_addr = NULL;
H5D_storage_t store; /* union of EFL and chunk pointer in file space */
H5FD_mpio_collective_opt_t last_coll_opt_mode =
H5FD_MPIO_COLLECTIVE_IO; /* Last parallel transfer with independent IO or collective IO with this mode
*/
H5FD_mpio_collective_opt_t orig_coll_opt_mode =
H5FD_MPIO_COLLECTIVE_IO; /* Original parallel transfer property on entering this function */
size_t total_chunk; /* Total # of chunks in dataset */
size_t u; /* Local index variable */
size_t num_chunk; /* Number of chunks for this process */
H5SL_node_t *piece_node = NULL; /* Current node in chunk skip list */
H5D_piece_info_t *next_chunk_info = NULL; /* Chunk info for next selected chunk */
size_t u; /* Local index variable */
H5D_mpio_actual_io_mode_t actual_io_mode =
H5D_MPIO_NO_COLLECTIVE; /* Local variable for tracking the I/O mode used. */
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
FUNC_ENTER_PACKAGE_TAG(dset_info->dset->oloc.addr)
HDassert(dset_info->layout->type == H5D_CHUNKED);
/* Get the current I/O collective opt mode so we can restore it later */
if (H5CX_get_mpio_coll_opt(&orig_coll_opt_mode) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O collective_op property")
/* Set the actual chunk opt mode property */
H5CX_set_mpio_actual_chunk_opt(H5D_MPIO_MULTI_CHUNK);
/* Retrieve total # of chunks in dataset */
H5_CHECKED_ASSIGN(total_chunk, size_t, fm->layout->u.chunk.nchunks, hsize_t);
H5_CHECKED_ASSIGN(total_chunk, size_t, dset_info->layout->u.chunk.nchunks, hsize_t);
HDassert(total_chunk != 0);
/* Allocate memories */
@@ -1916,47 +1999,62 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty
#endif
/* Obtain IO option for each chunk */
if (H5D__obtain_mpio_mode(io_info, fm, chunk_io_option, chunk_addr, mpi_rank, mpi_size) < 0)
if (H5D__obtain_mpio_mode(io_info, dset_info, chunk_io_option, chunk_addr, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTRECV, FAIL, "unable to obtain MPIO mode")
/* Set up contiguous I/O info object */
H5MM_memcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
ctg_io_info.store = &ctg_store;
ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
/* Initialize temporary contiguous storage info */
ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
/* Set up compact I/O info object */
H5MM_memcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
cpt_io_info.store = &cpt_store;
cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
/* Initialize temporary compact storage info */
cpt_store.compact.dirty = &cpt_dirty;
/* Set memory buffers */
io_info->base_maddr = dset_info->buf;
/* Set dataset storage for I/O info */
io_info->store = &store;
dset_info->store = &store;
/* Get the number of chunks with a selection */
num_chunk = H5SL_count(dset_info->layout_io_info.chunk_map->dset_sel_pieces);
if (num_chunk) {
/* Start at the beginning of the chunk map skiplist. Since these chunks are
* stored in index order and since we're iterating in index order we can
* just check for each chunk being selected in order */
if (NULL == (piece_node = H5SL_first(dset_info->layout_io_info.chunk_map->dset_sel_pieces)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't get piece node from skip list")
if (NULL == (next_chunk_info = (H5D_piece_info_t *)H5SL_item(piece_node)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't get piece info from skip list")
}
/* Loop over _all_ the chunks */
for (u = 0; u < total_chunk; u++) {
H5D_chunk_info_t *chunk_info; /* Chunk info for current chunk */
H5D_piece_info_t *chunk_info; /* Chunk info for current chunk */
H5S_t *fspace; /* Dataspace describing chunk & selection in it */
H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG_VA(mpi_rank, "mpi_rank = %d, chunk index = %zu", mpi_rank, u);
#endif
/* Get the chunk info for this chunk, if there are elements selected */
chunk_info = fm->select_chunk[u];
/* Set the storage information for chunks with selections */
if (chunk_info) {
HDassert(chunk_info->index == u);
/* Check if this chunk is the next chunk in the skip list, if there are
* selected chunks left to process */
HDassert(!num_chunk || next_chunk_info);
HDassert(!num_chunk || next_chunk_info->index >= u);
if (num_chunk && next_chunk_info->index == u) {
/* Next chunk is this chunk */
chunk_info = next_chunk_info;
/* One less chunk to process */
num_chunk--;
/* Advance next chunk to next node in skip list, if there are more chunks selected */
if (num_chunk) {
if (NULL == (piece_node = H5SL_next(piece_node)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk skip list terminated early")
if (NULL == (next_chunk_info = (H5D_piece_info_t *)H5SL_item(piece_node)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't get piece info from skip list")
}
/* Pass in chunk's coordinates in a union. */
store.chunk.scaled = chunk_info->scaled;
} /* end if */
}
else
chunk_info = NULL;
/* Collective IO for this chunk,
* Note: even there is no selection for this process, the process still
@@ -1994,10 +2092,10 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty
} /* end if */
/* Initialize temporary contiguous storage address */
ctg_store.contig.dset_addr = chunk_addr[u];
io_info->store_faddr = chunk_addr[u];
/* Perform the I/O */
if (H5D__inter_collective_io(&ctg_io_info, type_info, fspace, mspace) < 0)
if (H5D__inter_collective_io(io_info, dset_info, fspace, mspace) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
} /* end if */
else { /* possible independent IO for this chunk */
@@ -2028,10 +2126,10 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty
} /* end if */
/* Initialize temporary contiguous storage address */
ctg_store.contig.dset_addr = chunk_addr[u];
io_info->store_faddr = chunk_addr[u];
/* Perform the I/O */
if (H5D__inter_collective_io(&ctg_io_info, type_info, fspace, mspace) < 0)
if (H5D__inter_collective_io(io_info, dset_info, fspace, mspace) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG(mpi_rank, "after inter collective IO");
@@ -2043,12 +2141,17 @@ H5D__multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *ty
H5CX_set_mpio_actual_io_mode(actual_io_mode);
done:
/* Reset collective opt mode */
if (H5CX_set_mpio_coll_opt(orig_coll_opt_mode) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't reset MPI-I/O collective_op property")
/* Free memory */
if (chunk_io_option)
H5MM_xfree(chunk_io_option);
if (chunk_addr)
H5MM_xfree(chunk_addr);
FUNC_LEAVE_NOAPI(ret_value)
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5D__multi_chunk_collective_io */
/*-------------------------------------------------------------------------
@@ -2130,14 +2233,13 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5D_chunk_map_t *fm, int mpi_rank, int mpi_size)
H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, int mpi_rank,
int mpi_size)
{
H5D_filtered_collective_io_info_t *chunk_list = NULL; /* The list of chunks being read/written */
H5D_filtered_collective_io_info_t *chunk_hash_table = NULL;
unsigned char **chunk_msg_bufs = NULL;
H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
MPI_Datatype mem_type = MPI_BYTE;
MPI_Datatype file_type = MPI_BYTE;
hbool_t mem_type_is_derived = FALSE;
@@ -2150,11 +2252,9 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
int mpi_code;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
FUNC_ENTER_PACKAGE_TAG(dset_info->dset->oloc.addr)
HDassert(io_info);
HDassert(type_info);
HDassert(fm);
#ifdef H5Dmpio_DEBUG
H5D_MPIO_TRACE_ENTER(mpi_rank);
@@ -2172,8 +2272,8 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
H5CX_set_mpio_actual_io_mode(H5D_MPIO_CHUNK_COLLECTIVE);
/* Build a list of selected chunks in the collective IO operation */
if (H5D__mpio_collective_filtered_chunk_io_setup(io_info, type_info, fm, &chunk_list,
&chunk_list_num_entries, mpi_rank) < 0)
if (H5D__mpio_collective_filtered_chunk_io_setup(io_info, dset_info, &chunk_list, &chunk_list_num_entries,
mpi_rank) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't construct filtered I/O info list")
/* Retrieve the maximum number of chunks selected for any rank */
@@ -2187,11 +2287,6 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
/* Set up contiguous I/O info object */
H5MM_memcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
ctg_io_info.store = &ctg_store;
ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
/* Initialize temporary contiguous storage info */
ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
if (io_info->op_type == H5D_IO_OP_READ) { /* Filtered collective read */
for (i = 0; i < max_num_chunks; i++) {
@@ -2199,7 +2294,7 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
have_chunk_to_process = (i < chunk_list_num_entries);
if (H5D__mpio_collective_filtered_chunk_read(have_chunk_to_process ? &chunk_list[i] : NULL,
have_chunk_to_process ? 1 : 0, io_info, type_info,
have_chunk_to_process ? 1 : 0, io_info, dset_info,
mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't read filtered chunks")
@@ -2214,17 +2309,17 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
hsize_t mpi_buf_count;
/* Construct chunked index info */
H5D_MPIO_INIT_CHUNK_IDX_INFO(index_info, io_info);
H5D_MPIO_INIT_CHUNK_IDX_INFO(index_info, dset_info->dset);
if (mpi_size > 1) {
/* Redistribute shared chunks being written to */
if (H5D__mpio_redistribute_shared_chunks(chunk_list, chunk_list_num_entries, io_info, fm,
mpi_rank, mpi_size, NULL) < 0)
if (H5D__mpio_redistribute_shared_chunks(chunk_list, chunk_list_num_entries, io_info, mpi_rank,
mpi_size, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to redistribute shared chunks")
/* Send any chunk modification messages for chunks this rank no longer owns */
if (H5D__mpio_share_chunk_modification_data(chunk_list, &chunk_list_num_entries, io_info,
type_info, mpi_rank, mpi_size, &chunk_hash_table,
dset_info, mpi_rank, mpi_size, &chunk_hash_table,
&chunk_msg_bufs, &chunk_msg_bufs_len) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL,
"unable to send chunk modification data between MPI ranks")
@@ -2246,7 +2341,7 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
if (H5D__mpio_collective_filtered_chunk_update(have_chunk_to_process ? &chunk_list[i] : NULL,
have_chunk_to_process ? 1 : 0, chunk_hash_table,
chunk_msg_bufs, chunk_msg_bufs_len, io_info,
type_info, mpi_rank, mpi_size) < 0)
dset_info, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't update modified chunks")
/* All ranks now collectively re-allocate file space for all chunks */
@@ -2276,19 +2371,21 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
* Override the write buffer to point to the
* chunk's data buffer
*/
ctg_io_info.u.wbuf = chunk_list[i].buf;
ctg_io_info.base_maddr.cvp = chunk_list[i].buf;
/*
* Setup the base storage address for this
* operation to be the chunk's file address
*/
ctg_store.contig.dset_addr = chunk_list[i].chunk_new.offset;
ctg_io_info.store_faddr = chunk_list[i].chunk_new.offset;
}
else {
ctg_io_info.store_faddr = 0;
ctg_io_info.base_maddr = dset_info->buf;
}
else
ctg_store.contig.dset_addr = 0;
/* Perform the I/O */
if (H5D__final_collective_io(&ctg_io_info, type_info, mpi_buf_count, file_type, mem_type) < 0)
if (H5D__final_collective_io(&ctg_io_info, mpi_buf_count, file_type, mem_type) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish MPI-IO")
/* Free up resources in anticipation of following collective operation */
@@ -2302,7 +2399,7 @@ H5D__multi_chunk_filtered_collective_io(H5D_io_info_t *io_info, const H5D_type_i
*/
if (H5D__mpio_collective_filtered_chunk_reinsert(have_chunk_to_process ? &chunk_list[i] : NULL,
have_chunk_to_process ? 1 : 0, NULL, io_info,
&index_info, mpi_rank, mpi_size) < 0)
dset_info, &index_info, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL,
"couldn't collectively re-insert modified chunks into chunk index")
@@ -2346,7 +2443,7 @@ done:
H5D_MPIO_TRACE_EXIT(mpi_rank);
#endif
FUNC_LEAVE_NOAPI(ret_value)
FUNC_LEAVE_NOAPI_TAG(ret_value)
} /* end H5D__multi_chunk_filtered_collective_io() */
/*-------------------------------------------------------------------------
@@ -2363,7 +2460,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5S_t *file_space,
H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_dset_io_info_t *di, H5S_t *file_space,
H5S_t *mem_space)
{
int mpi_buf_count; /* # of MPI types */
@@ -2379,13 +2476,15 @@ H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
FUNC_ENTER_PACKAGE
#ifdef H5Dmpio_DEBUG
mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file);
mpi_rank = H5F_mpi_get_rank(di->dset->oloc.file);
H5D_MPIO_TRACE_ENTER(mpi_rank);
H5D_MPIO_TIME_START(mpi_rank, "Inter collective I/O");
if (mpi_rank < 0)
HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain MPI rank")
#endif
HDassert(io_info);
if ((file_space != NULL) && (mem_space != NULL)) {
int mpi_file_count; /* Number of file "objects" to transfer */
hsize_t *permute_map = NULL; /* array that holds the mapping from the old,
@@ -2394,12 +2493,14 @@ H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
point selection of the file space */
hbool_t is_permuted = FALSE;
HDassert(di);
/* Obtain disk and memory MPI derived datatype */
/* NOTE: The permute_map array can be allocated within H5S_mpio_space_type
* and will be fed into the next call to H5S_mpio_space_type
* where it will be freed.
*/
if (H5S_mpio_space_type(file_space, type_info->src_type_size, &mpi_file_type, &mpi_file_count,
if (H5S_mpio_space_type(file_space, di->type_info.src_type_size, &mpi_file_type, &mpi_file_count,
&mft_is_derived, /* OUT: datatype created */
TRUE, /* this is a file space, so
permute the datatype if the
@@ -2415,7 +2516,7 @@ H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
/* Sanity check */
if (is_permuted)
HDassert(permute_map);
if (H5S_mpio_space_type(mem_space, type_info->src_type_size, &mpi_buf_type, &mpi_buf_count,
if (H5S_mpio_space_type(mem_space, di->type_info.src_type_size, &mpi_buf_type, &mpi_buf_count,
&mbt_is_derived, /* OUT: datatype created */
FALSE, /* this is a memory space, so if
the file space is not
@@ -2449,7 +2550,7 @@ H5D__inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
#endif
/* Perform final collective I/O operation */
if (H5D__final_collective_io(io_info, type_info, (hsize_t)mpi_buf_count, mpi_file_type, mpi_buf_type) < 0)
if (H5D__final_collective_io(io_info, (hsize_t)mpi_buf_count, mpi_file_type, mpi_buf_type) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish collective MPI-IO")
done:
@@ -2481,8 +2582,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t mpi_buf_count,
MPI_Datatype mpi_file_type, MPI_Datatype mpi_buf_type)
H5D__final_collective_io(H5D_io_info_t *io_info, hsize_t mpi_buf_count, MPI_Datatype mpi_file_type,
MPI_Datatype mpi_buf_type)
{
#ifdef H5Dmpio_DEBUG
int mpi_rank;
@@ -2492,7 +2593,7 @@ H5D__final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
FUNC_ENTER_PACKAGE
#ifdef H5Dmpio_DEBUG
mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file);
mpi_rank = H5F_mpi_get_rank(io_info->dsets_info[0].dset->oloc.file);
H5D_MPIO_TRACE_ENTER(mpi_rank);
H5D_MPIO_TIME_START(mpi_rank, "Final collective I/O");
if (mpi_rank < 0)
@@ -2504,11 +2605,11 @@ H5D__final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set MPI-I/O collective I/O datatypes")
if (io_info->op_type == H5D_IO_OP_WRITE) {
if ((io_info->io_ops.single_write)(io_info, type_info, mpi_buf_count, NULL, NULL) < 0)
if ((io_info->md_io_ops.single_write_md)(io_info, mpi_buf_count, NULL, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
} /* end if */
else {
if ((io_info->io_ops.single_read)(io_info, type_info, mpi_buf_count, NULL, NULL) < 0)
if ((io_info->md_io_ops.single_read_md)(io_info, mpi_buf_count, NULL, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
} /* end else */
@@ -2523,28 +2624,26 @@ done:
} /* end H5D__final_collective_io */
/*-------------------------------------------------------------------------
* Function: H5D__cmp_chunk_addr
* Function: H5D__cmp_piece_addr
*
* Purpose: Routine to compare chunk addresses
* Purpose: Routine to compare piece addresses
*
* Description: Callback for qsort() to compare chunk addresses
* Description: Callback for qsort() to compare piece addresses
*
* Return: -1, 0, 1
*
* Programmer: Muqun Yang
* Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static int
H5D__cmp_chunk_addr(const void *chunk_addr_info1, const void *chunk_addr_info2)
H5D__cmp_piece_addr(const void *piece_info1, const void *piece_info2)
{
haddr_t addr1 = HADDR_UNDEF, addr2 = HADDR_UNDEF;
haddr_t addr1;
haddr_t addr2;
FUNC_ENTER_PACKAGE_NOERR
addr1 = ((const H5D_chunk_addr_info_t *)chunk_addr_info1)->chunk_addr;
addr2 = ((const H5D_chunk_addr_info_t *)chunk_addr_info2)->chunk_addr;
addr1 = (*((const H5D_piece_info_t *const *)piece_info1))->faddr;
addr2 = (*((const H5D_piece_info_t *const *)piece_info2))->faddr;
FUNC_LEAVE_NOAPI(H5F_addr_cmp(addr1, addr2))
} /* end H5D__cmp_chunk_addr() */
@@ -2704,178 +2803,6 @@ H5D__cmp_chunk_redistribute_info_orig_owner(const void *_entry1, const void *_en
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__cmp_chunk_redistribute_info_orig_owner() */
/*-------------------------------------------------------------------------
* Function: H5D__sort_chunk
*
* Purpose: Routine to sort chunks in increasing order of chunk address
* Each chunk address is also obtained.
*
* Description:
* For most cases, the chunk address has already been sorted in increasing order.
* The special sorting flag is used to optimize this common case.
* quick sort is used for necessary sorting.
*
* Parameters:
* Input: H5D_io_info_t* io_info,
* H5D_chunk_map_t *fm(global chunk map struct)
* Input/Output: H5D_chunk_addr_info_t chunk_addr_info_array[] : array to store chunk address
*and information many_chunk_opt : flag to optimize the way to obtain chunk addresses
* for many chunks
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Muqun Yang
* Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
H5D_chunk_addr_info_t chunk_addr_info_array[], int sum_chunk, int mpi_rank, int mpi_size)
{
H5SL_node_t *chunk_node; /* Current node in chunk skip list */
H5D_chunk_info_t *chunk_info; /* Current chunking info. of this node. */
haddr_t chunk_addr; /* Current chunking address of this node */
haddr_t *total_chunk_addr_array = NULL; /* The array of chunk address for the total number of chunk */
H5P_coll_md_read_flag_t md_reads_file_flag;
hbool_t md_reads_context_flag;
hbool_t restore_md_reads_state = FALSE;
hbool_t do_sort = FALSE; /* Whether the addresses need to be sorted */
int bsearch_coll_chunk_threshold;
int many_chunk_opt = H5D_OBTAIN_ONE_CHUNK_ADDR_IND;
int mpi_code; /* MPI return code */
int i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Calculate the actual threshold to obtain all chunk addresses collectively
* The bigger this number is, the more possible the use of obtaining chunk
* address collectively.
*/
/* For non-optimization one-link IO, actual bsearch threshold is always
* 0, we would always want to obtain the chunk addresses individually
* for each process.
*/
bsearch_coll_chunk_threshold = (sum_chunk * 100) / ((int)fm->layout->u.chunk.nchunks * mpi_size);
if ((bsearch_coll_chunk_threshold > H5D_ALL_CHUNK_ADDR_THRES_COL) &&
((sum_chunk / mpi_size) >= H5D_ALL_CHUNK_ADDR_THRES_COL_NUM))
many_chunk_opt = H5D_OBTAIN_ALL_CHUNK_ADDR_COL;
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG_VA(mpi_rank, "many_chunk_opt = %d", many_chunk_opt);
#endif
/* If we need to optimize the way to obtain the chunk address */
if (many_chunk_opt != H5D_OBTAIN_ONE_CHUNK_ADDR_IND) {
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG(mpi_rank, "Coming inside H5D_OBTAIN_ALL_CHUNK_ADDR_COL");
#endif
/* Allocate array for chunk addresses */
if (NULL == (total_chunk_addr_array =
(haddr_t *)H5MM_malloc(sizeof(haddr_t) * (size_t)fm->layout->u.chunk.nchunks)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory chunk address array")
if (mpi_rank == 0) {
herr_t result;
/*
* If enabled, disable collective metadata reads here.
* Since the chunk address mapping is done on rank 0
* only here, it will cause problems if collective
* metadata reads are enabled.
*/
if (H5F_get_coll_metadata_reads(io_info->dset->oloc.file)) {
md_reads_file_flag = H5P_FORCE_FALSE;
md_reads_context_flag = FALSE;
H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag,
&md_reads_context_flag);
restore_md_reads_state = TRUE;
}
result = H5D__chunk_addrmap(io_info, total_chunk_addr_array);
/* Ensure that we restore the old collective metadata reads state */
if (restore_md_reads_state) {
H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag,
&md_reads_context_flag);
restore_md_reads_state = FALSE;
}
if (result < 0) {
size_t u;
/* Clear total chunk address array */
for (u = 0; u < (size_t)fm->layout->u.chunk.nchunks; u++)
total_chunk_addr_array[u] = HADDR_UNDEF;
/* Push error, but still participate in following MPI_Bcast */
HDONE_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
}
} /* end if */
/* Broadcasting the MPI_IO option info. and chunk address info. */
if (MPI_SUCCESS != (mpi_code = MPI_Bcast(total_chunk_addr_array,
(int)(sizeof(haddr_t) * fm->layout->u.chunk.nchunks),
MPI_BYTE, (int)0, io_info->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code)
} /* end if */
/* Start at first node in chunk skip list */
i = 0;
if (NULL == (chunk_node = H5SL_first(fm->sel_chunks)))
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk node from skipped list")
/* Iterate over all chunks for this process */
while (chunk_node) {
if (NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_item(chunk_node)))
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
if (many_chunk_opt == H5D_OBTAIN_ONE_CHUNK_ADDR_IND) {
H5D_chunk_ud_t udata; /* User data for querying chunk info */
/* Get address of chunk */
if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
chunk_addr = udata.chunk_block.offset;
} /* end if */
else
chunk_addr = total_chunk_addr_array[chunk_info->index];
/* Check if chunk addresses are not in increasing order in the file */
if (i > 0 && chunk_addr < chunk_addr_info_array[i - 1].chunk_addr)
do_sort = TRUE;
/* Set the address & info for this chunk */
chunk_addr_info_array[i].chunk_addr = chunk_addr;
chunk_addr_info_array[i].chunk_info = *chunk_info;
/* Advance to next chunk in list */
i++;
chunk_node = H5SL_next(chunk_node);
} /* end while */
#ifdef H5Dmpio_DEBUG
H5D_MPIO_DEBUG(mpi_rank, "before Qsort");
#endif
if (do_sort) {
size_t num_chunks = H5SL_count(fm->sel_chunks);
HDqsort(chunk_addr_info_array, num_chunks, sizeof(chunk_addr_info_array[0]), H5D__cmp_chunk_addr);
} /* end if */
done:
/* Re-enable collective metadata reads if we disabled them */
if (restore_md_reads_state)
H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag, &md_reads_context_flag);
if (total_chunk_addr_array)
H5MM_xfree(total_chunk_addr_array);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__sort_chunk() */
/*-------------------------------------------------------------------------
* Function: H5D__obtain_mpio_mode
*
@@ -2902,7 +2829,7 @@ done:
* Parameters:
*
* Input: H5D_io_info_t* io_info,
* H5D_chunk_map_t *fm,(global chunk map struct)
* H5D_dset_io_info_t *di,(dataset info struct)
* Output: uint8_t assign_io_mode[], : IO mode, collective, independent or none
* haddr_t chunk_addr[], : chunk address array for each chunk
*
@@ -2914,7 +2841,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assign_io_mode[],
H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_dset_io_info_t *di, uint8_t assign_io_mode[],
haddr_t chunk_addr[], int mpi_rank, int mpi_size)
{
size_t total_chunks;
@@ -2924,7 +2851,7 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assig
uint8_t *mergebuf = NULL;
uint8_t *tempbuf;
H5SL_node_t *chunk_node;
H5D_chunk_info_t *chunk_info;
H5D_piece_info_t *chunk_info;
H5P_coll_md_read_flag_t md_reads_file_flag;
hbool_t md_reads_context_flag;
hbool_t restore_md_reads_state = FALSE;
@@ -2936,17 +2863,19 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assig
FUNC_ENTER_PACKAGE
HDassert(di->layout->type == H5D_CHUNKED);
/* Assign the rank 0 to the root */
root = 0;
comm = io_info->comm;
/* Setup parameters */
H5_CHECKED_ASSIGN(total_chunks, size_t, fm->layout->u.chunk.nchunks, hsize_t);
H5_CHECKED_ASSIGN(total_chunks, size_t, di->layout->u.chunk.nchunks, hsize_t);
if (H5CX_get_mpio_chunk_opt_ratio(&percent_nproc_per_chunk) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't get percent nproc per chunk")
/* if ratio is 0, perform collective io */
if (0 == percent_nproc_per_chunk) {
if (H5D__chunk_addrmap(io_info, chunk_addr) < 0)
if (H5D__chunk_addrmap(di->dset, chunk_addr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
for (ic = 0; ic < total_chunks; ic++)
assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
@@ -2967,9 +2896,9 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assig
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate recv I/O mode info buffer")
/* Obtain the regularity and selection information for all chunks in this process. */
chunk_node = H5SL_first(fm->sel_chunks);
chunk_node = H5SL_first(di->layout_io_info.chunk_map->dset_sel_pieces);
while (chunk_node) {
chunk_info = (H5D_chunk_info_t *)H5SL_item(chunk_node);
chunk_info = (H5D_piece_info_t *)H5SL_item(chunk_node);
io_mode_info[chunk_info->index] = H5D_CHUNK_SELECT_REG; /* this chunk is selected and is "regular" */
chunk_node = H5SL_next(chunk_node);
@@ -2992,11 +2921,10 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assig
* only here, it will cause problems if collective
* metadata reads are enabled.
*/
if (H5F_get_coll_metadata_reads(io_info->dset->oloc.file)) {
if (H5F_get_coll_metadata_reads(di->dset->oloc.file)) {
md_reads_file_flag = H5P_FORCE_FALSE;
md_reads_context_flag = FALSE;
H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag,
&md_reads_context_flag);
H5F_set_coll_metadata_reads(di->dset->oloc.file, &md_reads_file_flag, &md_reads_context_flag);
restore_md_reads_state = TRUE;
}
@@ -3006,7 +2934,7 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assig
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate nproc_per_chunk buffer")
/* calculating the chunk address */
if (H5D__chunk_addrmap(io_info, chunk_addr) < 0) {
if (H5D__chunk_addrmap(di->dset, chunk_addr) < 0) {
H5MM_free(nproc_per_chunk);
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
} /* end if */
@@ -3068,7 +2996,7 @@ H5D__obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm, uint8_t assig
done:
/* Re-enable collective metadata reads if we disabled them */
if (restore_md_reads_state)
H5F_set_coll_metadata_reads(io_info->dset->oloc.file, &md_reads_file_flag, &md_reads_context_flag);
H5F_set_coll_metadata_reads(di->dset->oloc.file, &md_reads_file_flag, &md_reads_context_flag);
if (io_mode_info)
H5MM_free(io_mode_info);
@@ -3098,8 +3026,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
const H5D_chunk_map_t *fm,
H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *di,
H5D_filtered_collective_io_info_t **chunk_list,
size_t *num_entries, int mpi_rank)
{
@@ -3113,36 +3040,36 @@ H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const
FUNC_ENTER_PACKAGE
HDassert(io_info);
HDassert(type_info);
HDassert(fm);
HDassert(di);
HDassert(chunk_list);
HDassert(num_entries);
#ifdef H5Dmpio_DEBUG
H5D_MPIO_TRACE_ENTER(mpi_rank);
H5D_MPIO_TIME_START(mpi_rank, "Filtered Collective I/O Setup");
#endif
HDassert(di->layout->type == H5D_CHUNKED);
/* Each rank builds a local list of the chunks they have selected */
if ((num_chunks_selected = H5SL_count(fm->sel_chunks))) {
H5D_chunk_info_t *chunk_info;
if ((num_chunks_selected = H5SL_count(di->layout_io_info.chunk_map->dset_sel_pieces))) {
H5D_piece_info_t *chunk_info;
H5SL_node_t *chunk_node;
hsize_t select_npoints;
hbool_t need_sort = FALSE;
/* Determine whether partial edge chunks should be filtered */
filter_partial_edge_chunks = !(io_info->dset->shared->layout.u.chunk.flags &
H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS);
filter_partial_edge_chunks =
!(di->dset->shared->layout.u.chunk.flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS);
if (NULL == (local_info_array = H5MM_malloc(num_chunks_selected * sizeof(*local_info_array))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate local io info array buffer")
chunk_node = H5SL_first(fm->sel_chunks);
chunk_node = H5SL_first(di->layout_io_info.chunk_map->dset_sel_pieces);
for (i = 0; chunk_node; i++) {
chunk_info = (H5D_chunk_info_t *)H5SL_item(chunk_node);
chunk_info = (H5D_piece_info_t *)H5SL_item(chunk_node);
/* Obtain this chunk's address */
if (H5D__chunk_lookup(io_info->dset, chunk_info->scaled, &udata) < 0)
if (H5D__chunk_lookup(di->dset, chunk_info->scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
/* Initialize rank-local chunk info */
@@ -3154,7 +3081,7 @@ H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const
local_info_array[i].buf = NULL;
select_npoints = H5S_GET_SELECT_NPOINTS(chunk_info->fspace);
local_info_array[i].io_size = (size_t)select_npoints * type_info->dst_type_size;
local_info_array[i].io_size = (size_t)select_npoints * di->type_info.dst_type_size;
/*
* Determine whether this chunk will need to be read from the file. If this is
@@ -3204,7 +3131,7 @@ H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const
local_info_array[i].need_read = TRUE;
else {
local_info_array[i].need_read =
local_info_array[i].io_size < (size_t)io_info->dset->shared->layout.u.chunk.size;
local_info_array[i].io_size < (size_t)di->dset->shared->layout.u.chunk.size;
}
local_info_array[i].skip_filter_pline = FALSE;
@@ -3213,9 +3140,9 @@ H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const
* If this is a partial edge chunk and the "don't filter partial edge
* chunks" flag is set, make sure not to apply filters to the chunk.
*/
if (H5D__chunk_is_partial_edge_chunk(io_info->dset->shared->ndims,
io_info->dset->shared->layout.u.chunk.dim,
chunk_info->scaled, io_info->dset->shared->curr_dims))
if (H5D__chunk_is_partial_edge_chunk(di->dset->shared->ndims,
di->dset->shared->layout.u.chunk.dim, chunk_info->scaled,
di->dset->shared->curr_dims))
local_info_array[i].skip_filter_pline = TRUE;
}
@@ -3244,7 +3171,7 @@ H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const
* extensible array code calculated instead of what was calculated
* in the chunk file mapping.
*/
if (io_info->dset->shared->layout.u.chunk.idx_type == H5D_CHUNK_IDX_EARRAY)
if (di->dset->shared->layout.u.chunk.idx_type == H5D_CHUNK_IDX_EARRAY)
local_info_array[i].index_info.chunk_idx = udata.chunk_idx;
else
local_info_array[i].index_info.chunk_idx = chunk_info->index;
@@ -3264,7 +3191,7 @@ H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const
H5D__mpio_dump_collective_filtered_chunk_list(local_info_array, num_chunks_selected, mpi_rank);
#endif
}
else if (H5F_get_coll_metadata_reads(io_info->dset->oloc.file)) {
else if (H5F_get_coll_metadata_reads(di->dset->oloc.file)) {
hsize_t scaled[H5O_LAYOUT_NDIMS] = {0};
/*
@@ -3281,7 +3208,7 @@ H5D__mpio_collective_filtered_chunk_io_setup(const H5D_io_info_t *io_info, const
* callback that can be used to ensure collectivity between ranks
* in a more natural way, but this hack should suffice for now.
*/
if (H5D__chunk_lookup(io_info->dset, scaled, &udata) < 0)
if (H5D__chunk_lookup(di->dset, scaled, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
}
@@ -3320,8 +3247,7 @@ done:
static herr_t
H5D__mpio_redistribute_shared_chunks(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries, const H5D_io_info_t *io_info,
const H5D_chunk_map_t *fm, int mpi_rank, int mpi_size,
size_t **rank_chunks_assigned_map)
int mpi_rank, int mpi_size, size_t **rank_chunks_assigned_map)
{
hbool_t redistribute_on_all_ranks;
size_t *num_chunks_map = NULL;
@@ -3334,7 +3260,6 @@ H5D__mpio_redistribute_shared_chunks(H5D_filtered_collective_io_info_t *chunk_li
HDassert(chunk_list || 0 == chunk_list_num_entries);
HDassert(io_info);
HDassert(fm);
HDassert(mpi_size > 1); /* No chunk sharing is possible for MPI Comm size of 1 */
#ifdef H5Dmpio_DEBUG
@@ -3368,7 +3293,7 @@ H5D__mpio_redistribute_shared_chunks(H5D_filtered_collective_io_info_t *chunk_li
redistribute_on_all_ranks = coll_chunk_list_size < H5D_CHUNK_REDISTRIBUTE_THRES;
if (H5D__mpio_redistribute_shared_chunks_int(chunk_list, num_chunks_map, redistribute_on_all_ranks,
io_info, fm, mpi_rank, mpi_size) < 0)
io_info, mpi_rank, mpi_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREDISTRIBUTE, FAIL, "can't redistribute shared chunks")
/*
@@ -3458,9 +3383,7 @@ done:
static herr_t
H5D__mpio_redistribute_shared_chunks_int(H5D_filtered_collective_io_info_t *chunk_list,
size_t *num_chunks_assigned_map, hbool_t all_ranks_involved,
const H5D_io_info_t *io_info,
const H5D_chunk_map_t H5_ATTR_NDEBUG_UNUSED *fm, int mpi_rank,
int mpi_size)
const H5D_io_info_t *io_info, int mpi_rank, int mpi_size)
{
MPI_Datatype struct_type;
MPI_Datatype packed_type;
@@ -3481,7 +3404,6 @@ H5D__mpio_redistribute_shared_chunks_int(H5D_filtered_collective_io_info_t *chun
HDassert(num_chunks_assigned_map);
HDassert(chunk_list || 0 == num_chunks_assigned_map[mpi_rank]);
HDassert(io_info);
HDassert(fm);
HDassert(mpi_size > 1);
#ifdef H5Dmpio_DEBUG
@@ -3789,7 +3711,7 @@ done:
static herr_t
H5D__mpio_share_chunk_modification_data(H5D_filtered_collective_io_info_t *chunk_list,
size_t *chunk_list_num_entries, H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, int mpi_rank,
H5D_dset_io_info_t *dset_info, int mpi_rank,
int H5_ATTR_NDEBUG_UNUSED mpi_size,
H5D_filtered_collective_io_info_t **chunk_hash_table,
unsigned char ***chunk_msg_bufs, int *chunk_msg_bufs_len)
@@ -3818,7 +3740,7 @@ H5D__mpio_share_chunk_modification_data(H5D_filtered_collective_io_info_t *chunk
HDassert(chunk_list_num_entries);
HDassert(chunk_list || 0 == *chunk_list_num_entries);
HDassert(io_info);
HDassert(type_info);
HDassert(dset_info);
HDassert(mpi_size > 1);
HDassert(chunk_msg_bufs);
HDassert(chunk_msg_bufs_len);
@@ -3891,7 +3813,7 @@ H5D__mpio_share_chunk_modification_data(H5D_filtered_collective_io_info_t *chunk
last_assigned_idx++;
}
else {
H5D_chunk_info_t *chunk_info = chunk_entry->chunk_info;
H5D_piece_info_t *chunk_info = chunk_entry->chunk_info;
unsigned char *mod_data_p = NULL;
hsize_t iter_nelmts;
size_t mod_data_size = 0;
@@ -3909,7 +3831,7 @@ H5D__mpio_share_chunk_modification_data(H5D_filtered_collective_io_info_t *chunk
iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace);
H5_CHECK_OVERFLOW(iter_nelmts, hsize_t, size_t);
mod_data_size += (size_t)iter_nelmts * type_info->src_type_size;
mod_data_size += (size_t)iter_nelmts * dset_info->type_info.src_type_size;
if (NULL == (msg_send_bufs[num_send_requests] = H5MM_malloc(mod_data_size)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL,
@@ -3926,14 +3848,14 @@ H5D__mpio_share_chunk_modification_data(H5D_filtered_collective_io_info_t *chunk
HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "unable to encode dataspace")
/* Initialize iterator for memory selection */
if (H5S_select_iter_init(mem_iter, chunk_info->mspace, type_info->src_type_size,
if (H5S_select_iter_init(mem_iter, chunk_info->mspace, dset_info->type_info.src_type_size,
H5S_SEL_ITER_SHARE_WITH_DATASPACE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"unable to initialize memory selection information")
mem_iter_init = TRUE;
/* Collect the modification data into the buffer */
if (0 == H5D__gather_mem(io_info->u.wbuf, mem_iter, (size_t)iter_nelmts, mod_data_p))
if (0 == H5D__gather_mem(dset_info->buf.cvp, mem_iter, (size_t)iter_nelmts, mod_data_p))
HGOTO_ERROR(H5E_IO, H5E_CANTGATHER, FAIL, "couldn't gather from write buffer")
/*
@@ -4202,10 +4124,9 @@ done:
static herr_t
H5D__mpio_collective_filtered_chunk_common_io(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries, const H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, int mpi_size)
int mpi_size)
{
H5D_io_info_t coll_io_info;
H5D_storage_t ctg_store;
MPI_Datatype file_type = MPI_DATATYPE_NULL;
MPI_Datatype mem_type = MPI_DATATYPE_NULL;
hbool_t mem_type_is_derived = FALSE;
@@ -4222,7 +4143,6 @@ H5D__mpio_collective_filtered_chunk_common_io(H5D_filtered_collective_io_info_t
HDassert(chunk_list || 0 == chunk_list_num_entries);
HDassert(io_info);
HDassert(type_info);
/* Initialize temporary I/O info */
coll_io_info = *io_info;
@@ -4258,9 +4178,7 @@ H5D__mpio_collective_filtered_chunk_common_io(H5D_filtered_collective_io_info_t
/*
* If this rank doesn't have a selection, it can
* skip I/O if independent I/O was requested at
* the low level, or if the MPI communicator size
* is 1.
* skip I/O if the MPI communicator size is 1.
*
* Otherwise, this rank has to participate in
* collective I/O, but probably has a NULL buf
@@ -4268,20 +4186,13 @@ H5D__mpio_collective_filtered_chunk_common_io(H5D_filtered_collective_io_info_t
* write/read function expects one.
*/
if (num_chunks == 0) {
H5FD_mpio_collective_opt_t coll_opt_mode;
/* Get the collective_opt property to check whether the application wants to do IO individually. */
if (H5CX_get_mpio_coll_opt(&coll_opt_mode) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get MPI-I/O collective_opt property")
if ((mpi_size == 1) || (H5FD_MPIO_INDIVIDUAL_IO == coll_opt_mode)) {
if (mpi_size == 1)
HGOTO_DONE(SUCCEED)
}
else {
if (io_info->op_type == H5D_IO_OP_WRITE)
coll_io_info.u.wbuf = &fake_buf;
coll_io_info.base_maddr.cvp = &fake_buf;
else
coll_io_info.u.rbuf = &fake_buf;
coll_io_info.base_maddr.vp = &fake_buf;
}
}
@@ -4297,18 +4208,15 @@ H5D__mpio_collective_filtered_chunk_common_io(H5D_filtered_collective_io_info_t
* to be the first chunk's file address
*/
if (io_info->op_type == H5D_IO_OP_WRITE)
ctg_store.contig.dset_addr = chunk_list[0].chunk_new.offset;
coll_io_info.store_faddr = chunk_list[0].chunk_new.offset;
else
ctg_store.contig.dset_addr = base_read_offset;
coll_io_info.store_faddr = base_read_offset;
}
else
ctg_store.contig.dset_addr = 0;
ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
coll_io_info.store = &ctg_store;
coll_io_info.store_faddr = 0;
/* Perform I/O */
if (H5D__final_collective_io(&coll_io_info, type_info, mpi_buf_count, file_type, mem_type) < 0)
if (H5D__final_collective_io(&coll_io_info, mpi_buf_count, file_type, mem_type) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't finish MPI I/O")
done:
@@ -4335,10 +4243,10 @@ done:
static herr_t
H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries, const H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, int mpi_rank, int mpi_size)
const H5D_dset_io_info_t *di, int mpi_rank, int mpi_size)
{
H5D_fill_buf_info_t fb_info;
H5D_chunk_info_t *chunk_info = NULL;
H5D_piece_info_t *chunk_info = NULL;
H5D_io_info_t coll_io_info;
H5Z_EDC_t err_detect; /* Error detection info */
H5Z_cb_t filter_cb; /* I/O filter callback function */
@@ -4356,7 +4264,7 @@ H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chun
HDassert(chunk_list || 0 == chunk_list_num_entries);
HDassert(io_info);
HDassert(type_info);
HDassert(di);
#ifdef H5Dmpio_DEBUG
H5D_MPIO_TRACE_ENTER(mpi_rank);
@@ -4366,8 +4274,8 @@ H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chun
#endif
/* Initialize temporary I/O info */
coll_io_info = *io_info;
coll_io_info.u.rbuf = NULL;
coll_io_info = *io_info;
coll_io_info.base_maddr.vp = NULL;
if (chunk_list_num_entries) {
/* Retrieve filter settings from API context */
@@ -4377,12 +4285,12 @@ H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chun
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get I/O filter callback function")
/* Set size of full chunks in dataset */
file_chunk_size = io_info->dset->shared->layout.u.chunk.size;
file_chunk_size = di->dset->shared->layout.u.chunk.size;
/* Determine if fill values should be "read" for unallocated chunks */
should_fill = (io_info->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC) ||
((io_info->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET) &&
io_info->dset->shared->dcpl_cache.fill.fill_defined);
should_fill = (di->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC) ||
((di->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET) &&
di->dset->shared->dcpl_cache.fill.fill_defined);
}
/*
@@ -4436,22 +4344,21 @@ H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chun
if (!fb_info_init) {
hsize_t chunk_dims[H5S_MAX_RANK];
HDassert(io_info->dset->shared->ndims == io_info->dset->shared->layout.u.chunk.ndims - 1);
for (size_t j = 0; j < io_info->dset->shared->layout.u.chunk.ndims - 1; j++)
chunk_dims[j] = (hsize_t)io_info->dset->shared->layout.u.chunk.dim[j];
HDassert(di->dset->shared->ndims == di->dset->shared->layout.u.chunk.ndims - 1);
for (size_t j = 0; j < di->dset->shared->layout.u.chunk.ndims - 1; j++)
chunk_dims[j] = (hsize_t)di->dset->shared->layout.u.chunk.dim[j];
/* Get a dataspace for filling chunk memory buffers */
if (NULL == (fill_space = H5S_create_simple(
io_info->dset->shared->layout.u.chunk.ndims - 1, chunk_dims, NULL)))
if (NULL == (fill_space = H5S_create_simple(di->dset->shared->layout.u.chunk.ndims - 1,
chunk_dims, NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create chunk fill dataspace")
/* Initialize fill value buffer */
if (H5D__fill_init(&fb_info, NULL, (H5MM_allocate_t)H5D__chunk_mem_alloc,
(void *)&io_info->dset->shared->dcpl_cache.pline,
(H5MM_free_t)H5D__chunk_mem_free,
(void *)&io_info->dset->shared->dcpl_cache.pline,
&io_info->dset->shared->dcpl_cache.fill, io_info->dset->shared->type,
io_info->dset->shared->type_id, 0, file_chunk_size) < 0)
if (H5D__fill_init(
&fb_info, NULL, (H5MM_allocate_t)H5D__chunk_mem_alloc,
(void *)&di->dset->shared->dcpl_cache.pline, (H5MM_free_t)H5D__chunk_mem_free,
(void *)&di->dset->shared->dcpl_cache.pline, &di->dset->shared->dcpl_cache.fill,
di->dset->shared->type, di->dset->shared->type_id, 0, file_chunk_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill value buffer")
fb_info_init = TRUE;
@@ -4459,8 +4366,8 @@ H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chun
/* Write fill value to memory buffer */
HDassert(fb_info.fill_buf);
if (H5D__fill(fb_info.fill_buf, io_info->dset->shared->type, chunk_list[i].buf,
type_info->mem_type, fill_space) < 0)
if (H5D__fill(fb_info.fill_buf, di->dset->shared->type, chunk_list[i].buf,
di->type_info.mem_type, fill_space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "couldn't fill chunk buffer with fill value")
}
}
@@ -4472,8 +4379,8 @@ H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chun
* read of chunks is essentially a no-op, so avoid it here.
*/
index_empty = FALSE;
if (io_info->dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_INCR)
if (H5D__chunk_index_empty(io_info->dset, &index_empty) < 0)
if (di->dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_INCR)
if (H5D__chunk_index_empty(di->dset, &index_empty) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't determine if chunk index is empty")
if (!index_empty) {
@@ -4482,11 +4389,11 @@ H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chun
* the first chunk data buffer being read into
*/
if (base_read_buf)
coll_io_info.u.rbuf = base_read_buf;
coll_io_info.base_maddr.vp = base_read_buf;
/* Perform collective chunk read */
if (H5D__mpio_collective_filtered_chunk_common_io(chunk_list, chunk_list_num_entries, &coll_io_info,
type_info, mpi_size) < 0)
mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't finish collective filtered chunk read")
}
@@ -4499,7 +4406,7 @@ H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chun
/* Unfilter the chunk, unless we didn't read it from the file */
if (chunk_list[i].need_read && !chunk_list[i].skip_filter_pline) {
if (H5Z_pipeline(&io_info->dset->shared->dcpl_cache.pline, H5Z_FLAG_REVERSE,
if (H5Z_pipeline(&di->dset->shared->dcpl_cache.pline, H5Z_FLAG_REVERSE,
&(chunk_list[i].index_info.filter_mask), err_detect, filter_cb,
(size_t *)&chunk_list[i].chunk_new.length, &chunk_list[i].chunk_buf_size,
&chunk_list[i].buf) < 0)
@@ -4509,8 +4416,8 @@ H5D__mpio_collective_filtered_chunk_read(H5D_filtered_collective_io_info_t *chun
/* Scatter the chunk data to the read buffer */
iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->fspace);
if (H5D_select_io_mem(io_info->u.rbuf, chunk_info->mspace, chunk_list[i].buf, chunk_info->fspace,
type_info->src_type_size, (size_t)iter_nelmts) < 0)
if (H5D_select_io_mem(di->buf.vp, chunk_info->mspace, chunk_list[i].buf, chunk_info->fspace,
di->type_info.src_type_size, (size_t)iter_nelmts) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "couldn't copy chunk data to read buffer")
}
@@ -4554,39 +4461,44 @@ H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *ch
size_t chunk_list_num_entries,
H5D_filtered_collective_io_info_t *chunk_hash_table,
unsigned char **chunk_msg_bufs, int chunk_msg_bufs_len,
const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
const H5D_io_info_t *io_info, const H5D_dset_io_info_t *di,
int H5_ATTR_NDEBUG_UNUSED mpi_rank, int mpi_size)
{
H5D_fill_buf_info_t fb_info;
H5D_chunk_info_t *chunk_info = NULL;
H5S_sel_iter_t *sel_iter = NULL; /* Dataspace selection iterator for H5D__scatter_mem */
H5D_io_info_t coll_io_info;
H5Z_EDC_t err_detect; /* Error detection info */
H5Z_cb_t filter_cb; /* I/O filter callback function */
hsize_t file_chunk_size = 0;
hsize_t iter_nelmts; /* Number of points to iterate over for the chunk IO operation */
hbool_t should_fill = FALSE;
hbool_t fb_info_init = FALSE;
hbool_t sel_iter_init = FALSE;
hbool_t index_empty = FALSE;
size_t i;
H5S_t *dataspace = NULL;
H5S_t *fill_space = NULL;
void *base_read_buf = NULL;
herr_t ret_value = SUCCEED;
const H5D_type_info_t *type_info = NULL;
H5D_fill_buf_info_t fb_info;
H5D_piece_info_t *chunk_info = NULL;
H5S_sel_iter_t *sel_iter = NULL; /* Dataspace selection iterator for H5D__scatter_mem */
H5D_io_info_t coll_io_info;
H5Z_EDC_t err_detect; /* Error detection info */
H5Z_cb_t filter_cb; /* I/O filter callback function */
hsize_t file_chunk_size = 0;
hsize_t iter_nelmts; /* Number of points to iterate over for the chunk IO operation */
hbool_t should_fill = FALSE;
hbool_t fb_info_init = FALSE;
hbool_t sel_iter_init = FALSE;
hbool_t index_empty = FALSE;
size_t i;
H5S_t *dataspace = NULL;
H5S_t *fill_space = NULL;
void *base_read_buf = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(chunk_list || 0 == chunk_list_num_entries);
HDassert((chunk_msg_bufs && chunk_hash_table) || 0 == chunk_msg_bufs_len);
HDassert(io_info);
HDassert(type_info);
HDassert(di);
#ifdef H5Dmpio_DEBUG
H5D_MPIO_TRACE_ENTER(mpi_rank);
H5D_MPIO_TIME_START(mpi_rank, "Filtered collective chunk update");
#endif
/* Set convenience pointers */
type_info = &(di->type_info);
HDassert(type_info);
if (chunk_list_num_entries) {
/* Retrieve filter settings from API context */
if (H5CX_get_err_detect(&err_detect) < 0)
@@ -4595,12 +4507,12 @@ H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *ch
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get I/O filter callback function")
/* Set size of full chunks in dataset */
file_chunk_size = io_info->dset->shared->layout.u.chunk.size;
file_chunk_size = di->dset->shared->layout.u.chunk.size;
/* Determine if fill values should be written to chunks */
should_fill = (io_info->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC) ||
((io_info->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET) &&
io_info->dset->shared->dcpl_cache.fill.fill_defined);
should_fill = (di->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_ALLOC) ||
((di->dset->shared->dcpl_cache.fill.fill_time == H5D_FILL_TIME_IFSET) &&
di->dset->shared->dcpl_cache.fill.fill_defined);
}
/*
@@ -4672,25 +4584,23 @@ H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *ch
if (!fb_info_init) {
hsize_t chunk_dims[H5S_MAX_RANK];
HDassert(io_info->dset->shared->ndims ==
io_info->dset->shared->layout.u.chunk.ndims - 1);
for (size_t j = 0; j < io_info->dset->shared->layout.u.chunk.ndims - 1; j++)
chunk_dims[j] = (hsize_t)io_info->dset->shared->layout.u.chunk.dim[j];
HDassert(di->dset->shared->ndims == di->dset->shared->layout.u.chunk.ndims - 1);
for (size_t j = 0; j < di->dset->shared->layout.u.chunk.ndims - 1; j++)
chunk_dims[j] = (hsize_t)di->dset->shared->layout.u.chunk.dim[j];
/* Get a dataspace for filling chunk memory buffers */
if (NULL == (fill_space = H5S_create_simple(
io_info->dset->shared->layout.u.chunk.ndims - 1, chunk_dims, NULL)))
di->dset->shared->layout.u.chunk.ndims - 1, chunk_dims, NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"unable to create chunk fill dataspace")
/* Initialize fill value buffer */
if (H5D__fill_init(&fb_info, NULL, (H5MM_allocate_t)H5D__chunk_mem_alloc,
(void *)&io_info->dset->shared->dcpl_cache.pline,
(void *)&di->dset->shared->dcpl_cache.pline,
(H5MM_free_t)H5D__chunk_mem_free,
(void *)&io_info->dset->shared->dcpl_cache.pline,
&io_info->dset->shared->dcpl_cache.fill,
io_info->dset->shared->type, io_info->dset->shared->type_id, 0,
file_chunk_size) < 0)
(void *)&di->dset->shared->dcpl_cache.pline,
&di->dset->shared->dcpl_cache.fill, di->dset->shared->type,
di->dset->shared->type_id, 0, file_chunk_size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill value buffer")
fb_info_init = TRUE;
@@ -4698,7 +4608,7 @@ H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *ch
/* Write fill value to memory buffer */
HDassert(fb_info.fill_buf);
if (H5D__fill(fb_info.fill_buf, io_info->dset->shared->type, chunk_list[i].buf,
if (H5D__fill(fb_info.fill_buf, di->dset->shared->type, chunk_list[i].buf,
type_info->mem_type, fill_space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"couldn't fill chunk buffer with fill value")
@@ -4715,8 +4625,8 @@ H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *ch
* read of chunks is essentially a no-op, so avoid it here.
*/
index_empty = FALSE;
if (io_info->dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_INCR)
if (H5D__chunk_index_empty(io_info->dset, &index_empty) < 0)
if (di->dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_INCR)
if (H5D__chunk_index_empty(di->dset, &index_empty) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "couldn't determine if chunk index is empty")
if (!index_empty) {
@@ -4731,12 +4641,13 @@ H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *ch
/* Override the read buffer to point to the address of the first
* chunk data buffer being read into
*/
if (base_read_buf)
coll_io_info.u.rbuf = base_read_buf;
if (base_read_buf) {
coll_io_info.base_maddr.vp = base_read_buf;
}
/* Read all chunks that need to be read from the file */
if (H5D__mpio_collective_filtered_chunk_common_io(chunk_list, chunk_list_num_entries, &coll_io_info,
type_info, mpi_size) < 0)
mpi_size) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't finish collective filtered chunk read")
}
@@ -4756,7 +4667,7 @@ H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *ch
* the file, so we need to unfilter it
*/
if (chunk_list[i].need_read && !chunk_list[i].skip_filter_pline) {
if (H5Z_pipeline(&io_info->dset->shared->dcpl_cache.pline, H5Z_FLAG_REVERSE,
if (H5Z_pipeline(&di->dset->shared->dcpl_cache.pline, H5Z_FLAG_REVERSE,
&(chunk_list[i].index_info.filter_mask), err_detect, filter_cb,
(size_t *)&chunk_list[i].chunk_new.length, &chunk_list[i].chunk_buf_size,
&chunk_list[i].buf) < 0)
@@ -4765,7 +4676,7 @@ H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *ch
iter_nelmts = H5S_GET_SELECT_NPOINTS(chunk_info->mspace);
if (H5D_select_io_mem(chunk_list[i].buf, chunk_info->fspace, io_info->u.wbuf, chunk_info->mspace,
if (H5D_select_io_mem(chunk_list[i].buf, chunk_info->fspace, di->buf.cvp, chunk_info->mspace,
type_info->dst_type_size, (size_t)iter_nelmts) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "couldn't copy chunk data to write buffer")
}
@@ -4834,10 +4745,9 @@ H5D__mpio_collective_filtered_chunk_update(H5D_filtered_collective_io_info_t *ch
/* Finally, filter all the chunks */
for (i = 0; i < chunk_list_num_entries; i++) {
if (!chunk_list[i].skip_filter_pline) {
if (H5Z_pipeline(&io_info->dset->shared->dcpl_cache.pline, 0,
&(chunk_list[i].index_info.filter_mask), err_detect, filter_cb,
(size_t *)&chunk_list[i].chunk_new.length, &chunk_list[i].chunk_buf_size,
&chunk_list[i].buf) < 0)
if (H5Z_pipeline(&di->dset->shared->dcpl_cache.pline, 0, &(chunk_list[i].index_info.filter_mask),
err_detect, filter_cb, (size_t *)&chunk_list[i].chunk_new.length,
&chunk_list[i].chunk_buf_size, &chunk_list[i].buf) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "output pipeline failed")
}
@@ -5088,8 +4998,8 @@ done:
static herr_t
H5D__mpio_collective_filtered_chunk_reinsert(H5D_filtered_collective_io_info_t *chunk_list,
size_t chunk_list_num_entries, size_t *num_chunks_assigned_map,
H5D_io_info_t *io_info, H5D_chk_idx_info_t *idx_info,
int mpi_rank, int mpi_size)
H5D_io_info_t *io_info, H5D_dset_io_info_t *di,
H5D_chk_idx_info_t *idx_info, int mpi_rank, int mpi_size)
{
H5D_chunk_ud_t chunk_ud;
MPI_Datatype send_type;
@@ -5110,6 +5020,7 @@ H5D__mpio_collective_filtered_chunk_reinsert(H5D_filtered_collective_io_info_t *
HDassert(chunk_list || 0 == chunk_list_num_entries);
HDassert(io_info);
HDassert(di);
HDassert(idx_info);
#ifdef H5Dmpio_DEBUG
@@ -5219,17 +5130,17 @@ H5D__mpio_collective_filtered_chunk_reinsert(H5D_filtered_collective_io_info_t *
* callback that accepts a chunk index and provides the
* caller with the scaled coordinates for that chunk.
*/
H5VM_array_calc_pre(chunk_ud.chunk_idx, io_info->dset->shared->ndims,
H5VM_array_calc_pre(chunk_ud.chunk_idx, di->dset->shared->ndims,
idx_info->layout->u.earray.swizzled_down_chunks, scaled_coords);
H5VM_unswizzle_coords(hsize_t, scaled_coords, idx_info->layout->u.earray.unlim_dim);
}
else {
H5VM_array_calc_pre(chunk_ud.chunk_idx, io_info->dset->shared->ndims,
io_info->dset->shared->layout.u.chunk.down_chunks, scaled_coords);
H5VM_array_calc_pre(chunk_ud.chunk_idx, di->dset->shared->ndims,
di->dset->shared->layout.u.chunk.down_chunks, scaled_coords);
}
scaled_coords[io_info->dset->shared->ndims] = 0;
scaled_coords[di->dset->shared->ndims] = 0;
#ifndef NDEBUG
/*
@@ -5243,7 +5154,7 @@ H5D__mpio_collective_filtered_chunk_reinsert(H5D_filtered_collective_io_info_t *
for (size_t dbg_idx = 0; dbg_idx < chunk_list_num_entries; dbg_idx++) {
if (coll_entry->index_info.chunk_idx == chunk_list[dbg_idx].index_info.chunk_idx) {
hbool_t coords_match = !HDmemcmp(scaled_coords, chunk_list[dbg_idx].chunk_info->scaled,
io_info->dset->shared->ndims * sizeof(hsize_t));
di->dset->shared->ndims * sizeof(hsize_t));
HDassert(coords_match && "Calculated scaled coordinates for chunk didn't match "
"chunk's actual scaled coordinates!");
@@ -5252,7 +5163,7 @@ H5D__mpio_collective_filtered_chunk_reinsert(H5D_filtered_collective_io_info_t *
}
#endif
if ((idx_info->storage->ops->insert)(idx_info, &chunk_ud, io_info->dset) < 0)
if ((idx_info->storage->ops->insert)(idx_info, &chunk_ud, di->dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk address into index")
}
+167 -152
View File
@@ -33,6 +33,7 @@
#include "H5ACprivate.h" /* Metadata cache */
#include "H5B2private.h" /* v2 B-trees */
#include "H5Fprivate.h" /* File access */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Gprivate.h" /* Groups */
#include "H5SLprivate.h" /* Skip lists */
#include "H5Tprivate.h" /* Datatypes */
@@ -44,20 +45,6 @@
/* Set the minimum object header size to create objects with */
#define H5D_MINHDR_SIZE 256
/* [Simple] Macro to construct a H5D_io_info_t from it's components */
#define H5D_BUILD_IO_INFO_WRT(io_info, ds, str, buf) \
(io_info)->dset = ds; \
(io_info)->f_sh = H5F_SHARED((ds)->oloc.file); \
(io_info)->store = str; \
(io_info)->op_type = H5D_IO_OP_WRITE; \
(io_info)->u.wbuf = buf
#define H5D_BUILD_IO_INFO_RD(io_info, ds, str, buf) \
(io_info)->dset = ds; \
(io_info)->f_sh = H5F_SHARED((ds)->oloc.file); \
(io_info)->store = str; \
(io_info)->op_type = H5D_IO_OP_READ; \
(io_info)->u.rbuf = buf
/* Flags for marking aspects of a dataset dirty */
#define H5D_MARK_SPACE 0x01
#define H5D_MARK_LAYOUT 0x02
@@ -83,6 +70,9 @@
#define H5D_BT2_SPLIT_PERC 100
#define H5D_BT2_MERGE_PERC 40
/* Macro to determine if the layout I/O callback should perform I/O */
#define H5D_LAYOUT_CB_PERFORM_IO(IO_INFO) (!(IO_INFO)->use_select_io || (IO_INFO)->count == 1)
/****************************/
/* Package Private Typedefs */
/****************************/
@@ -97,23 +87,20 @@ typedef struct H5D_type_info_t {
hid_t dst_type_id; /* Destination datatype ID */
/* Computed/derived values */
size_t src_type_size; /* Size of source type */
size_t dst_type_size; /* Size of destination type */
size_t max_type_size; /* Size of largest source/destination type */
hbool_t is_conv_noop; /* Whether the type conversion is a NOOP */
hbool_t is_xform_noop; /* Whether the data transform is a NOOP */
const H5T_subset_info_t *cmpd_subset; /* Info related to the compound subset conversion functions */
H5T_bkg_t need_bkg; /* Type of background buf needed */
size_t request_nelmts; /* Requested strip mine */
uint8_t *tconv_buf; /* Datatype conv buffer */
hbool_t tconv_buf_allocated; /* Whether the type conversion buffer was allocated */
uint8_t *bkg_buf; /* Background buffer */
hbool_t bkg_buf_allocated; /* Whether the background buffer was allocated */
size_t src_type_size; /* Size of source type */
size_t dst_type_size; /* Size of destination type */
hbool_t is_conv_noop; /* Whether the type conversion is a NOOP */
hbool_t is_xform_noop; /* Whether the data transform is a NOOP */
const H5T_subset_info_t *cmpd_subset; /* Info related to the compound subset conversion functions */
H5T_bkg_t need_bkg; /* Type of background buf needed */
size_t request_nelmts; /* Requested strip mine */
uint8_t *bkg_buf; /* Background buffer */
hbool_t bkg_buf_allocated; /* Whether the background buffer was allocated */
} H5D_type_info_t;
/* Forward declaration of structs used below */
struct H5D_io_info_t;
struct H5D_chunk_map_t;
struct H5D_dset_io_info_t;
typedef struct H5D_shared_t H5D_shared_t;
/* Function pointers for I/O on particular types of dataset layouts */
@@ -121,27 +108,27 @@ typedef herr_t (*H5D_layout_construct_func_t)(H5F_t *f, H5D_t *dset);
typedef herr_t (*H5D_layout_init_func_t)(H5F_t *f, const H5D_t *dset, hid_t dapl_id);
typedef hbool_t (*H5D_layout_is_space_alloc_func_t)(const H5O_storage_t *storage);
typedef hbool_t (*H5D_layout_is_data_cached_func_t)(const H5D_shared_t *shared_dset);
typedef herr_t (*H5D_layout_io_init_func_t)(struct H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space,
struct H5D_chunk_map_t *cm);
typedef herr_t (*H5D_layout_read_func_t)(struct H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space,
struct H5D_chunk_map_t *fm);
typedef herr_t (*H5D_layout_write_func_t)(struct H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space,
struct H5D_chunk_map_t *fm);
typedef ssize_t (*H5D_layout_readvv_func_t)(const struct H5D_io_info_t *io_info, size_t dset_max_nseq,
typedef herr_t (*H5D_layout_io_init_func_t)(struct H5D_io_info_t *io_info, struct H5D_dset_io_info_t *dinfo);
typedef herr_t (*H5D_layout_mdio_init_func_t)(struct H5D_io_info_t *io_info,
struct H5D_dset_io_info_t *dinfo);
typedef herr_t (*H5D_layout_read_func_t)(struct H5D_io_info_t *io_info, struct H5D_dset_io_info_t *dinfo);
typedef herr_t (*H5D_layout_write_func_t)(struct H5D_io_info_t *io_info, struct H5D_dset_io_info_t *dinfo);
typedef herr_t (*H5D_layout_read_md_func_t)(struct H5D_io_info_t *io_info);
typedef herr_t (*H5D_layout_write_md_func_t)(struct H5D_io_info_t *io_info);
typedef ssize_t (*H5D_layout_readvv_func_t)(const struct H5D_io_info_t *io_info,
const struct H5D_dset_io_info_t *dset_info, size_t dset_max_nseq,
size_t *dset_curr_seq, size_t dset_len_arr[],
hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[],
hsize_t mem_offset_arr[]);
typedef ssize_t (*H5D_layout_writevv_func_t)(const struct H5D_io_info_t *io_info, size_t dset_max_nseq,
typedef ssize_t (*H5D_layout_writevv_func_t)(const struct H5D_io_info_t *io_info,
const struct H5D_dset_io_info_t *dset_info, size_t dset_max_nseq,
size_t *dset_curr_seq, size_t dset_len_arr[],
hsize_t dset_offset_arr[], size_t mem_max_nseq,
size_t *mem_curr_seq, size_t mem_len_arr[],
hsize_t mem_offset_arr[]);
typedef herr_t (*H5D_layout_flush_func_t)(H5D_t *dataset);
typedef herr_t (*H5D_layout_io_term_func_t)(const struct H5D_chunk_map_t *cm);
typedef herr_t (*H5D_layout_io_term_func_t)(struct H5D_io_info_t *io_info, struct H5D_dset_io_info_t *di);
typedef herr_t (*H5D_layout_dest_func_t)(H5D_t *dataset);
/* Typedef for grouping layout I/O routines */
@@ -152,27 +139,28 @@ typedef struct H5D_layout_ops_t {
H5D_layout_is_data_cached_func_t
is_data_cached; /* Query routine to determine if any raw data is cached. If routine is not present
then the layout type never caches raw data. */
H5D_layout_io_init_func_t io_init; /* I/O initialization routine */
H5D_layout_read_func_t ser_read; /* High-level I/O routine for reading data in serial */
H5D_layout_write_func_t ser_write; /* High-level I/O routine for writing data in serial */
#ifdef H5_HAVE_PARALLEL
H5D_layout_read_func_t par_read; /* High-level I/O routine for reading data in parallel */
H5D_layout_write_func_t par_write; /* High-level I/O routine for writing data in parallel */
#endif /* H5_HAVE_PARALLEL */
H5D_layout_readvv_func_t readvv; /* Low-level I/O routine for reading data */
H5D_layout_writevv_func_t writevv; /* Low-level I/O routine for writing data */
H5D_layout_flush_func_t flush; /* Low-level I/O routine for flushing raw data */
H5D_layout_io_term_func_t io_term; /* I/O shutdown routine */
H5D_layout_dest_func_t dest; /* Destroy layout info */
H5D_layout_io_init_func_t io_init; /* I/O initialization routine */
H5D_layout_mdio_init_func_t mdio_init; /* Multi Dataset I/O initialization routine - called after all
datasets have done io_init and sel_pieces has been allocated */
H5D_layout_read_func_t ser_read; /* High-level I/O routine for reading data in serial */
H5D_layout_write_func_t ser_write; /* High-level I/O routine for writing data in serial */
H5D_layout_readvv_func_t readvv; /* Low-level I/O routine for reading data */
H5D_layout_writevv_func_t writevv; /* Low-level I/O routine for writing data */
H5D_layout_flush_func_t flush; /* Low-level I/O routine for flushing raw data */
H5D_layout_io_term_func_t io_term; /* I/O shutdown routine for multi-dset */
H5D_layout_dest_func_t dest; /* Destroy layout info */
} H5D_layout_ops_t;
/* Function pointers for either multiple or single block I/O access */
typedef herr_t (*H5D_io_single_read_func_t)(const struct H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space);
typedef herr_t (*H5D_io_single_write_func_t)(const struct H5D_io_info_t *io_info,
const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space);
typedef herr_t (*H5D_io_single_read_func_t)(const struct H5D_io_info_t *io_info,
const struct H5D_dset_io_info_t *dset_info);
typedef herr_t (*H5D_io_single_write_func_t)(const struct H5D_io_info_t *io_info,
const struct H5D_dset_io_info_t *dset_info);
typedef herr_t (*H5D_io_single_read_md_func_t)(const struct H5D_io_info_t *io_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space);
typedef herr_t (*H5D_io_single_write_md_func_t)(const struct H5D_io_info_t *io_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space);
/* Typedef for raw data I/O framework info */
typedef struct H5D_io_ops_t {
@@ -182,6 +170,14 @@ typedef struct H5D_io_ops_t {
H5D_io_single_write_func_t single_write; /* I/O routine for writing single block */
} H5D_io_ops_t;
/* Typedef for raw data I/O framework info (multi-dataset I/O) */
typedef struct H5D_md_io_ops_t {
H5D_layout_read_md_func_t multi_read_md; /* High-level I/O routine for reading data for multi-dset */
H5D_layout_write_md_func_t multi_write_md; /* High-level I/O routine for writing data for multi-dset */
H5D_io_single_read_md_func_t single_read_md; /* I/O routine for reading single block for multi-dset */
H5D_io_single_write_md_func_t single_write_md; /* I/O routine for writing single block for multi-dset */
} H5D_md_io_ops_t;
/* Typedefs for dataset storage information */
typedef struct {
haddr_t dset_addr; /* Address of dataset in file */
@@ -210,25 +206,79 @@ typedef enum H5D_io_op_type_t {
H5D_IO_OP_WRITE /* Write operation */
} H5D_io_op_type_t;
/* Piece info for a data chunk/block during I/O */
typedef struct H5D_piece_info_t {
haddr_t faddr; /* File address */
hsize_t index; /* "Index" of chunk in dataset */
hsize_t piece_points; /* Number of elements selected in piece */
hsize_t scaled[H5O_LAYOUT_NDIMS]; /* Scaled coordinates of chunk (in file dataset's dataspace) */
H5S_t *fspace; /* Dataspace describing chunk & selection in it */
unsigned fspace_shared; /* Indicate that the file space for a chunk is shared and shouldn't be freed */
H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
unsigned mspace_shared; /* Indicate that the memory space for a chunk is shared and shouldn't be freed */
struct H5D_dset_io_info_t *dset_info; /* Pointer to dset_info */
} H5D_piece_info_t;
/* I/O info for a single dataset */
typedef struct H5D_dset_io_info_t {
H5D_t *dset; /* Pointer to dataset being operated on */
H5D_storage_t *store; /* Dataset storage info */
H5D_layout_ops_t layout_ops; /* Dataset layout I/O operation function pointers */
H5_flexible_const_ptr_t buf; /* Buffer pointer */
H5D_io_ops_t io_ops; /* I/O operations for this dataset */
H5O_layout_t *layout; /* Dataset layout information*/
hsize_t nelmts; /* Number of elements selected in file & memory dataspaces */
H5S_t *file_space; /* Pointer to the file dataspace */
H5S_t *mem_space; /* Pointer to the memory dataspace */
union {
struct H5D_chunk_map_t *chunk_map; /* Chunk specific I/O info */
H5D_piece_info_t *contig_piece_info; /* Piece info for contiguous dataset */
} layout_io_info;
hid_t mem_type_id; /* memory datatype ID */
H5D_type_info_t type_info;
hbool_t skip_io; /* Whether to skip I/O for this dataset */
} H5D_dset_io_info_t;
/* I/O info for entire I/O operation */
typedef struct H5D_io_info_t {
const H5D_t *dset; /* Pointer to dataset being operated on */
/* QAK: Delete the f_sh field when oloc has a shared file pointer? */
/* QAK: Delete the f_sh field when oloc has a shared file pointer? */
H5F_shared_t *f_sh; /* Pointer to shared file struct that dataset is within */
#ifdef H5_HAVE_PARALLEL
MPI_Comm comm; /* MPI communicator for file */
hbool_t using_mpi_vfd; /* Whether the file is using an MPI-based VFD */
#endif /* H5_HAVE_PARALLEL */
H5D_storage_t *store; /* Dataset storage info */
H5D_layout_ops_t layout_ops; /* Dataset layout I/O operation function pointers */
H5D_io_ops_t io_ops; /* I/O operation function pointers */
H5D_io_op_type_t op_type;
hbool_t use_select_io; /* Whether to use selection I/O */
union {
void *rbuf; /* Pointer to buffer for read */
const void *wbuf; /* Pointer to buffer to write */
} u;
MPI_Comm comm; /* MPI communicator for file */
hbool_t using_mpi_vfd; /* Whether the file is using an MPI-based VFD */
#endif /* H5_HAVE_PARALLEL */
H5D_md_io_ops_t md_io_ops; /* Multi dataset I/O operation function pointers */
H5D_io_op_type_t op_type;
size_t count; /* Number of datasets in I/O request */
H5D_dset_io_info_t *dsets_info; /* dsets info where I/O is done to/from */
size_t piece_count; /* Number of pieces in I/O request */
size_t pieces_added; /* Number of pieces added so far to arrays */
H5D_piece_info_t **sel_pieces; /* Array of info struct for all pieces in I/O */
H5S_t **mem_spaces; /* Array of chunk memory spaces */
H5S_t **file_spaces; /* Array of chunk file spaces */
haddr_t *addrs; /* Array of chunk addresses */
size_t *element_sizes; /* Array of element sizes */
void **rbufs; /* Array of read buffers */
const void **wbufs; /* Array of write buffers */
haddr_t store_faddr; /* lowest file addr for read/write */
H5_flexible_const_ptr_t base_maddr; /* starting mem address */
hbool_t use_select_io; /* Whether to use selection I/O */
uint8_t *tconv_buf; /* Datatype conv buffer */
hbool_t tconv_buf_allocated; /* Whether the type conversion buffer was allocated */
size_t max_type_size; /* Largest of all source and destination type sizes */
} H5D_io_info_t;
/* Created to pass both at once for callback func */
typedef struct H5D_io_info_wrap_t {
H5D_io_info_t *io_info;
H5D_dset_io_info_t *dinfo;
} H5D_io_info_wrap_t;
/******************/
/* Chunk typedefs */
/******************/
@@ -330,46 +380,26 @@ typedef struct H5D_chunk_ops_t {
H5D_chunk_dest_func_t dest; /* Routine to destroy indexing information in memory */
} H5D_chunk_ops_t;
/* Structure holding information about a chunk's selection for mapping */
typedef struct H5D_chunk_info_t {
hsize_t index; /* "Index" of chunk in dataset */
uint32_t chunk_points; /* Number of elements selected in chunk */
hsize_t scaled[H5O_LAYOUT_NDIMS]; /* Scaled coordinates of chunk (in file dataset's dataspace) */
H5S_t *fspace; /* Dataspace describing chunk & selection in it */
hbool_t fspace_shared; /* Indicate that the file space for a chunk is shared and shouldn't be freed */
H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
hbool_t mspace_shared; /* Indicate that the memory space for a chunk is shared and shouldn't be freed */
} H5D_chunk_info_t;
/* Main structure holding the mapping between file chunks and memory */
typedef struct H5D_chunk_map_t {
H5O_layout_t *layout; /* Dataset layout information*/
hsize_t nelmts; /* Number of elements selected in file & memory dataspaces */
unsigned f_ndims; /* Number of dimensions for file dataspace */
H5S_t *file_space; /* Pointer to the file dataspace */
unsigned f_ndims; /* Number of dimensions for file dataspace */
H5S_t *mem_space; /* Pointer to the memory dataspace */
H5S_t *mchunk_tmpl; /* Dataspace template for new memory chunks */
H5S_sel_iter_t mem_iter; /* Iterator for elements in memory selection */
unsigned m_ndims; /* Number of dimensions for memory dataspace */
H5S_sel_type msel_type; /* Selection type in memory */
H5S_sel_type fsel_type; /* Selection type in file */
H5SL_t *sel_chunks; /* Skip list containing information for each chunk selected */
H5SL_t *dset_sel_pieces; /* Skip list containing information for each chunk selected */
H5S_t *single_space; /* Dataspace for single chunk */
H5D_chunk_info_t *single_chunk_info; /* Pointer to single chunk's info */
H5D_piece_info_t *single_piece_info; /* Pointer to single chunk's info */
hbool_t use_single; /* Whether I/O is on a single element */
hsize_t last_index; /* Index of last chunk operated on */
H5D_chunk_info_t *last_chunk_info; /* Pointer to last chunk's info */
H5D_piece_info_t *last_piece_info; /* Pointer to last chunk's info */
hsize_t chunk_dim[H5O_LAYOUT_NDIMS]; /* Size of chunk in each dimension */
#ifdef H5_HAVE_PARALLEL
H5D_chunk_info_t **select_chunk; /* Store the information about whether this chunk is selected or not */
#endif /* H5_HAVE_PARALLEL */
} H5D_chunk_map_t;
/* Cached information about a particular chunk */
@@ -415,7 +445,7 @@ typedef struct H5D_rdcc_t {
struct H5D_rdcc_ent_t **slot; /* Chunk slots, each points to a chunk*/
H5SL_t *sel_chunks; /* Skip list containing information for each chunk selected */
H5S_t *single_space; /* Dataspace for single element I/O on chunks */
H5D_chunk_info_t *single_chunk_info; /* Pointer to single chunk's info */
H5D_piece_info_t *single_piece_info; /* Pointer to single piece's info */
/* Cached information about scaled dataspace dimensions */
hsize_t scaled_dims[H5S_MAX_RANK]; /* The scaled dim sizes */
@@ -458,12 +488,13 @@ struct H5D_shared_t {
/* Buffered/cached information for types of raw data storage*/
struct {
H5D_rdcdc_t contig; /* Information about contiguous data */
/* (Note that the "contig" cache
* information can be used by a chunked
* dataset in certain circumstances)
*/
H5D_rdcc_t chunk; /* Information about chunked data */
H5D_rdcdc_t contig; /* Information about contiguous data */
/* (Note that the "contig" cache
* information can be used by a chunked
* dataset in certain circumstances)
*/
H5D_rdcc_t chunk; /* Information about chunked data */
H5SL_t *sel_pieces; /* Skip list containing information for each piece selected */
} cache;
H5D_append_flush_t append_flush; /* Append flush property information */
@@ -556,8 +587,8 @@ H5_DLL H5D_t *H5D__open_name(const H5G_loc_t *loc, const char *name, hid_t dapl
H5_DLL hid_t H5D__get_space(const H5D_t *dset);
H5_DLL hid_t H5D__get_type(const H5D_t *dset);
H5_DLL herr_t H5D__get_space_status(const H5D_t *dset, H5D_space_status_t *allocation);
H5_DLL herr_t H5D__alloc_storage(const H5D_io_info_t *io_info, H5D_time_alloc_t time_alloc,
hbool_t full_overwrite, hsize_t old_dim[]);
H5_DLL herr_t H5D__alloc_storage(H5D_t *dset, H5D_time_alloc_t time_alloc, hbool_t full_overwrite,
hsize_t old_dim[]);
H5_DLL herr_t H5D__get_storage_size(const H5D_t *dset, hsize_t *storage_size);
H5_DLL herr_t H5D__get_chunk_storage_size(H5D_t *dset, const hsize_t *offset, hsize_t *storage_size);
H5_DLL herr_t H5D__chunk_index_empty(const H5D_t *dset, hbool_t *empty);
@@ -582,16 +613,12 @@ H5_DLL herr_t H5D__refresh(H5D_t *dataset, hid_t dset_id);
H5_DLL herr_t H5D__format_convert(H5D_t *dataset);
/* Internal I/O routines */
H5_DLL herr_t H5D__read(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_space,
void *buf /*out*/);
H5_DLL herr_t H5D__write(H5D_t *dataset, hid_t mem_type_id, H5S_t *mem_space, H5S_t *file_space,
const void *buf);
H5_DLL herr_t H5D__read(size_t count, H5D_dset_io_info_t *dset_info);
H5_DLL herr_t H5D__write(size_t count, H5D_dset_io_info_t *dset_info);
/* Functions that perform direct serial I/O operations */
H5_DLL herr_t H5D__select_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space);
H5_DLL herr_t H5D__select_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space);
H5_DLL herr_t H5D__select_read(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
H5_DLL herr_t H5D__select_write(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
/* Functions that perform direct copying between memory buffers */
H5_DLL herr_t H5D_select_io_mem(void *dst_buf, H5S_t *dst_space, const void *src_buf, H5S_t *src_space,
@@ -601,10 +628,8 @@ H5_DLL herr_t H5D_select_io_mem(void *dst_buf, H5S_t *dst_space, const void *src
H5_DLL herr_t H5D__scatter_mem(const void *_tscat_buf, H5S_sel_iter_t *iter, size_t nelmts, void *_buf);
H5_DLL size_t H5D__gather_mem(const void *_buf, H5S_sel_iter_t *iter, size_t nelmts,
void *_tgath_buf /*out*/);
H5_DLL herr_t H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space);
H5_DLL herr_t H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space);
H5_DLL herr_t H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
H5_DLL herr_t H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info);
/* Functions that operate on dataset's layout information */
H5_DLL herr_t H5D__layout_set_io_ops(const H5D_t *dataset);
@@ -620,25 +645,23 @@ H5_DLL herr_t H5D__layout_oh_write(const H5D_t *dataset, H5O_t *oh, unsigned upd
H5_DLL herr_t H5D__contig_alloc(H5F_t *f, H5O_storage_contig_t *storage);
H5_DLL hbool_t H5D__contig_is_space_alloc(const H5O_storage_t *storage);
H5_DLL hbool_t H5D__contig_is_data_cached(const H5D_shared_t *shared_dset);
H5_DLL herr_t H5D__contig_fill(const H5D_io_info_t *io_info);
H5_DLL herr_t H5D__contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm);
H5_DLL herr_t H5D__contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm);
H5_DLL herr_t H5D__contig_fill(H5D_t *dset);
H5_DLL herr_t H5D__contig_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
H5_DLL herr_t H5D__contig_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
H5_DLL herr_t H5D__contig_copy(H5F_t *f_src, const H5O_storage_contig_t *storage_src, H5F_t *f_dst,
H5O_storage_contig_t *storage_dst, H5T_t *src_dtype, H5O_copy_t *cpy_info);
H5_DLL herr_t H5D__contig_delete(H5F_t *f, const H5O_storage_t *store);
/* Functions that operate on chunked dataset storage */
H5_DLL htri_t H5D__chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr, hbool_t write_op);
H5_DLL herr_t H5D__chunk_create(const H5D_t *dset /*in,out*/);
H5_DLL herr_t H5D__chunk_set_info(const H5D_t *dset);
H5_DLL htri_t H5D__chunk_cacheable(const H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info, haddr_t caddr,
hbool_t write_op);
H5_DLL herr_t H5D__chunk_create(const H5D_t *dset /*in,out*/);
H5_DLL herr_t H5D__chunk_set_info(const H5D_t *dset);
H5_DLL hbool_t H5D__chunk_is_space_alloc(const H5O_storage_t *storage);
H5_DLL hbool_t H5D__chunk_is_data_cached(const H5D_shared_t *shared_dset);
H5_DLL herr_t H5D__chunk_lookup(const H5D_t *dset, const hsize_t *scaled, H5D_chunk_ud_t *udata);
H5_DLL herr_t H5D__chunk_allocated(const H5D_t *dset, hsize_t *nbytes);
H5_DLL herr_t H5D__chunk_allocate(const H5D_io_info_t *io_info, hbool_t full_overwrite,
const hsize_t old_dim[]);
H5_DLL herr_t H5D__chunk_allocate(const H5D_t *dset, hbool_t full_overwrite, const hsize_t old_dim[]);
H5_DLL herr_t H5D__chunk_file_alloc(const H5D_chk_idx_info_t *idx_info, const H5F_block_t *old_chunk,
H5F_block_t *new_chunk, hbool_t *need_insert, const hsize_t *scaled);
H5_DLL void *H5D__chunk_mem_alloc(size_t size, void *pline);
@@ -651,7 +674,7 @@ H5_DLL hbool_t H5D__chunk_is_partial_edge_chunk(unsigned dset_ndims, const uint3
H5_DLL herr_t H5D__chunk_prune_by_extent(H5D_t *dset, const hsize_t *old_dim);
H5_DLL herr_t H5D__chunk_set_sizes(H5D_t *dset);
#ifdef H5_HAVE_PARALLEL
H5_DLL herr_t H5D__chunk_addrmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[]);
H5_DLL herr_t H5D__chunk_addrmap(const H5D_t *dset, haddr_t chunk_addr[]);
#endif /* H5_HAVE_PARALLEL */
H5_DLL herr_t H5D__chunk_update_cache(H5D_t *dset);
H5_DLL herr_t H5D__chunk_copy(H5F_t *f_src, H5O_storage_chunk_t *storage_src, H5O_layout_chunk_t *layout_src,
@@ -662,8 +685,8 @@ H5_DLL herr_t H5D__chunk_bh_info(const H5O_loc_t *loc, H5O_t *oh, H5O_layout_t *
H5_DLL herr_t H5D__chunk_dump_index(H5D_t *dset, FILE *stream);
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(const H5D_t *dset, uint32_t filters, hsize_t *offset,
uint32_t data_size, const void *buf);
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);
#ifdef H5D_CHUNK_DEBUG
H5_DLL herr_t H5D__chunk_stats(const H5D_t *dset, hbool_t headers);
@@ -711,39 +734,31 @@ H5_DLL herr_t H5D__fill_term(H5D_fill_buf_info_t *fb_info);
#define H5Dmpio_DEBUG
#endif /*H5Dmpio_DEBUG*/
#endif /*H5D_DEBUG*/
/* MPI-IO function to read, it will select either regular or irregular read */
H5_DLL herr_t H5D__mpio_select_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space);
/* MPI-IO function to read multi-dsets (Chunk, Contig), it will select either
* regular or irregular read */
H5_DLL herr_t H5D__mpio_select_read(const H5D_io_info_t *io_info, hsize_t nelmts, H5S_t *file_space,
H5S_t *mem_space);
/* MPI-IO function to write, it will select either regular or irregular read */
H5_DLL herr_t H5D__mpio_select_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space);
/* MPI-IO function to write multi-dsets (Chunk, Contig), it will select either
* regular or irregular write */
H5_DLL herr_t H5D__mpio_select_write(const H5D_io_info_t *io_info, hsize_t nelmts, H5S_t *file_space,
H5S_t *mem_space);
/* MPI-IO functions to handle contiguous collective IO */
H5_DLL herr_t H5D__contig_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space,
H5D_chunk_map_t *fm);
H5_DLL herr_t H5D__contig_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space,
H5D_chunk_map_t *fm);
/* MPI-IO functions to handle chunked collective IO */
H5_DLL herr_t H5D__chunk_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space,
H5D_chunk_map_t *fm);
H5_DLL herr_t H5D__chunk_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
hsize_t nelmts, H5S_t *file_space, H5S_t *mem_space,
H5D_chunk_map_t *fm);
/* MPI-IO functions to handle collective IO for multiple dsets (CONTIG, CHUNK) */
H5_DLL herr_t H5D__collective_read(H5D_io_info_t *io_info);
H5_DLL herr_t H5D__collective_write(H5D_io_info_t *io_info);
/* MPI-IO function to check if a direct I/O transfer is possible between
* memory and the file */
H5_DLL htri_t H5D__mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space,
const H5S_t *mem_space, const H5D_type_info_t *type_info);
H5_DLL htri_t H5D__mpio_opt_possible(H5D_io_info_t *io_info);
H5_DLL herr_t H5D__mpio_get_no_coll_cause_strings(char *local_cause, size_t local_cause_len,
char *global_cause, size_t global_cause_len);
#endif /* H5_HAVE_PARALLEL */
/* Free a piece (chunk or contiguous dataset data block) info struct */
H5_DLL herr_t H5D__free_piece_info(void *item, void *key, void *opdata);
/* Testing functions */
#ifdef H5D_TESTING
H5_DLL herr_t H5D__layout_version_test(hid_t did, unsigned *version);
+111
View File
@@ -850,6 +850,52 @@ H5_DLL haddr_t H5Dget_offset(hid_t dset_id);
H5_DLL herr_t H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, void *buf /*out*/);
/**
* --------------------------------------------------------------------------
* \ingroup H5D
*
* \brief Reads raw data from a set of datasets into the provided buffers
*
* \param[in] count Number of datasets to read from
* \param[in] dset_id Identifiers of the datasets to read from
* \param[in] mem_type_id Identifiers of the memory datatypes
* \param[in] mem_space_id Identifiers of the memory dataspaces
* \param[in] file_space_id Identifiers of the datasets' dataspaces in the file
* \param[in] dxpl_id Identifier of a transfer property list
* \param[out] buf Buffers to receive data read from file
*
* \return \herr_t
*
* \details H5Dread_multi() reads data from \p count datasets, whose identifiers
* are listed in the \p dset_id array, from the file into multiple
* application memory buffers listed in the \p buf array. Data transfer
* properties are defined by the argument \p dxpl_id. The memory
* datatypes of each dataset are listed by identifier in the \p
* mem_type_id array. The parts of each dataset to read are listed by
* identifier in the \p file_space_id array, and the parts of each
* application memory buffer to read to are listed by identifier in the
* \p mem_space_id array. All array parameters have length \p count.
*
* This function will produce the same results as \p count calls to
* H5Dread(). Information listed in that function about the specifics
* of its behaviour also apply to H5Dread_multi(). By calling
* H5Dread_multi() instead of multiple calls to H5Dread(), however, the
* library can in some cases pass information about the entire I/O
* operation to the file driver, which can improve performance.
*
* All datasets must be in the same HDF5 file, and each unique dataset
* may only be listed once. If this function is called collectively in
* parallel, each rank must pass exactly the same list of datasets in
* \p dset_id , though the other parameters may differ.
*
* \since 1.13.3
*
* \see H5Dread()
*
*/
H5_DLL herr_t H5Dread_multi(size_t count, hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, void *buf[] /*out*/);
/**
* --------------------------------------------------------------------------
* \ingroup ASYNC
@@ -859,6 +905,15 @@ H5_DLL herr_t H5Dread_async(const char *app_file, const char *app_func, unsigned
hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id,
void *buf /*out*/, hid_t es_id);
/**
* --------------------------------------------------------------------------
* \ingroup ASYNC
* \async_variant_of{H5Dread_multi}
*/
H5_DLL herr_t H5Dread_multi_async(const char *app_file, const char *app_func, unsigned app_line, size_t count,
hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, void *buf[] /*out*/, hid_t es_id);
/**
* --------------------------------------------------------------------------
* \ingroup H5D
@@ -975,6 +1030,53 @@ H5_DLL herr_t H5Dread_async(const char *app_file, const char *app_func, unsigned
H5_DLL herr_t H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, const void *buf);
/**
* --------------------------------------------------------------------------
* \ingroup H5D
*
* \brief Writes raw data from a set buffers to a set of datasets
*
* \param[in] count Number of datasets to write to
* \param[in] dset_id Identifiers of the datasets to write to
* \param[in] mem_type_id Identifiers of the memory datatypes
* \param[in] mem_space_id Identifiers of the memory dataspaces
* \param[in] file_space_id Identifiers of the datasets' dataspaces in the file
* \param[in] dxpl_id Identifier of a transfer property list
* \param[in] buf Buffers with data to be written to the file
*
* \return \herr_t
*
* \details H5Dwrite_multi() writes data to \p count datasets, whose identifiers
* are listed in the \p dset_id array, from multiple application memory
* buffers listed in the \p buf array. Data transfer properties are
* defined by the argument \p dxpl_id. The memory datatypes of each
* dataset are listed by identifier in the \p mem_type_id array. The
* parts of each dataset to write are listed by identifier in the \p
* file_space_id array, and the parts of each application memory buffer
* to write from are listed by identifier in the \p mem_space_id array.
* All array parameters have length \p count.
*
* This function will produce the same results as \p count calls to
* H5Dwrite(). Information listed in that function's documentation
* about the specifics of its behaviour also apply to H5Dwrite_multi().
* By calling H5Dwrite_multi() instead of multiple calls to H5Dwrite(),
* however, the library can in some cases pass information about the
* entire I/O operation to the file driver, which can improve
* performance.
*
* All datasets must be in the same HDF5 file, and each unique dataset
* may only be listed once. If this function is called collectively in
* parallel, each rank must pass exactly the same list of datasets in
* \p dset_id , though the other parameters may differ.
*
* \since 1.13.3
*
* \see H5Dwrite()
*
*/
H5_DLL herr_t H5Dwrite_multi(size_t count, hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[]);
/**
* --------------------------------------------------------------------------
* \ingroup ASYNC
@@ -984,6 +1086,15 @@ H5_DLL herr_t H5Dwrite_async(const char *app_file, const char *app_func, unsigne
hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id,
const void *buf, hid_t es_id);
/**
* --------------------------------------------------------------------------
* \ingroup ASYNC
* \async_variant_of{H5Dwrite_multi}
*/
H5_DLL herr_t H5Dwrite_multi_async(const char *app_file, const char *app_func, unsigned app_line,
size_t count, hid_t dset_id[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[], hid_t es_id);
/**
* --------------------------------------------------------------------------
* \ingroup H5D
+123 -102
View File
@@ -39,13 +39,13 @@
/********************/
/* Local Prototypes */
/********************/
static herr_t H5D__scatter_file(const H5D_io_info_t *io_info, H5S_sel_iter_t *file_iter, size_t nelmts,
const void *buf);
static size_t H5D__gather_file(const H5D_io_info_t *io_info, H5S_sel_iter_t *file_iter, size_t nelmts,
void *buf);
static herr_t H5D__scatter_file(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
H5S_sel_iter_t *file_iter, size_t nelmts, const void *buf);
static size_t H5D__gather_file(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
H5S_sel_iter_t *file_iter, size_t nelmts, void *buf);
static herr_t H5D__compound_opt_read(size_t nelmts, H5S_sel_iter_t *iter, const H5D_type_info_t *type_info,
void *user_buf /*out*/);
static herr_t H5D__compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info);
uint8_t *tconv_buf, void *user_buf /*out*/);
static herr_t H5D__compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info, uint8_t *tconv_buf);
/*********************/
/* Package Variables */
@@ -81,33 +81,40 @@ H5FL_SEQ_EXTERN(hsize_t);
*-------------------------------------------------------------------------
*/
static herr_t
H5D__scatter_file(const H5D_io_info_t *_io_info, H5S_sel_iter_t *iter, size_t nelmts, const void *_buf)
H5D__scatter_file(const H5D_io_info_t *_io_info, const H5D_dset_io_info_t *_dset_info, H5S_sel_iter_t *iter,
size_t nelmts, const void *_buf)
{
H5D_io_info_t tmp_io_info; /* Temporary I/O info object */
hsize_t *off = NULL; /* Pointer to sequence offsets */
hsize_t mem_off; /* Offset in memory */
size_t mem_curr_seq; /* "Current sequence" in memory */
size_t dset_curr_seq; /* "Current sequence" in dataset */
size_t *len = NULL; /* Array to store sequence lengths */
size_t orig_mem_len, mem_len; /* Length of sequence in memory */
size_t nseq; /* Number of sequences generated */
size_t nelem; /* Number of elements used in sequences */
size_t dxpl_vec_size; /* Vector length from API context's DXPL */
size_t vec_size; /* Vector length */
herr_t ret_value = SUCCEED; /* Return value */
H5D_io_info_t tmp_io_info; /* Temporary I/O info object */
H5D_dset_io_info_t tmp_dset_info; /* Temporary I/O info object */
hsize_t *off = NULL; /* Pointer to sequence offsets */
hsize_t mem_off; /* Offset in memory */
size_t mem_curr_seq; /* "Current sequence" in memory */
size_t dset_curr_seq; /* "Current sequence" in dataset */
size_t *len = NULL; /* Array to store sequence lengths */
size_t orig_mem_len, mem_len; /* Length of sequence in memory */
size_t nseq; /* Number of sequences generated */
size_t nelem; /* Number of elements used in sequences */
size_t dxpl_vec_size; /* Vector length from API context's DXPL */
size_t vec_size; /* Vector length */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Check args */
HDassert(_io_info);
HDassert(_dset_info);
HDassert(_dset_info->dset);
HDassert(_dset_info->store);
HDassert(iter);
HDassert(nelmts > 0);
HDassert(_buf);
/* Set up temporary I/O info object */
H5MM_memcpy(&tmp_io_info, _io_info, sizeof(*_io_info));
tmp_io_info.op_type = H5D_IO_OP_WRITE;
tmp_io_info.u.wbuf = _buf;
HDmemcpy(&tmp_dset_info, _dset_info, sizeof(*_dset_info));
tmp_io_info.op_type = H5D_IO_OP_WRITE;
tmp_dset_info.buf.cvp = _buf;
tmp_io_info.dsets_info = &tmp_dset_info;
/* Get info from API context */
if (H5CX_get_vec_size(&dxpl_vec_size) < 0)
@@ -135,12 +142,12 @@ H5D__scatter_file(const H5D_io_info_t *_io_info, H5S_sel_iter_t *iter, size_t ne
mem_off = 0;
/* Write sequence list out */
if ((*tmp_io_info.layout_ops.writevv)(&tmp_io_info, nseq, &dset_curr_seq, len, off, (size_t)1,
&mem_curr_seq, &mem_len, &mem_off) < 0)
if ((*tmp_dset_info.layout_ops.writevv)(&tmp_io_info, &tmp_dset_info, nseq, &dset_curr_seq, len, off,
(size_t)1, &mem_curr_seq, &mem_len, &mem_off) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
/* Update buffer */
tmp_io_info.u.wbuf = (const uint8_t *)tmp_io_info.u.wbuf + orig_mem_len;
tmp_dset_info.buf.cvp = (const uint8_t *)tmp_dset_info.buf.cvp + orig_mem_len;
/* Decrement number of elements left to process */
nelmts -= nelem;
@@ -178,35 +185,40 @@ done:
*-------------------------------------------------------------------------
*/
static size_t
H5D__gather_file(const H5D_io_info_t *_io_info, H5S_sel_iter_t *iter, size_t nelmts, void *_buf /*out*/)
H5D__gather_file(const H5D_io_info_t *_io_info, const H5D_dset_io_info_t *_dset_info, H5S_sel_iter_t *iter,
size_t nelmts, void *_buf /*out*/)
{
H5D_io_info_t tmp_io_info; /* Temporary I/O info object */
hsize_t *off = NULL; /* Pointer to sequence offsets */
hsize_t mem_off; /* Offset in memory */
size_t mem_curr_seq; /* "Current sequence" in memory */
size_t dset_curr_seq; /* "Current sequence" in dataset */
size_t *len = NULL; /* Pointer to sequence lengths */
size_t orig_mem_len, mem_len; /* Length of sequence in memory */
size_t nseq; /* Number of sequences generated */
size_t nelem; /* Number of elements used in sequences */
size_t dxpl_vec_size; /* Vector length from API context's DXPL */
size_t vec_size; /* Vector length */
size_t ret_value = nelmts; /* Return value */
H5D_io_info_t tmp_io_info; /* Temporary I/O info object */
H5D_dset_io_info_t tmp_dset_info; /* Temporary I/O info object */
hsize_t *off = NULL; /* Pointer to sequence offsets */
hsize_t mem_off; /* Offset in memory */
size_t mem_curr_seq; /* "Current sequence" in memory */
size_t dset_curr_seq; /* "Current sequence" in dataset */
size_t *len = NULL; /* Pointer to sequence lengths */
size_t orig_mem_len, mem_len; /* Length of sequence in memory */
size_t nseq; /* Number of sequences generated */
size_t nelem; /* Number of elements used in sequences */
size_t dxpl_vec_size; /* Vector length from API context's DXPL */
size_t vec_size; /* Vector length */
size_t ret_value = nelmts; /* Return value */
FUNC_ENTER_PACKAGE
/* Check args */
HDassert(_io_info);
HDassert(_io_info->dset);
HDassert(_io_info->store);
HDassert(_dset_info);
HDassert(_dset_info->dset);
HDassert(_dset_info->store);
HDassert(iter);
HDassert(nelmts > 0);
HDassert(_buf);
/* Set up temporary I/O info object */
H5MM_memcpy(&tmp_io_info, _io_info, sizeof(*_io_info));
tmp_io_info.op_type = H5D_IO_OP_READ;
tmp_io_info.u.rbuf = _buf;
HDmemcpy(&tmp_dset_info, _dset_info, sizeof(*_dset_info));
tmp_io_info.op_type = H5D_IO_OP_READ;
tmp_dset_info.buf.vp = _buf;
tmp_io_info.dsets_info = &tmp_dset_info;
/* Get info from API context */
if (H5CX_get_vec_size(&dxpl_vec_size) < 0)
@@ -234,12 +246,12 @@ H5D__gather_file(const H5D_io_info_t *_io_info, H5S_sel_iter_t *iter, size_t nel
mem_off = 0;
/* Read sequence list in */
if ((*tmp_io_info.layout_ops.readvv)(&tmp_io_info, nseq, &dset_curr_seq, len, off, (size_t)1,
&mem_curr_seq, &mem_len, &mem_off) < 0)
if ((*tmp_dset_info.layout_ops.readvv)(&tmp_io_info, &tmp_dset_info, nseq, &dset_curr_seq, len, off,
(size_t)1, &mem_curr_seq, &mem_len, &mem_off) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error")
/* Update buffer */
tmp_io_info.u.rbuf = (uint8_t *)tmp_io_info.u.rbuf + orig_mem_len;
tmp_dset_info.buf.vp = (uint8_t *)tmp_dset_info.buf.vp + orig_mem_len;
/* Decrement number of elements left to process */
nelmts -= nelem;
@@ -436,11 +448,10 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space)
H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info)
{
void *buf = io_info->u.rbuf; /* Local pointer to application buffer */
H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info*/
void *buf; /* Local pointer to application buffer */
H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info*/
hbool_t mem_iter_init = FALSE; /* Memory selection iteration info has been initialized */
H5S_sel_iter_t *bkg_iter = NULL; /* Background iteration info*/
hbool_t bkg_iter_init = FALSE; /* Background iteration info has been initialized */
@@ -454,13 +465,16 @@ H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
/* Sanity check */
HDassert(io_info);
HDassert(type_info);
HDassert(mem_space);
HDassert(file_space);
HDassert(buf);
HDassert(dset_info);
HDassert(dset_info->mem_space);
HDassert(dset_info->file_space);
HDassert(dset_info->buf.vp);
/* Set buf pointer */
buf = dset_info->buf.vp;
/* Check for NOOP read */
if (nelmts == 0)
if (dset_info->nelmts == 0)
HGOTO_DONE(SUCCEED)
/* Allocate the iterators */
@@ -472,24 +486,24 @@ H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate file iterator")
/* Figure out the strip mine size. */
if (H5S_select_iter_init(file_iter, file_space, type_info->src_type_size,
if (H5S_select_iter_init(file_iter, dset_info->file_space, dset_info->type_info.src_type_size,
H5S_SEL_ITER_GET_SEQ_LIST_SORTED) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
file_iter_init = TRUE; /*file selection iteration info has been initialized */
if (H5S_select_iter_init(mem_iter, mem_space, type_info->dst_type_size, 0) < 0)
if (H5S_select_iter_init(mem_iter, dset_info->mem_space, dset_info->type_info.dst_type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
mem_iter_init = TRUE; /*file selection iteration info has been initialized */
if (H5S_select_iter_init(bkg_iter, mem_space, type_info->dst_type_size, 0) < 0)
if (H5S_select_iter_init(bkg_iter, dset_info->mem_space, dset_info->type_info.dst_type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
bkg_iter_init = TRUE; /*file selection iteration info has been initialized */
/* Start strip mining... */
for (smine_start = 0; smine_start < nelmts; smine_start += smine_nelmts) {
for (smine_start = 0; smine_start < dset_info->nelmts; smine_start += smine_nelmts) {
size_t n; /* Elements operated on */
/* Go figure out how many elements to read from the file */
HDassert(H5S_SELECT_ITER_NELMTS(file_iter) == (nelmts - smine_start));
smine_nelmts = (size_t)MIN(type_info->request_nelmts, (nelmts - smine_start));
HDassert(H5S_SELECT_ITER_NELMTS(file_iter) == (dset_info->nelmts - smine_start));
smine_nelmts = (size_t)MIN(dset_info->type_info.request_nelmts, (dset_info->nelmts - smine_start));
/*
* Gather the data from disk into the datatype conversion
@@ -500,7 +514,7 @@ H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
/*
* Gather data
*/
n = H5D__gather_file(io_info, file_iter, smine_nelmts, type_info->tconv_buf /*out*/);
n = H5D__gather_file(io_info, dset_info, file_iter, smine_nelmts, io_info->tconv_buf /*out*/);
if (n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
@@ -508,13 +522,15 @@ H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
* and no conversion is needed, copy the data directly into user's buffer and
* bypass the rest of steps.
*/
if (type_info->cmpd_subset && H5T_SUBSET_FALSE != type_info->cmpd_subset->subset) {
if (H5D__compound_opt_read(smine_nelmts, mem_iter, type_info, buf /*out*/) < 0)
if (dset_info->type_info.cmpd_subset &&
H5T_SUBSET_FALSE != dset_info->type_info.cmpd_subset->subset) {
if (H5D__compound_opt_read(smine_nelmts, mem_iter, &dset_info->type_info, io_info->tconv_buf,
buf /*out*/) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
} /* end if */
else {
if (H5T_BKG_YES == type_info->need_bkg) {
n = H5D__gather_mem(buf, bkg_iter, smine_nelmts, type_info->bkg_buf /*out*/);
if (H5T_BKG_YES == dset_info->type_info.need_bkg) {
n = H5D__gather_mem(buf, bkg_iter, smine_nelmts, dset_info->type_info.bkg_buf /*out*/);
if (n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
} /* end if */
@@ -522,25 +538,26 @@ H5D__scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
/*
* Perform datatype conversion.
*/
if (H5T_convert(type_info->tpath, type_info->src_type_id, type_info->dst_type_id, smine_nelmts,
(size_t)0, (size_t)0, type_info->tconv_buf, type_info->bkg_buf) < 0)
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
dset_info->type_info.dst_type_id, smine_nelmts, (size_t)0, (size_t)0,
io_info->tconv_buf, dset_info->type_info.bkg_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
/* Do the data transform after the conversion (since we're using type mem_type) */
if (!type_info->is_xform_noop) {
if (!dset_info->type_info.is_xform_noop) {
H5Z_data_xform_t *data_transform; /* Data transform info */
/* Retrieve info from API context */
if (H5CX_get_data_transform(&data_transform) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data transform info")
if (H5Z_xform_eval(data_transform, type_info->tconv_buf, smine_nelmts, type_info->mem_type) <
0)
if (H5Z_xform_eval(data_transform, io_info->tconv_buf, smine_nelmts,
dset_info->type_info.mem_type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Error performing data transform")
}
/* Scatter the data into memory */
if (H5D__scatter_mem(type_info->tconv_buf, mem_iter, smine_nelmts, buf /*out*/) < 0)
if (H5D__scatter_mem(io_info->tconv_buf, mem_iter, smine_nelmts, buf /*out*/) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
} /* end else */
} /* end for */
@@ -576,11 +593,10 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space)
H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info)
{
const void *buf = io_info->u.wbuf; /* Local pointer to application buffer */
H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info*/
const void *buf; /* Local pointer to application buffer */
H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info*/
hbool_t mem_iter_init = FALSE; /* Memory selection iteration info has been initialized */
H5S_sel_iter_t *bkg_iter = NULL; /* Background iteration info*/
hbool_t bkg_iter_init = FALSE; /* Background iteration info has been initialized */
@@ -594,13 +610,16 @@ H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_in
/* Sanity check */
HDassert(io_info);
HDassert(type_info);
HDassert(mem_space);
HDassert(file_space);
HDassert(buf);
HDassert(dset_info);
HDassert(dset_info->mem_space);
HDassert(dset_info->file_space);
HDassert(dset_info->buf.vp);
/* Set buf pointer */
buf = dset_info->buf.cvp;
/* Check for NOOP write */
if (nelmts == 0)
if (dset_info->nelmts == 0)
HGOTO_DONE(SUCCEED)
/* Allocate the iterators */
@@ -612,32 +631,32 @@ H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_in
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate file iterator")
/* Figure out the strip mine size. */
if (H5S_select_iter_init(file_iter, file_space, type_info->dst_type_size,
if (H5S_select_iter_init(file_iter, dset_info->file_space, dset_info->type_info.dst_type_size,
H5S_SEL_ITER_GET_SEQ_LIST_SORTED) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
file_iter_init = TRUE; /*file selection iteration info has been initialized */
if (H5S_select_iter_init(mem_iter, mem_space, type_info->src_type_size, 0) < 0)
if (H5S_select_iter_init(mem_iter, dset_info->mem_space, dset_info->type_info.src_type_size, 0) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
mem_iter_init = TRUE; /*file selection iteration info has been initialized */
if (H5S_select_iter_init(bkg_iter, file_space, type_info->dst_type_size,
if (H5S_select_iter_init(bkg_iter, dset_info->file_space, dset_info->type_info.dst_type_size,
H5S_SEL_ITER_GET_SEQ_LIST_SORTED) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
bkg_iter_init = TRUE; /*file selection iteration info has been initialized */
/* Start strip mining... */
for (smine_start = 0; smine_start < nelmts; smine_start += smine_nelmts) {
for (smine_start = 0; smine_start < dset_info->nelmts; smine_start += smine_nelmts) {
size_t n; /* Elements operated on */
/* Go figure out how many elements to read from the file */
HDassert(H5S_SELECT_ITER_NELMTS(file_iter) == (nelmts - smine_start));
smine_nelmts = (size_t)MIN(type_info->request_nelmts, (nelmts - smine_start));
HDassert(H5S_SELECT_ITER_NELMTS(file_iter) == (dset_info->nelmts - smine_start));
smine_nelmts = (size_t)MIN(dset_info->type_info.request_nelmts, (dset_info->nelmts - smine_start));
/*
* Gather data from application buffer into the datatype conversion
* buffer. Also gather data from the file into the background buffer
* if necessary.
*/
n = H5D__gather_mem(buf, mem_iter, smine_nelmts, type_info->tconv_buf /*out*/);
n = H5D__gather_mem(buf, mem_iter, smine_nelmts, io_info->tconv_buf /*out*/);
if (n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed")
@@ -647,44 +666,46 @@ H5D__scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_in
* is a subset of the destination, the optimization is done in conversion
* function H5T_conv_struct_opt to protect the background data.
*/
if (type_info->cmpd_subset && H5T_SUBSET_DST == type_info->cmpd_subset->subset &&
type_info->dst_type_size == type_info->cmpd_subset->copy_size) {
if (H5D__compound_opt_write(smine_nelmts, type_info) < 0)
if (dset_info->type_info.cmpd_subset && H5T_SUBSET_DST == dset_info->type_info.cmpd_subset->subset &&
dset_info->type_info.dst_type_size == dset_info->type_info.cmpd_subset->copy_size) {
if (H5D__compound_opt_write(smine_nelmts, &dset_info->type_info, io_info->tconv_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
} /* end if */
else {
if (H5T_BKG_YES == type_info->need_bkg) {
n = H5D__gather_file(io_info, bkg_iter, smine_nelmts, type_info->bkg_buf /*out*/);
if (H5T_BKG_YES == dset_info->type_info.need_bkg) {
n = H5D__gather_file(io_info, dset_info, bkg_iter, smine_nelmts,
dset_info->type_info.bkg_buf /*out*/);
if (n != smine_nelmts)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
} /* end if */
/* Do the data transform before the type conversion (since
* transforms must be done in the memory type). */
if (!type_info->is_xform_noop) {
if (!dset_info->type_info.is_xform_noop) {
H5Z_data_xform_t *data_transform; /* Data transform info */
/* Retrieve info from API context */
if (H5CX_get_data_transform(&data_transform) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data transform info")
if (H5Z_xform_eval(data_transform, type_info->tconv_buf, smine_nelmts, type_info->mem_type) <
0)
if (H5Z_xform_eval(data_transform, io_info->tconv_buf, smine_nelmts,
dset_info->type_info.mem_type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "Error performing data transform")
}
/*
* Perform datatype conversion.
*/
if (H5T_convert(type_info->tpath, type_info->src_type_id, type_info->dst_type_id, smine_nelmts,
(size_t)0, (size_t)0, type_info->tconv_buf, type_info->bkg_buf) < 0)
if (H5T_convert(dset_info->type_info.tpath, dset_info->type_info.src_type_id,
dset_info->type_info.dst_type_id, smine_nelmts, (size_t)0, (size_t)0,
io_info->tconv_buf, dset_info->type_info.bkg_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
} /* end else */
/*
* Scatter the data out to the file.
*/
if (H5D__scatter_file(io_info, file_iter, smine_nelmts, type_info->tconv_buf) < 0)
if (H5D__scatter_file(io_info, dset_info, file_iter, smine_nelmts, io_info->tconv_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "scatter failed")
} /* end for */
@@ -740,7 +761,7 @@ done:
*/
static herr_t
H5D__compound_opt_read(size_t nelmts, H5S_sel_iter_t *iter, const H5D_type_info_t *type_info,
void *user_buf /*out*/)
uint8_t *tconv_buf, void *user_buf /*out*/)
{
uint8_t *ubuf = (uint8_t *)user_buf; /* Cast for pointer arithmetic */
uint8_t *xdbuf; /* Pointer into dataset buffer */
@@ -784,7 +805,7 @@ H5D__compound_opt_read(size_t nelmts, H5S_sel_iter_t *iter, const H5D_type_info_
copy_size = type_info->cmpd_subset->copy_size;
/* Loop until all elements are written */
xdbuf = type_info->tconv_buf;
xdbuf = tconv_buf;
while (nelmts > 0) {
size_t nseq; /* Number of sequences generated */
size_t curr_seq; /* Current sequence being processed */
@@ -869,7 +890,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info)
H5D__compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info, uint8_t *tconv_buf)
{
uint8_t *xsbuf, *xdbuf; /* Source & destination pointers into dataset buffer */
size_t src_stride, dst_stride; /* Strides through source & destination datatypes */
@@ -886,8 +907,8 @@ H5D__compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info)
dst_stride = type_info->dst_type_size;
/* Loop until all elements are written */
xsbuf = (uint8_t *)type_info->tconv_buf;
xdbuf = (uint8_t *)type_info->tconv_buf;
xsbuf = tconv_buf;
xdbuf = tconv_buf;
for (i = 0; i < nelmts; i++) {
HDmemmove(xdbuf, xsbuf, dst_stride);
+31 -31
View File
@@ -44,8 +44,8 @@
/* Local Prototypes */
/********************/
static herr_t H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, H5S_t *file_space,
H5S_t *mem_space);
static herr_t H5D__select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
size_t elmt_size);
/*********************/
/* Package Variables */
@@ -77,8 +77,7 @@ H5FL_EXTERN(H5S_sel_iter_t);
*-------------------------------------------------------------------------
*/
static herr_t
H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, H5S_t *file_space,
H5S_t *mem_space)
H5D__select_io(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, size_t elmt_size)
{
H5S_sel_iter_t *mem_iter = NULL; /* Memory selection iteration info */
hbool_t mem_iter_init = FALSE; /* Memory selection iteration info has been initialized */
@@ -95,19 +94,23 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, H5
size_t dxpl_vec_size; /* Vector length from API context's DXPL */
size_t vec_size; /* Vector length */
ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */
size_t nelmts; /* Number of elements to process */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Check args */
HDassert(io_info);
HDassert(io_info->dset);
HDassert(io_info->store);
HDassert(io_info->u.rbuf);
HDassert(dset_info->dset);
HDassert(dset_info->store);
HDassert(dset_info->buf.vp);
if (elmt_size == 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "invalid elmt_size of 0")
/* Initialize nelmts */
nelmts = dset_info->nelmts;
/* Check for only one element in selection */
if (nelmts == 1) {
hsize_t single_mem_off; /* Offset in memory */
@@ -116,9 +119,9 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, H5
size_t single_file_len; /* Length in the file */
/* Get offset of first element in selections */
if (H5S_SELECT_OFFSET(file_space, &single_file_off) < 0)
if (H5S_SELECT_OFFSET(dset_info->file_space, &single_file_off) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "can't retrieve file selection offset")
if (H5S_SELECT_OFFSET(mem_space, &single_mem_off) < 0)
if (H5S_SELECT_OFFSET(dset_info->mem_space, &single_mem_off) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "can't retrieve memory selection offset")
/* Set up necessary information for I/O operation */
@@ -130,16 +133,16 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, H5
/* Perform I/O on memory and file sequences */
if (io_info->op_type == H5D_IO_OP_READ) {
if ((tmp_file_len = (*io_info->layout_ops.readvv)(
io_info, file_nseq, &curr_file_seq, &single_file_len, &single_file_off, mem_nseq,
&curr_mem_seq, &single_mem_len, &single_mem_off)) < 0)
if ((tmp_file_len = (*dset_info->layout_ops.readvv)(
io_info, dset_info, file_nseq, &curr_file_seq, &single_file_len, &single_file_off,
mem_nseq, &curr_mem_seq, &single_mem_len, &single_mem_off)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
} /* end if */
else {
HDassert(io_info->op_type == H5D_IO_OP_WRITE);
if ((tmp_file_len = (*io_info->layout_ops.writevv)(
io_info, file_nseq, &curr_file_seq, &single_file_len, &single_file_off, mem_nseq,
&curr_mem_seq, &single_mem_len, &single_mem_off)) < 0)
if ((tmp_file_len = (*dset_info->layout_ops.writevv)(
io_info, dset_info, file_nseq, &curr_file_seq, &single_file_len, &single_file_off,
mem_nseq, &curr_mem_seq, &single_mem_len, &single_mem_off)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
} /* end else */
@@ -175,12 +178,13 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, H5
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "can't allocate file iterator")
/* Initialize file iterator */
if (H5S_select_iter_init(file_iter, file_space, elmt_size, H5S_SEL_ITER_GET_SEQ_LIST_SORTED) < 0)
if (H5S_select_iter_init(file_iter, dset_info->file_space, elmt_size,
H5S_SEL_ITER_GET_SEQ_LIST_SORTED) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
file_iter_init = 1; /* File selection iteration info has been initialized */
/* Initialize memory iterator */
if (H5S_select_iter_init(mem_iter, mem_space, elmt_size, 0) < 0)
if (H5S_select_iter_init(mem_iter, dset_info->mem_space, elmt_size, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
mem_iter_init = 1; /* Memory selection iteration info has been initialized */
@@ -214,16 +218,16 @@ H5D__select_io(const H5D_io_info_t *io_info, size_t elmt_size, size_t nelmts, H5
/* Perform I/O on memory and file sequences */
if (io_info->op_type == H5D_IO_OP_READ) {
if ((tmp_file_len =
(*io_info->layout_ops.readvv)(io_info, file_nseq, &curr_file_seq, file_len, file_off,
mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0)
if ((tmp_file_len = (*dset_info->layout_ops.readvv)(
io_info, dset_info, file_nseq, &curr_file_seq, file_len, file_off, mem_nseq,
&curr_mem_seq, mem_len, mem_off)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
} /* end if */
else {
HDassert(io_info->op_type == H5D_IO_OP_WRITE);
if ((tmp_file_len = (*io_info->layout_ops.writevv)(io_info, file_nseq, &curr_file_seq,
file_len, file_off, mem_nseq,
&curr_mem_seq, mem_len, mem_off)) < 0)
if ((tmp_file_len = (*dset_info->layout_ops.writevv)(
io_info, dset_info, file_nseq, &curr_file_seq, file_len, file_off, mem_nseq,
&curr_mem_seq, mem_len, mem_off)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
} /* end else */
@@ -452,16 +456,14 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__select_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space)
H5D__select_read(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Call generic selection operation */
H5_CHECK_OVERFLOW(nelmts, hsize_t, size_t);
if (H5D__select_io(io_info, type_info->src_type_size, (size_t)nelmts, file_space, mem_space) < 0)
if (H5D__select_io(io_info, dset_info, dset_info->type_info.src_type_size) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
done:
@@ -481,16 +483,14 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5D__select_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space)
H5D__select_write(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Call generic selection operation */
H5_CHECK_OVERFLOW(nelmts, hsize_t, size_t);
if (H5D__select_io(io_info, type_info->dst_type_size, (size_t)nelmts, file_space, mem_space) < 0)
if (H5D__select_io(io_info, dset_info, dset_info->type_info.dst_type_size) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
done:
+122 -80
View File
@@ -83,10 +83,9 @@
/* Layout operation callbacks */
static hbool_t H5D__virtual_is_data_cached(const H5D_shared_t *shared_dset);
static herr_t H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm);
static herr_t H5D__virtual_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t *fm);
static herr_t H5D__virtual_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__virtual_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__virtual_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
static herr_t H5D__virtual_flush(H5D_t *dset);
/* Other functions */
@@ -103,13 +102,13 @@ static herr_t H5D__virtual_build_source_name(char
size_t static_strlen, size_t nsubs, hsize_t blockno,
char **built_name);
static herr_t H5D__virtual_init_all(const H5D_t *dset);
static herr_t H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_t *file_space,
H5S_t *mem_space, hsize_t *tot_nelmts);
static herr_t H5D__virtual_pre_io(H5D_dset_io_info_t *dset_info, H5O_storage_virtual_t *storage,
H5S_t *file_space, H5S_t *mem_space, hsize_t *tot_nelmts);
static herr_t H5D__virtual_post_io(H5O_storage_virtual_t *storage);
static herr_t H5D__virtual_read_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5S_t *file_space, H5O_storage_virtual_srcdset_t *source_dset);
static herr_t H5D__virtual_write_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
H5S_t *file_space, H5O_storage_virtual_srcdset_t *source_dset);
static herr_t H5D__virtual_read_one(H5D_dset_io_info_t *dset_info,
H5O_storage_virtual_srcdset_t *source_dset);
static herr_t H5D__virtual_write_one(H5D_dset_io_info_t *dset_info,
H5O_storage_virtual_srcdset_t *source_dset);
/*********************/
/* Package Variables */
@@ -121,18 +120,15 @@ const H5D_layout_ops_t H5D_LOPS_VIRTUAL[1] = {{
H5D__virtual_init, /* init */
H5D__virtual_is_space_alloc, /* is_space_alloc */
H5D__virtual_is_data_cached, /* is_data_cached */
NULL, /* io_init */
H5D__virtual_io_init, /* io_init */
NULL, /* mdio_init */
H5D__virtual_read, /* ser_read */
H5D__virtual_write, /* ser_write */
#ifdef H5_HAVE_PARALLEL
NULL, /* par_read */
NULL, /* par_write */
#endif
NULL, /* readvv */
NULL, /* writevv */
H5D__virtual_flush, /* flush */
NULL, /* io_term */
NULL /* dest */
NULL, /* readvv */
NULL, /* writevv */
H5D__virtual_flush, /* flush */
NULL, /* io_term */
NULL /* dest */
}};
/*******************/
@@ -2370,6 +2366,29 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__virtual_is_data_cached() */
/*-------------------------------------------------------------------------
* Function: H5D__virtual_io_init
*
* Purpose: Performs initialization before any sort of I/O on the raw data
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Neil Fortner
* Sunday, May 22, 2022
*
*-------------------------------------------------------------------------
*/
static herr_t
H5D__virtual_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t H5_ATTR_UNUSED *dinfo)
{
FUNC_ENTER_PACKAGE_NOERR
/* Disable selection I/O */
io_info->use_select_io = FALSE;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__virtual_io_init() */
/*-------------------------------------------------------------------------
* Function: H5D__virtual_pre_io
*
@@ -2386,16 +2405,17 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_t *file_space,
H5D__virtual_pre_io(H5D_dset_io_info_t *dset_info, H5O_storage_virtual_t *storage, H5S_t *file_space,
H5S_t *mem_space, hsize_t *tot_nelmts)
{
hssize_t select_nelmts; /* Number of elements in selection */
hsize_t bounds_start[H5S_MAX_RANK]; /* Selection bounds start */
hsize_t bounds_end[H5S_MAX_RANK]; /* Selection bounds end */
int rank = 0;
hbool_t bounds_init = FALSE; /* Whether bounds_start, bounds_end, and rank are valid */
size_t i, j, k; /* Local index variables */
herr_t ret_value = SUCCEED; /* Return value */
const H5D_t *dset = dset_info->dset; /* Local pointer to dataset info */
hssize_t select_nelmts; /* Number of elements in selection */
hsize_t bounds_start[H5S_MAX_RANK]; /* Selection bounds start */
hsize_t bounds_end[H5S_MAX_RANK]; /* Selection bounds end */
int rank = 0;
hbool_t bounds_init = FALSE; /* Whether bounds_start, bounds_end, and rank are valid */
size_t i, j, k; /* Local index variables */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2407,7 +2427,7 @@ H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_
/* Initialize layout if necessary */
if (!storage->init)
if (H5D__virtual_init_all(io_info->dset) < 0)
if (H5D__virtual_init_all(dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize virtual layout")
/* Initialize tot_nelmts */
@@ -2427,7 +2447,7 @@ H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_
/* Get selection bounds if necessary */
if (!bounds_init) {
/* Get rank of VDS */
if ((rank = H5S_GET_EXTENT_NDIMS(io_info->dset->shared->space)) < 0)
if ((rank = H5S_GET_EXTENT_NDIMS(dset->shared->space)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get number of dimensions")
/* Get selection bounds */
@@ -2469,7 +2489,7 @@ H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_
* open the source dataset to patch it */
if (storage->list[i].source_space_status != H5O_VIRTUAL_STATUS_CORRECT) {
HDassert(!storage->list[i].sub_dset[j].dset);
if (H5D__virtual_open_source_dset(io_info->dset, &storage->list[i],
if (H5D__virtual_open_source_dset(dset, &storage->list[i],
&storage->list[i].sub_dset[j]) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open source dataset")
} /* end if */
@@ -2499,7 +2519,7 @@ H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of dataspace")
/* Get current VDS dimensions */
if (H5S_get_simple_extent_dims(io_info->dset->shared->space, tmp_dims, NULL) < 0)
if (H5S_get_simple_extent_dims(dset->shared->space, tmp_dims, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get VDS dimensions")
/* Copy virtual selection */
@@ -2554,7 +2574,7 @@ H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_
/* Open source dataset */
if (!storage->list[i].sub_dset[j].dset)
/* Try to open dataset */
if (H5D__virtual_open_source_dset(io_info->dset, &storage->list[i],
if (H5D__virtual_open_source_dset(dset, &storage->list[i],
&storage->list[i].sub_dset[j]) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL,
"unable to open source dataset")
@@ -2599,7 +2619,7 @@ H5D__virtual_pre_io(H5D_io_info_t *io_info, H5O_storage_virtual_t *storage, H5S_
/* Open source dataset */
if (!storage->list[i].source_dset.dset)
/* Try to open dataset */
if (H5D__virtual_open_source_dset(io_info->dset, &storage->list[i],
if (H5D__virtual_open_source_dset(dset, &storage->list[i],
&storage->list[i].source_dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open source dataset")
@@ -2697,11 +2717,11 @@ H5D__virtual_post_io(H5O_storage_virtual_t *storage)
*-------------------------------------------------------------------------
*/
static herr_t
H5D__virtual_read_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5S_t *file_space,
H5O_storage_virtual_srcdset_t *source_dset)
H5D__virtual_read_one(H5D_dset_io_info_t *dset_info, H5O_storage_virtual_srcdset_t *source_dset)
{
H5S_t *projected_src_space = NULL; /* File space for selection in a single source dataset */
herr_t ret_value = SUCCEED; /* Return value */
H5S_t *projected_src_space = NULL; /* File space for selection in a single source dataset */
H5D_dset_io_info_t source_dinfo; /* Dataset info for source dataset read */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2717,15 +2737,23 @@ H5D__virtual_read_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
/* Project intersection of file space and mapping virtual space onto
* mapping source space */
if (H5S_select_project_intersection(source_dset->clipped_virtual_select,
source_dset->clipped_source_select, file_space,
source_dset->clipped_source_select, dset_info->file_space,
&projected_src_space, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL,
"can't project virtual intersection onto source space")
/* Perform read on source dataset */
if (H5D__read(source_dset->dset, type_info->dst_type_id, source_dset->projected_mem_space,
projected_src_space, io_info->u.rbuf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read source dataset")
{
/* Initialize source_dinfo */
source_dinfo.dset = source_dset->dset;
source_dinfo.mem_space = source_dset->projected_mem_space;
source_dinfo.file_space = projected_src_space;
source_dinfo.buf.vp = dset_info->buf.vp;
source_dinfo.mem_type_id = dset_info->type_info.dst_type_id;
/* Read in the point (with the custom VL memory allocator) */
if (H5D__read(1, &source_dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read source dataset")
}
/* Close projected_src_space */
if (H5S_close(projected_src_space) < 0)
@@ -2734,7 +2762,7 @@ H5D__virtual_read_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
} /* end if */
done:
/* Release allocated resources on failure */
/* Release allocated resources */
if (projected_src_space) {
HDassert(ret_value < 0);
if (H5S_close(projected_src_space) < 0)
@@ -2757,12 +2785,12 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts, H5S_t *file_space,
H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm)
H5D__virtual_read(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
{
H5O_storage_virtual_t *storage; /* Convenient pointer into layout struct */
hsize_t tot_nelmts; /* Total number of elements mapped to mem_space */
H5S_t *fill_space = NULL; /* Space to fill with fill value */
size_t nelmts; /* Number of elements to process */
size_t i, j; /* Local index variables */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2770,22 +2798,25 @@ H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsiz
/* Sanity check */
HDassert(io_info);
HDassert(io_info->u.rbuf);
HDassert(type_info);
HDassert(mem_space);
HDassert(file_space);
HDassert(dset_info);
HDassert(dset_info->buf.vp);
HDassert(dset_info->mem_space);
HDassert(dset_info->file_space);
storage = &io_info->dset->shared->layout.storage.u.virt;
storage = &(dset_info->dset->shared->layout.storage.u.virt);
HDassert((storage->view == H5D_VDS_FIRST_MISSING) || (storage->view == H5D_VDS_LAST_AVAILABLE));
/* Initialize nelmts */
nelmts = H5S_GET_SELECT_NPOINTS(dset_info->file_space);
#ifdef H5_HAVE_PARALLEL
/* Parallel reads are not supported (yet) */
if (H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_HAS_MPI))
if (H5F_HAS_FEATURE(dset_info->dset->oloc.file, H5FD_FEAT_HAS_MPI))
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "parallel reads not supported on virtual datasets")
#endif /* H5_HAVE_PARALLEL */
/* Prepare for I/O operation */
if (H5D__virtual_pre_io(io_info, storage, file_space, mem_space, &tot_nelmts) < 0)
if (H5D__virtual_pre_io(dset_info, storage, dset_info->file_space, dset_info->mem_space, &tot_nelmts) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "unable to prepare for I/O operation")
/* Iterate over mappings */
@@ -2797,12 +2828,12 @@ H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsiz
if (storage->list[i].psfn_nsubs || storage->list[i].psdn_nsubs) {
/* Iterate over sub-source dsets */
for (j = storage->list[i].sub_dset_io_start; j < storage->list[i].sub_dset_io_end; j++)
if (H5D__virtual_read_one(io_info, type_info, file_space, &storage->list[i].sub_dset[j]) < 0)
if (H5D__virtual_read_one(dset_info, &storage->list[i].sub_dset[j]) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to read source dataset")
} /* end if */
else
/* Read from source dataset */
if (H5D__virtual_read_one(io_info, type_info, file_space, &storage->list[i].source_dset) < 0)
if (H5D__virtual_read_one(dset_info, &storage->list[i].source_dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to read source dataset")
} /* end for */
@@ -2811,13 +2842,13 @@ H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsiz
H5D_fill_value_t fill_status; /* Fill value status */
/* Check the fill value status */
if (H5P_is_fill_value_defined(&io_info->dset->shared->dcpl_cache.fill, &fill_status) < 0)
if (H5P_is_fill_value_defined(&dset_info->dset->shared->dcpl_cache.fill, &fill_status) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if fill value defined")
/* Always write fill value to memory buffer unless it is undefined */
if (fill_status != H5D_FILL_VALUE_UNDEFINED) {
/* Start with fill space equal to memory space */
if (NULL == (fill_space = H5S_copy(mem_space, FALSE, TRUE)))
if (NULL == (fill_space = H5S_copy(dset_info->mem_space, FALSE, TRUE)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy memory selection")
/* Iterate over mappings */
@@ -2837,8 +2868,8 @@ H5D__virtual_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsiz
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "unable to clip fill selection")
/* Write fill values to memory buffer */
if (H5D__fill(io_info->dset->shared->dcpl_cache.fill.buf, io_info->dset->shared->type,
io_info->u.rbuf, type_info->mem_type, fill_space) < 0)
if (H5D__fill(dset_info->dset->shared->dcpl_cache.fill.buf, dset_info->dset->shared->type,
dset_info->buf.vp, dset_info->type_info.mem_type, fill_space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "filling buf failed")
#ifndef NDEBUG
@@ -2887,11 +2918,11 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__virtual_write_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, H5S_t *file_space,
H5O_storage_virtual_srcdset_t *source_dset)
H5D__virtual_write_one(H5D_dset_io_info_t *dset_info, H5O_storage_virtual_srcdset_t *source_dset)
{
H5S_t *projected_src_space = NULL; /* File space for selection in a single source dataset */
herr_t ret_value = SUCCEED; /* Return value */
H5S_t *projected_src_space = NULL; /* File space for selection in a single source dataset */
H5D_dset_io_info_t source_dinfo; /* Dataset info for source dataset write */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
@@ -2909,15 +2940,23 @@ H5D__virtual_write_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
/* Project intersection of file space and mapping virtual space onto
* mapping source space */
if (H5S_select_project_intersection(source_dset->clipped_virtual_select,
source_dset->clipped_source_select, file_space,
source_dset->clipped_source_select, dset_info->file_space,
&projected_src_space, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL,
"can't project virtual intersection onto source space")
/* Perform write on source dataset */
if (H5D__write(source_dset->dset, type_info->dst_type_id, source_dset->projected_mem_space,
projected_src_space, io_info->u.wbuf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write to source dataset")
{
/* Initialize source_dinfo */
source_dinfo.dset = source_dset->dset;
source_dinfo.mem_space = source_dset->projected_mem_space;
source_dinfo.file_space = projected_src_space;
source_dinfo.buf.cvp = dset_info->buf.cvp;
source_dinfo.mem_type_id = dset_info->type_info.dst_type_id;
/* Read in the point (with the custom VL memory allocator) */
if (H5D__write(1, &source_dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read source dataset")
}
/* Close projected_src_space */
if (H5S_close(projected_src_space) < 0)
@@ -2926,7 +2965,7 @@ H5D__virtual_write_one(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
} /* end if */
done:
/* Release allocated resources on failure */
/* Release allocated resources */
if (projected_src_space) {
HDassert(ret_value < 0);
if (H5S_close(projected_src_space) < 0)
@@ -2949,11 +2988,11 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5D__virtual_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
H5S_t *file_space, H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm)
H5D__virtual_write(H5D_io_info_t *io_info, H5D_dset_io_info_t *dset_info)
{
H5O_storage_virtual_t *storage; /* Convenient pointer into layout struct */
hsize_t tot_nelmts; /* Total number of elements mapped to mem_space */
size_t nelmts; /* Number of elements to process */
size_t i, j; /* Local index variables */
herr_t ret_value = SUCCEED; /* Return value */
@@ -2961,22 +3000,25 @@ H5D__virtual_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsi
/* Sanity check */
HDassert(io_info);
HDassert(io_info->u.wbuf);
HDassert(type_info);
HDassert(mem_space);
HDassert(file_space);
HDassert(dset_info);
HDassert(dset_info->buf.cvp);
HDassert(dset_info->mem_space);
HDassert(dset_info->file_space);
storage = &io_info->dset->shared->layout.storage.u.virt;
storage = &(dset_info->dset->shared->layout.storage.u.virt);
HDassert((storage->view == H5D_VDS_FIRST_MISSING) || (storage->view == H5D_VDS_LAST_AVAILABLE));
/* Initialize nelmts */
nelmts = H5S_GET_SELECT_NPOINTS(dset_info->file_space);
#ifdef H5_HAVE_PARALLEL
/* Parallel writes are not supported (yet) */
if (H5F_HAS_FEATURE(io_info->dset->oloc.file, H5FD_FEAT_HAS_MPI))
if (H5F_HAS_FEATURE(dset_info->dset->oloc.file, H5FD_FEAT_HAS_MPI))
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "parallel writes not supported on virtual datasets")
#endif /* H5_HAVE_PARALLEL */
/* Prepare for I/O operation */
if (H5D__virtual_pre_io(io_info, storage, file_space, mem_space, &tot_nelmts) < 0)
if (H5D__virtual_pre_io(dset_info, storage, dset_info->file_space, dset_info->mem_space, &tot_nelmts) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "unable to prepare for I/O operation")
/* Fail if there are unmapped parts of the selection as they would not be
@@ -2994,12 +3036,12 @@ H5D__virtual_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsi
if (storage->list[i].psfn_nsubs || storage->list[i].psdn_nsubs) {
/* Iterate over sub-source dsets */
for (j = storage->list[i].sub_dset_io_start; j < storage->list[i].sub_dset_io_end; j++)
if (H5D__virtual_write_one(io_info, type_info, file_space, &storage->list[i].sub_dset[j]) < 0)
if (H5D__virtual_write_one(dset_info, &storage->list[i].sub_dset[j]) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write to source dataset")
} /* end if */
else
/* Write to source dataset */
if (H5D__virtual_write_one(io_info, type_info, file_space, &storage->list[i].source_dset) < 0)
if (H5D__virtual_write_one(dset_info, &storage->list[i].source_dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write to source dataset")
} /* end for */
+1 -1
View File
@@ -400,7 +400,7 @@ done:
PURPOSE
Get the number of elements in current selection
USAGE
hssize_t H5Sget_select_npoints(space)
hsize_t H5Sget_select_npoints(space)
H5S_t *space; IN: Dataspace of selection to query
RETURNS
The number of elements in selection on success, 0 on failure
+215 -38
View File
@@ -88,10 +88,12 @@ static void *H5VL__dataset_create(void *obj, const H5VL_loc_params_t *loc_param
hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req);
static void *H5VL__dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const H5VL_class_t *cls,
const char *name, hid_t dapl_id, hid_t dxpl_id, void **req);
static herr_t H5VL__dataset_read(void *dset, const H5VL_class_t *cls, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t dxpl_id, void *buf, void **req);
static herr_t H5VL__dataset_write(void *obj, const H5VL_class_t *cls, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t dxpl_id, const void *buf, void **req);
static herr_t H5VL__dataset_read(size_t count, void *obj[], const H5VL_class_t *cls, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id, void *buf[],
void **req);
static herr_t H5VL__dataset_write(size_t count, void *obj[], const H5VL_class_t *cls, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id,
const void *buf[], void **req);
static herr_t H5VL__dataset_get(void *obj, const H5VL_class_t *cls, H5VL_dataset_get_args_t *args,
hid_t dxpl_id, void **req);
static herr_t H5VL__dataset_specific(void *obj, const H5VL_class_t *cls, H5VL_dataset_specific_args_t *args,
@@ -2020,9 +2022,9 @@ done:
} /* end H5VLdataset_open() */
/*-------------------------------------------------------------------------
* Function: H5VL__dataset_read
* Function: H5VL__dataset_read
*
* Purpose: Reads data from dataset through the VOL
* Purpose: Reads data from dataset through the VOL
*
* Return: Success: Non-negative
* Failure: Negative
@@ -2030,8 +2032,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5VL__dataset_read(void *obj, const H5VL_class_t *cls, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t dxpl_id, void *buf, void **req)
H5VL__dataset_read(size_t count, void *obj[], const H5VL_class_t *cls, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id, void *buf[], void **req)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -2042,13 +2044,61 @@ H5VL__dataset_read(void *obj, const H5VL_class_t *cls, hid_t mem_type_id, hid_t
HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'dataset read' method")
/* Call the corresponding VOL callback */
if ((cls->dataset_cls.read)(obj, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, req) < 0)
if ((cls->dataset_cls.read)(count, obj, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, req) < 0)
HGOTO_ERROR(H5E_VOL, H5E_READERROR, FAIL, "dataset read failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__dataset_read() */
/*-------------------------------------------------------------------------
* Function: H5VL_dataset_read_direct
*
* Purpose: Reads data from dataset through the VOL. This is like
* H5VL_dataset_read, but takes an array of void * for the
* objects and a class pointer instead of an array of
* H5VL_object_t. This allows us to avoid allocating and
* copying an extra array (of H5VL_object_ts).
*
* Return: Success: Non-negative
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
H5VL_dataset_read_direct(size_t count, void *obj[], H5VL_t *connector, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id, void *buf[], void **req)
{
hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
H5VL_object_t tmp_vol_obj; /* Temporary VOL object for setting VOL wrapper */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
HDassert(obj);
HDassert(connector);
/* Set wrapper info in API context */
tmp_vol_obj.data = obj[0];
tmp_vol_obj.connector = connector;
tmp_vol_obj.rc = 1;
if (H5VL_set_vol_wrapper(&tmp_vol_obj) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
vol_wrapper_set = TRUE;
/* Call the corresponding internal VOL routine */
if (H5VL__dataset_read(count, obj, connector->cls, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf,
req) < 0)
HGOTO_ERROR(H5E_VOL, H5E_READERROR, FAIL, "dataset read failed")
done:
/* Reset object wrapping info in API context */
if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_dataset_read_direct() */
/*-------------------------------------------------------------------------
* Function: H5VL_dataset_read
*
@@ -2060,21 +2110,44 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5VL_dataset_read(const H5VL_object_t *vol_obj, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, void *buf, void **req)
H5VL_dataset_read(size_t count, const H5VL_object_t *vol_obj[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, void *buf[], void **req)
{
hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
herr_t ret_value = SUCCEED; /* Return value */
hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
void *obj_local; /* Local buffer for obj */
void **obj = &obj_local; /* Array of object pointers */
size_t i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
HDassert(vol_obj);
HDassert(vol_obj[0]);
/* Set wrapper info in API context */
if (H5VL_set_vol_wrapper(vol_obj) < 0)
if (H5VL_set_vol_wrapper(vol_obj[0]) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
vol_wrapper_set = TRUE;
/* Allocate obj array if necessary */
if (count > 1)
if (NULL == (obj = (void **)H5MM_malloc(count * sizeof(void *))))
HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate space for object array")
/* Build obj array */
for (i = 0; i < count; i++) {
/* Get the object */
obj[i] = vol_obj[i]->data;
/* Make sure the class matches */
if (vol_obj[i]->connector->cls->value != vol_obj[0]->connector->cls->value)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
"datasets are accessed through different VOL connectors and can't be used in the "
"same I/O call")
}
/* Call the corresponding internal VOL routine */
if (H5VL__dataset_read(vol_obj->data, vol_obj->connector->cls, mem_type_id, mem_space_id, file_space_id,
if (H5VL__dataset_read(count, obj, vol_obj[0]->connector->cls, mem_type_id, mem_space_id, file_space_id,
dxpl_id, buf, req) < 0)
HGOTO_ERROR(H5E_VOL, H5E_READERROR, FAIL, "dataset read failed")
@@ -2083,6 +2156,10 @@ done:
if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info")
/* Free memory */
if (obj != &obj_local)
H5MM_free(obj);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_dataset_read() */
@@ -2097,24 +2174,36 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5VLdataset_read(void *obj, hid_t connector_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, void *buf, void **req /*out*/)
H5VLdataset_read(size_t count, void *obj[], hid_t connector_id, hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, void *buf[], void **req /*out*/)
{
H5VL_class_t *cls; /* VOL connector's class struct */
size_t i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API_NOINIT
H5TRACE8("e", "*xiiiii*xx", obj, connector_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf,
req);
H5TRACE9("e", "z**xi*i*i*ii**xx", count, obj, connector_id, mem_type_id, mem_space_id, file_space_id,
dxpl_id, buf, req);
/* Check args and get class pointer */
if (NULL == obj)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "obj array not provided")
for (i = 1; i < count; i++)
if (NULL == obj[i])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
if (NULL == mem_type_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_type_id array not provided")
if (NULL == mem_space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_space_id array not provided")
if (NULL == file_space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_space_id array not provided")
if (NULL == buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf array not provided")
if (NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID")
/* Call the corresponding internal VOL routine */
if (H5VL__dataset_read(obj, cls, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, req) < 0)
if (H5VL__dataset_read(count, obj, cls, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, req) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to read dataset")
done:
@@ -2122,9 +2211,9 @@ done:
} /* end H5VLdataset_read() */
/*-------------------------------------------------------------------------
* Function: H5VL__dataset_write
* Function: H5VL__dataset_write
*
* Purpose: Writes data from dataset through the VOL
* Purpose: Writes data from dataset through the VOL
*
* Return: Success: Non-negative
* Failure: Negative
@@ -2132,8 +2221,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
H5VL__dataset_write(void *obj, const H5VL_class_t *cls, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t dxpl_id, const void *buf, void **req)
H5VL__dataset_write(size_t count, void *obj[], const H5VL_class_t *cls, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id, const void *buf[], void **req)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -2144,13 +2233,62 @@ H5VL__dataset_write(void *obj, const H5VL_class_t *cls, hid_t mem_type_id, hid_t
HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "VOL connector has no 'dataset write' method")
/* Call the corresponding VOL callback */
if ((cls->dataset_cls.write)(obj, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, req) < 0)
if ((cls->dataset_cls.write)(count, obj, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, req) < 0)
HGOTO_ERROR(H5E_VOL, H5E_WRITEERROR, FAIL, "dataset write failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__dataset_write() */
/*-------------------------------------------------------------------------
* Function: H5VL_dataset_write_direct
*
* Purpose: Writes data from dataset through the VOL. This is like
* H5VL_dataset_write, but takes an array of void * for the
* objects and a class pointer instead of an array of
* H5VL_object_t. This allows us to avoid allocating and
* copying an extra array (of H5VL_object_ts).
*
* Return: Success: Non-negative
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
herr_t
H5VL_dataset_write_direct(size_t count, void *obj[], H5VL_t *connector, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id, const void *buf[],
void **req)
{
hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
H5VL_object_t tmp_vol_obj; /* Temporary VOL object for setting VOL wrapper */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
HDassert(obj);
HDassert(connector);
/* Set wrapper info in API context */
tmp_vol_obj.data = obj[0];
tmp_vol_obj.connector = connector;
tmp_vol_obj.rc = 1;
if (H5VL_set_vol_wrapper(&tmp_vol_obj) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
vol_wrapper_set = TRUE;
/* Call the corresponding internal VOL routine */
if (H5VL__dataset_write(count, obj, connector->cls, mem_type_id, mem_space_id, file_space_id, dxpl_id,
buf, req) < 0)
HGOTO_ERROR(H5E_VOL, H5E_WRITEERROR, FAIL, "dataset write failed")
done:
/* Reset object wrapping info in API context */
if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_dataset_write_direct() */
/*-------------------------------------------------------------------------
* Function: H5VL_dataset_write
*
@@ -2162,21 +2300,44 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5VL_dataset_write(const H5VL_object_t *vol_obj, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, const void *buf, void **req)
H5VL_dataset_write(size_t count, const H5VL_object_t *vol_obj[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[], void **req)
{
hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
herr_t ret_value = SUCCEED; /* Return value */
hbool_t vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
void *obj_local; /* Local buffer for obj */
void **obj = &obj_local; /* Array of object pointers */
size_t i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
HDassert(vol_obj);
HDassert(vol_obj[0]);
/* Set wrapper info in API context */
if (H5VL_set_vol_wrapper(vol_obj) < 0)
if (H5VL_set_vol_wrapper(vol_obj[0]) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTSET, FAIL, "can't set VOL wrapper info")
vol_wrapper_set = TRUE;
/* Allocate obj array if necessary */
if (count > 1)
if (NULL == (obj = (void **)H5MM_malloc(count * sizeof(void *))))
HGOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, "can't allocate space for object array")
/* Build obj array */
for (i = 0; i < count; i++) {
/* Get the object */
obj[i] = vol_obj[i]->data;
/* Make sure the class matches */
if (vol_obj[i]->connector->cls->value != vol_obj[0]->connector->cls->value)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
"datasets are accessed through different VOL connectors and can't be used in the "
"same I/O call")
}
/* Call the corresponding internal VOL routine */
if (H5VL__dataset_write(vol_obj->data, vol_obj->connector->cls, mem_type_id, mem_space_id, file_space_id,
if (H5VL__dataset_write(count, obj, vol_obj[0]->connector->cls, mem_type_id, mem_space_id, file_space_id,
dxpl_id, buf, req) < 0)
HGOTO_ERROR(H5E_VOL, H5E_WRITEERROR, FAIL, "dataset write failed")
@@ -2185,6 +2346,10 @@ done:
if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
HDONE_ERROR(H5E_VOL, H5E_CANTRESET, FAIL, "can't reset VOL wrapper info")
/* Free memory */
if (obj != &obj_local)
H5MM_free(obj);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL_dataset_write() */
@@ -2199,24 +2364,36 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5VLdataset_write(void *obj, hid_t connector_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, const void *buf, void **req /*out*/)
H5VLdataset_write(size_t count, void *obj[], hid_t connector_id, hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[], void **req /*out*/)
{
H5VL_class_t *cls; /* VOL connector's class struct */
size_t i; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API_NOINIT
H5TRACE8("e", "*xiiiii*xx", obj, connector_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf,
req);
H5TRACE9("e", "z**xi*i*i*ii**xx", count, obj, connector_id, mem_type_id, mem_space_id, file_space_id,
dxpl_id, buf, req);
/* Check args and get class pointer */
if (NULL == obj)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "obj array not provided")
for (i = 1; i < count; i++)
if (NULL == obj[i])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object")
if (NULL == mem_type_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_type_id array not provided")
if (NULL == mem_space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mem_space_id array not provided")
if (NULL == file_space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file_space_id array not provided")
if (NULL == buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buf array not provided")
if (NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID")
/* Call the corresponding internal VOL routine */
if (H5VL__dataset_write(obj, cls, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, req) < 0)
if (H5VL__dataset_write(count, obj, cls, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf, req) < 0)
HGOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "unable to write dataset")
done:
+4 -4
View File
@@ -879,10 +879,10 @@ typedef struct H5VL_dataset_class_t {
hid_t type_id, hid_t space_id, hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req);
void *(*open)(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t dapl_id,
hid_t dxpl_id, void **req);
herr_t (*read)(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id,
void *buf, void **req);
herr_t (*write)(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t dxpl_id,
const void *buf, void **req);
herr_t (*read)(size_t count, void *dset[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, void *buf[], void **req);
herr_t (*write)(size_t count, void *dset[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[], void **req);
herr_t (*get)(void *obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **req);
herr_t (*specific)(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id, void **req);
herr_t (*optional)(void *obj, H5VL_optional_args_t *args, hid_t dxpl_id, void **req);
+6 -4
View File
@@ -107,10 +107,12 @@ H5_DLL void *H5VLdataset_create(void *obj, const H5VL_loc_params_t *loc_params,
hid_t dapl_id, hid_t dxpl_id, void **req);
H5_DLL void *H5VLdataset_open(void *obj, const H5VL_loc_params_t *loc_params, hid_t connector_id,
const char *name, hid_t dapl_id, hid_t dxpl_id, void **req);
H5_DLL herr_t H5VLdataset_read(void *dset, hid_t connector_id, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t plist_id, void *buf, void **req);
H5_DLL herr_t H5VLdataset_write(void *dset, hid_t connector_id, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t plist_id, const void *buf, void **req);
H5_DLL herr_t H5VLdataset_read(size_t count, void *dset[], hid_t connector_id, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t plist_id, void *buf[],
void **req);
H5_DLL herr_t H5VLdataset_write(size_t count, void *dset[], hid_t connector_id, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t plist_id,
const void *buf[], void **req);
H5_DLL herr_t H5VLdataset_get(void *dset, hid_t connector_id, H5VL_dataset_get_args_t *args, hid_t dxpl_id,
void **req);
H5_DLL herr_t H5VLdataset_specific(void *obj, hid_t connector_id, H5VL_dataset_specific_args_t *args,
+178 -119
View File
@@ -50,8 +50,11 @@
/********************/
/* Helper routines for read/write API calls */
static herr_t H5VL__native_dataset_io_setup(H5D_t *dset, hid_t dxpl_id, hid_t file_space_id,
hid_t mem_space_id, H5S_t **file_space, H5S_t **mem_space);
static herr_t H5VL__native_dataset_io_setup(size_t count, void *obj[], hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id,
H5_flexible_const_ptr_t buf[], H5D_dset_io_info_t *dinfo);
static herr_t H5VL__native_dataset_io_cleanup(size_t count, hid_t mem_space_id[], hid_t file_space_id[],
H5D_dset_io_info_t *dinfo);
/*********************/
/* Package Variables */
@@ -75,89 +78,153 @@ static herr_t H5VL__native_dataset_io_setup(H5D_t *dset, hid_t dxpl_id, hid_t fi
*-------------------------------------------------------------------------
*/
static herr_t
H5VL__native_dataset_io_setup(H5D_t *dset, hid_t dxpl_id, hid_t file_space_id, hid_t mem_space_id,
H5S_t **file_space, H5S_t **mem_space)
H5VL__native_dataset_io_setup(size_t count, void *obj[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, H5_flexible_const_ptr_t buf[],
H5D_dset_io_info_t *dinfo)
{
H5F_shared_t *f_sh;
size_t i;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity checks */
HDassert(dinfo);
/* Get shared file */
f_sh = H5F_SHARED(((H5D_t *)obj[0])->oloc.file);
/* Iterate over datasets */
for (i = 0; i < count; i++) {
/* Set up dset */
dinfo[i].dset = (H5D_t *)obj[i];
HDassert(dinfo[i].dset);
/* Check dataset's file pointer is valid */
if (NULL == dinfo[i].dset->oloc.file)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not associated with a file")
if (f_sh != H5F_SHARED(dinfo[i].dset->oloc.file))
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL,
"different files detected in multi dataset I/O request")
/* Set up memory type */
dinfo[i].mem_type_id = mem_type_id[i];
/* Set up file dataspace */
if (H5S_ALL == file_space_id[i])
/* Use dataspace for dataset */
dinfo[i].file_space = dinfo[i].dset->shared->space;
else if (H5S_BLOCK == file_space_id[i])
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "H5S_BLOCK is not allowed for file dataspace")
else if (H5S_PLIST == file_space_id[i]) {
H5P_genplist_t *plist; /* Property list pointer */
H5S_t *space; /* Dataspace to hold selection */
/* Get the plist structure */
if (NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_DATASET, H5E_BADID, FAIL, "bad dataset transfer property list")
/* Get a pointer to the file space in the property list */
if (H5P_peek(plist, H5D_XFER_DSET_IO_SEL_NAME, &space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error getting dataset I/O selection")
/* Use dataspace for dataset */
dinfo[i].file_space = dinfo[i].dset->shared->space;
/* Copy, but share, selection from property list to dataset's dataspace */
if (H5S_SELECT_COPY(dinfo[i].file_space, space, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy dataset I/O selection")
} /* end else-if */
else {
/* Get the dataspace pointer */
if (NULL == (dinfo[i].file_space = (H5S_t *)H5I_object_verify(file_space_id[i], H5I_DATASPACE)))
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "file_space_id is not a dataspace ID")
} /* end else */
/* Get dataspace for memory buffer */
if (H5S_ALL == mem_space_id[i])
dinfo[i].mem_space = dinfo[i].file_space;
else if (H5S_BLOCK == mem_space_id[i]) {
hsize_t nelmts; /* # of selected elements in file */
/* Get the # of elements selected */
nelmts = H5S_GET_SELECT_NPOINTS(dinfo[i].file_space);
/* Check for any elements */
if (nelmts > 0) {
/* Create a 1-D dataspace of the same # of elements */
if (NULL == (dinfo[i].mem_space = H5S_create_simple(1, &nelmts, NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create simple memory dataspace")
} /* end if */
else {
/* Create a NULL dataspace of the same # of elements */
if (NULL == (dinfo[i].mem_space = H5S_create(H5S_NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create NULL memory dataspace")
} /* end else */
} /* end if */
else if (H5S_PLIST == mem_space_id[i])
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "H5S_PLIST is not allowed for memory dataspace")
else {
/* Get the dataspace pointer */
if (NULL == (dinfo[i].mem_space = (H5S_t *)H5I_object_verify(mem_space_id[i], H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "mem_space_id is not a dataspace ID")
} /* end else */
/* Check for valid selections */
if (H5S_SELECT_VALID(dinfo[i].file_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL,
"selection + offset not within extent for file dataspace")
if (H5S_SELECT_VALID(dinfo[i].mem_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL,
"selection + offset not within extent for memory dataspace")
/* Set up buf */
dinfo[i].buf = buf[i];
}
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__native_dataset_io_setup() */
/*-------------------------------------------------------------------------
* Function: H5VL__native_dataset_io_cleanup
*
* Purpose: Frees memory allocated by H5VL__native_dataset_io_setup()
*
* Return: SUCCEED/FAIL
*
*-------------------------------------------------------------------------
*/
static herr_t
H5VL__native_dataset_io_cleanup(size_t count, hid_t mem_space_id[], hid_t file_space_id[],
H5D_dset_io_info_t *dinfo)
{
size_t i;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity checks */
HDassert(dset);
HDassert(file_space && NULL == *file_space);
HDassert(mem_space && NULL == *mem_space);
HDassert(dinfo);
/* Set up file dataspace */
if (H5S_ALL == file_space_id)
/* Use dataspace for dataset */
*file_space = dset->shared->space;
else if (H5S_BLOCK == file_space_id)
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "H5S_BLOCK is not allowed for file dataspace")
else if (H5S_PLIST == file_space_id) {
H5P_genplist_t *plist; /* Property list pointer */
H5S_t *space; /* Dataspace to hold selection */
/* Iterate over datasets */
for (i = 0; i < count; i++) {
/* Free memory dataspace if it was created. Use HDONE_ERROR in this function so we always
* try to free everything we can. */
if (H5S_BLOCK == mem_space_id[i] && dinfo[i].mem_space)
if (H5S_close(dinfo[i].mem_space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL,
"unable to release temporary memory dataspace for H5S_BLOCK")
/* Get the plist structure */
if (NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_DATASET, H5E_BADID, FAIL, "bad dataset transfer property list")
/* Reset file dataspace selection if it was copied from the property list */
if (H5S_PLIST == file_space_id[i] && dinfo[i].file_space)
if (H5S_select_all(dinfo[i].file_space, TRUE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL,
"unable to release file dataspace selection for H5S_PLIST")
}
/* See if a dataset I/O selection is already set, and free it if it is */
if (H5P_peek(plist, H5D_XFER_DSET_IO_SEL_NAME, &space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error getting dataset I/O selection")
/* Use dataspace for dataset */
*file_space = dset->shared->space;
/* Copy, but share, selection from property list to dataset's dataspace */
if (H5S_SELECT_COPY(*file_space, space, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy dataset I/O selection")
} /* end else-if */
else {
/* Get the dataspace pointer */
if (NULL == (*file_space = (H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "file_space_id is not a dataspace ID")
} /* end else */
/* Get dataspace for memory buffer */
if (H5S_ALL == mem_space_id)
*mem_space = *file_space;
else if (H5S_BLOCK == mem_space_id) {
hsize_t nelmts; /* # of selected elements in file */
/* Get the # of elements selected */
nelmts = H5S_GET_SELECT_NPOINTS(*file_space);
/* Check for any elements */
if (nelmts > 0) {
/* Create a 1-D dataspace of the same # of elements */
if (NULL == (*mem_space = H5S_create_simple(1, &nelmts, NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create simple memory dataspace")
} /* end if */
else {
/* Create a NULL dataspace of the same # of elements */
if (NULL == (*mem_space = H5S_create(H5S_NULL)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "unable to create NULL memory dataspace")
} /* end else */
} /* end if */
else if (H5S_PLIST == mem_space_id)
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "H5S_PLIST is not allowed for memory dataspace")
else {
/* Get the dataspace pointer */
if (NULL == (*mem_space = (H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "mem_space_id is not a dataspace ID")
} /* end else */
/* Check for valid selections */
if (H5S_SELECT_VALID(*file_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL,
"selection + offset not within extent for file dataspace")
if (H5S_SELECT_VALID(*mem_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL,
"selection + offset not within extent for memory dataspace")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__native_dataset_io_setup() */
} /* end H5VL__native_dataset_io_cleanup() */
/*-------------------------------------------------------------------------
* Function: H5VL__native_dataset_create
@@ -267,43 +334,39 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5VL__native_dataset_read(void *obj, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, void *buf, void H5_ATTR_UNUSED **req)
H5VL__native_dataset_read(size_t count, void *obj[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, void *buf[], void H5_ATTR_UNUSED **req)
{
H5D_t *dset = (H5D_t *)obj;
H5S_t *mem_space = NULL;
H5S_t *file_space = NULL;
herr_t ret_value = SUCCEED; /* Return value */
H5D_dset_io_info_t dinfo_local;
H5D_dset_io_info_t *dinfo = &dinfo_local;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Check arguments */
if (NULL == dset->oloc.file)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not associated with a file")
/* Allocate dataset info array if necessary */
if (count > 1)
if (NULL == (dinfo = (H5D_dset_io_info_t *)H5MM_malloc(count * sizeof(H5D_dset_io_info_t))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate dset info array buffer")
/* Get file & memory dataspaces */
if (H5VL__native_dataset_io_setup(dset, dxpl_id, file_space_id, mem_space_id, &file_space, &mem_space) <
0)
if (H5VL__native_dataset_io_setup(count, obj, mem_type_id, mem_space_id, file_space_id, dxpl_id,
(H5_flexible_const_ptr_t *)buf, dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up file and memory dataspaces")
/* Set DXPL for operation */
H5CX_set_dxpl(dxpl_id);
/* Read raw data */
if (H5D__read(dset, mem_type_id, mem_space, file_space, buf /*out*/) < 0)
/* Read raw data. Call H5D__read directly in single dset case. */
if (H5D__read(count, dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
done:
/* Clean up */
if (H5S_BLOCK == mem_space_id && mem_space) {
if (H5S_close(mem_space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL,
"unable to release temporary memory dataspace for H5S_BLOCK")
} /* end if */
else if (H5S_PLIST == file_space_id && file_space)
if (H5S_select_all(file_space, TRUE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL,
"unable to release file dataspace selection for H5S_PLIST")
if (H5VL__native_dataset_io_cleanup(count, mem_space_id, file_space_id, dinfo) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to release dataset info")
if (dinfo != &dinfo_local)
H5MM_xfree(dinfo);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__native_dataset_read() */
@@ -318,43 +381,39 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
H5VL__native_dataset_write(void *obj, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t dxpl_id, const void *buf, void H5_ATTR_UNUSED **req)
H5VL__native_dataset_write(size_t count, void *obj[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[], void H5_ATTR_UNUSED **req)
{
H5D_t *dset = (H5D_t *)obj;
H5S_t *mem_space = NULL;
H5S_t *file_space = NULL;
herr_t ret_value = SUCCEED; /* Return value */
H5D_dset_io_info_t dinfo_local;
H5D_dset_io_info_t *dinfo = &dinfo_local;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* check arguments */
if (NULL == dset->oloc.file)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not associated with a file")
/* Allocate dataset info array if necessary */
if (count > 1)
if (NULL == (dinfo = (H5D_dset_io_info_t *)H5MM_malloc(count * sizeof(H5D_dset_io_info_t))))
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate dset info array buffer")
/* Get file & memory dataspaces */
if (H5VL__native_dataset_io_setup(dset, dxpl_id, file_space_id, mem_space_id, &file_space, &mem_space) <
0)
if (H5VL__native_dataset_io_setup(count, obj, mem_type_id, mem_space_id, file_space_id, dxpl_id,
(H5_flexible_const_ptr_t *)buf, dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up file and memory dataspaces")
/* Set DXPL for operation */
H5CX_set_dxpl(dxpl_id);
/* Write the data */
if (H5D__write(dset, mem_type_id, mem_space, file_space, buf) < 0)
/* Write raw data. Call H5D__write directly in single dset case. */
if (H5D__write(count, dinfo) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
done:
/* Clean up */
if (H5S_BLOCK == mem_space_id && mem_space) {
if (H5S_close(mem_space) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL,
"unable to release temporary memory dataspace for H5S_BLOCK")
} /* end if */
else if (H5S_PLIST == file_space_id && file_space)
if (H5S_select_all(file_space, TRUE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL,
"unable to release file dataspace selection for H5S_PLIST")
if (H5VL__native_dataset_io_cleanup(count, mem_space_id, file_space_id, dinfo) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to release dataset info")
if (dinfo != &dinfo_local)
H5MM_xfree(dinfo);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__native_dataset_write() */
+4 -4
View File
@@ -61,10 +61,10 @@ H5_DLL void *H5VL__native_dataset_create(void *obj, const H5VL_loc_params_t *lo
hid_t dapl_id, hid_t dxpl_id, void **req);
H5_DLL void *H5VL__native_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
hid_t dapl_id, hid_t dxpl_id, void **req);
H5_DLL herr_t H5VL__native_dataset_read(void *dset, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t plist_id, void *buf, void **req);
H5_DLL herr_t H5VL__native_dataset_write(void *dset, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t plist_id, const void *buf, void **req);
H5_DLL herr_t H5VL__native_dataset_read(size_t count, void *obj[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, void *buf[], void **req);
H5_DLL herr_t H5VL__native_dataset_write(size_t count, void *obj[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t dxpl_id, const void *buf[], void **req);
H5_DLL herr_t H5VL__native_dataset_get(void *dset, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **req);
H5_DLL herr_t H5VL__native_dataset_specific(void *dset, H5VL_dataset_specific_args_t *args, hid_t dxpl_id,
void **req);
+62 -19
View File
@@ -121,11 +121,12 @@ static void *H5VL_pass_through_dataset_create(void *obj, const H5VL_loc_params_
hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req);
static void *H5VL_pass_through_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name,
hid_t dapl_id, hid_t dxpl_id, void **req);
static herr_t H5VL_pass_through_dataset_read(void *dset, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t plist_id, void *buf, void **req);
static herr_t H5VL_pass_through_dataset_write(void *dset, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t plist_id, const void *buf,
void **req);
static herr_t H5VL_pass_through_dataset_read(size_t count, void *dset[], hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t plist_id,
void *buf[], void **req);
static herr_t H5VL_pass_through_dataset_write(size_t count, void *dset[], hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t plist_id,
const void *buf[], void **req);
static herr_t H5VL_pass_through_dataset_get(void *dset, H5VL_dataset_get_args_t *args, hid_t dxpl_id,
void **req);
static herr_t H5VL_pass_through_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id,
@@ -1197,22 +1198,43 @@ H5VL_pass_through_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, c
*-------------------------------------------------------------------------
*/
static herr_t
H5VL_pass_through_dataset_read(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t plist_id, void *buf, void **req)
H5VL_pass_through_dataset_read(size_t count, void *dset[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t plist_id, void *buf[], void **req)
{
H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset;
herr_t ret_value;
void *obj_local; /* Local buffer for obj */
void **obj = &obj_local; /* Array of object pointers */
size_t i; /* Local index variable */
herr_t ret_value;
#ifdef ENABLE_PASSTHRU_LOGGING
printf("------- PASS THROUGH VOL DATASET Read\n");
#endif
ret_value = H5VLdataset_read(o->under_object, o->under_vol_id, mem_type_id, mem_space_id, file_space_id,
plist_id, buf, req);
/* Allocate obj array if necessary */
if (count > 1)
if (NULL == (obj = (void **)malloc(count * sizeof(void *))))
return -1;
/* Build obj array */
for (i = 0; i < count; i++) {
/* Get the object */
obj[i] = ((H5VL_pass_through_t *)dset[i])->under_object;
/* Make sure the class matches */
if (((H5VL_pass_through_t *)dset[i])->under_vol_id != ((H5VL_pass_through_t *)dset[0])->under_vol_id)
return -1;
}
ret_value = H5VLdataset_read(count, obj, ((H5VL_pass_through_t *)dset[0])->under_vol_id, mem_type_id,
mem_space_id, file_space_id, plist_id, buf, req);
/* Check for async request */
if (req && *req)
*req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
*req = H5VL_pass_through_new_obj(*req, ((H5VL_pass_through_t *)dset[0])->under_vol_id);
/* Free memory */
if (obj != &obj_local)
free(obj);
return ret_value;
} /* end H5VL_pass_through_dataset_read() */
@@ -1228,22 +1250,43 @@ H5VL_pass_through_dataset_read(void *dset, hid_t mem_type_id, hid_t mem_space_id
*-------------------------------------------------------------------------
*/
static herr_t
H5VL_pass_through_dataset_write(void *dset, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id,
hid_t plist_id, const void *buf, void **req)
H5VL_pass_through_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t mem_space_id[],
hid_t file_space_id[], hid_t plist_id, const void *buf[], void **req)
{
H5VL_pass_through_t *o = (H5VL_pass_through_t *)dset;
herr_t ret_value;
void *obj_local; /* Local buffer for obj */
void **obj = &obj_local; /* Array of object pointers */
size_t i; /* Local index variable */
herr_t ret_value;
#ifdef ENABLE_PASSTHRU_LOGGING
printf("------- PASS THROUGH VOL DATASET Write\n");
#endif
ret_value = H5VLdataset_write(o->under_object, o->under_vol_id, mem_type_id, mem_space_id, file_space_id,
plist_id, buf, req);
/* Allocate obj array if necessary */
if (count > 1)
if (NULL == (obj = (void **)malloc(count * sizeof(void *))))
return -1;
/* Build obj array */
for (i = 0; i < count; i++) {
/* Get the object */
obj[i] = ((H5VL_pass_through_t *)dset[i])->under_object;
/* Make sure the class matches */
if (((H5VL_pass_through_t *)dset[i])->under_vol_id != ((H5VL_pass_through_t *)dset[0])->under_vol_id)
return -1;
}
ret_value = H5VLdataset_write(count, obj, ((H5VL_pass_through_t *)dset[0])->under_vol_id, mem_type_id,
mem_space_id, file_space_id, plist_id, buf, req);
/* Check for async request */
if (req && *req)
*req = H5VL_pass_through_new_obj(*req, o->under_vol_id);
*req = H5VL_pass_through_new_obj(*req, ((H5VL_pass_through_t *)dset[0])->under_vol_id);
/* Free memory */
if (obj != &obj_local)
free(obj);
return ret_value;
} /* end H5VL_pass_through_dataset_write() */
+12 -4
View File
@@ -177,10 +177,18 @@ H5_DLL void *H5VL_dataset_create(const H5VL_object_t *vol_obj, const H5VL_loc_p
hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id, void **req);
H5_DLL void *H5VL_dataset_open(const H5VL_object_t *vol_obj, const H5VL_loc_params_t *loc_params,
const char *name, hid_t dapl_id, hid_t dxpl_id, void **req);
H5_DLL herr_t H5VL_dataset_read(const H5VL_object_t *vol_obj, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t dxpl_id, void *buf, void **req);
H5_DLL herr_t H5VL_dataset_write(const H5VL_object_t *vol_obj, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t dxpl_id, const void *buf, void **req);
H5_DLL herr_t H5VL_dataset_read(size_t count, const H5VL_object_t *vol_obj[], hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id, void *buf[],
void **req);
H5_DLL herr_t H5VL_dataset_read_direct(size_t count, void *obj[], H5VL_t *connector, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id,
void *buf[], void **req);
H5_DLL herr_t H5VL_dataset_write(size_t count, const H5VL_object_t *vol_obj[], hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id,
const void *buf[], void **req);
H5_DLL herr_t H5VL_dataset_write_direct(size_t count, void *obj[], H5VL_t *connector, hid_t mem_type_id[],
hid_t mem_space_id[], hid_t file_space_id[], hid_t dxpl_id,
const void *buf[], void **req);
H5_DLL herr_t H5VL_dataset_get(const H5VL_object_t *vol_obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id,
void **req);
H5_DLL herr_t H5VL_dataset_specific(const H5VL_object_t *cls, H5VL_dataset_specific_args_t *args,
+3 -1
View File
@@ -2512,7 +2512,9 @@ H5_DLL herr_t H5CX_pop(hbool_t update_dxpl_props);
/* Union for const/non-const pointer for use by functions that manipulate
* pointers but do not write to their targets or return pointers to const
* specified locations. This helps us avoid compiler warnings. */
* specified locations. Also used for I/O functions that work for read and
* write - these functions are expected to never write to these locations in the
* write case. This helps us avoid compiler warnings. */
typedef union {
void *vp;
const void *cvp;
+1
View File
@@ -339,6 +339,7 @@ set (H5_TESTS
dsets
chunk_info # compression lib link
cmpd_dset
mdset
filter_fail
extend
direct_chunk # compression lib link
+2 -2
View File
@@ -64,7 +64,7 @@ TEST_PROG= testhdf5 \
cache cache_api cache_image cache_tagging lheap ohdr \
stab gheap evict_on_close farray earray btree2 fheap \
accum hyperslab istore bittests dt_arith page_buffer \
dtypes dsets chunk_info cmpd_dset cmpd_dtransform filter_fail extend direct_chunk \
dtypes dsets chunk_info cmpd_dset mdset cmpd_dtransform filter_fail extend direct_chunk \
external efc objcopy objcopy_ref links unlink twriteorder big mtime \
fillval mount \
flush1 flush2 app_ref enum set_extent ttsafe enc_dec_plist \
@@ -184,7 +184,7 @@ flush2.chkexe_: flush1.chkexe_
# specifying a file prefix or low-level driver. Changing the file
# prefix or low-level driver with environment variables will influence
# the temporary file name in ways that the makefile is not aware of.
CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offset.h5 \
CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 mdset.h5 compact_dataset.h5 dataset.h5 dset_offset.h5 \
max_compact_dataset.h5 simple.h5 set_local.h5 random_chunks.h5 \
huge_chunks.h5 chunk_cache.h5 big_chunk.h5 chunk_fast.h5 chunk_expand.h5 \
chunk_fixed.h5 copy_dcpl_newfile.h5 partial_chunks.h5 layout_extend.h5 \
+714
View File
@@ -0,0 +1,714 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Programmer: Neil Fortner
* March 10, 2014
*
* Purpose: Test H5Dwrite_multi() and H5Dread_multi using randomized
* parameters. Also tests H5Dwrite() and H5Dread() using a similar
* method.
*/
#include "h5test.h"
#define NAME_BUF_SIZE 1024
#define MAX_DSETS 6
#define MAX_DSET_X 10
#define MAX_DSET_Y 10
#define MAX_CHUNK_X 4
#define MAX_CHUNK_Y 4
#define MAX_HS_X 6
#define MAX_HS_Y 6
#define MAX_HS 3
#define MAX_POINTS 6
#define OPS_PER_FILE 50
#define DSET_MAX_NAME_LEN 8
#define EXT_FILENAME "mdset_ext.h5"
#define SOURCE_DS_NAME "vds_source"
/* Option flags */
#define MDSET_FLAG_CHUNK 0x01u
#define MDSET_FLAG_MLAYOUT 0x02u
#define MDSET_FLAG_SHAPESAME 0x04u
#define MDSET_FLAG_MDSET 0x08u
#define MDSET_FLAG_TCONV 0x10u
#define MDSET_FLAG_FILTER 0x20u
#define MDSET_ALL_FLAGS \
(MDSET_FLAG_CHUNK | MDSET_FLAG_MLAYOUT | MDSET_FLAG_SHAPESAME | MDSET_FLAG_MDSET | MDSET_FLAG_TCONV | \
MDSET_FLAG_FILTER)
const char *FILENAME[] = {"mdset", "mdset1", "mdset2", NULL};
/* Names for datasets */
char dset_name[MAX_DSETS][DSET_MAX_NAME_LEN];
/* Whether these filters are available */
htri_t deflate_avail = FALSE;
htri_t fletcher32_avail = FALSE;
static int
test_mdset_location(hid_t fapl_id)
{
hid_t file_id1, file_id2;
herr_t ret;
hid_t dset_ids[2];
hid_t mem_type_ids[2];
hid_t mem_space_ids[2];
hid_t file_space_ids[2];
void *rbufs[2];
const void *wbufs[2];
hsize_t dset_dims[2];
int *buf = NULL;
char filename1[NAME_BUF_SIZE];
char filename2[NAME_BUF_SIZE];
TESTING("mdset location");
h5_fixname(FILENAME[1], fapl_id, filename1, sizeof filename1);
h5_fixname(FILENAME[2], fapl_id, filename2, sizeof filename2);
/* Create files */
if ((file_id1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
TEST_ERROR;
if ((file_id2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
TEST_ERROR;
if (NULL == (buf = (int *)HDcalloc(2 * MAX_DSET_X * MAX_DSET_Y, sizeof(int))))
TEST_ERROR;
/* Generate memory dataspace */
dset_dims[0] = MAX_DSET_X;
dset_dims[1] = MAX_DSET_Y;
if ((file_space_ids[0] = H5Screate_simple(2, dset_dims, NULL)) < 0)
TEST_ERROR;
if ((file_space_ids[1] = H5Screate_simple(2, dset_dims, NULL)) < 0)
TEST_ERROR;
mem_space_ids[0] = H5S_ALL;
mem_space_ids[1] = H5S_ALL;
mem_type_ids[0] = H5T_NATIVE_UINT;
mem_type_ids[1] = H5T_NATIVE_UINT;
if ((dset_ids[0] = H5Dcreate2(file_id1, dset_name[0], H5T_NATIVE_UINT, file_space_ids[0], H5P_DEFAULT,
H5P_DEFAULT, H5P_DEFAULT)) < 0)
TEST_ERROR;
if ((dset_ids[1] = H5Dcreate2(file_id2, dset_name[1], H5T_NATIVE_UINT, file_space_ids[1], H5P_DEFAULT,
H5P_DEFAULT, H5P_DEFAULT)) < 0)
TEST_ERROR;
wbufs[0] = buf;
wbufs[1] = buf + (MAX_DSET_X * MAX_DSET_Y);
H5E_BEGIN_TRY
{
ret = H5Dwrite_multi(2, dset_ids, mem_type_ids, mem_space_ids, file_space_ids, H5P_DEFAULT, wbufs);
}
H5E_END_TRY
if (ret >= 0) {
fprintf(stderr, "H5Dmulti_write with datasets in multiple files should fail.\n");
TEST_ERROR;
}
rbufs[0] = buf;
rbufs[1] = buf + (MAX_DSET_X * MAX_DSET_Y);
H5E_BEGIN_TRY
{
ret = H5Dread_multi(2, dset_ids, mem_type_ids, mem_space_ids, file_space_ids, H5P_DEFAULT, rbufs);
}
H5E_END_TRY
if (ret >= 0) {
fprintf(stderr, "H5Dmulti_read with datasets in multiple files should fail.\n");
TEST_ERROR;
}
H5Dclose(dset_ids[0]);
H5Sclose(file_space_ids[0]);
H5Dclose(dset_ids[1]);
H5Sclose(file_space_ids[1]);
H5Fclose(file_id1);
H5Fclose(file_id2);
if (buf)
free(buf);
PASSED();
return 0;
error:
if (buf)
free(buf);
return -1;
}
/*-------------------------------------------------------------------------
* Function: test_mdset
*
* Purpose: Test randomized I/O using one or more datasets. Creates a
* file, runs OPS_PER_FILE read or write operations verifying
* that reads return the expected data, then closes the file.
* Runs the test with a new file niter times.
*
* The operations can use either hyperslab or point
* selections. Options are available for chunked or
* contiguous layout, use of multiple datasets and H5D*_multi
* calls, and use of the "shapesame" algorithm code path. To
* avoid the shapesame path when that option is not set, this
* function simply adds a dimension to the memory buffer in a
* way that the shapesame code is not designed to handle.
*
* Return: Number of errors
*
* Programmer: Neil Fortner
* Monday, March 10, 2014
*
*-------------------------------------------------------------------------
*/
static int
test_mdset(size_t niter, unsigned flags, hid_t fapl_id)
{
hid_t dset_ids[MAX_DSETS];
hid_t mem_type_ids[MAX_DSETS];
hid_t mem_space_ids[MAX_DSETS];
hid_t file_space_ids[MAX_DSETS];
void *rbufs[MAX_DSETS];
const void *wbufs[MAX_DSETS];
size_t max_dsets;
size_t buf_size;
size_t ndsets;
hid_t file_id = -1;
hid_t dcpl_id[MAX_DSETS];
hsize_t dset_dims[MAX_DSETS][3];
hsize_t chunk_dims[2];
hsize_t max_dims[2] = {H5S_UNLIMITED, H5S_UNLIMITED};
unsigned *rbuf = NULL;
unsigned *rbufi[MAX_DSETS][MAX_DSET_X];
unsigned *erbuf = NULL;
unsigned *erbufi[MAX_DSETS][MAX_DSET_X];
unsigned *wbuf = NULL;
unsigned *wbufi[MAX_DSETS][MAX_DSET_X];
unsigned *efbuf = NULL;
unsigned *efbufi[MAX_DSETS][MAX_DSET_X];
hbool_t do_read;
hsize_t start[3];
hsize_t count[3];
hsize_t points[3 * MAX_POINTS];
char filename[NAME_BUF_SIZE];
size_t i, j, k, l, m, n;
TESTING("random I/O");
h5_fixname(FILENAME[0], fapl_id, filename, sizeof filename);
/* Calculate maximum number of datasets */
max_dsets = (flags & MDSET_FLAG_MDSET) ? MAX_DSETS : 1;
/* Calculate buffer size */
buf_size = max_dsets * MAX_DSET_X * MAX_DSET_Y * sizeof(unsigned);
/* Initialize dcpl_id array */
for (i = 0; i < max_dsets; i++)
dcpl_id[i] = -1;
/* Allocate buffers */
if (NULL == (rbuf = (unsigned *)HDmalloc(buf_size)))
TEST_ERROR;
if (NULL == (erbuf = (unsigned *)HDmalloc(buf_size)))
TEST_ERROR;
if (NULL == (wbuf = (unsigned *)HDmalloc(buf_size)))
TEST_ERROR;
if (NULL == (efbuf = (unsigned *)HDmalloc(buf_size)))
TEST_ERROR;
/* Initialize buffer indices */
for (i = 0; i < max_dsets; i++)
for (j = 0; j < MAX_DSET_X; j++) {
rbufi[i][j] = rbuf + (i * MAX_DSET_X * MAX_DSET_Y) + (j * MAX_DSET_Y);
erbufi[i][j] = erbuf + (i * MAX_DSET_X * MAX_DSET_Y) + (j * MAX_DSET_Y);
wbufi[i][j] = wbuf + (i * MAX_DSET_X * MAX_DSET_Y) + (j * MAX_DSET_Y);
efbufi[i][j] = efbuf + (i * MAX_DSET_X * MAX_DSET_Y) + (j * MAX_DSET_Y);
} /* end for */
/* Initialize 3rd dimension information (for tricking library into using
* non-"shapesame" code */
for (i = 0; i < max_dsets; i++)
dset_dims[i][2] = 1;
start[2] = 0;
count[2] = 1;
/* Initialize IDs */
for (i = 0; i < max_dsets; i++) {
dset_ids[i] = -1;
file_space_ids[i] = -1;
mem_type_ids[i] = H5T_NATIVE_UINT;
mem_space_ids[i] = -1;
} /* end for */
/* Generate memory dataspace */
dset_dims[0][0] = MAX_DSET_X;
dset_dims[0][1] = MAX_DSET_Y;
if ((mem_space_ids[0] = H5Screate_simple((flags & MDSET_FLAG_SHAPESAME) ? 2 : 3, dset_dims[0], NULL)) < 0)
TEST_ERROR;
for (i = 1; i < max_dsets; i++)
if ((mem_space_ids[i] = H5Scopy(mem_space_ids[0])) < 0)
TEST_ERROR;
/* Create dcpl 0 */
if ((dcpl_id[0] = H5Pcreate(H5P_DATASET_CREATE)) < 0)
TEST_ERROR;
/* Set fill time to alloc, and alloc time to early (so we always know
* what's in the file) */
if (H5Pset_fill_time(dcpl_id[0], H5D_FILL_TIME_ALLOC) < 0)
TEST_ERROR;
if (H5Pset_alloc_time(dcpl_id[0], H5D_ALLOC_TIME_EARLY) < 0)
TEST_ERROR;
/* Set filters if requested */
if (flags & MDSET_FLAG_FILTER) {
if (fletcher32_avail)
if (H5Pset_fletcher32(dcpl_id[0]) < 0)
TEST_ERROR;
if (deflate_avail)
if (H5Pset_deflate(dcpl_id[0], 1) < 0)
TEST_ERROR;
}
/* Copy dcpl 0 to other slots in dcpl_id array */
for (i = 1; i < MAX_DSETS; i++)
if ((dcpl_id[i] = H5Pcopy(dcpl_id[0])) < 0)
TEST_ERROR;
/* If this is a multi layout run, set up different filters and layouts. Chunked and virtual
* datasets will be set every iteration (with different dims), and contiguous is the default, so
* no need to set either of those. */
if (flags & MDSET_FLAG_MLAYOUT) {
/* Set filters on dataset 2 */
if (fletcher32_avail)
if (H5Pset_fletcher32(dcpl_id[2]) < 0)
TEST_ERROR;
if (deflate_avail)
if (H5Pset_deflate(dcpl_id[2], 1) < 0)
TEST_ERROR;
/* Dataset 3 is compact */
if (H5Pset_layout(dcpl_id[3], H5D_COMPACT) < 0)
TEST_ERROR;
/* Dataset 4 is external */
if (H5Pset_external(dcpl_id[4], EXT_FILENAME, 0, H5F_UNLIMITED) < 0)
TEST_ERROR;
}
for (i = 0; i < niter; i++) {
/* Determine number of datasets */
ndsets = (flags & MDSET_FLAG_MLAYOUT) ? 6
: (flags & MDSET_FLAG_MDSET) ? (size_t)((size_t)HDrandom() % max_dsets) + 1
: 1;
/* Create file */
if ((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
TEST_ERROR;
/* Create datasets */
for (j = 0; j < ndsets; j++) {
hid_t source_dset;
hbool_t use_chunk =
(flags & MDSET_FLAG_CHUNK) || ((flags & MDSET_FLAG_MLAYOUT) && (j == 1 || j == 2));
/* Generate file dataspace */
dset_dims[j][0] = (hsize_t)((HDrandom() % MAX_DSET_X) + 1);
dset_dims[j][1] = (hsize_t)((HDrandom() % MAX_DSET_Y) + 1);
if ((file_space_ids[j] = H5Screate_simple(2, dset_dims[j], use_chunk ? max_dims : NULL)) < 0)
TEST_ERROR;
/* Generate chunk if called for by configuration (multi layout uses chunked for datasets
* 1 and 2) */
if (use_chunk) {
chunk_dims[0] = (hsize_t)((HDrandom() % MAX_CHUNK_X) + 1);
chunk_dims[1] = (hsize_t)((HDrandom() % MAX_CHUNK_Y) + 1);
if (H5Pset_chunk(dcpl_id[j], 2, chunk_dims) < 0)
TEST_ERROR;
} /* end if */
else if ((flags & MDSET_FLAG_CHUNK) && j == 5) {
/* Dataset 5 is virtual in multi layout case */
/* Set to contiguous to clear previous VDS settings */
if (H5Pset_layout(dcpl_id[j], H5D_CONTIGUOUS) < 0)
TEST_ERROR;
/* Set virtual dataset layout, ALL<>ALL mapping */
if (H5Pset_virtual(dcpl_id[j], file_space_ids[j], ".", SOURCE_DS_NAME, file_space_ids[j]) < 0)
TEST_ERROR;
}
/* Create dataset */
/* If MDSET_FLAG_TCONV is set, use a different datatype with 50% probability, so
* some datasets require type conversion and others do not */
if ((dset_ids[j] = H5Dcreate2(file_id, dset_name[j],
(flags & MDSET_FLAG_TCONV && HDrandom() % 2) ? H5T_NATIVE_LONG
: H5T_NATIVE_UINT,
file_space_ids[j], H5P_DEFAULT, dcpl_id[j], H5P_DEFAULT)) < 0)
TEST_ERROR;
/* Create virtual source dataset if necessary. Use dcpl_id[0] for a contiguous dataset
*/
if ((flags & MDSET_FLAG_MLAYOUT) && (j == 6)) {
if ((source_dset = H5Dcreate2(file_id, SOURCE_DS_NAME,
(flags & MDSET_FLAG_TCONV && HDrandom() % 2) ? H5T_NATIVE_LONG
: H5T_NATIVE_UINT,
file_space_ids[j], H5P_DEFAULT, dcpl_id[0], H5P_DEFAULT)) < 0)
TEST_ERROR;
if (H5Dclose(source_dset) < 0)
TEST_ERROR;
}
} /* end for */
/* Initialize read buffer and expected read buffer */
(void)HDmemset(rbuf, 0, buf_size);
(void)HDmemset(erbuf, 0, buf_size);
/* Initialize write buffer */
for (j = 0; j < max_dsets; j++)
for (k = 0; k < MAX_DSET_X; k++)
for (l = 0; l < MAX_DSET_Y; l++)
wbufi[j][k][l] = (unsigned)((j * MAX_DSET_X * MAX_DSET_Y) + (k * MAX_DSET_Y) + l);
/* Initialize expected file buffer */
(void)HDmemset(efbuf, 0, buf_size);
/* Perform read/write operations */
for (j = 0; j < OPS_PER_FILE; j++) {
/* Decide whether to read or write. Can't read on the first iteration with external
* layout because the write is needed to create the external file. */
do_read = (j == 0 && flags & MDSET_FLAG_MLAYOUT) ? FALSE : (hbool_t)(HDrandom() % 2);
/* Loop over datasets */
for (k = 0; k < ndsets; k++) {
int sel_type;
/* Reset selection */
if (H5Sselect_none(mem_space_ids[k]) < 0)
TEST_ERROR;
if (H5Sselect_none(file_space_ids[k]) < 0)
TEST_ERROR;
/* Decide whether to do a hyperslab, point, or all selection */
sel_type = HDrandom() % 3;
if (sel_type == 0) {
/* Hyperslab */
size_t nhs = (size_t)((HDrandom() % MAX_HS) + 1); /* Number of hyperslabs */
size_t max_hs_x = (MAX_HS_X <= dset_dims[k][0])
? MAX_HS_X
: dset_dims[k][0]; /* Determine maximum hyperslab size in X */
size_t max_hs_y = (MAX_HS_Y <= dset_dims[k][1])
? MAX_HS_Y
: dset_dims[k][1]; /* Determine maximum hyperslab size in Y */
for (l = 0; l < nhs; l++) {
/* Generate hyperslab */
count[0] = (hsize_t)(((hsize_t)HDrandom() % max_hs_x) + 1);
count[1] = (hsize_t)(((hsize_t)HDrandom() % max_hs_y) + 1);
start[0] = (count[0] == dset_dims[k][0])
? 0
: (hsize_t)HDrandom() % (dset_dims[k][0] - count[0] + 1);
start[1] = (count[1] == dset_dims[k][1])
? 0
: (hsize_t)HDrandom() % (dset_dims[k][1] - count[1] + 1);
/* Select hyperslab */
if (H5Sselect_hyperslab(mem_space_ids[k], H5S_SELECT_OR, start, NULL, count, NULL) <
0)
TEST_ERROR;
if (H5Sselect_hyperslab(file_space_ids[k], H5S_SELECT_OR, start, NULL, count, NULL) <
0)
TEST_ERROR;
/* Update expected buffers */
if (do_read) {
for (m = start[0]; m < (start[0] + count[0]); m++)
for (n = start[1]; n < (start[1] + count[1]); n++)
erbufi[k][m][n] = efbufi[k][m][n];
} /* end if */
else
for (m = start[0]; m < (start[0] + count[0]); m++)
for (n = start[1]; n < (start[1] + count[1]); n++)
efbufi[k][m][n] = wbufi[k][m][n];
} /* end for */
} /* end if */
else if (sel_type == 1) {
/* Point selection */
size_t npoints = (size_t)(((size_t)HDrandom() % MAX_POINTS) + 1); /* Number of points */
/* Generate points */
for (l = 0; l < npoints; l++) {
points[2 * l] = (unsigned)((hsize_t)HDrandom() % dset_dims[k][0]);
points[(2 * l) + 1] = (unsigned)((hsize_t)HDrandom() % dset_dims[k][1]);
} /* end for */
/* Select points in file */
if (H5Sselect_elements(file_space_ids[k], H5S_SELECT_APPEND, npoints, points) < 0)
TEST_ERROR;
/* Update expected buffers */
if (do_read) {
for (l = 0; l < npoints; l++)
erbufi[k][points[2 * l]][points[(2 * l) + 1]] =
efbufi[k][points[2 * l]][points[(2 * l) + 1]];
} /* end if */
else
for (l = 0; l < npoints; l++)
efbufi[k][points[2 * l]][points[(2 * l) + 1]] =
wbufi[k][points[2 * l]][points[(2 * l) + 1]];
/* Convert to 3D for memory selection, if not using
* "shapesame" */
if (!(flags & MDSET_FLAG_SHAPESAME)) {
for (l = npoints - 1; l > 0; l--) {
points[(3 * l) + 2] = 0;
points[(3 * l) + 1] = points[(2 * l) + 1];
points[3 * l] = points[2 * l];
} /* end for */
points[2] = 0;
} /* end if */
/* Select points in memory */
if (H5Sselect_elements(mem_space_ids[k], H5S_SELECT_APPEND, npoints, points) < 0)
TEST_ERROR;
} /* end else */
else {
/* All selection */
/* Select entire dataset in file */
if (H5Sselect_all(file_space_ids[k]) < 0)
TEST_ERROR;
/* Select entire dataset in memory using hyperslab */
start[0] = 0;
start[1] = 0;
count[0] = dset_dims[k][0];
count[1] = dset_dims[k][1];
if (H5Sselect_hyperslab(mem_space_ids[k], H5S_SELECT_SET, start, NULL, count, NULL) < 0)
TEST_ERROR;
/* Update expected buffers */
if (do_read) {
for (m = 0; m < dset_dims[k][0]; m++)
for (n = 0; n < dset_dims[k][1]; n++)
erbufi[k][m][n] = efbufi[k][m][n];
} /* end if */
else
for (m = 0; m < dset_dims[k][0]; m++)
for (n = 0; n < dset_dims[k][1]; n++)
efbufi[k][m][n] = wbufi[k][m][n];
}
} /* end for */
/* Perform I/O */
if (do_read) {
if (flags & MDSET_FLAG_MDSET) {
/* Set buffers */
for (k = 0; k < ndsets; k++)
rbufs[k] = rbufi[k][0];
/* Read datasets */
if (H5Dread_multi(ndsets, dset_ids, mem_type_ids, mem_space_ids, file_space_ids,
H5P_DEFAULT, rbufs) < 0)
TEST_ERROR;
} /* end if */
else
/* Read */
if (H5Dread(dset_ids[0], mem_type_ids[0], mem_space_ids[0], file_space_ids[0],
H5P_DEFAULT, rbuf) < 0)
TEST_ERROR;
/* Verify data */
if (0 != memcmp(rbuf, erbuf, buf_size))
TEST_ERROR;
} /* end if */
else {
if (flags & MDSET_FLAG_MDSET) {
/* Set buffers */
for (k = 0; k < ndsets; k++)
wbufs[k] = wbufi[k][0];
/* Write datasets */
if (H5Dwrite_multi(ndsets, dset_ids, mem_type_ids, mem_space_ids, file_space_ids,
H5P_DEFAULT, wbufs) < 0)
TEST_ERROR;
} /* end if */
else
/* Write */
if (H5Dwrite(dset_ids[0], mem_type_ids[0], mem_space_ids[0], file_space_ids[0],
H5P_DEFAULT, wbuf) < 0)
TEST_ERROR;
/* Update wbuf */
for (l = 0; l < max_dsets; l++)
for (m = 0; m < MAX_DSET_X; m++)
for (n = 0; n < MAX_DSET_Y; n++)
wbufi[l][m][n] += (unsigned)max_dsets * MAX_DSET_X * MAX_DSET_Y;
} /* end else */
} /* end for */
/* Close */
for (j = 0; j < ndsets; j++) {
if (H5Dclose(dset_ids[j]) < 0)
TEST_ERROR;
dset_ids[j] = -1;
if (H5Sclose(file_space_ids[j]) < 0)
TEST_ERROR;
file_space_ids[j] = -1;
} /* end for */
if (H5Fclose(file_id) < 0)
TEST_ERROR;
file_id = -1;
/* Cleanup external file. Need to do this because otherwise there is garbage when the
* dataset is created, even with early allocation and fill time. */
HDremove(EXT_FILENAME);
} /* end for */
/* Close */
for (i = 0; i < max_dsets; i++) {
if (H5Sclose(mem_space_ids[i]) < 0)
TEST_ERROR;
mem_space_ids[i] = -1;
} /* end for */
for (i = 0; i < MAX_DSETS; i++) {
if (H5Pclose(dcpl_id[i]) < 0)
TEST_ERROR;
dcpl_id[i] = -1;
}
free(rbuf);
rbuf = NULL;
free(erbuf);
erbuf = NULL;
free(wbuf);
wbuf = NULL;
free(efbuf);
efbuf = NULL;
PASSED();
return 0;
error:
H5E_BEGIN_TRY
{
for (i = 0; i < max_dsets; i++) {
H5Dclose(dset_ids[i]);
H5Sclose(mem_space_ids[i]);
H5Sclose(file_space_ids[i]);
H5Pclose(dcpl_id[i]);
} /* end for */
H5Fclose(file_id);
}
H5E_END_TRY
if (rbuf)
free(rbuf);
if (erbuf)
free(erbuf);
if (wbuf)
free(wbuf);
if (efbuf)
free(efbuf);
return -1;
} /* end test_mdset() */
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Runs all tests with all combinations of configuration
* flags.
*
* Return: Success: 0
* Failure: 1
*
* Programmer: Neil Fortner
* Monday, March 10, 2014
*
*-------------------------------------------------------------------------
*/
int
main(void)
{
hid_t fapl_id;
int nerrors = 0;
unsigned i;
int ret;
h5_reset();
fapl_id = h5_fileaccess();
/* Initialize random number seed */
HDsrandom((unsigned)HDtime(NULL));
/* Fill dset_name array */
for (i = 0; i < MAX_DSETS; i++) {
if ((ret = snprintf(dset_name[i], DSET_MAX_NAME_LEN, "dset%u", i)) < 0)
TEST_ERROR;
if (ret >= DSET_MAX_NAME_LEN)
TEST_ERROR;
} /* end for */
/* Check if deflate and fletcher32 filters are available */
if ((deflate_avail = H5Zfilter_avail(H5Z_FILTER_DEFLATE)) < 0)
TEST_ERROR;
if ((fletcher32_avail = H5Zfilter_avail(H5Z_FILTER_FLETCHER32)) < 0)
TEST_ERROR;
for (i = 0; i <= MDSET_ALL_FLAGS; i++) {
/* Skip incompatible flag combinations */
if (((i & MDSET_FLAG_MLAYOUT) && (i & MDSET_FLAG_CHUNK)) ||
((i & MDSET_FLAG_MLAYOUT) && !(i & MDSET_FLAG_MDSET)) ||
((i & MDSET_FLAG_FILTER) && !(i & MDSET_FLAG_CHUNK)))
continue;
/* Print flag configuration */
puts("\nConfiguration:");
printf(" Layout: %s\n", (i & MDSET_FLAG_MLAYOUT) ? "Multi"
: (i & MDSET_FLAG_CHUNK) ? "Chunked"
: "Contiguous");
printf(" Shape same: %s\n", (i & MDSET_FLAG_SHAPESAME) ? "Yes" : "No");
printf(" I/O type: %s\n", (i & MDSET_FLAG_MDSET) ? "Multi" : "Single");
printf(" Type conversion: %s\n", (i & MDSET_FLAG_TCONV) ? "Yes" : "No");
printf(" Data filter: %s\n", (i & MDSET_FLAG_MLAYOUT) ? "Mixed"
: (i & MDSET_FLAG_FILTER) ? "Yes"
: "No");
nerrors += test_mdset(50, i, fapl_id);
}
/* test all datasets in same container */
nerrors += test_mdset_location(fapl_id);
h5_cleanup(FILENAME, fapl_id);
if (nerrors)
goto error;
puts("All multi dataset tests passed.");
return 0;
error:
nerrors = MAX(1, nerrors);
printf("***** %d multi dataset TEST%s FAILED! *****\n", nerrors, 1 == nerrors ? "" : "S");
return 1;
} /* end main() */
+1 -1
View File
@@ -50,7 +50,7 @@ HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs):
#001: (file name) line (number) in H5D__read_api_common(): can't read data
major: Dataset
minor: Read failed
#002: (file name) line (number) in H5VL_dataset_read(): dataset read failed
#002: (file name) line (number) in H5VL_dataset_read_direct(): dataset read failed
major: Virtual Object Layer
minor: Read failed
#003: (file name) line (number) in H5VL__dataset_read(): dataset read failed
+1
View File
@@ -95,6 +95,7 @@ set (H5P_TESTS
t_pshutdown
t_prestart
t_init_term
t_pmulti_dset
t_shapesame
t_filters_parallel
t_subfiling_vfd
+2 -2
View File
@@ -34,7 +34,7 @@ check_SCRIPTS = $(TEST_SCRIPT_PARA)
# Test programs. These are our main targets.
#
TEST_PROG_PARA=t_mpi t_bigio testphdf5 t_cache t_cache_image t_pread t_pshutdown t_prestart t_init_term t_shapesame t_filters_parallel t_2Gio t_vfd
TEST_PROG_PARA=t_mpi t_bigio testphdf5 t_cache t_cache_image t_pread t_pshutdown t_prestart t_init_term t_pmulti_dset t_shapesame t_filters_parallel t_2Gio t_vfd
if SUBFILING_VFD_CONDITIONAL
TEST_PROG_PARA += t_subfiling_vfd
@@ -59,6 +59,6 @@ LDADD = $(LIBH5TEST) $(LIBHDF5)
# after_mpi_fin.h5 is from t_init_term
# go is used for debugging. See testphdf5.c.
CHECK_CLEANFILES+=MPItest.h5 Para*.h5 bigio_test.h5 CacheTestDummy.h5 \
ShapeSameTest.h5 shutdown.h5 after_mpi_fin.h5 go
ShapeSameTest.h5 shutdown.h5 pmulti_dset.h5 after_mpi_fin.h5 go
include $(top_srcdir)/config/conclude.am
+767
View File
@@ -0,0 +1,767 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Programmer: Neil Fortner
* March 10, 2014
*
* Purpose: Test H5Dwrite_multi() and H5Dread_multi using randomized
* parameters in parallel. Also tests H5Dwrite() and H5Dread()
* using a similar method.
*
* Note that this test currently relies on all processes generating
* the same sequence of random numbers after using a shared seed
* value, therefore it may not work across multiple machines.
*/
#include "h5test.h"
#include "testpar.h"
#define T_PMD_ERROR \
do { \
nerrors++; \
H5_FAILED(); \
AT(); \
printf("seed = %u\n", seed); \
} while (0)
#define FILENAME "pmulti_dset.h5"
#define MAX_DSETS 5
#define MAX_DSET_X 15
#define MAX_DSET_Y 10
#define MAX_CHUNK_X 8
#define MAX_CHUNK_Y 6
#define MAX_HS_X 4
#define MAX_HS_Y 2
#define MAX_HS 2
#define MAX_POINTS 6
#define MAX_SEL_RETRIES 10
#define OPS_PER_FILE 25
#define DSET_MAX_NAME_LEN 8
/* Option flags */
#define MDSET_FLAG_CHUNK 0x01u
#define MDSET_FLAG_MLAYOUT 0x02u
#define MDSET_FLAG_SHAPESAME 0x04u
#define MDSET_FLAG_MDSET 0x08u
#define MDSET_FLAG_COLLECTIVE 0x10u
#define MDSET_FLAG_COLLECTIVE_OPT 0x20u
#define MDSET_FLAG_TCONV 0x40u
#define MDSET_FLAG_FILTER 0x80u
#define MDSET_ALL_FLAGS \
(MDSET_FLAG_CHUNK | MDSET_FLAG_MLAYOUT | MDSET_FLAG_SHAPESAME | MDSET_FLAG_MDSET | \
MDSET_FLAG_COLLECTIVE | MDSET_FLAG_COLLECTIVE_OPT | MDSET_FLAG_TCONV | MDSET_FLAG_FILTER)
/* MPI variables */
int mpi_size;
int mpi_rank;
/* Names for datasets */
char dset_name[MAX_DSETS][DSET_MAX_NAME_LEN];
/* Random number seed */
unsigned seed;
/* Number of errors */
int nerrors = 0;
/* Whether these filters are available */
htri_t deflate_avail = FALSE;
htri_t fletcher32_avail = FALSE;
/*-------------------------------------------------------------------------
* Function: test_pmdset
*
* Purpose: Test randomized I/O using one or more datasets. Creates a
* file, runs OPS_PER_FILE read or write operations verifying
* that reads return the expected data, then closes the file.
* Runs the test with a new file niter times.
*
* The operations can use either hyperslab or point
* selections. Options are available for chunked or
* contiguous layout, use of multiple datasets and H5D*_multi
* calls, and use of the "shapesame" algorithm code path. To
* avoid the shapesame path when that option is not set, this
* function simply adds a dimension to the memory buffer in a
* way that the shapesame code is not designed to handle.
*
* Return: Number of errors
*
* Programmer: Neil Fortner
* Monday, March 10, 2014
*
*-------------------------------------------------------------------------
*/
static void
test_pmdset(size_t niter, unsigned flags)
{
hid_t dset_ids[MAX_DSETS];
hid_t mem_type_ids[MAX_DSETS];
hid_t mem_space_ids[MAX_DSETS];
hid_t file_space_ids[MAX_DSETS];
void *rbufs[MAX_DSETS];
const void *wbufs[MAX_DSETS];
size_t max_dsets;
size_t buf_size;
size_t ndsets;
hid_t file_id = -1;
hid_t fapl_id = -1;
hid_t dcpl_id[MAX_DSETS];
hid_t dxpl_id = -1;
hsize_t dset_dims[MAX_DSETS][3];
hsize_t chunk_dims[2];
hsize_t max_dims[2] = {H5S_UNLIMITED, H5S_UNLIMITED};
unsigned *rbuf = NULL;
unsigned *rbufi[MAX_DSETS][MAX_DSET_X];
unsigned *erbuf = NULL;
unsigned *erbufi[MAX_DSETS][MAX_DSET_X];
unsigned *wbuf = NULL;
unsigned *wbufi[MAX_DSETS][MAX_DSET_X];
unsigned *efbuf = NULL;
unsigned *efbufi[MAX_DSETS][MAX_DSET_X];
unsigned char *dset_usage;
unsigned char *dset_usagei[MAX_DSETS][MAX_DSET_X];
hbool_t do_read;
hbool_t last_read;
hbool_t overlap;
hsize_t start[MAX_HS][3];
hsize_t count[MAX_HS][3];
hsize_t points[3 * MAX_POINTS];
int rank_data_diff;
unsigned op_data_incr;
size_t i, j, k, l, m, n, o, p;
if (mpi_rank == 0)
TESTING("random I/O");
/* Skipped configurations */
if (!(flags & MDSET_FLAG_COLLECTIVE_OPT)) {
if (mpi_rank == 0)
SKIPPED();
return;
}
/* Calculate maximum number of datasets */
max_dsets = (flags & MDSET_FLAG_MDSET) ? MAX_DSETS : 1;
/* Calculate data increment per write operation */
op_data_incr = (unsigned)max_dsets * MAX_DSET_X * MAX_DSET_Y * (unsigned)mpi_size;
/* Calculate buffer size */
buf_size = max_dsets * MAX_DSET_X * MAX_DSET_Y * sizeof(unsigned);
/* Initialize dcpl_id array */
for (i = 0; i < max_dsets; i++)
dcpl_id[i] = -1;
/* Allocate buffers */
if (NULL == (rbuf = (unsigned *)HDmalloc(buf_size)))
T_PMD_ERROR;
if (NULL == (erbuf = (unsigned *)HDmalloc(buf_size)))
T_PMD_ERROR;
if (NULL == (wbuf = (unsigned *)HDmalloc(buf_size)))
T_PMD_ERROR;
if (NULL == (efbuf = (unsigned *)HDmalloc(buf_size)))
T_PMD_ERROR;
if (NULL == (dset_usage = (unsigned char *)HDmalloc(max_dsets * MAX_DSET_X * MAX_DSET_Y)))
T_PMD_ERROR;
/* Initialize buffer indices */
for (i = 0; i < max_dsets; i++)
for (j = 0; j < MAX_DSET_X; j++) {
rbufi[i][j] = rbuf + (i * MAX_DSET_X * MAX_DSET_Y) + (j * MAX_DSET_Y);
erbufi[i][j] = erbuf + (i * MAX_DSET_X * MAX_DSET_Y) + (j * MAX_DSET_Y);
wbufi[i][j] = wbuf + (i * MAX_DSET_X * MAX_DSET_Y) + (j * MAX_DSET_Y);
efbufi[i][j] = efbuf + (i * MAX_DSET_X * MAX_DSET_Y) + (j * MAX_DSET_Y);
dset_usagei[i][j] = dset_usage + (i * MAX_DSET_X * MAX_DSET_Y) + (j * MAX_DSET_Y);
} /* end for */
/* Initialize 3rd dimension information (for tricking library into using
* non-"shapesame" code */
for (i = 0; i < max_dsets; i++)
dset_dims[i][2] = 1;
for (i = 0; i < MAX_HS; i++) {
start[i][2] = 0;
count[i][2] = 1;
} /* end for */
/* Initialize IDs */
for (i = 0; i < max_dsets; i++) {
dset_ids[i] = -1;
file_space_ids[i] = -1;
mem_type_ids[i] = H5T_NATIVE_UINT;
mem_space_ids[i] = -1;
} /* end for */
/* Generate memory dataspace */
dset_dims[0][0] = MAX_DSET_X;
dset_dims[0][1] = MAX_DSET_Y;
if ((mem_space_ids[0] = H5Screate_simple((flags & MDSET_FLAG_SHAPESAME) ? 2 : 3, dset_dims[0], NULL)) < 0)
T_PMD_ERROR;
for (i = 1; i < max_dsets; i++)
if ((mem_space_ids[i] = H5Scopy(mem_space_ids[0])) < 0)
T_PMD_ERROR;
/* Create fapl */
if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
T_PMD_ERROR;
/* Set MPIO file driver */
if ((H5Pset_fapl_mpio(fapl_id, MPI_COMM_WORLD, MPI_INFO_NULL)) < 0)
T_PMD_ERROR;
/* Create dcpl 0 */
if ((dcpl_id[0] = H5Pcreate(H5P_DATASET_CREATE)) < 0)
T_PMD_ERROR;
/* Set fill time to alloc, and alloc time to early (so we always know
* what's in the file) */
if (H5Pset_fill_time(dcpl_id[0], H5D_FILL_TIME_ALLOC) < 0)
T_PMD_ERROR;
if (H5Pset_alloc_time(dcpl_id[0], H5D_ALLOC_TIME_EARLY) < 0)
T_PMD_ERROR;
/* Set filters if requested */
if (flags & MDSET_FLAG_FILTER) {
if (fletcher32_avail)
if (H5Pset_fletcher32(dcpl_id[0]) < 0)
T_PMD_ERROR;
if (deflate_avail)
if (H5Pset_deflate(dcpl_id[0], 1) < 0)
T_PMD_ERROR;
}
/* Copy dcpl 0 to other slots in dcpl_id array */
for (i = 1; i < MAX_DSETS; i++)
if ((dcpl_id[i] = H5Pcopy(dcpl_id[0])) < 0)
T_PMD_ERROR;
/* If this is a multi layout run, dataset 2 will use filters, set them now */
if (flags & MDSET_FLAG_MLAYOUT) {
if (fletcher32_avail)
if (H5Pset_fletcher32(dcpl_id[2]) < 0)
T_PMD_ERROR;
if (deflate_avail)
if (H5Pset_deflate(dcpl_id[2], 1) < 0)
T_PMD_ERROR;
}
/* Create dxpl */
if ((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0)
T_PMD_ERROR;
/* Set collective or independent I/O */
if (flags & MDSET_FLAG_COLLECTIVE) {
if (H5Pset_dxpl_mpio(dxpl_id, H5FD_MPIO_COLLECTIVE) < 0)
T_PMD_ERROR;
/* Set low level I/O mode */
if (flags & MDSET_FLAG_COLLECTIVE_OPT) {
if (H5Pset_dxpl_mpio_collective_opt(dxpl_id, H5FD_MPIO_COLLECTIVE_IO) < 0)
T_PMD_ERROR;
}
else if (H5Pset_dxpl_mpio_collective_opt(dxpl_id, H5FD_MPIO_INDIVIDUAL_IO) < 0)
T_PMD_ERROR;
} /* end if */
else if (H5Pset_dxpl_mpio(dxpl_id, H5FD_MPIO_INDEPENDENT) < 0)
T_PMD_ERROR;
for (i = 0; i < niter; i++) {
/* Determine number of datasets */
ndsets = (flags & MDSET_FLAG_MLAYOUT) ? 3
: (flags & MDSET_FLAG_MDSET) ? (size_t)((size_t)HDrandom() % max_dsets) + 1
: 1;
/* Create file */
if ((file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
T_PMD_ERROR;
/* Create datasets */
for (j = 0; j < ndsets; j++) {
hbool_t use_chunk =
(flags & MDSET_FLAG_CHUNK) || ((flags & MDSET_FLAG_MLAYOUT) && (j == 1 || j == 2));
/* Generate file dataspace */
dset_dims[j][0] = (hsize_t)((HDrandom() % MAX_DSET_X) + 1);
dset_dims[j][1] = (hsize_t)((HDrandom() % MAX_DSET_Y) + 1);
if ((file_space_ids[j] = H5Screate_simple(2, dset_dims[j], use_chunk ? max_dims : NULL)) < 0)
T_PMD_ERROR;
/* Generate chunk if called for by configuration (multi layout uses chunked for datasets
* 1 and 2) */
if (use_chunk) {
chunk_dims[0] = (hsize_t)((HDrandom() % MAX_CHUNK_X) + 1);
chunk_dims[1] = (hsize_t)((HDrandom() % MAX_CHUNK_Y) + 1);
if (H5Pset_chunk(dcpl_id[j], 2, chunk_dims) < 0)
T_PMD_ERROR;
} /* end if */
/* Create dataset */
/* If MDSET_FLAG_TCONV is set, use a different datatype with 50% probability, so
* some datasets require type conversion and others do not */
if ((dset_ids[j] = H5Dcreate2(file_id, dset_name[j],
(flags & MDSET_FLAG_TCONV && HDrandom() % 2) ? H5T_NATIVE_LONG
: H5T_NATIVE_UINT,
file_space_ids[j], H5P_DEFAULT, dcpl_id[j], H5P_DEFAULT)) < 0)
T_PMD_ERROR;
} /* end for */
/* Initialize read buffer and expected read buffer */
(void)HDmemset(rbuf, 0, buf_size);
(void)HDmemset(erbuf, 0, buf_size);
/* Initialize write buffer */
for (j = 0; j < max_dsets; j++)
for (k = 0; k < MAX_DSET_X; k++)
for (l = 0; l < MAX_DSET_Y; l++)
wbufi[j][k][l] = (unsigned)(((unsigned)mpi_rank * max_dsets * MAX_DSET_X * MAX_DSET_Y) +
(j * MAX_DSET_X * MAX_DSET_Y) + (k * MAX_DSET_Y) + l);
/* Initialize expected file buffer */
(void)HDmemset(efbuf, 0, buf_size);
/* Set last_read to TRUE so we don't reopen the file on the first
* iteration */
last_read = TRUE;
/* Perform read/write operations */
for (j = 0; j < OPS_PER_FILE; j++) {
/* Decide whether to read or write */
do_read = (hbool_t)(HDrandom() % 2);
/* Barrier to ensure processes have finished the previous operation
*/
MPI_Barrier(MPI_COMM_WORLD);
/* If the last operation was a write we must close and reopen the
* file to ensure consistency */
/* Possibly change to MPI_FILE_SYNC at some point? -NAF */
if (!last_read) {
/* Close datasets */
for (k = 0; k < ndsets; k++) {
if (H5Dclose(dset_ids[k]) < 0)
T_PMD_ERROR;
dset_ids[k] = -1;
} /* end for */
/* Close file */
if (H5Fclose(file_id) < 0)
T_PMD_ERROR;
file_id = -1;
/* Barrier */
MPI_Barrier(MPI_COMM_WORLD);
/* Reopen file */
if ((file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, fapl_id)) < 0)
T_PMD_ERROR;
/* Reopen datasets */
for (k = 0; k < ndsets; k++) {
if ((dset_ids[k] = H5Dopen2(file_id, dset_name[k], H5P_DEFAULT)) < 0)
T_PMD_ERROR;
} /* end for */
/* Barrier */
MPI_Barrier(MPI_COMM_WORLD);
} /* end if */
/* Keep track of whether the last operation was a read */
last_read = do_read;
/* Loop over datasets */
for (k = 0; k < ndsets; k++) {
/* Reset selection */
if (H5Sselect_none(mem_space_ids[k]) < 0)
T_PMD_ERROR;
if (H5Sselect_none(file_space_ids[k]) < 0)
T_PMD_ERROR;
/* Reset dataset usage array, if writing */
if (!do_read)
HDmemset(dset_usage, 0, max_dsets * MAX_DSET_X * MAX_DSET_Y);
/* Iterate over processes */
for (l = 0; l < (size_t)mpi_size; l++) {
/* Calculate difference between data in process being
* iterated over and that in this process */
rank_data_diff =
(int)((unsigned)max_dsets * MAX_DSET_X * MAX_DSET_Y) * ((int)l - (int)mpi_rank);
/* Decide whether to do a hyperslab or point selection */
if (HDrandom() % 2) {
/* Hyperslab */
size_t nhs = (size_t)((HDrandom() % MAX_HS) + 1); /* Number of hyperslabs */
size_t max_hs_x = (MAX_HS_X <= dset_dims[k][0])
? MAX_HS_X
: dset_dims[k][0]; /* Determine maximum hyperslab size in X */
size_t max_hs_y = (MAX_HS_Y <= dset_dims[k][1])
? MAX_HS_Y
: dset_dims[k][1]; /* Determine maximum hyperslab size in Y */
for (m = 0; m < nhs; m++) {
overlap = TRUE;
for (n = 0; overlap && (n < MAX_SEL_RETRIES); n++) {
/* Generate hyperslab */
count[m][0] = (hsize_t)(((hsize_t)HDrandom() % max_hs_x) + 1);
count[m][1] = (hsize_t)(((hsize_t)HDrandom() % max_hs_y) + 1);
start[m][0] = (count[m][0] == dset_dims[k][0])
? 0
: (hsize_t)HDrandom() % (dset_dims[k][0] - count[m][0] + 1);
start[m][1] = (count[m][1] == dset_dims[k][1])
? 0
: (hsize_t)HDrandom() % (dset_dims[k][1] - count[m][1] + 1);
/* If writing, check for overlap with other processes */
overlap = FALSE;
if (!do_read)
for (o = start[m][0]; (o < (start[m][0] + count[m][0])) && !overlap; o++)
for (p = start[m][1]; (p < (start[m][1] + count[m][1])) && !overlap;
p++)
if (dset_usagei[k][o][p])
overlap = TRUE;
} /* end for */
/* If we did not find a non-overlapping hyperslab
* quit trying to generate new ones */
if (overlap) {
nhs = m;
break;
} /* end if */
/* Select hyperslab if this is the current process
*/
if (l == (size_t)mpi_rank) {
if (H5Sselect_hyperslab(mem_space_ids[k], H5S_SELECT_OR, start[m], NULL,
count[m], NULL) < 0)
T_PMD_ERROR;
if (H5Sselect_hyperslab(file_space_ids[k], H5S_SELECT_OR, start[m], NULL,
count[m], NULL) < 0)
T_PMD_ERROR;
} /* end if */
/* Update expected buffers */
if (do_read) {
if (l == (size_t)mpi_rank)
for (n = start[m][0]; n < (start[m][0] + count[m][0]); n++)
for (o = start[m][1]; o < (start[m][1] + count[m][1]); o++)
erbufi[k][n][o] = efbufi[k][n][o];
} /* end if */
else
for (n = start[m][0]; n < (start[m][0] + count[m][0]); n++)
for (o = start[m][1]; o < (start[m][1] + count[m][1]); o++)
efbufi[k][n][o] = (unsigned)((int)wbufi[k][n][o] + rank_data_diff);
} /* end for */
/* Update dataset usage array if writing */
if (!do_read)
for (m = 0; m < nhs; m++)
for (n = start[m][0]; n < (start[m][0] + count[m][0]); n++)
for (o = start[m][1]; o < (start[m][1] + count[m][1]); o++)
dset_usagei[k][n][o] = (unsigned char)1;
} /* end if */
else {
/* Point selection */
size_t npoints =
(size_t)(((size_t)HDrandom() % MAX_POINTS) + 1); /* Number of points */
/* Reset dataset usage array if reading, since in this case we don't care
* about overlapping selections between processes */
if (do_read)
HDmemset(dset_usage, 0, max_dsets * MAX_DSET_X * MAX_DSET_Y);
/* Generate points */
for (m = 0; m < npoints; m++) {
overlap = TRUE;
for (n = 0; overlap && (n < MAX_SEL_RETRIES); n++) {
/* Generate point */
points[2 * m] = (unsigned)((hsize_t)HDrandom() % dset_dims[k][0]);
points[(2 * m) + 1] = (unsigned)((hsize_t)HDrandom() % dset_dims[k][1]);
/* Check for overlap with other processes (write) or this process
* (always) */
overlap = FALSE;
if (dset_usagei[k][points[2 * m]][points[(2 * m) + 1]])
overlap = TRUE;
} /* end for */
/* If we did not find a non-overlapping point quit
* trying to generate new ones */
if (overlap) {
npoints = m;
break;
} /* end if */
/* Update dataset usage array after each point to prevent the same point
* being selected twice by a single process, since this is not supported
* by MPI */
dset_usagei[k][points[2 * m]][points[(2 * m) + 1]] = (unsigned char)1;
} /* end for */
/* Select points in file if this is the current process
*/
if ((l == (size_t)mpi_rank) && (npoints > 0))
if (H5Sselect_elements(file_space_ids[k], H5S_SELECT_APPEND, npoints, points) < 0)
T_PMD_ERROR;
/* Update expected buffers */
if (do_read) {
if (l == (size_t)mpi_rank)
for (m = 0; m < npoints; m++)
erbufi[k][points[2 * m]][points[(2 * m) + 1]] =
efbufi[k][points[2 * m]][points[(2 * m) + 1]];
} /* end if */
else
for (m = 0; m < npoints; m++)
efbufi[k][points[2 * m]][points[(2 * m) + 1]] =
(unsigned)((int)wbufi[k][points[2 * m]][points[(2 * m) + 1]] +
rank_data_diff);
/* Select points in memory if this is the current
* process */
if ((l == (size_t)mpi_rank) && (npoints > 0)) {
/* Convert to 3D for memory selection, if not using
* "shapesame" */
if (!(flags & MDSET_FLAG_SHAPESAME)) {
for (m = npoints - 1; m > 0; m--) {
points[(3 * m) + 2] = 0;
points[(3 * m) + 1] = points[(2 * m) + 1];
points[3 * m] = points[2 * m];
} /* end for */
points[2] = 0;
} /* end if */
/* Select elements */
if (H5Sselect_elements(mem_space_ids[k], H5S_SELECT_APPEND, npoints, points) < 0)
T_PMD_ERROR;
} /* end if */
} /* end else */
} /* end for */
} /* end for */
/* Perform I/O */
if (do_read) {
if (flags & MDSET_FLAG_MDSET) {
/* Set buffers */
for (k = 0; k < ndsets; k++)
rbufs[k] = rbufi[k][0];
/* Read datasets */
if (H5Dread_multi(ndsets, dset_ids, mem_type_ids, mem_space_ids, file_space_ids, dxpl_id,
rbufs) < 0)
T_PMD_ERROR;
} /* end if */
else
/* Read */
if (H5Dread(dset_ids[0], mem_type_ids[0], mem_space_ids[0], file_space_ids[0], dxpl_id,
rbuf) < 0)
T_PMD_ERROR;
/* Verify data */
if (0 != memcmp(rbuf, erbuf, buf_size))
T_PMD_ERROR;
} /* end if */
else {
if (flags & MDSET_FLAG_MDSET) {
/* Set buffers */
for (k = 0; k < ndsets; k++)
wbufs[k] = wbufi[k][0];
/* Write datasets */
if (H5Dwrite_multi(ndsets, dset_ids, mem_type_ids, mem_space_ids, file_space_ids, dxpl_id,
wbufs) < 0)
T_PMD_ERROR;
} /* end if */
else
/* Write */
if (H5Dwrite(dset_ids[0], mem_type_ids[0], mem_space_ids[0], file_space_ids[0], dxpl_id,
wbuf) < 0)
T_PMD_ERROR;
/* Update wbuf */
for (l = 0; l < max_dsets; l++)
for (m = 0; m < MAX_DSET_X; m++)
for (n = 0; n < MAX_DSET_Y; n++)
wbufi[l][m][n] += op_data_incr;
} /* end else */
} /* end for */
/* Close */
for (j = 0; j < ndsets; j++) {
if (H5Dclose(dset_ids[j]) < 0)
T_PMD_ERROR;
dset_ids[j] = -1;
if (H5Sclose(file_space_ids[j]) < 0)
T_PMD_ERROR;
file_space_ids[j] = -1;
} /* end for */
if (H5Fclose(file_id) < 0)
T_PMD_ERROR;
file_id = -1;
} /* end for */
/* Close */
for (i = 0; i < max_dsets; i++) {
if (H5Sclose(mem_space_ids[i]) < 0)
T_PMD_ERROR;
mem_space_ids[i] = -1;
} /* end for */
if (H5Pclose(dxpl_id) < 0)
T_PMD_ERROR;
dxpl_id = -1;
for (i = 0; i < MAX_DSETS; i++) {
if (H5Pclose(dcpl_id[i]) < 0)
T_PMD_ERROR;
dcpl_id[i] = -1;
}
if (H5Pclose(fapl_id) < 0)
T_PMD_ERROR;
fapl_id = -1;
free(rbuf);
rbuf = NULL;
free(erbuf);
erbuf = NULL;
free(wbuf);
wbuf = NULL;
free(efbuf);
efbuf = NULL;
free(dset_usage);
dset_usage = NULL;
if (mpi_rank == 0)
PASSED();
return;
} /* end test_mdset() */
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Runs all tests with all combinations of configuration
* flags.
*
* Return: Success: 0
* Failure: 1
*
* Programmer: Neil Fortner
* Monday, March 10, 2014
*
*-------------------------------------------------------------------------
*/
int
main(int argc, char *argv[])
{
unsigned i;
int ret;
h5_reset();
/* Initialize MPI */
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
/* Generate random number seed, if rank 0 */
if (MAINPROCESS)
seed = (unsigned)HDtime(NULL);
/* Broadcast seed from rank 0 (other ranks will receive rank 0's seed) */
if (MPI_SUCCESS != MPI_Bcast(&seed, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD))
T_PMD_ERROR;
/* Seed random number generator with shared seed (so all ranks generate the
* same sequence) */
HDsrandom(seed);
/* Fill dset_name array */
for (i = 0; i < MAX_DSETS; i++) {
if ((ret = snprintf(dset_name[i], DSET_MAX_NAME_LEN, "dset%u", i)) < 0)
T_PMD_ERROR;
if (ret >= DSET_MAX_NAME_LEN)
T_PMD_ERROR;
} /* end for */
/* Check if deflate and fletcher32 filters are available */
if ((deflate_avail = H5Zfilter_avail(H5Z_FILTER_DEFLATE)) < 0)
T_PMD_ERROR;
if ((fletcher32_avail = H5Zfilter_avail(H5Z_FILTER_FLETCHER32)) < 0)
T_PMD_ERROR;
for (i = 0; i <= MDSET_ALL_FLAGS; i++) {
/* Skip incompatible flag combinations */
if (((i & MDSET_FLAG_MLAYOUT) && (i & MDSET_FLAG_CHUNK)) ||
((i & MDSET_FLAG_MLAYOUT) && !(i & MDSET_FLAG_MDSET)) ||
((i & MDSET_FLAG_MLAYOUT) && !(i & MDSET_FLAG_COLLECTIVE)) ||
((i & MDSET_FLAG_MLAYOUT) && (i & MDSET_FLAG_TCONV)) ||
((i & MDSET_FLAG_FILTER) && !(i & MDSET_FLAG_CHUNK)) ||
((i & MDSET_FLAG_FILTER) && !(i & MDSET_FLAG_COLLECTIVE)) ||
((i & MDSET_FLAG_FILTER) && (i & MDSET_FLAG_TCONV)) ||
(!(i & MDSET_FLAG_COLLECTIVE_OPT) && !(i & MDSET_FLAG_COLLECTIVE)))
continue;
/* Print flag configuration */
if (MAINPROCESS) {
puts("\nConfiguration:");
printf(" Layout: %s\n", (i & MDSET_FLAG_MLAYOUT) ? "Multi"
: (i & MDSET_FLAG_CHUNK) ? "Chunked"
: "Contiguous");
printf(" Shape same: %s\n", (i & MDSET_FLAG_SHAPESAME) ? "Yes" : "No");
printf(" I/O type: %s\n", (i & MDSET_FLAG_MDSET) ? "Multi" : "Single");
printf(" MPI I/O type: %s\n", (i & MDSET_FLAG_COLLECTIVE) ? "Collective" : "Independent");
if (i & MDSET_FLAG_COLLECTIVE)
printf(" Low level MPI I/O:%s\n",
(i & MDSET_FLAG_COLLECTIVE_OPT) ? "Collective" : "Independent");
printf(" Type conversion: %s\n", (i & MDSET_FLAG_TCONV) ? "Yes" : "No");
printf(" Data filter: %s\n", (i & MDSET_FLAG_MLAYOUT) ? "Mixed"
: (i & MDSET_FLAG_FILTER) ? "Yes"
: "No");
} /* end if */
test_pmdset(10, i);
} /* end for */
/* Barrier to make sure all ranks are done before deleting the file, and
* also to clean up output (make sure PASSED is printed before any of the
* following messages) */
if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD))
T_PMD_ERROR;
/* Delete file */
if (mpi_rank == 0)
if (MPI_SUCCESS != MPI_File_delete(FILENAME, MPI_INFO_NULL))
T_PMD_ERROR;
/* Gather errors from all processes */
MPI_Allreduce(&nerrors, &ret, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
nerrors = ret;
if (MAINPROCESS) {
printf("===================================\n");
if (nerrors)
printf("***Parallel multi dataset tests detected %d errors***\n", nerrors);
else
printf("Parallel multi dataset tests finished with no errors\n");
printf("===================================\n");
} /* end if */
/* close HDF5 library */
H5close();
/* MPI_Finalize must be called AFTER H5close which may use MPI calls */
MPI_Finalize();
/* cannot just return (nerrors) because exit code is limited to 1 byte */
return (nerrors != 0);
} /* end main() */